Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Chatgeschiedenis en geheugen van agents zijn cruciale mogelijkheden waarmee agents context kunnen onderhouden in gesprekken, gebruikersvoorkeuren kunnen onthouden en persoonlijke ervaringen kunnen bieden. Het Agent Framework biedt meerdere functies die geschikt zijn voor verschillende gebruiksvoorbeelden, van eenvoudige opslag van chatberichten in het geheugen tot permanente databases en gespecialiseerde geheugenservices.
Chatgeschiedenis
Verschillende opslagopties voor chatgeschiedenis worden ondersteund door Agent Framework. De beschikbare opties variƫren per agenttype en de onderliggende service(s) die worden gebruikt om de agent te bouwen.
De twee belangrijkste ondersteunde scenario's zijn:
-
In-memory opslag: Agent is gebouwd op een service die geen ondersteuning biedt voor in-serviceopslag van chatgeschiedenis (bijvoorbeeld Voltooiing van OpenAI-chat). Standaard slaat Agent Framework de volledige chatgeschiedenis in het geheugen op in het
AgentThreadobject, maar ontwikkelaars kunnen een aangepasteChatMessageStoreimplementatie bieden voor het opslaan van chatgeschiedenis in een winkel van derden, indien nodig. -
In-serviceopslag: Agent is gebouwd op een service waarvoor in-serviceopslag van chatgeschiedenis is vereist (bijvoorbeeld Permanente Agents van Azure AI Foundry). Agent Framework slaat de id van de externe chatgeschiedenis op in het
AgentThreadobject en er worden geen andere opslagopties voor chatgeschiedenis ondersteund.
Opslag van chatgeschiedenis in het geheugen
Wanneer u een service gebruikt die geen ondersteuning biedt voor in-serviceopslag van chatgeschiedenis, wordt in agent framework standaard ingesteld op het opslaan van de chatgeschiedenis in het geheugen in het AgentThread object. In dit geval wordt de volledige chatgeschiedenis die is opgeslagen in het threadobject, plus eventuele nieuwe berichten, geleverd aan de onderliggende service bij elke agentuitvoering. Dit ontwerp biedt een natuurlijke gesprekservaring met de agent. De beller levert alleen het nieuwe gebruikersbericht en de agent retourneert alleen nieuwe antwoorden. Maar de agent heeft toegang tot de volledige gespreksgeschiedenis en gebruikt deze bij het genereren van het antwoord.
Wanneer u OpenAI Chat Completion gebruikt als de onderliggende service voor agents, resulteert de volgende code in het thread-object met de chatgeschiedenis van de agentuitvoering.
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));
Waar berichten in het geheugen worden opgeslagen, is het mogelijk om de lijst met berichten op te halen uit de thread en de berichten rechtstreeks te bewerken, indien nodig.
IList<ChatMessage>? messages = thread.GetService<IList<ChatMessage>>();
Opmerking
Berichten ophalen van het AgentThread object op deze manier werkt alleen als er in-memory opslag wordt gebruikt.
Vermindering van chatgeschiedenis met opslag in het geheugen
De ingebouwde InMemoryChatMessageStore functionaliteit die standaard wordt gebruikt wanneer de onderliggende service geen ondersteuning biedt voor opslag in de service, kan worden geconfigureerd met een reducer om de grootte van de chatgeschiedenis te beheren.
Dit is handig om te voorkomen dat de limieten voor de contextgrootte van de onderliggende service worden overschreden.
De InMemoryChatMessageStore kan een optionele Microsoft.Extensions.AI.IChatReducer implementatie nemen om de grootte van de chatgeschiedenis te verkleinen.
Hiermee kunt u ook de gebeurtenis configureren waarbij de reducer wordt aangeroepen, nadat een bericht is toegevoegd aan de chatgeschiedenis of voordat de chatgeschiedenis wordt geretourneerd voor de volgende aanroep.
Als u de InMemoryChatMessageStore met een reducer wilt configureren, kunt u een fabriek opgeven om een nieuwe InMemoryChatMessageStore voor elke nieuwe AgentThread te maken en deze door te geven aan een reducer van uw keuze. De InMemoryChatMessageStore kan ook worden doorgegeven aan een optionele triggergebeurtenis die kan worden ingesteld op of InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAddedInMemoryChatMessageStore.ChatReducerTriggerEvent.BeforeMessagesRetrieval.
AIAgent agent = new OpenAIClient("<your_api_key>")
.GetChatClient(modelName)
.CreateAIAgent(new ChatClientAgentOptions
{
Name = JokerName,
ChatOptions = new() { Instructions = JokerInstructions },
ChatMessageStoreFactory = ctx => new InMemoryChatMessageStore(
new MessageCountingChatReducer(2),
ctx.SerializedState,
ctx.JsonSerializerOptions,
InMemoryChatMessageStore.ChatReducerTriggerEvent.AfterMessageAdded)
});
Opmerking
Deze functie wordt alleen ondersteund wanneer u de InMemoryChatMessageStorefunctie gebruikt. Wanneer een service in-service chatgeschiedenisopslag heeft, is het aan de service zelf om de grootte van de chatgeschiedenis te beheren. Op dezelfde manier is het bij gebruik van opslag van derden (zie hieronder) het aan de opslagoplossing van derden om de grootte van de chatgeschiedenis te beheren. Als u een ChatMessageStoreFactory berichtarchief opgeeft, maar u een service gebruikt met ingebouwde chatgeschiedenisopslag, wordt de fabriek niet gebruikt.
Opslag van chatgeschiedenis van deductieservice
Wanneer u een service gebruikt waarvoor in-serviceopslag van de chatgeschiedenis is vereist, slaat Agent Framework de id op van de externe chatgeschiedenis in het AgentThread object.
Wanneer u bijvoorbeeld OpenAI-antwoorden met store=true gebruikt als de onderliggende service voor agents, resulteert de volgende code in het threadobject met de laatste antwoord-id die door de service wordt geretourneerd.
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));
Opmerking
Sommige services bieden bijvoorbeeld OpenAI-antwoorden ondersteuning voor in-serviceopslag van chatgeschiedenis (store=true) of het leveren van de volledige chatgeschiedenis voor elke aanroep (store=false). Afhankelijk van de modus waarin de service wordt gebruikt, wordt de volledige chatgeschiedenis in het geheugen standaard opgeslagen in Agent Framework of wordt een id-verwijzing opgeslagen naar de opgeslagen chatgeschiedenis van de service opgeslagen.
Opslag van chatgeschiedenis van derden
Wanneer u een service gebruikt die geen ondersteuning biedt voor in-serviceopslag van chatgeschiedenis, kunnen ontwikkelaars met Agent Framework de standaardopslag in het geheugen van de chatgeschiedenis vervangen door opslag van chatgeschiedenis van derden. De ontwikkelaar moet een subklasse van de basisabstraheerde ChatMessageStore klasse opgeven.
De ChatMessageStore klasse definieert de interface voor het opslaan en ophalen van chatberichten. Ontwikkelaars moeten de AddMessagesAsync en GetMessagesAsync methoden implementeren om berichten toe te voegen aan het externe archief terwijl ze worden gegenereerd en berichten ophalen uit het externe archief voordat ze de onderliggende service aanroepen.
De agent gebruikt alle berichten die worden geretourneerd bij GetMessagesAsync het verwerken van een gebruikersquery. Het is aan de implementeerfunctie ChatMessageStore om ervoor te zorgen dat de grootte van de chatgeschiedenis niet groter is dan het contextvenster van de onderliggende service.
Wanneer u een aangepaste ChatMessageStore versie implementeert waarin de chatgeschiedenis in een extern archief wordt opgeslagen, moet de chatgeschiedenis voor die thread worden opgeslagen onder een sleutel die uniek is voor die thread. De ChatMessageStore implementatie moet deze sleutel genereren en deze in de status houden.
ChatMessageStore heeft een Serialize methode die kan worden overschreven om de status ervan te serialiseren wanneer de thread wordt geserialiseerd. De ChatMessageStore moet ook een constructor bieden die een JsonElement als invoer nodig heeft om deserialisatie van de status te ondersteunen.
Als u een aangepaste ChatMessageStore aan een ChatClientAgentwilt opgeven, kunt u de optie gebruiken bij het ChatMessageStoreFactory maken van de agent.
Hier volgt een voorbeeld waarin wordt getoond hoe u de aangepaste implementatie doorgeeft aan een ChatMessageStore implementatie die is gebaseerd op voltooiing van ChatClientAgent De Azure OpenAI-chat.
AIAgent agent = new AzureOpenAIClient(
new Uri(endpoint),
new AzureCliCredential())
.GetChatClient(deploymentName)
.CreateAIAgent(new ChatClientAgentOptions
{
Name = JokerName,
ChatOptions = new() { 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);
}
});
Aanbeveling
Zie de zelfstudie Chatgeschiedenis opslaan in opslag van derden voor een gedetailleerd voorbeeld van het maken van een aangepast berichtenarchief.
Langetermijngeheugen
Met het Agent Framework kunnen ontwikkelaars aangepaste onderdelen leveren die herinneringen kunnen extraheren of herinneringen kunnen leveren aan een agent.
Voor het implementeren van een dergelijk geheugenonderdeel moet de ontwikkelaar de AIContextProvider abstracte basisklasse subklasse subklasse. Deze klasse heeft twee kernmethoden en InvokingAsyncInvokedAsync. Wanneer dit wordt overschreven, InvokedAsync kunnen ontwikkelaars alle berichten inspecteren die door gebruikers worden geleverd of door de agent worden gegenereerd.
InvokingAsync stelt ontwikkelaars in staat om extra context te injecteren voor een specifieke agentuitvoering. Systeeminstructies, extra berichten en aanvullende functies kunnen worden verstrekt.
Aanbeveling
Zie de zelfstudie Geheugen toevoegen aan een agent voor een gedetailleerd voorbeeld over het maken van een aangepast geheugenonderdeel.
Serialisatie van AgentThread
Het is belangrijk om een AgentThread object tussen agentaanroepen te kunnen behouden. Dit maakt situaties mogelijk waarin een gebruiker een vraag van de agent kan stellen en het lang duurt om vervolgvragen te stellen. Hierdoor kan de AgentThread status de service of app opnieuw opstarten.
Zelfs als de chatgeschiedenis is opgeslagen in een externe opslag, bevat het AgentThread object nog steeds een id die verwijst naar de geschiedenis van de externe chat. Als u de AgentThread status verliest, verliest u daarom ook de id van de geschiedenis van de externe chat.
De AgentThread objecten die eraan zijn gekoppeld, bieden daarom allemaal de methode om hun SerializeAsync status te serialiseren. Het AIAgent biedt ook een DeserializeThread methode waarmee een thread opnieuw wordt gemaakt op basis van de geserialiseerde status. Met DeserializeThread de methode wordt de thread opnieuw gemaakt met de ChatMessageStore en AIContextProvider geconfigureerde op de agent.
// 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);
Opmerking
AgentThread objecten kunnen meer dan alleen chatgeschiedenis bevatten, bijvoorbeeld contextproviders kunnen ook de status opslaan in het threadobject. Daarom is het belangrijk om altijd het hele AgentThread object te serialiseren, op te slaan en te deserialiseren om ervoor te zorgen dat alle status behouden blijft.
Belangrijk
AgentThread Behandel objecten altijd als ondoorzichtige objecten, tenzij u zeer zeker bent van de interne kenmerken. De inhoud kan niet alleen per agenttype verschillen, maar ook per servicetype en configuratie.
Waarschuwing
Het deserialiseren van een thread met een andere agent dan die die oorspronkelijk is gemaakt, of met een agent met een andere configuratie dan de oorspronkelijke agent, kan leiden tot fouten of onverwacht gedrag.
Geheugentypen
Het Agent Framework ondersteunt verschillende soorten geheugen voor verschillende gebruiksvoorbeelden, waaronder het beheren van de chatgeschiedenis als onderdeel van het kortetermijngeheugen en het bieden van uitbreidingspunten voor het extraheren, opslaan en injecteren van langetermijngeheugens in agents.
In-Memory Storage (standaard)
De eenvoudigste vorm van geheugen waarin de gespreksgeschiedenis wordt opgeslagen in het geheugen tijdens de runtime van de toepassing. Dit is het standaardgedrag en vereist geen aanvullende configuratie.
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)
Permanente berichtarchieven
Voor toepassingen die de gespreksgeschiedenis tussen sessies moeten behouden, biedt ChatMessageStore het framework implementaties:
Ingebouwde ChatMessageStore
De standaard implementatie in het geheugen die kan worden geserialiseerd:
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 Message Store
Voor productietoepassingen waarvoor permanente opslag is vereist:
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
)
Aangepast berichtenarchief
U kunt uw eigen back-end voor opslag implementeren door het ChatMessageStoreProtocolvolgende te implementeren:
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"]
Aanbeveling
Zie de zelfstudie Chatgeschiedenis opslaan in opslag van derden voor een gedetailleerd voorbeeld van het maken van een aangepast berichtenarchief.
Contextproviders (dynamisch geheugen)
Contextproviders maken geavanceerde geheugenpatronen mogelijk door relevante context te injecteren voordat elke agent aanroept:
Basiscontextprovider
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
Aanbeveling
Zie de zelfstudie Geheugen toevoegen aan een agent voor een gedetailleerd voorbeeld over het maken van een aangepast geheugenonderdeel.
Externe geheugenservices
Het framework ondersteunt integratie met gespecialiseerde geheugenservices zoals 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
)
Threadserialisatie en persistentie
Het framework biedt ondersteuning voor het serialiseren van volledige threadstatussen voor persistentie tijdens het opnieuw opstarten van toepassingen:
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)