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.
Aqui estão os dois principais cenários com suporte:
-
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 armazenará o histórico completo de chat na memória no objeto, mas os
AgentThreaddesenvolvedores podem fornecer uma implementação personalizadaChatMessageStorepara 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 armazenará a ID do histórico de chat remoto no
AgentThreadobjeto 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 usará o padrão para armazenar o histórico de chat na memória no AgentThread objeto. Nesse caso, o histórico de chat completo armazenado no objeto thread, além de novas mensagens, será fornecido ao serviço subjacente em cada execução do agente. Isso permite uma experiência de conversa natural com o agente, em que 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 resultará no objeto thread que contém o histórico de chat da execução do agente.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.CreateAIAgent(JokerInstructions, JokerName);
AgentThread thread = agent.GetNewThread();
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 do thread e manipular as mensagens diretamente, se necessário.
IList<ChatMessage>? messages = thread.GetService<IList<ChatMessage>>();
Observação
A recuperação de mensagens do AgentThread objeto dessa maneira só funcionará se o armazenamento na memória estiver sendo usado.
Redução do histórico de chat com armazenamento de In-Memory
O interno InMemoryChatMessageStore que é 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.
É InMemoryChatMessageStore 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 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. Também InMemoryChatMessageStore pode ser passado um evento de gatilho opcional que pode ser definido como ou InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAddedInMemoryChatMessageStore.ChatReducerTriggerEvent.BeforeMessagesRetrieval.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.CreateAIAgent(new ChatClientAgentOptions
{
Name = JokerName,
Instructions = JokerInstructions,
ChatMessageStoreFactory = ctx => new InMemoryChatMessageStore(
new MessageCountingChatReducer(2),
ctx.SerializedState,
ctx.JsonSerializerOptions,
InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded)
});
Observação
Esse recurso só tem suporte ao usar o InMemoryChatMessageStore. 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 ChatMessageStoreFactory repositório de mensagens, 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 requer o armazenamento em serviço do histórico de chat, o Agent Framework armazenará a ID do histórico de chat remoto no AgentThread 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 thread que contém a última ID de resposta retornada pelo serviço.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetOpenAIResponseClient(modelName)
.CreateAIAgent(JokerInstructions, JokerName);
AgentThread thread = agent.GetNewThread();
Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread));
Observação
Alguns serviços, por exemplo, Respostas OpenAI 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 ChatMessageStore base.
A ChatMessageStore classe define a interface para armazenar e recuperar mensagens de chat. Os desenvolvedores devem implementar os métodos e AddMessagesAsync os GetMessagesAsync 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 GetMessagesAsync ao processar uma consulta de usuário. Cabe ao implementador ChatMessageStore garantir que o tamanho do histórico de chat não exceda a janela de contexto do serviço subjacente.
Ao implementar um personalizado ChatMessageStore que armazena o histórico de chat em um repositório remoto, o histórico de chat desse thread deve ser armazenado em 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 a um ChatClientAgent, você pode usar a opção ChatMessageStoreFactory ao criar o agente.
Aqui está um exemplo mostrando como passar a implementação personalizada de ChatMessageStore uma ChatClientAgent que se baseia na Conclusão do Chat do Azure OpenAI.
AIAgent agent = new AzureOpenAIClient(
new Uri(endpoint),
new AzureCliCredential())
.GetChatClient(deploymentName)
.CreateAIAgent(new ChatClientAgentOptions
{
Name = JokerName,
Instructions = JokerInstructions,
ChatMessageStoreFactory = ctx =>
{
// 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.
return new CustomMessageStore(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 AgentThread
É importante poder persistir um AgentThread 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 AgentThread 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 AgentThread objeto ainda contém uma ID que faz referência ao histórico de chat remoto. A perda do AgentThread estado resultará, portanto, na perda da ID do histórico de chat remoto.
Assim AgentThread como todos os objetos anexados a ele, todos fornecem, portanto, o SerializeAsync método para serializar seu estado. O AIAgent também fornece um DeserializeThread método que recria um thread do estado serializado. O DeserializeThread método recria o thread com o ChatMessageStore agente e AIContextProvider configurado.
// 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 = AIAgent.DeserializeThread(serializedThreadState);
Observação
AgentThread 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 thread. Portanto, é importante sempre serializar, armazenar e desserializar todo AgentThread o objeto para garantir que todo o estado seja preservado.
Importante
Sempre trate AgentThread 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 um thread com um agente diferente daquele que o 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)