Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El historial y la memoria del chat del agente son funcionalidades cruciales que permiten a los agentes mantener el contexto entre conversaciones, recordar las preferencias del usuario y proporcionar experiencias personalizadas. Agent Framework proporciona varias características para adaptarse a diferentes casos de uso, desde el almacenamiento simple de mensajes de chat en memoria a bases de datos persistentes y servicios de memoria especializados.
Historial de chats
El marco del agente admite varias opciones de almacenamiento del historial de chat. Las opciones disponibles varían según el tipo de agente y los servicios subyacentes que se usan para compilar el agente.
Estos son los dos escenarios principales admitidos:
-
Almacenamiento en memoria: el agente se basa en un servicio que no admite el almacenamiento en el servicio del historial de chat (por ejemplo, finalización de chat de OpenAI). Agent Framework almacenará de forma predeterminada el historial de chat completo en memoria en el
AgentThreadobjeto, pero los desarrolladores pueden proporcionar una implementación personalizadaChatMessageStorepara almacenar el historial de chat en un almacén de terceros si es necesario. -
Almacenamiento en servicio: el agente se basa en un servicio que requiere almacenamiento en servicio del historial de chat (por ejemplo, agentes persistentes de Azure AI Foundry). Agent Framework almacenará el identificador del historial de chat remoto en el
AgentThreadobjeto y no se admiten otras opciones de almacenamiento del historial de chat.
Almacenamiento del historial de chat en memoria
Cuando se usa un servicio que no admite el almacenamiento en el servicio del historial de chats, Agent Framework almacenará el historial de chat en memoria en el AgentThread objeto de forma predeterminada. En este caso, el historial de chat completo que se almacena en el objeto de subproceso, además de cualquier mensaje nuevo, se proporcionará al servicio subyacente en cada ejecución del agente. Esto permite una experiencia conversacional natural con el agente, donde el autor de la llamada solo proporciona el nuevo mensaje de usuario y el agente solo devuelve nuevas respuestas, pero el agente tiene acceso al historial de conversación completo y lo usará al generar su respuesta.
Cuando se usa la finalización del chat de OpenAI como servicio subyacente para agentes, el código siguiente dará como resultado el objeto de subproceso que contiene el historial de chats de la ejecución del 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));
Cuando los mensajes se almacenan en memoria, es posible recuperar la lista de mensajes del subproceso y manipularlos directamente si es necesario.
IList<ChatMessage>? messages = thread.GetService<IList<ChatMessage>>();
Nota:
La recuperación de mensajes del AgentThread objeto de esta manera solo funcionará si se usa el almacenamiento en memoria.
Reducción del historial de chat con almacenamiento de In-Memory
El integrado InMemoryChatMessageStore que se usa de forma predeterminada cuando el servicio subyacente no admite el almacenamiento en el servicio, se puede configurar con un reductor para administrar el tamaño del historial de chat.
Esto resulta útil para evitar superar los límites de tamaño de contexto del servicio subyacente.
InMemoryChatMessageStore Puede tomar una implementación opcional Microsoft.Extensions.AI.IChatReducer para reducir el tamaño del historial de chat.
También permite configurar el evento durante el cual se invoca el reductor, ya sea después de agregar un mensaje al historial de chat o antes de que se devuelva el historial de chat para la siguiente invocación.
Para configurar con InMemoryChatMessageStore un reductor, puede proporcionar un generador para construir un nuevo para cada nuevo InMemoryChatMessageStoreAgentThread y pasarlo a un reductor de su elección.
InMemoryChatMessageStore También se puede pasar un evento de desencadenador opcional que se puede establecer en InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded o InMemoryChatMessageStore.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)
});
Nota:
Esta característica solo se admite cuando se usa .InMemoryChatMessageStore Cuando un servicio tiene almacenamiento de historial de chats en el servicio, es hasta el propio servicio para administrar el tamaño del historial de chat. Del mismo modo, al usar el almacenamiento de terceros (consulte a continuación), es hasta la solución de almacenamiento de terceros para administrar el tamaño del historial de chat. Si proporciona un ChatMessageStoreFactory para un almacén de mensajes, pero usa un servicio con almacenamiento de historial de chat integrado, no se usará la fábrica.
Almacenamiento del historial de chat del servicio de inferencia
Cuando se usa un servicio que requiere almacenamiento en el servicio del historial de chat, El marco del agente almacenará el identificador del historial de chat remoto en el AgentThread objeto .
Por ejemplo, al usar respuestas de OpenAI con store=true como servicio subyacente para agentes, el código siguiente dará como resultado el objeto de subproceso que contiene el último identificador de respuesta devuelto por el servicio.
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));
Nota:
Algunos servicios, por ejemplo, las respuestas de OpenAI admiten el almacenamiento en servicio del historial de chat (store=true) o proporcionar el historial de chat completo en cada invocación (store=false). Por lo tanto, dependiendo del modo en el que se usa el servicio, El marco del agente almacenará de forma predeterminada el historial de chat completo en la memoria o almacenará una referencia de identificador al historial de chat almacenado del servicio.
Almacenamiento del historial de chat de terceros
Cuando se usa un servicio que no admite el almacenamiento en el servicio del historial de chat, Agent Framework permite a los desarrolladores reemplazar el almacenamiento en memoria predeterminado del historial de chat por el almacenamiento del historial de chat de terceros. El desarrollador es necesario para proporcionar una subclase de la clase abstracta ChatMessageStore base.
La ChatMessageStore clase define la interfaz para almacenar y recuperar mensajes de chat. Los desarrolladores deben implementar los AddMessagesAsync métodos y GetMessagesAsync para agregar mensajes al almacén remoto a medida que se generan y recuperar mensajes del almacén remoto antes de invocar el servicio subyacente.
El agente usará todos los mensajes devueltos por GetMessagesAsync al procesar una consulta de usuario. Es el implementador de para asegurarse de ChatMessageStore que el tamaño del historial de chat no supera la ventana de contexto del servicio subyacente.
Al implementar un personalizado ChatMessageStore que almacena el historial de chat en un almacén remoto, el historial de chat de ese subproceso debe almacenarse bajo una clave que sea única para ese subproceso. La ChatMessageStore implementación debe generar esta clave y mantenerla en su estado.
ChatMessageStore tiene un Serialize método que se puede invalidar para serializar su estado cuando se serializa el subproceso.
ChatMessageStore También debe proporcionar un constructor que tome como JsonElement entrada para admitir la deserialización de su estado.
Para proporcionar un personalizado ChatMessageStore a , ChatClientAgentpuede usar la ChatMessageStoreFactory opción al crear el agente.
Este es un ejemplo que muestra cómo pasar la implementación personalizada de ChatMessageStore a una ChatClientAgent que se basa en la finalización del chat de OpenAI de Azure.
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);
}
});
Sugerencia
Para obtener un ejemplo detallado sobre cómo crear un almacén de mensajes personalizado, consulte el tutorial Almacenamiento del historial de chat en almacenamiento de terceros .
Memoria a largo plazo
Agent Framework permite a los desarrolladores proporcionar componentes personalizados que pueden extraer memorias o proporcionar memorias a un agente.
Para implementar este componente de memoria, el desarrollador debe subclase la AIContextProvider clase base abstracta. Esta clase tiene dos métodos principales y InvokingAsyncInvokedAsync. Cuando se invalida, InvokedAsync permite a los desarrolladores inspeccionar todos los mensajes proporcionados por los usuarios o generados por el agente.
InvokingAsync permite a los desarrolladores insertar contexto adicional para una ejecución de agente específica. Se pueden proporcionar instrucciones del sistema, mensajes adicionales y funciones adicionales.
Sugerencia
Para obtener un ejemplo detallado sobre cómo crear un componente de memoria personalizado, consulte el tutorial Adición de memoria a un agente .
Serialización de AgentThread
Es importante poder conservar un AgentThread objeto entre invocaciones de agente. Esto permite situaciones en las que un usuario puede hacer una pregunta del agente y tardar mucho tiempo en formular preguntas de seguimiento. Esto permite que el AgentThread estado sobreviva al servicio o a los reinicios de la aplicación.
Incluso si el historial de chat se almacena en un almacén remoto, el AgentThread objeto todavía contiene un identificador que hace referencia al historial de chat remoto. Por lo tanto, perder el AgentThread estado también perderá el identificador del historial de chat remoto.
Así AgentThread como cualquier objeto adjunto a él, todo ello proporciona el SerializeAsync método para serializar su estado.
AIAgent también proporciona un DeserializeThread método que vuelve a crear un subproceso a partir del estado serializado. El DeserializeThread método vuelve a crear el subproceso con ChatMessageStore y AIContextProvider configurado en el 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 = AIAgent.DeserializeThread(serializedThreadState);
Nota:
AgentThread Los objetos pueden contener más que solo el historial de chat, por ejemplo, los proveedores de contexto también pueden almacenar el estado en el objeto de subproceso. Por lo tanto, es importante serializar, almacenar y deserializar siempre todo AgentThread el objeto para asegurarse de que se conserva todo el estado.
Importante
AgentThread Trate siempre los objetos como objetos opacos, a menos que esté muy seguro de los elementos internos. El contenido puede variar no solo por tipo de agente, sino también por tipo de servicio y configuración.
Advertencia
Deserializar un subproceso con un agente diferente al que originalmente lo creó o con un agente que tenga una configuración diferente a la del agente original, puede producir errores o un comportamiento inesperado.
Tipos de memoria
Agent Framework admite varios tipos de memoria para dar cabida a diferentes casos de uso, incluida la administración del historial de chat como parte de la memoria a corto plazo y proporcionar puntos de extensión para extraer, almacenar e insertar memorias a largo plazo en agentes.
almacenamiento de In-Memory (valor predeterminado)
Forma más sencilla de memoria donde el historial de conversaciones se almacena en memoria durante el tiempo de ejecución de la aplicación. Este es el comportamiento predeterminado y no requiere ninguna configuración 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)
Almacenes de mensajes persistentes
En el caso de las aplicaciones que necesitan conservar el historial de conversaciones entre sesiones, el marco proporciona ChatMessageStore implementaciones:
ChatMessageStore integrado
La implementación predeterminada en memoria que se puede serializar:
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
)
Almacén de mensajes de Redis
Para las aplicaciones de producción que requieren almacenamiento 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
)
Almacén de mensajes personalizado
Puede implementar su propio back-end de almacenamiento mediante la implementación de 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"]
Sugerencia
Para obtener un ejemplo detallado sobre cómo crear un almacén de mensajes personalizado, consulte el tutorial Almacenamiento del historial de chat en almacenamiento de terceros .
Proveedores de contexto (memoria dinámica)
Los proveedores de contexto permiten patrones de memoria sofisticados insertando contexto relevante antes de cada invocación de agente:
Proveedor 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
Sugerencia
Para obtener un ejemplo detallado sobre cómo crear un componente de memoria personalizado, consulte el tutorial Adición de memoria a un agente .
Servicios de memoria externa
El marco admite la integración con servicios de memoria 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
)
Serialización y persistencia de subprocesos
El marco de trabajo admite la serialización de estados de subprocesos completos para la persistencia en los reinicios de la aplicación:
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)