Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O histórico e a memória das conversas dos agentes são capacidades cruciais que permitem aos agentes manter o contexto nas conversas, recordar as preferências dos utilizadores e proporcionar experiências personalizadas. O Agent Framework oferece múltiplas funcionalidades para diferentes casos de uso, desde armazenamento simples de mensagens em memória até bases de dados persistentes e serviços de memória especializados.
Histórico do bate-papo
Várias opções de armazenamento de histórico de chat são suportadas pelo Agent Framework. As opções disponíveis variam de acordo com o tipo de agente e o(s) serviço(s) subjacente(s) usado(s) para criar o agente.
Os dois principais cenários suportados são:
-
Armazenamento em memória: O Agent é construído sobre um serviço que não suporta armazenamento em serviço do histórico de chat (por exemplo, OpenAI Chat Completion). Por defeito, o Agent Framework armazena todo o histórico de chat em memória no
AgentThreadobjeto, mas os programadores podem fornecer uma implementação personalizadaChatMessageStorepara armazenar o histórico de chat numa loja de terceiros, se necessário. -
Armazenamento em serviço: O Agent é construído sobre um serviço que requer armazenamento em serviço do histórico de chat (por exemplo, Azure AI Foundry Persistent Agents). O Agent Framework armazena o ID do histórico de chat remoto no
AgentThreadobjeto, e não são suportadas outras opções de armazenamento de histórico de chat.
Armazenamento do histórico de bate-papo na memória
Ao usar um serviço que não suporta armazenamento em serviço do histórico de conversa, o Agent Framework passa por defeito a armazenar o histórico de conversas na memória do AgentThread objeto. Neste caso, o histórico completo de chat armazenado no objeto thread, juntamente com quaisquer novas mensagens, será fornecido ao serviço subjacente em cada execução de agente. Este design permite uma experiência conversacional natural com o agente. O chamador apenas fornece a mensagem do novo utilizador, e o agente apenas devolve novas respostas. Mas o agente tem acesso ao histórico completo das conversas e irá usá-lo ao gerar a resposta.
Ao usar o OpenAI Chat Completion como serviço subjacente para os agentes, o código seguinte resulta no objeto thread contendo o histórico de chat do agente a ser executado.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.AsAIAgent(JokerInstructions, JokerName);
AgentThread thread = await agent.GetNewThreadAsync();
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
Quando as mensagens são armazenadas na memória, é possível recuperar a lista de mensagens da thread e manipular as mensagens diretamente, se necessário.
IList<ChatMessage>? messages = thread.GetService<IList<ChatMessage>>();
Observação
Recuperar mensagens do AgentThread objeto desta forma só funciona se estiver a ser usado armazenamento em memória.
Redução do histórico de chat com armazenamento em memória
O sistema incorporado InMemoryChatMessageStore , que é usado por defeito quando o serviço subjacente não suporta armazenamento em serviço, pode ser configurado com um redutor para gerir o tamanho do histórico de chat.
Isso é útil para evitar exceder os limites de tamanho de contexto do serviço subjacente.
O InMemoryChatMessageStore pode ter uma implementação opcional Microsoft.Extensions.AI.IChatReducer para reduzir o tamanho do histórico de bate-papo.
Ele também permite que você configure o evento durante o qual o redutor é invocado, seja depois que uma mensagem é adicionada ao histórico de bate-papo ou antes que o histórico de bate-papo seja retornado para a próxima invocação.
Para configurar o InMemoryChatMessageStore com um redutor, você pode fornecer uma fábrica para construir um novo InMemoryChatMessageStore para cada novo AgentThread e passá-lo um redutor de sua escolha. O InMemoryChatMessageStore também pode ser passado um evento de gatilho opcional que pode ser definido como um InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded ou InMemoryChatMessageStore.ChatReducerTriggerEvent.BeforeMessagesRetrieval.
A fábrica é uma função assíncrona que recebe um objeto de contexto e um token de cancelamento.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.AsAIAgent(new ChatClientAgentOptions
{
Name = JokerName,
ChatOptions = new() { Instructions = JokerInstructions },
ChatMessageStoreFactory = (ctx, ct) => new ValueTask<ChatMessageStore>(
new InMemoryChatMessageStore(
new MessageCountingChatReducer(2),
ctx.SerializedState,
ctx.JsonSerializerOptions,
InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded))
});
Observação
Este recurso só é suportado ao usar o InMemoryChatMessageStore. Quando um serviço tem armazenamento de histórico de bate-papo em serviço, cabe ao próprio serviço gerenciar o tamanho do histórico de bate-papo. Da mesma forma, ao usar o armazenamento de terceiros (veja abaixo), cabe à solução de armazenamento de terceiros gerenciar o tamanho do histórico de bate-papo. Se você fornecer um ChatMessageStoreFactory para um armazenamento de mensagens, mas usar um serviço com armazenamento de histórico de bate-papo integrado, a fábrica não será usada.
Armazenamento do histórico de chat do serviço de inferência
Ao usar um serviço que requer armazenamento em serviço do histórico de chat, o Agent Framework armazena o ID do histórico de chat remoto no AgentThread objeto.
Por exemplo, ao usar OpenAI Responses com store=true como serviço subjacente para agentes, o código seguinte resultará no objeto thread contendo o último ID de resposta devolvido pelo serviço.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetOpenAIResponseClient(modelName)
.AsAIAgent(JokerInstructions, JokerName);
AgentThread thread = await agent.GetNewThreadAsync();
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
Observação
Alguns serviços, por exemplo, o OpenAI Responses, suportam o armazenamento em serviço do histórico de conversas (store=true), ou a disponibilização do histórico completo de chat em cada invocação (store=false). Portanto, dependendo do modo em que o serviço é utilizado, o Agent Framework irá armazenar por defeito o histórico completo de conversas na memória, ou guardar uma referência de ID no histórico de chat armazenado do serviço.
Armazenamento do histórico de chat de terceiros
Ao utilizar um serviço que não suporta armazenamento em serviço do histórico de conversas, o Agent Framework permite aos programadores substituir o armazenamento padrão em memória do histórico de conversas por armazenamento de terceiros. O desenvolvedor é obrigado a fornecer uma subclasse da classe abstrata ChatMessageStore base.
A ChatMessageStore classe define a interface para armazenar e recuperar mensagens de chat. Os desenvolvedores devem implementar os InvokedAsync métodos e InvokingAsync para adicionar mensagens ao armazenamento remoto à medida que são geradas e recuperar mensagens do repositório remoto antes de invocar o serviço subjacente.
O agente usará todas as mensagens retornadas ao InvokingAsync processar uma consulta de usuário. Cabe ao implementador garantir que o tamanho do histórico de ChatMessageStore bate-papo não exceda a janela de contexto do serviço subjacente.
Ao implementar um personalizado ChatMessageStore que armazena o histórico de bate-papo em um repositório remoto, o histórico de bate-papo desse thread deve ser armazenado sob uma chave exclusiva para esse thread. A ChatMessageStore implementação deve gerar essa chave e mantê-la em seu estado.
ChatMessageStore tem um Serialize método que pode ser substituído para serializar seu estado quando o thread é serializado. O ChatMessageStore também deve fornecer um construtor que usa um JsonElement como entrada para dar suporte à desserialização de seu estado.
Para fornecer um personalizado ChatMessageStore para um ChatClientAgent, você pode usar a ChatMessageStoreFactory opção ao criar o agente.
Aqui está um exemplo mostrando como passar a implementação personalizada de para um ChatMessageStore que é baseado na conclusão do ChatClientAgent Chat do Azure OpenAI.
A fábrica é uma função assíncrona que recebe um objeto de contexto e um token de cancelamento.
AIAgent agent = new AzureOpenAIClient(
new Uri(endpoint),
new AzureCliCredential())
.GetChatClient(deploymentName)
.AsAIAgent(new ChatClientAgentOptions
{
Name = JokerName,
ChatOptions = new() { Instructions = JokerInstructions },
ChatMessageStoreFactory = (ctx, ct) => new ValueTask<ChatMessageStore>(
// Create a new chat message store for this agent that stores the messages in a custom store.
// Each thread must get its own copy of the CustomMessageStore, since the store
// also contains the ID that the thread is stored under.
new CustomMessageStore(
vectorStore,
ctx.SerializedState,
ctx.JsonSerializerOptions))
});
Sugestão
Para obter um exemplo detalhado sobre como criar um armazenamento de mensagens personalizado, consulte o tutorial Armazenando histórico de bate-papo no armazenamento de terceiros 3rd .
Memória de longo prazo
O Agent Framework permite que os desenvolvedores forneçam componentes personalizados que podem extrair memórias ou fornecer memórias a um agente.
Para implementar esse componente de memória, o desenvolvedor precisa subclassificar a AIContextProvider classe base abstrata. Esta classe tem dois métodos principais, InvokingAsync e InvokedAsync. Quando substituído, InvokedAsync permite que os desenvolvedores inspecionem todas as mensagens fornecidas pelos usuários ou geradas pelo agente.
InvokingAsync permite que os desenvolvedores injetem contexto adicional para uma execução específica do agente. Instruções do sistema, mensagens adicionais e funções adicionais podem ser fornecidas.
Sugestão
Para obter um exemplo detalhado sobre como criar um componente de memória personalizado, consulte o tutorial Adicionando memória a um agente .
Serialização do AgentThread
É importante ser capaz de persistir um AgentThread objeto entre as invocações do agente. Isto permite situações em que um utilizador pode fazer uma pergunta ao agente e demorar muito tempo a fazer perguntas de seguimento. Isso permite que o AgentThread estado sobreviva às reinicializações de serviço ou aplicativo.
Mesmo que o histórico da conversa esteja armazenado numa loja remota, o AgentThread objeto ainda contém um ID que faz referência ao histórico da conversa remota. Perder o AgentThread estado resultará, portanto, também na perda do ID do histórico de chat remoto.
O AgentThread bem como quaisquer objetos anexados a ele, todos, portanto, fornecem o Serialize método para serializar seu estado. O AIAgent também fornece um DeserializeThreadAsync método que recria um thread a partir do estado serializado. O DeserializeThreadAsync método recria o thread com o ChatMessageStore e AIContextProvider configurado no agente.
// Serialize the thread state to a JsonElement, so it can be stored for later use.
JsonElement serializedThreadState = thread.Serialize();
// Re-create the thread from the JsonElement.
AgentThread resumedThread = await agent.DeserializeThreadAsync(serializedThreadState);
Observação
AgentThread Os objetos podem conter mais do que apenas o histórico de bate-papo, por exemplo, os provedores de contexto também podem armazenar o estado no objeto de thread. Portanto, é importante sempre serializar, armazenar e desserializar todo AgentThread o objeto para garantir que todo o estado seja preservado.
Importante
Trate AgentThread sempre os objetos como objetos opacos, a menos que tenha muita certeza dos elementos internos. O conteúdo pode variar não apenas por tipo de agente, mas também por tipo de serviço e configuração.
Advertência
Desserializar um thread com um agente diferente daquele que o criou originalmente, ou com um agente com uma configuração diferente do agente original, pode resultar em erros ou comportamentos inesperados.
Tipos de memória
O Agent Framework suporta vários tipos de memória para acomodar diferentes casos de uso, incluindo o gerenciamento do histórico de bate-papo como parte da memória de curto prazo e o fornecimento de pontos de extensão para extrair, armazenar e injetar memórias de longo prazo nos agentes.
In-Memory Storage (padrão)
A forma mais simples de memória em que o histórico de conversas é armazenado na memória durante o tempo de execução do aplicativo. Este é o comportamento padrão e não requer nenhuma configuração adicional.
from agent_framework import ChatAgent
from agent_framework.openai import OpenAIChatClient
# Default behavior - uses in-memory storage
agent = ChatAgent(
chat_client=OpenAIChatClient(),
instructions="You are a helpful assistant."
)
# Conversation history is maintained in memory for this thread
thread = agent.get_new_thread()
response = await agent.run("Hello, my name is Alice", thread=thread)
Armazenamentos de mensagens persistentes
Para aplicativos que precisam persistir o histórico de conversas entre sessões, a estrutura fornece ChatMessageStore implementações:
ChatMessageStore incorporado
A implementação na memória padrão que pode ser serializada:
from agent_framework import ChatMessageStore
# Create a custom message store
def create_message_store():
return ChatMessageStore()
agent = ChatAgent(
chat_client=OpenAIChatClient(),
instructions="You are a helpful assistant.",
chat_message_store_factory=create_message_store
)
Armazenamento de Mensagens Redis
Para aplicativos de produção que exigem armazenamento persistente:
from agent_framework.redis import RedisChatMessageStore
def create_redis_store():
return RedisChatMessageStore(
redis_url="redis://localhost:6379",
thread_id="user_session_123",
max_messages=100 # Keep last 100 messages
)
agent = ChatAgent(
chat_client=OpenAIChatClient(),
instructions="You are a helpful assistant.",
chat_message_store_factory=create_redis_store
)
Armazenamento de mensagens personalizadas
Você pode implementar seu próprio back-end de armazenamento implementando o ChatMessageStoreProtocol:
from agent_framework import ChatMessage, ChatMessageStoreProtocol
from typing import Any
from collections.abc import Sequence
class DatabaseMessageStore(ChatMessageStoreProtocol):
def __init__(self, connection_string: str):
self.connection_string = connection_string
self._messages: list[ChatMessage] = []
async def add_messages(self, messages: Sequence[ChatMessage]) -> None:
"""Add messages to database."""
# Implement database insertion logic
self._messages.extend(messages)
async def list_messages(self) -> list[ChatMessage]:
"""Retrieve messages from database."""
# Implement database query logic
return self._messages
async def serialize(self, **kwargs: Any) -> Any:
"""Serialize store state for persistence."""
return {"connection_string": self.connection_string}
async def update_from_state(self, serialized_store_state: Any, **kwargs: Any) -> None:
"""Update store from serialized state."""
if serialized_store_state:
self.connection_string = serialized_store_state["connection_string"]
Sugestão
Para obter um exemplo detalhado sobre como criar um armazenamento de mensagens personalizado, consulte o tutorial Armazenando histórico de bate-papo no armazenamento de terceiros 3rd .
Provedores de contexto (memória dinâmica)
Os provedores de contexto permitem padrões de memória sofisticados injetando contexto relevante antes de cada chamada de agente:
Provedor de contexto básico
from agent_framework import ContextProvider, Context, ChatMessage
from collections.abc import MutableSequence
from typing import Any
class UserPreferencesMemory(ContextProvider):
def __init__(self):
self.preferences = {}
async def invoking(self, messages: ChatMessage | MutableSequence[ChatMessage], **kwargs: Any) -> Context:
"""Provide user preferences before each invocation."""
if self.preferences:
preferences_text = ", ".join([f"{k}: {v}" for k, v in self.preferences.items()])
instructions = f"User preferences: {preferences_text}"
return Context(instructions=instructions)
return Context()
async def invoked(
self,
request_messages: ChatMessage | Sequence[ChatMessage],
response_messages: ChatMessage | Sequence[ChatMessage] | None = None,
invoke_exception: Exception | None = None,
**kwargs: Any,
) -> None:
"""Extract and store user preferences from the conversation."""
# Implement preference extraction logic
pass
Sugestão
Para obter um exemplo detalhado sobre como criar um componente de memória personalizado, consulte o tutorial Adicionando memória a um agente .
Serviços de memória externa
A estrutura suporta a integração com serviços de memória especializados como Mem0:
from agent_framework.mem0 import Mem0Provider
# Using Mem0 for advanced memory capabilities
memory_provider = Mem0Provider(
api_key="your-mem0-api-key",
user_id="user_123",
application_id="my_app"
)
agent = ChatAgent(
chat_client=OpenAIChatClient(),
instructions="You are a helpful assistant with memory.",
context_providers=memory_provider
)
Serialização e persistência de threads
A estrutura suporta a serialização de estados de thread inteiros para persistência em reinicializações de aplicativos:
import json
# Create agent and thread
agent = ChatAgent(chat_client=OpenAIChatClient())
thread = agent.get_new_thread()
# Have conversation
await agent.run("Hello, my name is Alice", thread=thread)
# Serialize thread state
serialized_thread = await thread.serialize()
# Save to file/database
with open("thread_state.json", "w") as f:
json.dump(serialized_thread, f)
# Later, restore the thread
with open("thread_state.json", "r") as f:
thread_data = json.load(f)
restored_thread = await agent.deserialize_thread(thread_data)
# Continue conversation with full context
await agent.run("What's my name?", thread=restored_thread)