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

config.json 文件是固定名称,存储描述信息,比如需要的变量名称、描述等。下面是一个 completion 类型的插件配置文件示例,除了一些跟提示模板相关的配置,还有一些聊天的配置,如最大 t

{ "schema": 1, "type": "completion", "description": "根据用户问题写一首简短而有趣的诗.", "completion": { "max_tokens": 200, "temperature": 0.5, "top_p": 0.0, "presence_penalty": 0.0, "frequency_penalty": 0.0 }, "input": { "parameters": [ { "name": "input", "description": "诗的主题", "defaultValue": "" } ] } }

创建插件目录和文件后,在代码中以提示模板的方式加载:

// 加载插件,表示该插件是提示模板 builder.Plugins.AddFromPromptDirectory("./plugins/WriterPlugin"); var kernel = builder.Build(); Console.WriteLine("输入诗的主题:"); var input = Console.ReadLine(); // WriterPlugin 插件名称,与插件目录一致,插件目录下可以有多个子模板目录。 FunctionResult result = await kernel.InvokeAsync("WriterPlugin", "ShortPoem", new() { { "input", input } }); Console.WriteLine(result.GetValue<string>());

输入问题以及 AI 回复:

输入诗的主题: 春天 春天,春天,你是生命的诗篇, 万物复苏,爱的季节。 郁郁葱葱的小草中, 是你轻响的诗人的脚步音。 春天,春天,你是花芯的深渊, 桃红柳绿,或妩媚或清纯。 在温暖的微风中, 是你舞动的裙摆。 春天,春天,你是蓝空的情儿, 百鸟鸣叫,放歌天际无边。 在你湛蓝的天幕下, 是你独角戏的绚烂瞬间。 春天,春天,你是河流的眼睛, 如阿瞒甘霖,滋养大地生灵。 你的涓涓细流, 是你悠悠的歌声。 春天,春天,你是生命的诗篇, 用温暖的手指,照亮这灰色的世间。 你的绽放,微笑与欢欣, 就是我心中永恒的春天。

插件文件的编写可参考官方文档:https://learn.microsoft.com/en-us/semantic-kernel/prompts/saving-prompts-as-files?tabs=Csharp

根据 AI 自动调用插件函数

使用 Semantic Kernel 加载插件类后,Semantic Kernel 可以自动根据 AI 对话调用这些插件类中的函数。

比如有一个插件类型,用于修改或获取灯的状态。

代码如下:

public class LightPlugin { public bool IsOn { get; set; } = false; [KernelFunction] [Description("获取灯的状态.")] public string GetState() => IsOn ? "亮" : "暗"; [KernelFunction] [Description("修改灯的状态.'")] public string ChangeState(bool newState) { this.IsOn = newState; var state = GetState(); Console.WriteLine($"[灯的状态是: {state}]"); return state; } }

每个函数都使用了[Description]特性设置了注释信息,这些注释信息非常重要,AI 靠这些注释理解函数的功能作用。

然后加载插件类,并在聊天中被 Semantic Kernel 调用:

// 加载插件类 builder.Plugins.AddFromType<LightPlugin>(); var kernel = builder.Build(); var history = new ChatHistory(); // 聊天服务 var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>(); while (true) { Console.Write("User > "); var userInput = Console.ReadLine(); // 添加到聊天记录中 history.AddUserMessage(userInput); // 开启函数调用 OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions }; // 获取函数 var result = await chatCompletionService.GetChatMessageContentAsync( history, executionSettings: openAIPromptExecutionSettings, kernel: kernel); Console.WriteLine("Assistant > " + result); // 添加到聊天记录中 history.AddMessage(result.Role, result.Content ?? string.Empty); }

可以先断点调试 LightPlugin 中的函数,然后在控制台输入问题让 AI 调用本地函数:

User > 灯的状态 Assistant > 当前灯的状态是暗的。 User > 开灯 [灯的状态是: 亮] Assistant > 灯已经开启,现在是亮的状态。 User > 关灯 [灯的状态是: 暗]

