news 2026/6/10 1:45:23

.Net——AI智能体开发基于 Microsoft Agent Framework 实现第三方聊天历史存储

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
.Net——AI智能体开发基于 Microsoft Agent Framework 实现第三方聊天历史存储

基于 Microsoft Agent Framework 实现第三方聊天历史存储

理解 Microsoft Agent Framework

Microsoft Agent Framework 是一个用于构建对话式 AI 应用的框架,支持自然语言处理和上下文管理。其核心组件包括 Bot Framework SDK 和 Azure Bot Service,但默认聊天历史通常存储在 Azure 服务中。

具体实现可参考NetCoreKevin的kevin.AI.AgentFramework和KevinAIChatMessageStore服务模块

基于NET构建的现代化AI智能体Saas企业级架构:

项目地址:github:https://github.com/junkai-li/NetCoreKevin
Gitee: https://gitee.com/netkevin-li/NetCoreKevin

配置自定义存储提供程序
  1. **实现ChatMessageStore**
    创建自定义存储类继承Microsoft.Bot.Builder.IStorage,需实现以下方法:

    publicsealedclassKevinChatMessageStore:ChatMessageStore{privateIKevinAIChatMessageStore_chatMessageStore;publicstringThreadDbKey{get;privateset;}publicKevinChatMessageStore(IKevinAIChatMessageStorevectorStore,JsonElementserializedStoreState,stringAIChatsId,JsonSerializerOptions?jsonSerializerOptions=null){this._chatMessageStore=vectorStore??thrownewArgumentNullException(nameof(vectorStore));this.ThreadDbKey=AIChatsId;}publicoverrideasyncTaskAddMessagesAsync(IEnumerable<ChatMessage>messages,CancellationTokencancellationToken){await_chatMessageStore.AddMessagesAsync(messages.Select(x=>newChatHistoryItemDto(){Key=this.ThreadDbKey+x.MessageId,Timestamp=DateTimeOffset.UtcNow,ThreadId=this.ThreadDbKey,MessageId=x.MessageId,Role=x.Role.Value,SerializedMessage=JsonSerializer.Serialize(x),MessageText=x.Text}).ToList(),cancellationToken);// 设置前景色为红色// 保存原始颜色,以便之后恢复ConsoleColororiginalColor=Console.ForegroundColor;Console.ForegroundColor=ConsoleColor.Red;Console.WriteLine("聊天消息记录:",Color.Red);messages.Select(x=>x.Text).ToList().ForEach(t=>Console.WriteLine(t));// 设置前景色为红色Console.ForegroundColor=ConsoleColor.Red;Console.WriteLine("聊天消息记录添加完成",Color.Red);// 恢复原始颜色Console.ForegroundColor=originalColor;}publicoverrideasyncTask<IEnumerable<ChatMessage>>GetMessagesAsync(CancellationTokencancellationToken){vardata=await_chatMessageStore.GetMessagesAsync(this.ThreadDbKey,cancellationToken);varmessages=data.ConvertAll(x=>JsonSerializer.Deserialize<ChatMessage>(x.SerializedMessage!)!);messages.Reverse();ConsoleColororiginalColor=Console.ForegroundColor;Console.ForegroundColor=ConsoleColor.Red;Console.WriteLine("所有聊天消息记录开始:",Color.Red);messages.Select(x=>x.Text).ToList().ForEach(t=>Console.WriteLine(t));Console.WriteLine("所有聊天消息记录结束:",Color.Red);// 恢复原始颜色Console.ForegroundColor=originalColor;returnmessages;}publicoverrideJsonElementSerialize(JsonSerializerOptions?jsonSerializerOptions=null)=>// We have to serialize the thread id, so that on deserialization you can retrieve the messages using the same thread id.JsonSerializer.SerializeToElement(this.ThreadDbKey);}
  2. 实现IKevinAIChatMessageStore

    TaskAddMessagesAsync(List<ChatHistoryItemDto>chatHistoryItems,CancellationTokencancellationToken);Task<List<ChatHistoryItemDto>>GetMessagesAsync(stringthreadId,CancellationTokencancellationToken);
  3. 实现注入到AI中间件中
    1.定义AI服务:

    /// <summary>/// AI服务/// </summary>publicclassAIAgentService:IAIAgentService{publicAIAgentService(){}publicasyncTask<AIAgent>CreateOpenAIAgent(stringname,stringprompt,stringdescription,stringurl,stringmodel,stringkeySecret,IList<AITool>?tools=null,ChatResponseFormat?chatResponseFormat=null,Func<IChatClient,IChatClient>?clientFactory=null,ILoggerFactory?loggerFactory=null,IServiceProvider?services=null){OpenAIClientOptionsopenAIClientOptions=newOpenAIClientOptions();openAIClientOptions.Endpoint=newUri(url);varai=newOpenAIClient(newApiKeyCredential(keySecret),openAIClientOptions);if(chatResponseFormat!=default){ChatOptionschatOptions=new(){ResponseFormat=chatResponseFormat};returnai.GetChatClient(model).CreateAIAgent(newChatClientAgentOptions(){Name=name,Instructions=prompt,ChatOptions=chatOptions,Description=description});}returnai.GetChatClient(model).CreateAIAgent(instructions:prompt,name:name,prompt,tools,clientFactory,loggerFactory,services);}publicasyncTask<AIAgent>CreateOpenAIAgent(stringmsg,stringurl,stringmodel,stringkeySecret,ChatClientAgentOptionschatClientAgentOptions){OpenAIClientOptionsopenAIClientOptions=newOpenAIClientOptions();openAIClientOptions.Endpoint=newUri(url);varai=newOpenAIClient(newApiKeyCredential(keySecret),openAIClientOptions);returnai.GetChatClient(model).CreateAIAgent(chatClientAgentOptions);}/// <summary>/// 智能体转换为McpServerTool/// </summary>/// <param name="aIAgent">智能体</param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>publicMcpServerToolAIAgentAsMcpServerTool(AIAgentaIAgent){returnMcpServerTool.Create(aIAgent.AsAIFunction());}/// <summary>/// 获取代理/// </summary>/// <returns></returns>publicIChatClientGetChatClient(stringurl,stringmodel,stringkeySecret){OpenAIClientOptionsopenAIClientOptions=newOpenAIClientOptions();openAIClientOptions.Endpoint=newUri(url);varai=newOpenAIClient(newApiKeyCredential(model),openAIClientOptions);returnai.GetChatClient(keySecret).AsIChatClient();}publicasyncTask<(AIAgent,AgentRunResponse)>CreateOpenAIAgentAndSendMSG(stringmsg,stringname,stringprompt,stringdescription,stringurl,stringmodel,stringkeySecret,IList<AITool>?tools=null,ChatResponseFormat?chatResponseFormat=null,Func<IChatClient,IChatClient>?clientFactory=null,ILoggerFactory?loggerFactory=null,IServiceProvider?services=null){OpenAIClientOptionsopenAIClientOptions=newOpenAIClientOptions();openAIClientOptions.Endpoint=newUri(url);varai=newOpenAIClient(newApiKeyCredential(keySecret),openAIClientOptions);varaiAgent=ai.GetChatClient(model).CreateAIAgent(instructions:prompt,name:name,prompt,tools,clientFactory,loggerFactory,services);if(chatResponseFormat!=default){ChatOptionschatOptions=new(){ResponseFormat=chatResponseFormat};aiAgent=ai.GetChatClient(model).CreateAIAgent(newChatClientAgentOptions(){Name=name,Instructions=prompt,ChatOptions=chatOptions,Description=description});}varreslut=awaitaiAgent.RunAsync(msg);return(aiAgent,reslut);}publicasyncTask<(AIAgent,AgentRunResponse)>CreateOpenAIAgentAndSendMSG(stringmsg,stringurl,stringmodel,stringkeySecret,ChatClientAgentOptionschatClientAgentOptions){OpenAIClientOptionsopenAIClientOptions=newOpenAIClientOptions();openAIClientOptions.Endpoint=newUri(url);varai=newOpenAIClient(newApiKeyCredential(keySecret),openAIClientOptions);varaiAgent=ai.GetChatClient(model).CreateAIAgent(chatClientAgentOptions);varreslut=awaitaiAgent.RunAsync(msg);return(aiAgent,reslut);}}

2.使用AI服务

addAi.Content=(awaitaIAgentService.CreateOpenAIAgentAndSendMSG(add.Content,aIModels.EndPoint,aIModels.ModelName,aIModels.ModelKey,newChatClientAgentOptions{Name=aiapp.Name,Instructions=aIPrompts.Prompt,Description=aIPrompts.Description??"你是一个智能体,请根据你的提示词进行相关回答",ChatMessageStoreFactory=ctx=>{// Create a new chat message store for this agent that stores the messages in a vector store.returnnewKevinChatMessageStore(kevinAIChatMessageStore,ctx.SerializedState,par.AIChatsId.ToString(),ctx.JsonSerializerOptions);}})).Item2.Text;
数据库设计建议

对于关系型数据库(如 SQL Server),建议的表结构:

/// <summary>/// 专门用于存储AI聊天记录的表/// </summary>[Table("TAIChatMessageStore")][Description("专门用于存储AI聊天记录的表")][Index(nameof(Key))][Index(nameof(ThreadId))][Index(nameof(Role))][Index(nameof(MessageId))]publicclass TAIChatMessageStore : CUD_User {[MaxLength(200)]publicstringKey{ get;set;}[MaxLength(100)]publicstring ThreadId { get;set;}[Description("消息时间stamp")]publicDateTimeOffset?Timestamp{ get;set;}/// <summary>/// 角色标识/// </summary>[MaxLength(50)]publicstring Role { get;set;}publicstring SerializedMessage { get;set;}/// <summary>/// 消息内容/// </summary>publicstring? MessageText { get;set;}/// <summary>/// 消息id/// </summary>[Description("消息id")][MaxLength(100)]publicstring? MessageId { get;set;} }
实现数据持久化
  1. 写入示例
    使用 Entity Framework Core 保存数据:

    publicasyncTaskAddMessagesAsync(List<ChatHistoryItemDto>chatHistoryItems,CancellationTokencancellationToken){varadddata=chatHistoryItems.Select(t=>newTAIChatMessageStore{Id=SnowflakeIdService.GetNextId(),CreateTime=DateTime.Now,CreateUserId=CurrentUser.UserId,IsDelete=false,TenantId=CurrentUser.TenantId,ThreadId=t.ThreadId,Timestamp=t.Timestamp,Role=t.Role,Key=t.Key,SerializedMessage=t.SerializedMessage,MessageText=t.MessageText,MessageId=t.MessageId}).ToList();aIChatMessageStoreRp.AddRange(adddata);awaitaIChatMessageStoreRp.SaveChangesAsync();}
  2. 读取示例

    publicTask<List<ChatHistoryItemDto>>GetMessagesAsync(stringthreadId,CancellationTokencancellationToken){returnaIChatMessageStoreRp.Query().Where(t=>t.ThreadId==threadId&&t.IsDelete==false).Select(t=>newChatHistoryItemDto{Key=t.Key,ThreadId=t.ThreadId,Timestamp=t.Timestamp,SerializedMessage=t.SerializedMessage,MessageText=t.MessageText,Role=t.Role,MessageId=t.MessageId}).ToListAsync();}
性能优化建议
  • 为高频查询字段(如UserIdChannelId)添加索引
  • 实现数据分片策略应对大规模历史记录
  • 考虑使用 Redis 缓存热点对话数据
安全注意事项
  • 加密存储敏感对话内容
  • 实现数据保留策略定期清理旧记录
  • 遵守 GDPR 等数据隐私法规
测试验证方法
  1. 编写单元测试验证存储接口实现
  2. 使用 Bot Framework Emulator 进行端到端测试
  3. 进行负载测试验证性能表现
扩展可能性
  1. 添加全文检索支持(如 Azure Cognitive Search)
  2. 实现跨渠道对话历史同步
  3. 开发分析模块生成对话洞察报告

这种实现方式允许完全控制数据存储位置和格式,同时保持与 Bot Framework 的兼容性。根据具体需求可选择 SQL Server、Cosmos DB 或其他数据库解决方案。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/8 19:45:05

28、Vim 自动补全与语法高亮全解析

Vim 自动补全与语法高亮全解析 1. Vim 自动补全方法 Vim 提供了多种自动补全方法,以下为你详细介绍: - 使用 complete 选项定义匹配搜索范围 :该方法使用 complete 选项定义匹配搜索的范围。在弹出列表中,可通过 CTRL - N 向前或 CTRL - P 向后移动来高亮选择项…

作者头像 李华
网站建设 2026/6/8 20:02:45

29、Vim编程增强功能:语法高亮与编译错误检查

Vim编程增强功能:语法高亮与编译错误检查 1. 语法高亮基础 Vim允许用户对文本的语法高亮进行调整,以满足个人喜好。主要涉及 colorscheme 、 highlight 两个命令和 background 选项。 1.1 语法组 Vim将不同类型的文本分类到不同的组中,每个组都有相应的颜色和高亮…

作者头像 李华
网站建设 2026/6/7 21:09:31

37、深入了解vile编辑器:功能与特性全解析

深入了解vile编辑器:功能与特性全解析 1. 文本选择与操作 在vile编辑器中,文本选择操作十分便捷。你可以通过双击或三击来选择单个单词或整行文本。若要扩展选择范围,点击鼠标右键即可。和使用鼠标左键一样,按住右键并拖动,就能调整或滚动选择区域。而且,在打开同一缓冲…

作者头像 李华
网站建设 2026/6/9 0:56:56

慧知开源充电桩平台 - 小区电动汽车及电动自行车智能充电基础设施一体化建设方案

小区电动汽车及电动自行车智能充电基础设施一体化建设方案前言&#xff1a;时代背景与项目意义 当前&#xff0c;全球正经历一场深刻的能源革命与交通变革。中国作为全球最大的新能源汽车市场&#xff0c;已将发展新能源汽车产业上升为国家战略。《新能源汽车产业发展规划&…

作者头像 李华
网站建设 2026/6/9 1:25:47

Azure CLI量子作业日志深度解析(专家级排错指南)

第一章&#xff1a;Azure CLI量子作业日志分析概述随着量子计算在科研与工业领域的逐步落地&#xff0c;Azure Quantum 作为微软云平台的重要组成部分&#xff0c;提供了强大的量子作业调度与执行能力。在实际应用中&#xff0c;对量子作业的运行状态、性能指标及异常行为进行深…

作者头像 李华
网站建设 2026/6/9 2:00:38

GSE宏编译器完整指南:从零开始掌握魔兽世界自动化战斗

GSE宏编译器完整指南&#xff1a;从零开始掌握魔兽世界自动化战斗 【免费下载链接】GSE-Advanced-Macro-Compiler GSE is an alternative advanced macro editor and engine for World of Warcraft. It uses Travis for UnitTests, Coveralls to report on test coverage and t…

作者头像 李华