.NET+AI | Agent | Agent 记忆线程(2)
2026/8/6 6:24:04 网站建设 项目流程

目录

一句话简介

🎯 核心价值

💡 问题场景

🚀 解决方案:三步实现记忆对话

核心机制

实现代码

🌊 流式多轮对话

🔒 多用户场景:线程隔离

实现代码

📜 访问对话历史

📊 API 速查表

核心 API

调用模式对比

🏢 企业级最佳实践

✅ 推荐做法

❌ 常见错误

🎯 总结


上一篇

一句话简介

AgentThread 是 Microsoft Agent Framework 提供的对话线程管理机制,通过显式创建并复用线程对象,让 AI Agent 在多轮对话中拥有完整的上下文记忆能力。


🎯 核心价值

  • 多轮记忆:Agent 自动记住所有对话历史

  • 线程隔离:多用户场景下对话互不干扰

  • 简单易用:三行代码实现带记忆的对话

  • 流式支持:同时支持同步和流式多轮对话


💡 问题场景

很多开发者在使用 Agent 时会遇到"失忆"问题:

// ❌ 问题演示 await agent.RunAsync("我叫张三"); await agent.RunAsync("你知道我叫什么吗?"); // Agent: "抱歉,我不知道您的名字"

原因:每次调用RunAsync()不传thread参数时,MAF 会临时创建新线程并在调用结束后丢弃,导致历史消息丢失。


🚀 解决方案:三步实现记忆对话

核心机制

实现代码

// 步骤1: 创建 Agent var chatClient = AIClientHelper.GetDefaultChatClient(); AIAgent agent = chatClient.CreateAIAgent( instructions: "你是专业助理,记住用户所有信息并提供个性化服务", name: "PersonalAssistant" ); // 步骤2: 创建 Thread(关键!) AgentThread thread = agent.GetNewThread(); // 步骤3: 多轮对话(复用同一个 thread) await agent.RunAsync("我叫李明,是软件工程师,喜欢咖啡", thread); await agent.RunAsync("你记得我叫什么吗?", thread); // ✅ 能准确回答 await agent.RunAsync("我喜欢什么饮料?", thread); // ✅ 能准确回答

核心要点:

  • 🔧 使用GetNewThread()创建线程

  • 🔧 所有调用都传入同一个thread对象

  • 🔧 Thread 自动管理所有历史消息


🌊 流式多轮对话

AgentThread 同样支持流式调用,适合长文本生成场景。

// 创建故事创作 Agent AIAgent storyWriter = chatClient.CreateAIAgent( instructions: "你是创意写作助手,记住所有故事元素保持一致性", name: "StoryWriter" ); // 创建线程 AgentThread storyThread = storyWriter.GetNewThread(); // 第一轮:设定背景 awaitforeach (var chunk in storyWriter.RunStreamingAsync( "科幻故事,2150年火星殖民地,主角阿尔法是工程师", storyThread)) { Console.Write(chunk); } // 第二轮:引入冲突(Agent 记得前面设定) awaitforeach (var chunk in storyWriter.RunStreamingAsync( "生命支持系统故障,阿尔法需24小时内修复", storyThread)) { Console.Write(chunk); } // 第三轮:添加转折(Agent 记得所有情节) awaitforeach (var chunk in storyWriter.RunStreamingAsync( "阿尔法发现故障是人为破坏", storyThread)) { Console.Write(chunk); }

🔒 多用户场景:线程隔离

AgentThread 的重要特性是线程隔离,每个用户应有独立线程。

实现代码

// 创建客服 Agent AIAgent customerService = chatClient.CreateAIAgent( instructions: "电商客服,记住每位客户信息提供个性化服务", name: "CustomerService" ); // 为两个用户创建独立线程 AgentThread threadZhangSan = customerService.GetNewThread(); AgentThread threadLiSi = customerService.GetNewThread(); // 张三的对话 await customerService.RunAsync("我叫张三,想买笔记本电脑,预算8000元", threadZhangSan); await customerService.RunAsync("主要用来做软件开发", threadZhangSan); // 李四的对话(完全隔离) await customerService.RunAsync("我是李四,想买游戏鼠标", threadLiSi); await customerService.RunAsync("价格300元以内", threadLiSi); // 验证隔离:两个用户各自记得自己的信息 await customerService.RunAsync("你记得我的预算和用途吗?", threadZhangSan); await customerService.RunAsync("我刚才想买什么?", threadLiSi);