读者可以在官方文档了解更多:https://learn.microsoft.com/en-us/semantic-kernel/agents/plugins/using-the-kernelfunction-decorator?tabs=Csharp

由于几乎没有文档资料说明原理,因此建议读者去研究源码,这里就不再赘述了。

聊天中明确调用函数

我们可以在提示模板中明确调用一个函数。

定义一个插件类型 ConversationSummaryPlugin,其功能十分简单,将历史记录直接返回,input 参数表示历史记录。

public class ConversationSummaryPlugin { [KernelFunction, Description("给你一份很长的谈话记录,总结一下谈话内容.")] public async Task<string> SummarizeConversationAsync( [Description("长对话记录\r\n.")] string input, Kernel kernel) { await Task.CompletedTask; return input; } }

为了在聊天记录中使用该插件函数,我们需要在提示模板中使用{{ConversationSummaryPlugin.SummarizeConversation $history}},其中$history是自定义的变量名称,名称可以随意,只要是个字符串即可。

var chat = kernel.CreateFunctionFromPrompt( @"{{ConversationSummaryPlugin.SummarizeConversation $history}} User: {{$request}} Assistant: " );

完整代码如下:

// 加载总结插件 builder.Plugins.AddFromType<ConversationSummaryPlugin>(); var kernel = builder.Build(); var chat = kernel.CreateFunctionFromPrompt( @"{{ConversationSummaryPlugin.SummarizeConversation $history}} User: {{$request}} Assistant: " ); var history = new ChatHistory(); while (true) { Console.Write("User > "); var request = Console.ReadLine(); // 添加到聊天记录中 history.AddUserMessage(request); // 流式对话 var chatResult = kernel.InvokeStreamingAsync<StreamingChatMessageContent>( chat, new KernelArguments { { "request", request }, { "history", string.Join("\n", history.Select(x => x.Role + ": " + x.Content)) } }); string message = ""; await foreach (var chunk in chatResult) { if (chunk.Role.HasValue) { Console.Write(chunk.Role + " > "); } message += chunk; Console.Write(chunk); } Console.WriteLine(); history.AddAssistantMessage(message); }

由于模板的开头是{{ConversationSummaryPlugin.SummarizeConversation $history}},因此,每次聊天之前,都会先调用该函数。

比如输入吃饭睡觉打豆豆的时候,首先执行 ConversationSummaryPlugin.SummarizeConversation 函数,然后将返回结果存储到模板中。

最后生成的提示词对比如下:

@"{{ConversationSummaryPlugin.SummarizeConversation $history}} User: {{$request}} Assistant: "
user: 吃饭睡觉打豆豆 User: 吃饭睡觉打豆豆 Assistant:

可以看到,调用函数返回结果后,提示词字符串前面自动使用 User 角色。

实现总结

Semantic Kernel 中有很多文本处理工具,比如TextChunker类型,可以帮助我们提取文本中的行、段。设定场景如下,用户提问一大段文本,然后我们使用 AI 总结这段文本。

Semantic Kernel 有一些工具,但是不多,而且是针对英文开发的。

设定一个场景,用户可以每行输入一句话,当用户使用000结束输入后,每句话都推送给 AI 总结(不是全部放在一起总结)。

这个示例的代码比较长,建议读者在 vs 中调试代码,慢慢阅读。

