Krok 4: Paměť a trvalost

Přidejte do agenta kontext, abyste si mohli pamatovat uživatelské předvolby, minulé interakce nebo externí znalosti.

Ve výchozím nastavení budou agenti ukládat historii chatu buď v InMemoryChatHistoryProvider, nebo v podkladové službě AI, v závislosti na požadavcích této služby.

Následující agent používá dokončování chatu OpenAI, které nepodporuje ani nevyžaduje úložiště historie chatu v rámci služby, takže automaticky vytvoří a použije InMemoryChatHistoryProvider.

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
    ?? throw new InvalidOperationException("Set AZURE_OPENAI_ENDPOINT");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(
        model: deploymentName,
        instructions: "You are a friendly assistant. Keep your answers brief.",
        name: "MemoryAgent");

Warning

DefaultAzureCredential je vhodný pro vývoj, ale vyžaduje pečlivé zvážení v produkčním prostředí. V produkčním prostředí zvažte použití konkrétních přihlašovacích údajů (např ManagedIdentityCredential. ) k zabránění problémům s latencí, neúmyslnému testování přihlašovacích údajů a potenciálním bezpečnostním rizikům z náhradních mechanismů.

Pokud chcete použít vlastní ChatHistoryProvider, můžete ho předat možnostem agenta:

using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;

var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT")
    ?? throw new InvalidOperationException("Set AZURE_OPENAI_ENDPOINT");
var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini";

AIAgent agent = new AIProjectClient(new Uri(endpoint), new DefaultAzureCredential())
    .AsAIAgent(model: deploymentName, options: new ChatClientAgentOptions()
    {
        ChatOptions = new() { Instructions = "You are a helpful assistant." },
        ChatHistoryProvider = new CustomChatHistoryProvider()
    });

Použití relace ke sdílení kontextu napříč spuštěními:

AgentSession session = await agent.CreateSessionAsync();

Console.WriteLine(await agent.RunAsync("Hello! What's the square root of 9?", session));
Console.WriteLine(await agent.RunAsync("My name is Alice", session));
Console.WriteLine(await agent.RunAsync("What is my name?", session));

Tip

Tady najdete úplnou spustitelnou ukázkovou aplikaci.

Úplná ukázka definuje poskytovatele kontextu, přidá ho do agenta a použije jednu relaci k zachování stavu přizpůsobení:

import asyncio
from typing import Any

from agent_framework import Agent, AgentSession, ContextProvider, SessionContext
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential


class UserMemoryProvider(ContextProvider):
    def __init__(self) -> None:
        super().__init__("user_memory")

    async def before_run(
        self,
        *,
        agent: Any,
        session: AgentSession | None,
        context: SessionContext,
        state: dict[str, Any],
    ) -> None:
        user_name = state.get("user_name")
        instructions = (
            f"The user's name is {user_name}. Address them by name." if user_name else "Ask for the user's name."
        )
        context.extend_instructions(self.source_id, instructions)

    async def after_run(
        self,
        *,
        agent: Any,
        session: AgentSession | None,
        context: SessionContext,
        state: dict[str, Any],
    ) -> None:
        for message in context.input_messages:
            text = message.text
            if not isinstance(text, str):
                continue
            _, marker, name = text.lower().partition("my name is")
            if marker and name.strip():
                state["user_name"] = name.split()[0].capitalize()


async def main() -> None:
    agent = Agent(
        client=FoundryChatClient(
            project_endpoint="https://your-account.services.ai.azure.com/api/projects/your-project",
            model="gpt-6-luna",
            credential=AzureCliCredential(),
        ),
        instructions="You are a friendly assistant.",
        context_providers=[UserMemoryProvider()],
    )
    session = agent.create_session()

    print(await agent.run("Hello! What's the square root of 9?", session=session))
    print(await agent.run("My name is Alice", session=session))
    print(await agent.run("What is 2 + 2?", session=session))


if __name__ == "__main__":
    asyncio.run(main())

Tip

Podívejte se na úplnou ukázku kompletního spustitelného souboru.

Poznámka:

V Pythonu se zpracovává trvalost/paměť pomocí implementací ContextProvider a HistoryProvider. InMemoryHistoryProvider je integrovaný místní poskytovatel historie v paměti. RawAgent může automaticky přidávat InMemoryHistoryProvider() v konkrétních případech (například při použití relace bez nakonfigurovaných zprostředkovatelů kontextu a bez indikátorů úložiště na straně služby), ale to není zaručeno ve všech scénářích. Pokud vždy chcete mít místní trvalost, přidejte InMemoryHistoryProvider explicitně. Také se ujistěte, že má jenom jeden poskytovatel load_messages=Truehistorie , takže nepřehráváte více úložišť do stejného vyvolání.

