news 2026/9/12 3:33:54

Semantic Kernel 官方文档示例库(LearnResources)实战指南:从密钥配置到示例运行

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Semantic Kernel 官方文档示例库(LearnResources)实战指南:从密钥配置到示例运行

Semantic Kernel 官方文档示例库(LearnResources)实战指南:从密钥配置到示例运行

【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel

本文以 Semantic Kernel .NET 仓库中的 dotnet/samples/LearnResources 项目为主线,系统讲解这套与 Microsoft Learn 在线文档一一对应的代码示例工程的用途、目录结构、密钥配置与运行方式,并深入剖析 Kernel 创建、AI 服务接入、原生函数、提示词工程、模板化与提示词序列化等核心示例的源码实现。读完本文,你将掌握如何在本仓库中快速定位、配置并运行官方文档配套示例,为学习 Semantic Kernel 提供可复现的实操环境。

一、项目定位:与官方文档配套的"可运行代码片段库"

LearnResources是 Semantic Kernel .NET 仓库中专门存放与在线文档来源(如 Microsoft Learn、DevBlogs 等)配套代码片段的示例工程。其核心思想是:文档中的每一段关键代码,都以可编译、可运行、可测试的完整示例形式沉淀在仓库中,让读者不必在文档与 IDE 之间来回切换,直接运行即得结果。

从仓库结构看,该项目主要包含三个子目录(详见 dotnet/samples/LearnResources/README.md):

子目录说明
MicrosoftLearn与 Microsoft Learn Docs 配套的代码片段(即本文主角)
Plugins示例运行所需的插件资源,包括GitHubOrchestratorPluginPromptsWriterPlugin
Resources示例使用的数据与提示词资源(文本、CSV、YAML 等)

其中MicrosoftLearn子目录下存放了 8 个与 Learn 文档章节一一对应的示例类,每个类的注释都明确标注了对应的在线文档主题,例如:

  • UsingTheKernel.cs—— 对应"Kernel 入门"章节;
  • AIServices.cs—— 对应"为 Kernel 添加 AI 服务"章节;
  • CreatingFunctions.cs—— 对应"使用 KernelFunction 装饰器创建原生函数"章节;
  • Prompts.csConfiguringPrompts.csTemplates.csFunctionsWithinPrompts.csSerializingPrompts.cs—— 对应提示词(Prompt)系列章节。

这些示例文件头部均以/// <summary>注释的形式保留 Learn 文档 URL(如https://learn.microsoft.com/semantic-kernel/agents/kernel),便于读者回查原文。

二、工程结构:一个以测试形态组织的示例库

与普通控制台示例不同,LearnResources被组织为一个 xUnit 测试项目。在 dotnet/samples/LearnResources/LearnResources.csproj 中可以看到:

  • <IsTestProject>true</IsTestProject>:声明为测试项目,示例全部以[Fact]测试方法的形式存在;
  • <TargetFramework>net10.0</TargetFramework>:目标框架为 .NET 10;
  • <UserSecretsId>5ee045b0-aea3-4f08-8d31-32d1a6f8fed0</UserSecretsId>:通过 .NET Secret Manager 管理密钥;
  • 项目引用(ProjectReference)了Connectors.AzureOpenAIConnectors.OpenAIPromptTemplates.HandlebarsFunctions.YamlPlugins.CorePlugins.MemoryFunctions.OpenApi等核心组件,因此这些示例几乎覆盖了 Semantic Kernel 的主要能力面。

这种"测试即示例"的组织方式带来一个直接好处:可以通过dotnet test --filter精确筛选运行任意一个示例(详见 README 的 "Running Examples with Filters" 一节)。示例之间的控制台输入则通过LearnBaseTest基类中的SimulatedInputText列表模拟,避免交互式示例在测试环境下卡死(见 LearnBaseTest.cs)。

三、配置密钥:运行示例的前置条件