// 总结内容的最大 token const int MaxTokens = 1024; // 提示模板 const string SummarizeConversationDefinition = @"开始内容总结: {{$request}} 最后对内容进行总结。 在“内容到总结”中总结对话,找出讨论的要点和得出的任何结论。 不要加入其他常识。 摘要是纯文本形式,在完整的句子中,没有标记或标记。 开始总结: "; // 配置 PromptExecutionSettings promptExecutionSettings = new() { ExtensionData = new Dictionary<string, object>() { { "Temperature", 0.1 }, { "TopP", 0.5 }, { "MaxTokens", MaxTokens } } }; // 这里不使用 kernel.CreateFunctionFromPrompt 了 // KernelFunctionFactory 可以帮助我们通过代码的方式配置提示词 var func = KernelFunctionFactory.CreateFromPrompt( SummarizeConversationDefinition, // 提示词 description: "给出一段对话记录,总结这部分对话.", // 描述 executionSettings: promptExecutionSettings); // 配置 #pragma warning disable SKEXP0055 // 类型仅用于评估,在将来的更新中可能会被更改或删除。取消此诊断以继续。 var request = ""; while (true) { Console.Write("User > "); var input = Console.ReadLine(); if (input == "000") { break; } request += Environment.NewLine; request += input; } // SK 提供的文本拆分器,将文本分成一行行的 List<string> lines = TextChunker.SplitPlainTextLines(request, MaxTokens); // 将文本拆成段落 List<string> paragraphs = TextChunker.SplitPlainTextParagraphs(lines, MaxTokens); string[] results = new string[paragraphs.Count]; for (int i = 0; i < results.Length; i++) { // 一段段地总结 results[i] = (await func.InvokeAsync(kernel, new() { ["request"] = paragraphs[i] }).ConfigureAwait(false)) .GetValue<string>() ?? string.Empty; } Console.WriteLine($""" 总结如下: {string.Join("\n", results)} """);

输入一堆内容后,新的一行使用000结束提问,让 AI 总结用户的话。

不过经过调试发现,TextChunker 对这段文本的处理似乎不佳,因为文本这么多行只识别为一行、一段。

可能跟 TextChunker 分隔符有关,SK 主要是面向英语的。

本小节的演示效果不佳,不过主要目的是,让用户了解KernelFunctionFactory.CreateFromPrompt可以更加方便创建提示模板、使用 PromptExecutionSettings 配置温度、使用 TextChunker 切割文本。

配置 PromptExecutionSettings 时,出现了三个参数,其中 MaxTokens 表示机器人回复最大的 tokens 数量,这样可以避免机器人废话太多。

其它两个参数的作用是:

Temperature:值范围在 0-2 之间,简单来说,temperature的参数值越小,模型就会返回越确定的一个结果。值越大,AI 的想象力越强,越可能偏离现实。一般诗歌、科幻这些可以设置大一些,让 AI 实现天马行空的回复。

TopP:与 Temperature 不同的另一种方法,称为核抽样,其中模型考虑了具有 TopP 概率质量的令牌的结果。因此,0.1 意味着只考虑构成前10% 概率质量的令牌的结果。

一般建议是改变其中一个参数就行,不用两个都调整。

更多相关的参数配置,请查看 https://learn.microsoft.com/en-us/azure/ai-services/openai/reference

配置提示词

前面提到了一个新的创建函数的用法:

