Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Память агента — это важная возможность, которая позволяет агентам поддерживать контекст в беседах, запоминать предпочтения пользователей и предоставлять персонализированные возможности. Платформа агента предоставляет несколько механизмов памяти для различных вариантов использования, от простого хранилища в памяти до постоянных баз данных и специализированных служб памяти.
Agent Framework поддерживает несколько типов памяти для размещения различных вариантов использования, включая управление журналом чата в рамках краткосрочной памяти и предоставление точек расширения для извлечения, хранения и внедрения долгосрочных воспоминаний в агенты.
Журнал чата (краткосрочная память)
Различные варианты хранения журнала чата поддерживаются платформой Agent Framework. Доступные параметры зависят от типа агента и базовых служб, используемых для создания агента.
Ниже приведены два основных сценария:
-
Хранилище в памяти: агент основан на службе, которая не поддерживает хранение журнала чата в службе (например, завершение openAI Chat). Платформа agent Framework по умолчанию будет хранить полный журнал чата в памяти в объекте
AgentThread, но разработчики могут предоставить пользовательскуюChatMessageStoreреализацию для хранения журнала чатов в 3-м стороннем хранилище при необходимости. -
Хранилище в службе. Агент основан на службе, требующей хранения в службе журнала чата (например, azure AI Foundry Persistent Agent). Платформа агента будет хранить идентификатор журнала удаленного чата в объекте
AgentThread, а другие варианты хранения журнала чата не поддерживаются.
Хранилище журнала чата в памяти
При использовании службы, которая не поддерживает хранилище журнала чата в службе, платформа агента по умолчанию будет хранить журнал чатов в памяти в объекте AgentThread . В этом случае полный журнал чата, хранящийся в объекте потока, а также любые новые сообщения, будут предоставлены базовой службе для каждого запуска агента. Это позволяет использовать естественный диалог с агентом, где вызывающий объект предоставляет только новое сообщение пользователя, а агент возвращает только новые ответы, но агент имеет доступ к полной истории бесед и будет использовать его при создании ответа.
При использовании openAI Chat Completion в качестве базовой службы для агентов следующий код приведет к тому, что поток содержит журнал чата из запуска агента.
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));
Где сообщения хранятся в памяти, можно получить список сообщений из потока и управлять сообщениями непосредственно при необходимости.
IList<ChatMessage>? messages = thread.GetService<IList<ChatMessage>>();
Замечание
Получение сообщений из AgentThread объекта таким образом будет работать только в том случае, если используется хранилище в памяти.
Сокращение журнала чата с помощью хранилища In-Memory
Встроенный InMemoryChatMessageStore , используемый по умолчанию, если базовая служба не поддерживает хранилище в службе, можно настроить с помощью средства уменьшения размера журнала чата.
Это полезно, чтобы избежать превышения ограничений размера контекста базовой службы.
Можно InMemoryChatMessageStore выполнить необязательную Microsoft.Extensions.AI.IChatReducer реализацию, чтобы уменьшить размер журнала чата.
Он также позволяет настроить событие, в течение которого вызывается редуктор, либо после добавления сообщения в журнал чата, либо до возврата журнала чата для следующего вызова.
Чтобы настроить InMemoryChatMessageStore с помощью средства уменьшения, можно предоставить фабрику, чтобы создать новую для каждого нового InMemoryChatMessageStoreAgentThread и передать ее редуктор по вашему выбору. Кроме InMemoryChatMessageStore того, можно передать необязательное событие триггера, которое можно задать для любого InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded или 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)
});
Замечание
Эта функция поддерживается только при использовании InMemoryChatMessageStore. Если служба имеет хранилище журнала чата в службе, она зависит от самой службы для управления размером журнала чата. Аналогичным образом, при использовании 3-го стороннего хранилища (см. ниже), это до решения 3-го стороннего хранилища для управления размером журнала чата. Если вы предоставляете ChatMessageStoreFactory хранилище сообщений, но используете службу со встроенным хранилищем журнала чатов, фабрика не будет использоваться.
Хранилище журнала чата вывода
При использовании службы, требующей хранения журнала чата в службе, платформа agent Framework будет хранить идентификатор журнала удаленного чата в объекте AgentThread .
Например, при использовании ответов OpenAI с store=true в качестве базовой службы для агентов следующий код приведет к тому, что объект потока, содержащий последний идентификатор ответа, возвращенный службой.
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));
Замечание
Некоторые службы, например OpenAI Responses, поддерживают хранилище журнала чата (store=true) или предоставляют полный журнал чата для каждого вызова (store=false). Таким образом, в зависимости от режима, в котором используется служба, платформа агента по умолчанию будет хранить полный журнал чата в памяти или хранить ссылку на идентификатор хранимой журнал чата службы.
Хранилище журнала чата стороннего поставщика
При использовании службы, которая не поддерживает хранение журнала чата в службе, платформа agent Framework позволяет разработчикам заменить хранилище журнала чата по умолчанию на хранилище журнала чата стороннего поставщика. Разработчику требуется предоставить подкласс базового абстрактного ChatMessageStore класса.
Класс ChatMessageStore определяет интерфейс для хранения и получения сообщений чата. Разработчики должны реализовать AddMessagesAsync и GetMessagesAsync методы для добавления сообщений в удаленное хранилище по мере их создания и получения сообщений из удаленного хранилища перед вызовом базовой службы.
Агент будет использовать все сообщения, возвращаемые GetMessagesAsync при обработке пользовательского запроса. Это зависит от реализации ChatMessageStore , чтобы убедиться, что размер журнала чата не превышает контекстное окно базовой службы.
При реализации настраиваемого ChatMessageStore хранилища, в котором хранится журнал чата в удаленном хранилище, журнал чата для этого потока должен храниться под ключом, уникальным для этого потока. Реализация ChatMessageStore должна создать этот ключ и сохранить его в состоянии.
ChatMessageStore
Serialize имеет метод, который можно переопределить для сериализации состояния при сериализации потока. Он ChatMessageStore также должен предоставить конструктор, который принимает входные JsonElement данные для поддержки десериализации его состояния.
Чтобы предоставить пользовательский ChatMessageStoreChatClientAgentобъект, можно использовать ChatMessageStoreFactory этот параметр при создании агента.
Ниже приведен пример передачи пользовательской реализации ChatMessageStore в объект ChatClientAgent , основанный на завершении Чата 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);
}
});
Подсказка
Подробный пример создания пользовательского хранилища сообщений см. в руководстве по хранению журнала чатов в 3-м хранилище сторон .
Долгосрочная память
Платформа agent Framework позволяет разработчикам предоставлять пользовательские компоненты, которые могут извлекать воспоминания или предоставлять воспоминания агенту.
Чтобы реализовать такой компонент памяти, разработчику необходимо подкласс абстрактного AIContextProvider базового класса. Этот класс имеет два основных метода и InvokingAsyncInvokedAsync. При переопределении InvokedAsync разработчики могут проверять все сообщения, предоставляемые пользователями или созданные агентом.
InvokingAsync позволяет разработчикам внедрять дополнительный контекст для конкретного запуска агента. Системные инструкции, дополнительные сообщения и дополнительные функции можно предоставить.
Подсказка
Подробный пример создания пользовательского компонента памяти см. в руководстве по добавлению памяти в агент .
Сериализация agentThread
Важно иметь возможность сохранять AgentThread объект между вызовами агента. Это позволяет в ситуациях, когда пользователь может задать вопрос агента и занять много времени, чтобы задать дальнейшие вопросы. Это позволяет состоянию AgentThread выжить перезапуск службы или приложения.
Даже если журнал чата хранится в удаленном хранилище, AgentThread объект по-прежнему содержит идентификатор, ссылающийся на журнал удаленного чата.
AgentThread Поэтому потеря состояния приведет к потере идентификатора журнала удаленного чата.
Таким AgentThread образом, все объекты, подключенные к нему, предоставляют SerializeAsync метод для сериализации их состояния. Он AIAgent также предоставляет DeserializeThread метод, который повторно создает поток из сериализованного состояния. Метод DeserializeThread повторно создает поток с ChatMessageStore помощью агента и AIContextProvider настроен.
// 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);
Замечание
AgentThread Объекты могут содержать больше, чем только журнал чата, например поставщики контекстов также могут хранить состояние в объекте потока. Поэтому важно всегда сериализовать, хранить и десериализировать весь AgentThread объект, чтобы обеспечить сохранение всего состояния.
Это важно
Всегда рассматривать AgentThread объекты как непрозрачные объекты, если вы не уверены во внутренних элементах. Содержимое может отличаться не только по типу агента, но и по типу службы и конфигурации.
Предупреждение
Десериализация потока с другим агентом, отличным от того, который изначально создал его, или с агентом, который имеет конфигурацию, отличную от исходного агента, может привести к ошибкам или неожиданному поведению.
Типы памяти
Agent Framework поддерживает несколько типов памяти для размещения различных вариантов использования, включая управление журналом чата в рамках краткосрочной памяти и предоставление точек расширения для извлечения, хранения и внедрения долгосрочных воспоминаний в агенты.
хранилище In-Memory (по умолчанию)
Простейшая форма памяти, в которой журнал бесед хранится в памяти во время выполнения приложения. Это поведение по умолчанию и не требует дополнительной настройки.
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)
Хранилища постоянных сообщений
Для приложений, которые должны сохранять журнал бесед в сеансах, платформа предоставляет ChatMessageStore реализации:
Встроенный ChatMessageStore
Реализация по умолчанию в памяти, которую можно сериализовать:
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
)
Хранилище сообщений Redis
Для рабочих приложений, требующих постоянного хранения:
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
)
Пользовательское хранилище сообщений
Вы можете реализовать собственную серверную часть хранилища, реализуя следующую 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"]
Подсказка
Подробный пример создания пользовательского хранилища сообщений см. в руководстве по хранению журнала чатов в 3-м хранилище сторон .
Поставщики контекстов (динамическая память)
Поставщики контекстов обеспечивают сложные шаблоны памяти путем внедрения соответствующего контекста перед вызовом каждого агента:
Базовый поставщик контекста
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
Подсказка
Подробный пример создания пользовательского компонента памяти см. в руководстве по добавлению памяти в агент .
Внешние службы памяти
Платформа поддерживает интеграцию со специализированными службами памяти, такими как 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
)
Сериализация потоков и сохраняемость
Платформа поддерживает сериализацию всех состояний потока для сохраняемости при перезапуске приложения:
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)