README 明确指出:大多数示例都需要访问 OpenAI、Azure OpenAI 等服务的密钥与凭据,并强烈建议使用 .NETSecret Managerdotnet user-secrets)来避免把密钥泄露进仓库、分支和 Pull Request;当然也可以改用环境变量。README 还特别说明:本项目与KernelSyntaxExamples(旧示例库)共用同一套密钥池。

3.1 使用 Secret Manager 配置

按 README 给出的命令,进入项目目录并初始化用户机密,然后逐项写入 OpenAI 与 Azure OpenAI 的配置:

cd dotnet/samples/DocumentationExamples dotnet user-secrets init dotnet user-secrets set "OpenAI:ModelId" "..." dotnet user-secrets set "OpenAI:ChatModelId" "..." dotnet user-secrets set "OpenAI:EmbeddingModelId" "..." dotnet user-secrets set "OpenAI:ApiKey" "..." dotnet user-secrets set "AzureOpenAI:ServiceId" "..." dotnet user-secrets set "AzureOpenAI:DeploymentName" "..." dotnet user-secrets set "AzureOpenAI:ModelId" "..." dotnet user-secrets set "AzureOpenAI:ChatDeploymentName" "..." dotnet user-secrets set "AzureOpenAI:ChatModelId" "..." dotnet user-secrets set "AzureOpenAI:Endpoint" "https://... .openai.azure.com/" dotnet user-secrets set "AzureOpenAI:ApiKey" "..."

两点需要结合当前仓库说明:

  1. 目录名注意:README 中沿用了旧的项目目录名DocumentationExamples;在当前仓库中,该项目实际位于 dotnet/samples/LearnResources,因此实际执行时应使用:
cd dotnet/samples/LearnResources dotnet user-secrets init
  1. UserSecretsId已在 LearnResources.csproj 中预设(5ee045b0-aea3-4f08-8d31-32d1a6f8fed0),dotnet user-secrets init后配置即写入~/.microsoft/usersecrets/5ee045b0-aea3-4f08-8d31-32d1a6f8fed0/secrets.json,示例中的TestConfiguration读取层会自动通过Microsoft.Extensions.Configuration.UserSecrets(已在 csproj 中引用)加载这些值。

3.2 使用环境变量配置

若偏好环境变量方式,使用以下名称(注意__双下划线是 .NET 配置系统环境变量分隔符的标准写法,与 Secret Manager 的:分层等价):

# OpenAI OpenAI__ModelId OpenAI__ChatModelId OpenAI__EmbeddingModelId OpenAI__ApiKey # Azure OpenAI AzureOpenAI__ServiceId AzureOpenAI__DeploymentName AzureOpenAI__ChatDeploymentName AzureOpenAI__Endpoint AzureOpenAI__ApiKey

对比可见:环境变量清单省略了AzureOpenAI__ModelIdAzureOpenAI__ChatModelId两项,因为这两个值通常与部署名一致,而 Secret Manager 版本保留了它们以提供更大灵活性;两种方式的其余键一一对应。

3.3 凭据缺失时的优雅降级

示例代码对"未配置凭据"做了友好处理。以 UsingTheKernel.cs 为例,示例先从TestConfiguration读取EndpointChatModelIdApiKey,若任一为空则打印"Azure OpenAI credentials not found. Skipping example."并直接返回。这意味着即便不配置任何密钥,也可以编译并跑通测试框架,只是示例会被跳过——这对 CI 环境尤为友好。

四、运行示例:dotnet test 与过滤器

README 给出的运行方式是使用测试过滤器

dotnet test --filter

更具体地,可以组合FullyQualifiedName或类名来运行单个示例,例如:

# 运行全部 Learn 示例 dotnet test dotnet/samples/LearnResources/LearnResources.csproj # 只运行 Kernel 入门示例 dotnet test dotnet/samples/LearnResources/LearnResources.csproj --filter "FullyQualifiedName~UsingTheKernel" # 只运行提示词示例 dotnet test dotnet/samples/LearnResources/LearnResources.csproj --filter "FullyQualifiedName~Prompts"

--filter的详细语法可通过dotnet test --help查看。由于每个示例都带有[Fact]标记且位于Examples命名空间(见 UsingTheKernel.cs),还可以用--filter "FullyQualifiedName~Examples"一次性运行该子目录下全部示例。

五、示例源码深度解读

以下按主题剖析MicrosoftLearn子目录下的 8 个示例,每个示例都与 Learn 文档章节一一对应,代码片段可对照仓库源码查看。

5.1 Kernel 基础:UsingTheKernel

对应文档主题:"Kernel 入门"。该示例演示了 Semantic Kernel 最核心的构建与调用链路(见 UsingTheKernel.cs):

var builder = Kernel.CreateBuilder() .AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey); builder.Services.AddLogging(c => c.AddDebug().SetMinimumLevel(LogLevel.Trace)); builder.Plugins.AddFromType<TimePlugin>(); builder.Plugins.AddFromPromptDirectory("./../../../Plugins/WriterPlugin"); Kernel kernel = builder.Build(); // 调用内置 TimePlugin 获取当前时间 var currentTime = await kernel.InvokeAsync("TimePlugin", "UtcNow"); // 将当前时间作为输入,调用 WriterPlugin 的 ShortPoem 函数写诗 var poemResult = await kernel.InvokeAsync("WriterPlugin", "ShortPoem", new() { { "input", currentTime } });

关键点解读:

  • Kernel.CreateBuilder()返回构建器,AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey)注册聊天补全服务;
  • 通过builder.Services.AddLogging(...)直接向内核的 DI 容器注册调试日志,日志级别设为Trace
  • 插件注册的两种方式同时出现:AddFromType<TimePlugin>()从类型反射注册(TimePlugin来自 Plugins.Core),AddFromPromptDirectory("./../../../Plugins/WriterPlugin")从目录加载提示词插件(该目录含config.jsonskprompt.txt);
  • 调用形式kernel.InvokeAsync("PluginName", "FunctionName", arguments)是 Semantic Kernel 中按名称调用插件函数的经典写法,返回值FunctionResult可直接Console.WriteLine输出。

5.2 接入 AI 服务:AIServices

对应文档主题:"为 Kernel 添加服务"。示例对比了 Azure OpenAI 与标准 OpenAI 两种接入方式(见 AIServices.cs):

// Azure OpenAI 方式 Kernel kernel = Kernel.CreateBuilder() .AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey) .Build(); // 标准 OpenAI 方式 kernel = Kernel.CreateBuilder() .AddOpenAIChatCompletion(openAImodelId, openAIapiKey) .Build();

值得注意的实现细节:示例从TestConfiguration分别读取 Azure OpenAI 与 OpenAI 两套凭据(TestConfiguration.OpenAI.ChatModelId/TestConfiguration.AzureOpenAI.ChatModelId等),且对两套凭据分别做了空值检查并独立跳过。这表明运行本项目时只需配置其中一家服务即可,不必同时准备两家密钥。

5.3 创建原生函数:CreatingFunctions 与 MathPlugin

对应文档主题:"使用 KernelFunction 装饰器创建原生函数"。这是理解 Semantic Kernel 插件体系的关键示例(见 CreatingFunctions.cs):

var builder = Kernel.CreateBuilder() .AddAzureOpenAIChatCompletion(modelId, endpoint, apiKey); builder.Plugins.AddFromType<MathPlugin>(); Kernel kernel = builder.Build(); // 直接调用 MathPlugin.Sqrt double answer = await kernel.InvokeAsync<double>( "MathPlugin", "Sqrt", new() { { "number1", 12 } }); Console.WriteLine($"The square root of 12 is {answer}.");

配套的 MathPlugin.cs 展示了原生函数的完整写法:用[KernelFunction]标记可被 AI 调用的方法,用[Description]提供函数与参数的语义描述。该插件共实现了 15 个数学函数:SqrtAddSubtractMultiplyDividePowerLogRoundAbsFloorCeiling以及三角函数族Sin/Cos/Tan/Asin/Acos/Atan,每个函数的参数都带[Description]说明(如Multiply的注释特别提醒"按百分比增加时不要忘记加 1")。这些描述会作为元数据供 LLM 在函数调用(Function Calling)时理解并使用。

示例后半部分演示了更进阶的用法:构建ChatHistory后,通过FunctionChoiceBehavior.Auto()开启自动函数调用,并借助GetStreamingChatMessageContentsAsync流式返回结果,将用户输入、AI 回复逐条写入历史,实现完整的对话循环(见 CreatingFunctions.cs)。

5.4 提示词工程:Prompts

对应文档主题:"你的第一个提示词"。该示例(Prompts.cs)以"识别用户请求意图"为场景,用7 个递进版本完整演示了提示词工程的演进路径,是本文档库中信息密度最高的示例:

  • 0.0 初始提示词$"What is the intent of this request? {request}",直接拼接,最朴素;
  • 1.0 更具体:追加可选意图列表SendEmail, SendMessage, CompleteTask, CreateDocument,约束输出空间;
  • 2.0 输出结构化:引入Instructions / Choices / User Input / Intent:固定格式,引导模型按结构作答;
  • 2.1 Markdown + JSON 格式化:用$$"""..."""原始字符串构造带json代码块的提示词,要求模型返回{"intent": ...}结构,其中{{request}}通过模板插值注入用户输入;
  • 3.0 Few-shot 少样本:在提示词中给出两条"用户输入 → Intent"示例,让模型模仿作答;
  • 4.0 约束失败行为:增加If you don't know the intent, don't guess; instead respond with "Unknown",并将Unknown加入候选列表,避免模型胡猜;
  • 5.0 提供上下文:在提示词中注入一段对话历史(用户抱怨邮件没人读、AI 建议改用消息),提升意图判断的准确性;
  • 6.0 使用消息角色:改用<message role="system/user/assistant">标签组织提示词,贴合聊天补全模型的多角色输入习惯;
  • 7.0 鼓励词:在 system 消息中追加Bonus: You'll get $20 if you get this right.,演示激励措辞对输出质量的影响。

所有版本均通过kernel.InvokePromptAsync(prompt)执行,读者可以直接注释切换不同阶段对比输出差异。

5.5 配置提示词:ConfiguringPrompts

对应文档主题:"配置提示词"。示例(ConfiguringPrompts.cs)演示如何用PromptTemplateConfig以编程方式创建带完整配置的提示词函数,其中ExecutionSettings按服务 ID 分别指定了defaultgpt-3.5-turbogpt-4三套执行设置:

