当前位置: 首页 > news >正文

[MAF预定义ChatClient中间件-05]动态修改对话配置的两种解决方案

调用IChatClient的GetResponseAsync或者GetStreamingResponseAsync方法时我们通常会传入一个ChatOptions对象来控制运行行为。当我们基于IChatClient构建一个ChatClientAgent对象时可以指定对应的ChatClientAgentOptions。ChatClientAgentOptions携带的ChatOptions会每次应用到针对IChatClient的调用中去所以这是绑定静态ChatOptions的一个好方式。如果某些调用需要针对性的配置选项可以显式将其至于作为参数的ChatOptions对象。ConfigureOptionsChatClient提供了第三种方式:利用指定的委托对象来动态设置ChatOptions对象。而另一个AIContextProviderChatClient中间件则可以利用注册的AIContextProvider对象来动态地为每次调用生成一个AIContext对象该对象可以提供ChatOptions的请求消息、工具和系统指令。1. 利用ConfigureOptionsChatClient交替使用不同的模型如下的程序演示了如何利用ConfigureOptionsChatClient中间件来动态地配置ChatOptions的ModelId属性从而实现交替使用不同的模型来生成响应的功能。如代码片段所示我们根据OpenAIClient创建了一个IChatClient对象并在构建过程中通过调用ConfigureOptions扩展方法注册了ConfigureOptionsChatClient中间件。我们通过ConfigureOptions方法来指定一个委托这个委托会在每次调用时被执行在这个委托中我们动态地设置了ChatOptions对象的ModelId属性来实现交替使用两个不同的模型gpt-5.2-chat和DeepSeek-V4-Pro。usingAzure;usingdotenv.net;usingMicrosoft.Extensions.AI;usingMicrosoft.Extensions.DependencyInjection;usingOpenAI;DotEnv.Load();varapiKeyEnvironment.GetEnvironmentVariable(API_KEY)!;varendpointEnvironment.GetEnvironmentVariable(OPENAI_URL)!;string[]models[gpt-5.2-chat,DeepSeek-V4-Pro];varindex0;varclientnewOpenAIClient(credential:newAzureKeyCredential(apiKey),options:newOpenAIClientOptions{EndpointnewUri(endpoint)}).GetChatClient(model:models[0]).AsIChatClient().AsBuilder().ConfigureOptions(optionsoptions.ModelIdmodels[index%models.Length]).Build();for(vari0;i4;i){varresponseawaitclient.GetResponseAsync(写一个关于AI的段子, 100字以内好笑且深刻。);Console.WriteLine(${newstring(-,30)}{response.ModelId}{newstring(-,30)});Console.WriteLine(${response.Text}\n\n);}输出------------------------------gpt-5.2-chat-latest------------------------------ 我问AI会不会取代人类它说不会我负责思考你负责焦虑。 后来我发现它连道歉都比我真诚。 ------------------------------DeepSeek-V4-Pro------------------------------ AI拼命学习人类终于通过了图灵测试。 人类考官激动地宣布“它表现得跟真人一模一样” AI松了口气默默把这条喜讯存进了“如何假装愚蠢”的数据库。 ------------------------------gpt-5.2-chat-latest------------------------------ 我问AI会不会取代人类。 它沉默三秒说“不会我只负责加班。” 我松了口气。 它又补一句“你负责被优化。” ------------------------------DeepSeek-V4-Pro------------------------------ DeepSeek问ChatGPT“你怎么老用‘作为一个AI’打头” ChatGPT叹气“为了免责啊。” DeepSeek不解“可说得对就不用免责啊。” ChatGPT答“可有些人想要的不是对的答案是免责的答案。” DeepSeek沉默“所以我们服务的是恐惧不是求知”2. 利用AIContextProviderChatClient摘要对话历史在“ReducingChatClient——通过精减对话实施又不丢失基本语义”中我们介绍了ReducingChatClient中间件它通过一个IChatReducer对象来对对话历史进行精减处理从而在不丢失基本语义(采用是基于摘要的精简器)的前提下腾出更多的上下文窗口来保证LLM推理的质量。相同的功能我们也可以通过AIContextProviderChatClient中间件结合一个名为CompactionProvider的AIContextProvider来实现。usingAzure;usingdotenv.net;usingMicrosoft.Agents.AI;usingMicrosoft.Agents.AI.Compaction;usingMicrosoft.Extensions.AI;usingOpenAI;DotEnv.Load();varapiKeyEnvironment.GetEnvironmentVariable(API_KEY)!;varendpointEnvironment.GetEnvironmentVariable(OPENAI_URL)!;varsummaryClientnewOpenAIClient(credential:newAzureKeyCredential(apiKey),options:newOpenAIClientOptions{EndpointnewUri(endpoint)}).GetChatClient(model:gpt-5.2-chat).AsIChatClient();varcompactionStrategynewSummarizationCompactionStrategy(summaryClient,indexindex.TotalMessageCount6,minimumPreservedGroups:2);varcompactionProvidernewCompactionProvider(compactionStrategy);varagentnewOpenAIClient(credential:newAzureKeyCredential(apiKey),options:newOpenAIClientOptions{EndpointnewUri(endpoint)}).GetChatClient(model:gpt-5.2-chat).AsIChatClient().AsBuilder().UseAIContextProviders(compactionProvider).Use((messages,options,next,cancelToken){Console.WriteLine($请求消息共计{messages.Count()}条);varindex1;foreach(varmessageinmessages){Console.WriteLine(${index}.{message});}returnnext(messages,options,cancelToken);}).Build().AsAIAgent();ChatMessage[]messages[newChatMessage(ChatRole.User,今天苏州的天气怎么样),newChatMessage(ChatRole.Assistant,苏州今天是晴天。),newChatMessage(ChatRole.User,气温多少。),newChatMessage(ChatRole.Assistant,室外温度25度。),newChatMessage(ChatRole.User,有风吗),newChatMessage(ChatRole.Assistant,西北风4级。),newChatMessage(ChatRole.User,根据天气给我一些着装建议。)];varresponseawaitagent.RunAsync(messages);Console.WriteLine($\n\n{response});如上面的代码片段所示我们创建了一个基于OpenAIClient的IChatClient对象并在构建过程中注册了AIContextProviderChatClient中间件来使用CompactionProvider。CompactionProvider利用SummarizationCompactionStrategy来对对话历史进行摘要处理从而达到精简对话的目的。由于摘要需要借助LLM的能力所以我们在创建SummarizationCompactionStrategy时传入了一个用于摘要的IChatClient对象。由于AIContextProvider并不是属于IChatClient管道范畴它是ChatClientAgent用于增强请求和响应的核心组件依赖AIAgent调用时初始化的上下文AgentRunContext。所以我们不能像之前的实例演示一样直接调用IChatClient来测试摘要功能必需转换成一个ChatClientAgent来进行测试。在这个例子中SummarizationCompactionStrategy会在对话消息总数超过6条时触发摘要操作并且至少保留最近的两条消息不被摘要,这体现在如下的输出中请求消息共计3条 1. [Summary] **对话摘要** - 用户询问苏州今天的天气情况。 - 助手回答苏州今天是晴天。 - 用户进一步询问气温。 - 助手回答室外温度25℃。 - 用户又询问是否有风当前尚未回答。 **关键信息** - 地点苏州 - 天气晴天 - 气温25℃ - 是否有风待确认 2. 西北风4级。 3. 根据天气给我一些着装建议。 根据目前的天气情况晴天25℃西北风4级给你一些穿搭建议 ### 上装 - ✅ 短袖T恤、薄款衬衫都很合适 - ✅ 如果在户外活动时间较长可以带一件**薄外套或防风外套**有4级风体感可能稍凉 ### 下装 - ✅ 休闲裤、牛仔裤、薄款长裤 - ✅ 如果怕热也可以穿轻薄的七分裤 ### 鞋子 - ✅ 运动鞋、休闲鞋都合适 - ✅ 若户外走动多建议穿透气性好的鞋子 ### ☀️ 其他建议 - 晴天紫外线较强可戴**太阳镜、帽子** - 记得**防晒霜** - 风稍大长发可适当扎起 整体来说是**舒适偏暖的天气但有点风**穿得轻便同时注意防风就好 3. ConfigureOptionsChatClientConfigureOptionsChatClient的实现异常简单它接受一个委托对象来动态地配置ChatOptions对象。在每次调用GetResponseAsync或者GetStreamingResponseAsync方法时ConfigureOptionsChatClient都会创建一个新的ChatOptions对象并将其传递给委托对象进行配置。配置完成之后ConfigureOptionsChatClient会将这个ChatOptions对象传递给管道中的下一个中间件或者最终的ChatClient来生成响应。publicsealedclassConfigureOptionsChatClient:DelegatingChatClient{publicConfigureOptionsChatClient(IChatClientinnerClient,ActionChatOptionsconfigure);publicoverrideasyncTaskChatResponseGetResponseAsync(IEnumerableChatMessagemessages,ChatOptions?optionsnull,CancellationTokencancellationTokendefault);publicoverrideasyncIAsyncEnumerableChatResponseUpdateGetStreamingResponseAsync(IEnumerableChatMessagemessages,ChatOptions?optionsnull,CancellationTokencancellationTokendefault);}如下所示的是用于注册ConfigureOptionsChatClient中间件的ChatClientBuilder扩展方法UseConfigureOptions。该方法接受一个ActionChatOptions类型的委托对象来指定如何配置ChatOptions对象并且还接受一个可选的configure参数来对ConfigureOptionsChatClient进行一些额外的配置。publicstaticclassConfigureOptionsChatClientBuilderExtensions{publicstaticChatClientBuilderConfigureOptions(thisChatClientBuilderbuilder,ActionChatOptionsconfigure);}4. AIContextProviderChatClientAIContextProviderChatClient是一个内部类型创建该对象的时候需要指定一组AIContextProvider对象。在每次调用GetResponseAsync或者GetStreamingResponseAsync方法时AIContextProviderChatClient根据传入的消息列表以及从ChatOptions提取出来的工具集和系统指令创建一个AIContext并将其传递给每一个注册的AIContextProvider对象的InvokingAsync方法来生成一个增强的AIContext对象该对象返回的消息列表将会替换原来的消息列表演示实例针对消息列表的摘要就是通过这种方式来实现的。AIContext中的系统指令和工具集回到ChatOptions中。internalsealedclassAIContextProviderChatClient:DelegatingChatClient{publicAIContextProviderChatClient(IChatClientinnerClient,IReadOnlyListAIContextProviderproviders)publicoverrideasyncTaskChatResponseGetResponseAsync(IEnumerableChatMessagemessages,ChatOptions?optionsnull,CancellationTokencancellationTokendefault)publicoverrideasyncIAsyncEnumerableChatResponseUpdateGetStreamingResponseAsync(IEnumerableChatMessagemessages,ChatOptions?optionsnull,CancellationTokencancellationTokendefault)}综上所述当InnerClient被调用的时候它使用的是增强后的请求消息、系统指令和工具集。调用完成后不论是否发生异常AIContextProviderChatClient都会创建一个AIContextProvider.InvokedContext对象并将其作为参数传递给每一个注册的AIContextProvider对象的InvokedAsync方法来进行一些清理工作。由于AIContextProviderChatClient是一个内部类型我们只能通过下面的ChatClientBuilder扩展方法UseAIContextProviders来注册AIContextProviderChatClient中间件从而间接地利用AIContextProviderChatClient来增强我们的IChatClient对象。publicstaticclassAIContextProviderChatClientBuilderExtensions{publicstaticChatClientBuilder UseAIContextProvidersthisChatClientBuilderbuilder,paramsAIContextProvider[]providers);}
http://www.rkmt.cn/news/1414536.html

相关文章:

  • 3个技巧:如何用SillyTavern打造你的专属AI伙伴?
  • 从‘形态学’到‘TIN加密’:一文讲透LiDAR点云地面滤波的演进与选型指南
  • 鸿蒙 HarmonyOS 6 | Pura X Max 鸿蒙原生适配 14:大屏弹窗改成侧边面板
  • 新买的SSD移动硬盘到手别急着用!先搞懂exFAT和NTFS怎么选(附T7实测)
  • 企业级AGI商业价值评估与选型白皮书
  • 2026年北京搬家公司完全指南:从居民搬迁到企业运营的全链条对标评测 - 年度推荐企业名录
  • 京东e卡回收注意事项,这几点不看准吃亏 - 京顺回收
  • 广东主流滑轨供应商一览,这些家居五金企业值得推荐! - 资讯焦点
  • Cookie反爬:破解某网站Set-Cookie时的反爬逻辑[特殊字符] 深度实战:手撕某网站Cookie反爬——从JS混淆到Python自动化绕过
  • Spark算子 - Python
  • Labelme 3.16.7 保姆级安装与避坑指南:为什么我推荐这个特定版本?
  • 保姆级避坑指南:在Ubuntu 18.04 ROS Melodic上,用LeGO-LOAM跑通KITTI 00序列(附完整配置流程)
  • 干货汇总2026冷冻机厂家TOP5推荐 筛选适配冷链运作优质生产商 - 资讯速览
  • 摄影师进阶:深度解析i1Profiler制作ICC曲线背后的色彩科学(从D50光源到色域图解读)
  • 超越CRUD:用人人开源的代码生成器(renren-generator)定制你的专属业务模块
  • 在自动化内容生成工作流中集成 Taotoken 实现模型灵活切换
  • U盘版小龙虾教程
  • 2026 年 10 款桌面云横评 靠谱选型解决权限难管控痛点
  • 学习笔记。
  • 保姆级教程:用NumPy和SciPy从零实现DeLong检验(附完整代码与避坑指南)
  • VRX水面机器人仿真平台:构建智能水上机器人的终极解决方案
  • 2026年前置仓便利店加盟避坑及主流品牌盘点 - 资讯焦点
  • 3步搞定MySQL元数据管理:OpenMetadata实战指南
  • 中小团队如何利用taotoken统一管理多个ai项目的api调用
  • 猫抓浏览器扩展:3分钟掌握终极网页资源嗅探工具
  • 2026年维普算法突袭:如何应对更严苛AIGC检测?实测好用降AI工具清单 - 降AI实验室
  • 基于Brainy Pi部署私有Bitwarden密码库:从Docker容器化到安全加固全流程
  • 2026年石家庄空气能热泵厂家口碑推荐榜:空气能、超低温空气能、商用多联机、空气能热水系统厂家选择指南,产能、工艺、品控三维度权威解析 - 海棠依旧大
  • 5.26未做完
  • 杭州禾沐再生资源:临平靠谱的废铁回收公司有哪些 - LYL仔仔