var func = KernelFunctionFactory.CreateFromPrompt( SummarizeConversationDefinition, // 提示词 description: "给出一段对话记录,总结这部分对话.", // 描述 executionSettings: promptExecutionSettings); // 配置

创建提示模板时,可以使用 PromptTemplateConfig 类型 调整控制提示符行为的参数。

// 总结内容的最大 token const int MaxTokens = 1024; // 提示模板 const string SummarizeConversationDefinition = "..."; var func = kernel.CreateFunctionFromPrompt(new PromptTemplateConfig { // Name 不支持中文和特殊字符 Name = "chat", Description = "给出一段对话记录,总结这部分对话.", Template = SummarizeConversationDefinition, TemplateFormat = "semantic-kernel", InputVariables = new List<InputVariable> { new InputVariable{Name = "request", Description = "用户的问题", IsRequired = true } }, ExecutionSettings = new Dictionary<string, PromptExecutionSettings> { { "default", new OpenAIPromptExecutionSettings() { MaxTokens = MaxTokens, Temperature = 0 } }, } });

ExecutionSettings 部分的配置,可以针对使用的模型起效,这里的配置不会全部同时起效,会根据实际使用的模型起效。

ExecutionSettings = new Dictionary<string, PromptExecutionSettings> { { "default", new OpenAIPromptExecutionSettings() { MaxTokens = 1000, Temperature = 0 } }, { "gpt-3.5-turbo", new OpenAIPromptExecutionSettings() { ModelId = "gpt-3.5-turbo-0613", MaxTokens = 4000, Temperature = 0.2 } }, { "gpt-4", new OpenAIPromptExecutionSettings() { ModelId = "gpt-4-1106-preview", MaxTokens = 8000, Temperature = 0.3 } } }

聊到这里,重新说一下前面使用文件配置提示模板文件的,两者是相似的。

我们也可以使用文件的形式存储与代码一致的配置,其目录文件结构如下:

└─── chat | └─── config.json └─── skprompt.txt

模板文件由 config.json 和 skprompt.txt 组成,skprompt.txt 中配置提示词,跟 PromptTemplateConfig 的 Template 字段配置一致。

config.json 中涉及的内容比较多,你可以对照下面的 json 跟 实现总结 一节的代码,两者几乎是一模一样的。

{ "schema": 1, "type": "completion", "description": "给出一段对话记录,总结这部分对话", "execution_settings": { "default": { "max_tokens": 1000, "temperature": 0 }, "gpt-3.5-turbo": { "model_id": "gpt-3.5-turbo-0613", "max_tokens": 4000, "temperature": 0.1 }, "gpt-4": { "model_id": "gpt-4-1106-preview", "max_tokens": 8000, "temperature": 0.3 } }, "input_variables": [ { "name": "request", "description": "用户的问题.", "required": true }, { "name": "history", "description": "用户的问题.", "required": true } ] }
http://www.cnnetsun.cn/news/3097363.html

相关文章:

  • 云康e家最新消息,资金减损核定方案公布。
  • 异步方法调用详解
  • 零食生产线爬坡转弯输送系统(双爬坡机+转弯机)选型指南
  • 透明质酸敷料批发商实力之选:四川昂宇医疗器械有限公司深度解析
  • WinBtrfs完全指南:在Windows系统上无缝访问Linux Btrfs文件系统
  • 九年深耕亚克力,以匠心方寸,承载世界赛事的荣光
  • 【安全月报】| 6 月加密货币领域因安全事件损失约 8173 万美元
  • 深度学习图像数据集构建:从采集到标注的工程化实践
  • 自编码器驱动的图像标注:构建可解释、可演化的标注先验引擎
  • 公证亲属关系需要多少钱?公证亲属关系办理时长?
  • 三、本次入侵需要带来启示的点
  • Web渗透测试“一课一得”——从信息收集到漏洞利用的实战总结
  • 豆包怎么生成 Word 文档?Markdown 转 docx、表格和公式处理思路
  • docker~BuildKit的介绍
  • 锂离子电池保护电路设计:BQ29200与STM32实战解析
  • 计算机毕业设计之基于大数据加护的国产美妆行业发展状况研究
  • AI芯片吃电太猛?横向供电扛不住了,VPD垂直供电来了
  • AI 自动写作覆盖自媒体,四成团队已落地流程
  • 《AJRCCM》(IF: 21.7)|空间单细胞蛋白组揭示EGFR/KRAS突变特异的免疫生态位与NSCLC预后标志物
  • 然后用上面的API测试数据运行下看下效果,发现构建出来的树完全符合我们的预期:
  • Java中String.valueOf(null)的惊天大坑:对比两个数时,日志打印的两数都是null,但Objects.equals()返回false!
  • 2026年想在常州买靠谱二手车?这些门道你不可不知!
  • 5分钟快速上手:终极免费Chrome视频下载插件完整指南
  • 06 — 接口层架构与实现
  • 场外衍生品的详细解读:从产品结构到业务流程,一文看懂核心逻辑
  • KMR221与PIC32MZ的高精度电压监测方案解析
  • 程序员不想只靠死工资增收!盘点 5 类适合技术人深耕的优质副业,闲暇时间额外增加收入
  • JMeter性能测试实战:精准测量QPS、TPS与吞吐量的完整指南
  • 信创系统修复合集①:统信UOS竟然自带系统修复工具
  • PostgreSQL pg_dump工具存在安全漏洞,可导致源数据库服务器的超级用户在客户端执行psql恢复操作时,触发任意代码执行HGVE-2025-E007