Vytvořte klienta projektu a úložiště paměti podle spravované sémantické paměti Microsoft Foundry. Pak zkombinujte místní historii přepisu, spravovanou paměť a úložiště auditu:

from agent_framework import InMemoryHistoryProvider
from agent_framework.foundry import FoundryMemoryProvider

history = InMemoryHistoryProvider(load_messages=True)
memory = FoundryMemoryProvider(
    project_client=project_client,
    memory_store_name="user-memory",
    scope="user-123",
)
audit_store = InMemoryHistoryProvider(
    "audit",
    load_messages=False,
    store_context_messages=True,  # include context added by other providers
)

agent = client.as_agent(
    name="MemoryAgent",
    instructions="You are a friendly assistant.",
    context_providers=[history, memory, audit_store],  # audit store last
)

Ve výchozím nastavení používají agenti místní historii v paměti nebo historii spravovanou službou v závislosti na poskytovateli a relaci.

Následující agent Foundry používá nasazení modelu navázané na projekt. Přidejte poskytovatele kontextu, pokud chcete používat paměť specifickou pro aplikaci nebo stav personalizace nad rámec historie konverzace.

a := foundryprovider.NewAgent(
    endpoint,
    token,
    foundryprovider.ModelDeployment(model),
    foundryprovider.AgentConfig{
        Instructions: "You are a friendly assistant. Keep your answers brief.",
        Config: agent.Config{
            Name: "MemoryAgent",
        },
    },
)

Definujte zprostředkovatele kontextu, který ukládá informace o uživateli ve stavu relace a vloží pokyny k přizpůsobení:

import (
    "context"
    "fmt"
    "strings"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/message"
)

const userMemorySourceID = "user_memory"

type providerState struct {
    UserName string `json:"user_name,omitempty"`
}

func newUserMemoryProvider() agent.ContextProvider {
    return agent.NewContextProvider(agent.ContextProviderConfig{
        SourceID: userMemorySourceID,
        Provide:  provideUserMemory,
        Store:    storeUserMemory,
    })
}

func provideUserMemory(ctx context.Context, invoking agent.InvokingContext) ([]*message.Message, []agent.Option, error) {
    session, _ := agent.GetOption(invoking.Options, agent.WithSession)
    var state providerState
    _, _ = session.Get(userMemorySourceID, &state)

    instructions := "You don't know the user's name yet. Ask for it politely."
    if state.UserName != "" {
        instructions = fmt.Sprintf("The user's name is %s. Always address them by name.", state.UserName)
    }
    return nil, []agent.Option{agent.WithInstructions(instructions)}, nil
}

func storeUserMemory(ctx context.Context, invoked agent.InvokedContext) error {
    session, _ := agent.GetOption(invoked.Options, agent.WithSession)
    var state providerState
    _, _ = session.Get(userMemorySourceID, &state)
    for _, msg := range invoked.RequestMessages {
        text := strings.TrimSpace(msg.Contents.Text())
        lower := strings.ToLower(text)
        if idx := strings.Index(lower, "my name is"); idx >= 0 {
            parts := strings.Fields(text[idx+len("my name is"):])
            if len(parts) == 0 {
                continue
            }
            state.UserName = strings.Trim(parts[0], ".,!?")
            session.Set(userMemorySourceID, state)
            break
        }
    }
    return nil
}

Vytvořte agenta s poskytovatelem kontextu:

a := foundryprovider.NewAgent(
    endpoint,
    token,
    foundryprovider.ModelDeployment(model),
    foundryprovider.AgentConfig{
        Instructions: "You are a friendly assistant.",
        Config: agent.Config{
            Name:             "MemoryAgent",
            ContextProviders: []agent.ContextProvider{newUserMemoryProvider()},
        },
    },
)

Spusťte ho – agent teď má přístup k kontextu:

ctx := context.Background()
session, err := a.CreateSession(ctx)
if err != nil {
    panic(err)
}

// The provider doesn't know the user yet.
resp, err := a.RunText(ctx, "Hello, what is the square root of 9?", agent.WithSession(session)).Collect()
fmt.Println(resp, err)

// Teach the provider the user's name.
resp, err = a.RunText(ctx, "My name is Alice", agent.WithSession(session)).Collect()
fmt.Println(resp, err)

// Subsequent calls are personalized using session state.
resp, err = a.RunText(ctx, "What is 2 + 2?", agent.WithSession(session)).Collect()
fmt.Println(resp, err)

Tip

Podívejte se na úplnou ukázku kompletního spustitelného souboru.

Další kroky

Jděte hlouběji: