Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O histórico de chat e a memória do agente são recursos cruciais que permitem aos agentes manter o contexto entre conversas, lembrar as preferências do usuário e fornecer experiências personalizadas. A Estrutura do Agente fornece vários recursos para atender a diferentes casos de uso, desde o simples armazenamento de mensagens de chat na memória até bancos de dados persistentes e serviços de memória especializados.
Histórico de chats
Várias opções de armazenamento de histórico de chat são compatíveis com o Agent Framework. As opções disponíveis variam de acordo com o tipo de agente e os serviços subjacentes usados para criar o agente.
Os dois principais cenários com suporte são:
-
Armazenamento na memória: o Agente é criado em um serviço que não dá suporte ao armazenamento em serviço do histórico de chat (por exemplo, preenchimento de chat openai). Por padrão, o Agent Framework armazena o histórico completo de chat na memória no objeto, mas os
AgentSessiondesenvolvedores podem fornecer uma implementação personalizadaChatHistoryProviderpara armazenar o histórico de chat em um repositório de terceiros, se necessário. -
Armazenamento em serviço: o Agente é criado em um serviço que requer o armazenamento em serviço do histórico de chat (por exemplo, Agentes Persistentes de Descoberta de IA do Azure). O Agent Framework armazena a ID do histórico de chat remoto no
AgentSessionobjeto e não há suporte para nenhuma outra opção de armazenamento de histórico de chat.
Armazenamento de histórico de chat na memória
Ao usar um serviço que não dá suporte ao armazenamento em serviço do histórico de chat, o Agent Framework usa como padrão armazenar o histórico de chat na memória no AgentSession objeto. Nesse caso, o histórico de chat completo armazenado no objeto de sessão, além de novas mensagens, será fornecido ao serviço subjacente em cada execução do agente. Esse design permite uma experiência de conversa natural com o agente. O chamador fornece apenas a nova mensagem de usuário e o agente retorna apenas novas respostas. Mas o agente tem acesso ao histórico completo da conversa e o usará ao gerar sua resposta.
Ao usar o OpenAI Chat Completion como o serviço subjacente para agentes, o código a seguir resulta no objeto de sessão que contém o histórico de chat da execução do agente.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.AsAIAgent(JokerInstructions, JokerName);
AgentSession session = await agent.GetNewSessionAsync();
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session));
Quando as mensagens são armazenadas na memória, é possível recuperar a lista de mensagens da sessão e manipular as mensagens diretamente, se necessário.
IList<ChatMessage>? messages = session.GetService<IList<ChatMessage>>();
Observação
A recuperação de mensagens do AgentSession objeto dessa maneira só funcionará se o armazenamento na memória estiver sendo usado.
Redução do histórico de chat com armazenamento na memória
O interno InMemoryChatHistoryProvider usado por padrão quando o serviço subjacente não dá suporte ao armazenamento em serviço pode ser configurado com um redutor para gerenciar o tamanho do histórico de chat.
Isso é útil para evitar exceder os limites de tamanho de contexto do serviço subjacente.
É InMemoryChatHistoryProvider possível usar uma implementação opcional Microsoft.Extensions.AI.IChatReducer para reduzir o tamanho do histórico de chat.
Ele também permite que você configure o evento durante o qual o redutor é invocado, depois que uma mensagem é adicionada ao histórico de chat ou antes que o histórico de chat seja retornado para a próxima invocação.
Para configurar o InMemoryChatHistoryProvider com um redutor, você pode fornecer uma fábrica para construir um novo InMemoryChatHistoryProvider para cada novo AgentSession e passá-lo um redutor de sua escolha. Também InMemoryChatHistoryProvider pode ser passado um evento de gatilho opcional que pode ser definido como ou InMemoryChatHistoryProvider.ChatReducerTriggerEvent.AfterMessageAddedInMemoryChatHistoryProvider.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 },
ChatHistoryProviderFactory = (ctx, ct) => new ValueTask<ChatHistoryProvider>(
new InMemoryChatHistoryProvider(
new MessageCountingChatReducer(2),
ctx.SerializedState,
ctx.JsonSerializerOptions,
InMemoryChatHistoryProvider.ChatReducerTriggerEvent.AfterMessageAdded))
});
Observação
Esse recurso só tem suporte ao usar o InMemoryChatHistoryProvider. Quando um serviço tem armazenamento de histórico de chat no serviço, cabe ao próprio serviço gerenciar o tamanho do histórico de chat. 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 chat. Se você fornecer um ChatHistoryProviderFactory provedor de histórico de chat, mas usar um serviço com armazenamento interno de histórico de chat, a fábrica não será usada.
Armazenamento de histórico de chat do serviço de inferência
Ao usar um serviço que exige o armazenamento em serviço do histórico de chat, o Agent Framework armazena a ID do histórico de chat remoto no AgentSession objeto.
Por exemplo, ao usar o OpenAI Responses com store=true como o serviço subjacente para agentes, o código a seguir resultará no objeto de sessão que contém a última ID de resposta retornada pelo serviço.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetOpenAIResponseClient(modelName)
.AsAIAgent(JokerInstructions, JokerName);
AgentSession session = await agent.GetNewSessionAsync();
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", session));
Observação
Alguns serviços, por exemplo, o OpenAI Responses dão suporte ao armazenamento em serviço do histórico de chat (store=true) ou ao fornecer o histórico de chat completo em cada invocação (store=false). Portanto, dependendo do modo em que o serviço é usado, o Agent Framework usará o padrão para armazenar o histórico de chat completo na memória ou armazenar uma referência de ID para o histórico de chat armazenado do serviço.
Armazenamento de histórico de chat de terceiros
Ao usar um serviço que não dá suporte ao armazenamento em serviço do histórico de chat, o Agent Framework permite que os desenvolvedores substituam o armazenamento na memória padrão do histórico de chat pelo armazenamento de histórico de chat de terceiros. O desenvolvedor é necessário para fornecer uma subclasse da classe abstrata ChatHistoryProvider base.
A ChatHistoryProvider classe define a interface para armazenar e recuperar mensagens de chat. Os desenvolvedores devem implementar os métodos e InvokedAsync os InvokingAsync métodos para adicionar mensagens ao repositório remoto conforme são gerados e recuperar mensagens do repositório remoto antes de invocar o serviço subjacente.
O agente usará todas as mensagens retornadas InvokingAsync ao processar uma consulta de usuário. Cabe ao implementador ChatHistoryProvider garantir que o tamanho do histórico de chat não exceda a janela de contexto do serviço subjacente.
Ao implementar um personalizado ChatHistoryProvider que armazena o histórico de chat em um repositório remoto, o histórico de chat dessa sessão deve ser armazenado sob uma chave exclusiva para essa sessão. A ChatHistoryProvider implementação deve gerar essa chave e mantê-la em seu estado.
ChatHistoryProvider tem um Serialize método que pode ser substituído para serializar seu estado quando a sessão é serializada. O ChatHistoryProvider também deve fornecer um construtor que usa um JsonElement como entrada para dar suporte à desserialização de seu estado.
Para fornecer um personalizado ChatHistoryProvider a um ChatClientAgent, você pode usar a opção ChatHistoryProviderFactory ao criar o agente.
Aqui está um exemplo mostrando como passar a implementação personalizada de ChatHistoryProvider uma ChatClientAgent que se baseia na Conclusão do 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 },
ChatHistoryProviderFactory = (ctx, ct) => new ValueTask<ChatHistoryProvider>(
// Create a new chat history provider for this agent that stores the messages in a custom store.
// Each session must get its own copy of the CustomChatHistoryProvider, since the provider
// also contains the ID that the session is stored under.
new CustomChatHistoryProvider(
vectorStore,
ctx.SerializedState,
ctx.JsonSerializerOptions))
});
Dica
Para obter um exemplo detalhado sobre como criar um repositório de mensagens personalizado, consulte o tutorial Armazenamento de Histórico de Chat no Armazenamento de Terceiros .
Memória de longo prazo
A Estrutura do Agente 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 subclasse a AIContextProvider classe base abstrata. Essa classe tem dois métodos InvokingAsync principais 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 insiram contexto adicional para uma execução de agente específica. Instruções do sistema, mensagens adicionais e funções adicionais podem ser fornecidas.
Dica
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 AgentSession
É importante poder persistir um AgentSession objeto entre invocações de agente. Isso permite situações em que um usuário pode fazer uma pergunta ao agente e levar muito tempo para fazer perguntas de acompanhamento. Isso permite que o AgentSession estado sobreviva às reinicializações de serviço ou aplicativo.
Mesmo que o histórico de chat seja armazenado em um repositório remoto, o AgentSession objeto ainda conterá uma ID referenciando o histórico de chat remoto. A perda do AgentSession estado resultará, portanto, na perda da ID do histórico de chat remoto.
Assim AgentSession como todos os objetos anexados a ele, todos fornecem, portanto, o Serialize método para serializar seu estado. O AIAgent também fornece um DeserializeSessionAsync método que recria uma sessão do estado serializado. O DeserializeSessionAsync método recria a sessão com o ChatHistoryProvider agente e AIContextProvider configurado.
// Serialize the session state to a JsonElement, so it can be stored for later use.
JsonElement serializedSessionState = session.Serialize();
// Re-create the session from the JsonElement.
AgentSession resumedSession = await agent.DeserializeSessionAsync(serializedSessionState);
Observação
AgentSession os objetos podem conter mais do que apenas o histórico de chat, por exemplo, os provedores de contexto também podem armazenar o estado no objeto de sessão. Portanto, é importante sempre serializar, armazenar e desserializar todo AgentSession o objeto para garantir que todo o estado seja preservado.
Importante
Sempre trate AgentSession objetos como objetos opacos, a menos que você tenha muita certeza dos internos. O conteúdo pode variar não apenas por tipo de agente, mas também por tipo de serviço e configuração.
Aviso
Desserializar uma sessão com um agente diferente daquele que a criou originalmente ou com um agente que tenha uma configuração diferente do agente original pode resultar em erros ou comportamento inesperado.
Tipos de memória
O Agent Framework dá suporte a vários tipos de memória para acomodar diferentes casos de uso, incluindo o gerenciamento do histórico de chat 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 em agentes.
Armazenamento de In-Memory (padrão)
A forma mais simples de memória em que o histórico de conversas é armazenado na memória durante o runtime do aplicativo. Esse é 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)
Repositórios de Mensagens Persistentes
Para aplicativos que precisam persistir o histórico de conversas entre sessões, a estrutura fornece ChatMessageStore implementações:
ChatMessageStore interno
A implementação padrão na memória 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
)
Repositório 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
)
Repositório de Mensagens Personalizado
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"]
Dica
Para obter um exemplo detalhado sobre como criar um repositório de mensagens personalizado, consulte o tutorial Armazenamento de Histórico de Chat no Armazenamento de Terceiros .
Provedores de contexto (memória dinâmica)
Os provedores de contexto permitem padrões de memória sofisticados injetando contexto relevante antes da invocação de cada 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
Dica
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 Externos
A estrutura dá suporte à integração com serviços de memória especializados como o 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 thread
A estrutura dá suporte à serialização de estados de thread inteiros para persistência entre reinicializações do aplicativo:
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)