📜 访问对话历史

Thread 内部维护历史消息列表,可用于统计、调试、导出等场景。

// 获取历史消息 IList<ChatMessage>? chatHistory = thread.GetService<IList<ChatMessage>>(); if (chatHistory != null) { Console.WriteLine($"总消息数: {chatHistory.Count}"); // 统计不同角色的消息 var userMessages = chatHistory.Where(m => m.Role == ChatRole.User).Count(); var assistantMessages = chatHistory.Where(m => m.Role == ChatRole.Assistant).Count(); // 遍历显示 foreach (var message in chatHistory) { Console.WriteLine($"[{message.Role}]: {message.Text}"); } }

使用场景:

  • 📊 统计对话轮数

  • 🔍 调试和日志记录

  • 📝 导出对话历史

  • ⚠️ 监控 Token 使用量

注意事项:

  • ⚠️ 历史消息只读访问,不建议直接修改

  • ⚠️ 长对话需注意 Token 限制,可用 ChatReducer 自动裁剪

  • ⚠️ 多用户场景务必线程隔离


📊 API 速查表

核心 API

API

功能

场景

agent.GetNewThread()

创建新线程

用户会话开始

RunAsync(msg, thread)

同步多轮对话

记忆上下文

RunStreamingAsync(msg, thread)

流式多轮对话

长文本生成

thread.ThreadId

获取线程ID

日志、调试

thread.GetService<IList<ChatMessage>>()

获取历史消息

统计、导出

调用模式对比

调用方式

Thread 参数

是否记忆

使用场景

RunAsync("消息")

❌ 不传

❌ 不记忆

单次查询

RunAsync("消息", thread)

✅ 传入

✅ 记忆

多轮对话

RunStreamingAsync("消息")

❌ 不传

❌ 不记忆

单次流式

RunStreamingAsync("消息", thread)

✅ 传入

✅ 记忆

多轮流式


🏢 企业级最佳实践

✅ 推荐做法

1. 为每个用户会话创建独立 Thread

// 用户登录时 var userThread = agent.GetNewThread(); _userThreads[userId] = userThread;

2. 整个对话过程复用同一个 Thread

var thread = _userThreads[userId]; await agent.RunAsync(message, thread);

3. 添加元数据便于管理

thread.Metadata["UserId"] = userId; thread.Metadata["SessionStartTime"] = DateTime.UtcNow;

❌ 常见错误

1. 忘记传入 Thread 参数

// ❌ 错误:每次都创建新线程 await agent.RunAsync("第一句话"); await agent.RunAsync("第二句话"); // 忘记了第一句话

2. 每次调用都创建新 Thread

// ❌ 错误:不复用线程 var thread1 = agent.GetNewThread(); await agent.RunAsync("第一句话", thread1); var thread2 = agent.GetNewThread(); // ❌ 不应该创建新的! await agent.RunAsync("第二句话", thread2);

3. 多用户共用一个 Thread

// ❌ 错误:会导致对话混乱 var sharedThread = agent.GetNewThread(); await agent.RunAsync("用户A的消息", sharedThread); await agent.RunAsync("用户B的消息", sharedThread); // B能看到A的历史!

🎯 总结

  • AgentThread 核心作用:管理对话历史,实现多轮对话记忆

  • 使用方法:创建 Thread → 复用 Thread → 自动记忆

  • 线程隔离:每个用户独立 Thread,多用户场景安全

  • 流式支持:同步和流式调用都支持 Thread

  • 历史访问:可获取历史消息用于统计、调试、导出

核心原则:一个用户会话 = 一个 Thread,始终复用!

下一篇

引入地址

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询