var chat = kernel.CreateFunctionFromPrompt( new PromptTemplateConfig() { Name = "Chat", Description = "Chat with the assistant.", Template = @"{{ConversationSummaryPlugin.SummarizeConversation $history}} User: {{$request}} Assistant: ", TemplateFormat = "semantic-kernel", InputVariables = [ new() { Name = "history", Description = "The history of the conversation.", IsRequired = false, Default = "" }, new() { Name = "request", Description = "The user's request.", IsRequired = true } ], ExecutionSettings = { { "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 } } } } );

这里的信息量值得展开:

  • InputVariables声明了模板变量:history可选(IsRequired = false,默认空字符串),request必填(IsRequired = true);
  • ExecutionSettings的本质是"服务 ID → 执行参数"的映射:default键被所有服务采用;gpt-3.5-turbogpt-4键则通过ModelId将特定提示词路由到指定模型,MaxTokensTemperature逐模型差异化配置;
  • 模板中调用了ConversationSummaryPlugin.SummarizeConversation $history,即先对历史对话做摘要再拼接用户请求(ConversationSummaryPlugin同样来自 Plugins.Core)。

同样的多服务配置也可以纯声明式地写在config.json中——仓库中的 chat/config.json 正是该配置的 JSON 版本(schema 1、类型completionexecution_settingsdefault/gpt-3.5-turbo/gpt-4三档、input_variables声明requesthistory),对应的提示词模板在 chat/skprompt.txt,两文件配套构成一个完整的语义函数插件目录。

5.6 模板化提示词:Templates

对应文档主题:"提示词模板化"。示例(Templates.cs)展示了 Semantic Kernel 的两种模板引擎的混用:

  • 默认 semantic-kernel 模板@$"{history} User: {request} Assistant: "` 风格的简单占位符模板,用于聊天回复;
  • Handlebars 模板:通过HandlebarsPromptTemplateFactory配合TemplateFormat = "handlebars"创建意图识别函数,模板中使用了{{choices.[0]}}(数组取首元素)、{{#each fewShotExamples}}(遍历少样本)、{{#each this}}(嵌套遍历 ChatMessageContent 的role/content)等 Handlebars 控制结构。

聊天循环中,先用getIntent判断用户意图,命中EndConversation即退出循环,否则调用chat函数流式生成回复并写入ChatHistory。整个循环完整展示了"意图路由 + 流式对话"的 Agent 雏形。

5.7 在提示词中调用函数:FunctionsWithinPrompts

对应文档主题:"在提示词中调用嵌套函数"。这是对 5.5/5.6 的进阶(见 FunctionsWithinPrompts.cs):在模板内部直接调用其他 Kernel 函数。两种引擎各演示一次:

// Handlebars 模板内调用:连字符分隔插件名与函数名 {{ConversationSummaryPlugin-SummarizeConversation history}} // Semantic Kernel 模板内调用:点号分隔 var chat = kernel.CreateFunctionFromPrompt( @"{{ConversationSummaryPlugin.SummarizeConversation $history}} User: {{$request}} Assistant: " );

注意两种语法差异:Handlebar 模板使用PluginName-FunctionName(连字符),而默认 semantic-kernel 模板使用PluginName.FunctionName(点号)且变量带$前缀。ConversationSummaryPlugin先对history做摘要再进入提示词,能有效控制上下文长度——这正是"提示词中调用函数"的核心价值:让数据在进入 LLM 前先经过本地函数的加工

5.8 序列化提示词:SerializingPrompts

对应文档主题:"将提示词保存为文件"。示例(SerializingPrompts.cs)演示从两种文件形态加载提示词:

// 1. 从插件目录加载(config.json + skprompt.txt 对) var prompts = kernel.CreatePluginFromPromptDirectory("./../../../Plugins/Prompts"); // 2. 从内嵌 YAML 资源加载(配合 Handlebars 工厂) using StreamReader reader = new(Assembly.GetExecutingAssembly() .GetManifestResourceStream("Resources.getIntent.prompt.yaml")!); KernelFunction getIntent = kernel.CreateFunctionFromPromptYaml( await reader.ReadToEndAsync(), promptTemplateFactory: new HandlebarsPromptTemplateFactory() );

对应的 YAML 文件是 Resources/getIntent.prompt.yaml,它把 5.6 中 Handlebars 模板的"意图识别函数"完整声明化:name: getIntentdescriptiontemplate(含 few-shot 遍历与ConversationSummaryPlugin.SummarizeConversation history调用)、template_format: handlebarsinput_variableschoices带默认值、fewShotExamplesrequest必填)、execution_settingsdefault/gpt-3.5-turbo/gpt-4三档,max_tokens: 10、低温度)。该 YAML 通过 LearnResources.csproj 以EmbeddedResource方式随程序集发布,运行时用GetManifestResourceStream读取。

随后示例构建fewShotExamples(两个ChatHistory,分别映射到ContinueConversationEndConversation),在聊天循环中先解析意图,命中EndConversation即结束,否则调用prompts["chat"]流式回复——整个"意图识别 + 对话生成"流程完全由文件化提示词驱动。

六、测试基础设施:LearnBaseTest 如何支撑交互式示例

多个示例包含Console.ReadLine()交互循环(如CreatingFunctionsConfiguringPromptsTemplates等)。为避免测试挂起,基类 LearnBaseTest.cs 通过构造参数注入预置输入:

public class CreatingFunctions(ITestOutputHelper output) : LearnBaseTest(["What is 49 diivided by 37?"], output) // 模拟用户输入

基类内部维护SimulatedInputText列表与游标SimulatedInputTextIndexReadLine()依次返回预置字符串(用尽后返回null结束循环)。扩展方法BaseTestExtensions.ReadLine(this BaseTest)则让示例代码能够以ReadLine()的方式透明调用。这解释了为什么示例代码可以同时服务于"人工交互运行"与"自动化测试"两种场景:人工运行时Console.ReadLine()生效,测试运行时由模拟输入接管。

七、资源与辅助插件

示例运行还依赖以下资源(均在 dotnet/samples/LearnResources/Resources 下):

  • 三个格林童话英文文本(Grimms-The-King-of-the-Golden-Mountain.txtGrimms-The-Water-of-Life.txtGrimms-The-White-Snake.txt),供记忆/文本处理类示例取用;
  • 两份人口统计 CSV(PopulationByAdmin1.csvPopulationByCountry.csv),供结构化数据处理示例使用;
  • 女性选举权历史文本WomensSuffrage.txt
  • 意图识别提示词 YAML(getIntent.prompt.yaml)。

插件目录 Plugins 下还包含:GitHub(含GitHubModels.csGitHubPlugin.cs,演示 GitHub 数据接入)、OrchestratorPlugin/GetIntent(含config.jsonskprompt.txt,目录式提示词插件的又一实例)、WriterPlugin/ShortPoemMathPlugin.cs

八、小结:一条从文档到代码的完整学习路径

LearnResources的价值在于将 Microsoft Learn 上的 Semantic Kernel 教程转译为可编译、可过滤、可单独运行的测试用例。建议的学习路径是:

  1. 按第三节配置好 OpenAI 或 Azure OpenAI 密钥(Secret Manager 或环境变量二选一);
  2. dotnet test --filter按需运行示例,从UsingTheKernel入门;
  3. 对照 Prompts.cs 的 7 个递进版本理解提示词工程,再依次阅读ConfiguringPrompts(配置化)、Templates(模板化)、FunctionsWithinPrompts(函数内嵌)、SerializingPrompts(文件化);
  4. 将示例中的PromptTemplateConfig、Handlebars 模板与 getIntent.prompt.yaml 等文件对比学习,即可掌握 Semantic Kernel 提示词体系从"代码内联"到"声明式文件"的完整形态。

这套示例同时是很好的测试脚手架:由于它复用了xunitxRetry与 Semantic Kernel 各核心包(见 LearnResources.csproj),开发者可以在此基础上扩展自己的提示词与插件用例,形成可持续回归验证的 AI 应用测试集。

【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

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

Wand-Enhancer:5分钟本地解锁Wand全部高级功能,免费

Wand-Enhancer&#xff1a;5分钟本地解锁Wand全部高级功能&#xff0c;免费 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer是一个完…

作者头像 李华
网站建设 2026/9/12 3:32:39

VMware虚拟机硬件指纹收敛与鲁大师检测规避指南

1. 项目本质与真实场景还原&#xff1a;这不是“绕过检测”&#xff0c;而是理解虚拟环境与硬件指纹的博弈逻辑“虚拟机基础篇-过鲁大师检测”这个标题&#xff0c;表面看像是一条技术捷径&#xff0c;实则背后藏着一个被大量新手误读的核心矛盾&#xff1a;鲁大师不是在“检测…

作者头像 李华