将上下文添加到代理,以便它可以记住用户首选项、过去的交互或外部知识。
默认情况下,代理会将聊天记录存储在 InMemoryChatHistoryProvider 或基础 AI 服务中,具体取决于基础服务的需求。
以下代理使用 OpenAI 聊天完成功能,因其既不支持也不需要服务内聊天历史记录存储,因此会自动创建并使用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 对于开发来说很方便,但在生产中需要仔细考虑。 在生产环境中,请考虑使用特定凭据(例如), ManagedIdentityCredential以避免延迟问题、意外凭据探测以及回退机制的潜在安全风险。
若要使用自定义 ChatHistoryProvider,你可以将其一个实例传递给智能体选项:
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()
});
使用会话来在多次运行中共享上下文:
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
有关完整的可运行示例应用程序,请参阅 此处 。
完整示例定义上下文提供程序,将其添加到代理,并使用一个会话来保留个性化状态:
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
请查看完整示例以获取完整的可运行文件。
注释
在 Python 中,持久性和内存由 ContextProvider 和 HistoryProvider 实现进行管理。
InMemoryHistoryProvider 是内置的本地内存历史记录提供程序。
RawAgent 可以在特定情况下自动添加 InMemoryHistoryProvider() (例如,在没有配置的上下文提供程序和服务端存储指示器的情况下使用会话时),但这在所有方案中都不能保证。
如果始终需要本地持久性,请显式添加一个 InMemoryHistoryProvider 。 此外,请确保只有一个历史记录提供程序包含 load_messages=True,以免在同一次调用中回放多个存储。
按照 Microsoft Foundry 托管语义内存中的说明创建项目客户端和内存存储。 然后合并本地转录历史记录、托管内存和审核存储:
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
)
默认情况下,代理使用本地内存中历史记录或服务管理的历史记录,具体取决于提供程序和会话。
以下 Foundry 智能体使用项目支持的模型部署。 如果您希望拥有对话历史之外的应用程序专属记忆或个性化状态,请添加上下文提供程序。
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",
},
},
)
定义一个上下文提供程序,该提供程序将用户信息存储在会话状态并注入个性化说明:
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
}
使用上下文提供程序来创建代理:
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()},
},
},
)
运行它 — 代理现在有权访问上下文:
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
请查看完整示例以获取完整的可运行文件。
后续步骤
更深入: