news 2026/7/1 21:23:28

.NET+AI | Agent | 自定义上下文记忆-示例(16)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
.NET+AI | Agent | 自定义上下文记忆-示例(16)

AIContextProvider 实战:用户信息记忆组件

一句话简介

从零实现完整的 UserInfoMemory 类,支持自动提取用户信息、序列化持久化和跨 Thread 共享。


🎯 核心功能

  • 自动提取:从对话中提取用户姓名和年龄

  • 智能询问:未知信息时主动询问,已知时直接使用

  • 状态持久化:支持序列化和反序列化

  • 跨 Thread 共享:在不同对话线程间共享记忆


💻 完整实现

步骤 1:定义数据模型

public class UserInfo { public string? UserName { get; set; } public int? UserAge { get; set; } }

步骤 2:实现 UserInfoMemory

public sealedclassUserInfoMemory : AIContextProvider { privatereadonly IChatClient _chatClient; public UserInfo UserInfo { get; set; } // 构造函数1:首次创建 public UserInfoMemory(IChatClient chatClient, UserInfo? userInfo = null) { _chatClient = chatClient; UserInfo = userInfo ?? new UserInfo(); } // 构造函数2:反序列化恢复 public UserInfoMemory(IChatClient chatClient, JsonElement serializedState, ...) { _chatClient = chatClient; UserInfo = serializedState.Deserialize<UserInfo>() ?? new UserInfo(); } // 调用前:注入用户信息到上下文 public override ValueTask<AIContext> InvokingAsync( InvokingContext context, CancellationToken ct = default) { var instructions = new StringBuilder(); instructions.AppendLine(UserInfo.UserName isnull ? "Ask the user for their name." : $"The user's name is {UserInfo.UserName}."); instructions.AppendLine(UserInfo.UserAge isnull ? "Ask the user for their age." : $"The user's age is {UserInfo.UserAge}."); returnnew ValueTask<AIContext>(new AIContext { Instructions = instructions.ToString() }); } // 调用后:从对话中提取用户信息 public override async ValueTask InvokedAsync( InvokedContext context, CancellationToken ct = default) { if ((UserInfo.UserName isnull || UserInfo.UserAge isnull) && context.RequestMessages.Any(x => x.Role == ChatRole.User)) { try { var result = await _chatClient.GetResponseAsync<UserInfo>( context.RequestMessages, new ChatOptions { Instructions = "Extract user's name and age if present." }, ct); // 仅更新未知信息 UserInfo.UserName ??= result.Result.UserName; UserInfo.UserAge ??= result.Result.UserAge; } catch { /* 提取失败不影响主流程 */ } } } // 序列化:只保存数据状态 public override JsonElement Serialize(JsonSerializerOptions? options = null) { return JsonSerializer.SerializeToElement(UserInfo, options); } }

💻 注册到 Agent

var chatClient = AIClientHelper.GetDefaultChatClient(); var options = new ChatClientAgentOptions { Instructions = "You are a friendly assistant.", AIContextProviderFactory = ctx => new UserInfoMemory( chatClient, ctx.SerializedState, ctx.JsonSerializerOptions) }; var agent = chatClient.CreateAIAgent(options);

🧪 测试效果

4 轮对话流程

第 1 轮:用户说"你好" → Agent 询问姓名和年龄 第 2 轮:用户说"我叫张三" → Agent 确认姓名,继续询问年龄 第 3 轮:用户说"25岁" → Agent 确认年龄,信息收集完成 第 4 轮:用户说"天气怎么样?" → Agent 记住用户是张三(记忆生效)

序列化与恢复

// 序列化当前状态 var serialized = thread.Serialize(); // 恢复对话 var restored = agent.DeserializeThread(serialized); var memory = restored.GetService<UserInfoMemory>(); Console.WriteLine(memory.UserInfo.UserName); // "张三"

跨 Thread 共享

// 从原 Thread 提取用户信息 var userInfo = oldThread.GetService<UserInfoMemory>()?.UserInfo; // 注入到新 Thread var newMemory = newThread.GetService<UserInfoMemory>(); newMemory.UserInfo = userInfo; // 新 Thread 直接拥有用户信息(无需重新询问)

🏢 最佳实践

技术要点

说明

两个构造函数

首次创建 + 反序列化恢复

使用 ??= 运算符

仅更新未知信息,不覆盖已知

异常处理

InvokedAsync 中的异常不影响主流程

只序列化数据

不序列化服务依赖(如 IChatClient)

验证记忆恢复

反序列化后通过对话测试验证


🎯 总结

  • 完整实现:InvokingAsync(注入)+ InvokedAsync(提取)+ Serialize(持久化)

  • 智能询问:根据记忆状态动态生成 Instructions

  • 序列化支持:保存和恢复对话状态

  • 跨 Thread 共享:通过直接赋值实现记忆共享


如需获取文章配套完整代码,可扫码咨询领取。👇

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

基于SerDes的PCB封装走线等长控制项目应用

高速SerDes设计的“命门”&#xff1a;封装走线等长控制如何决定系统成败你有没有遇到过这样的情况——FPGA和ADC之间的高速链路总是间歇性断开&#xff0c;眼图闭合得像一条细缝&#xff0c;协议分析仪频频报出“帧同步丢失”&#xff0c;而硬件工程师反复检查电源、时钟、参考…

作者头像 李华
网站建设 2026/7/1 10:21:07

【计算机毕业设计案例】基于springboot+vue的医院综合管理系统实现与设计基于SpringBoot+Vue技术的医院运营管理系统的设计与实现(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/26 1:59:15

Spring Boot自动配置

Spring Boot自动配置 一、核心思想与目标 自动配置是Spring Boot的基石&#xff0c;其核心目标是&#xff1a;根据项目中引入的依赖&#xff08;JAR包&#xff09;和预设的配置&#xff0c;自动、智能地组装和配置Spring应用所需的Bean&#xff0c;实现 “约定大于配置” &am…

作者头像 李华
网站建设 2026/6/30 13:36:16

微信小程序体育球馆场地租赁商城系统

文章目录 具体实现截图主要技术与实现手段系统设计与实现的思路系统设计方法java类核心代码部分展示结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01; 具体实现截图 本系统&#xff08;程序源码数据库调试部署讲解&#xff09;带文档1…

作者头像 李华
网站建设 2026/7/1 1:39:56

挑战篇-02-认识一个AI模型聚合平台

AI 模型聚合平台 主打让普通用户方便用用各种大模型。 聊天&#xff0c;写东西&#xff0c;问知识切换模型就能体验不同的AI能力。 不用挨个网站去注册。 头部的AI模型聚合平台&#xff0c; 就比如 POE 官网如下 https://poe.com/ 用户量多&#xff0c; 模型也全&#xff0c; 像…

作者头像 李华
网站建设 2026/6/26 1:59:10

Dockerfile

目录 前言&#xff1a; 一&#xff0c;Dockerfile 核心理论 1.1、Docker 镜像的分层架构&#xff1a;Dockerfile 的设计基石 1.2、Dockerfile 的构建上下文&#xff1a;指令的作用范围 1.3、Dockerfile 指令的深层执行逻辑 1.3.1. 基础镜像指令&#xff1a;FROM 与 ARG 的…

作者头像 李华