Semantic Kernel 函数与内核结果类型演进:从 SKContext 到 FunctionResult / KernelResult 的设计解析与实践指南

发布时间:2026/9/11 5:30:25

Semantic Kernel 函数与内核结果类型演进:从 SKContext 到 FunctionResult / KernelResult 的设计解析与实践指南 Semantic Kernel 函数与内核结果类型演进从 SKContext 到 FunctionResult / KernelResult 的设计解析与实践指南【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel导读本文基于 Semantic Kernel 仓库中的架构决策记录 ADR 0011Replace SKContext as Function/Kernel result type with FunctionResult and KernelResult models系统梳理 .NET 版 Semantic Kernel 将函数调用与内核执行的结果类型从SKContext迁移到FunctionResult/KernelResult的完整设计脉络。你将理解为什么需要这两个新类型、object Value与泛型GetValueT如何支撑复杂类型与流式返回、Metadata如何携带执行元数据以及如何从FunctionResults集合中精准定位流水线中任意函数的结果。文中所有示例均以当前仓库中 FunctionResult.cs 的真实实现为基准可直接对照使用。一、背景为什么SKContext不再适合作为结果类型在引入FunctionResult/KernelResult之前function.InvokeAsync与kernel.RunAsync都以SKContext作为返回类型。该架构决策记录0011-function-and-kernel-result-types.md指出了四个核心问题无法返回复杂类型SKContext的Result属性是string任何非字符串的返回都被迫序列化为文本更谈不上支持流式streaming能力。耦合了 LLM 专属逻辑SKContext中的ModelResults属性与具体模型响应强绑定仅对部分场景下的语义函数适用无法作为通用的结果载体。职责错位SKContext本质上是流水线内部在多个函数之间传递信息的机制不应暴露给调用方。调用 Kernel 的人应该给输入、拿结果而不是拿到一个内部上下文对象。缺少流水线细粒度信息SKContext只携带最后一次执行的函数相关信息无法回答流水线中某个特定函数到底返回了什么、表现如何。这四个痛点共同指向一个结论结果类型必须与内部上下文机制解耦。二、决策驱动与备选方案决策驱动该 ADR 明确了五项决策驱动因素成为后续设计的验收标准Kernel 应能返回复杂类型同时支持流式能力Kernel 应能以不耦合 AI 逻辑的方式返回函数执行数据例如 token 用量SKContext退居为函数之间传递信息的内部机制由于函数结果与内核结果本质不同、未来可能承载不同的属性集合二者应可区分调用方应能访问流水线中间某个特定函数的结果从而洞察每个函数的执行表现。备选方案对比方案说明结论使用dynamic作为返回类型提供一定灵活性但破坏 .NET 世界推崇的强类型且无法区分函数结果与内核结果被否决定义新类型FunctionResult与KernelResult保持强类型语义清晰两种结果各自演进被采纳最终决策是新建FunctionResult与KernelResult两个返回类型覆盖复杂类型返回、流式支持以及按函数分别访问结果的能力。三、核心设计object Value 泛型GetValueT设计思想FunctionResult中用object Value存放单个函数的结果KernelResult中用object Value存放执行流水线中最后一个函数的结果。为了让调用方以强类型方式取回数据两个类型都提供泛型方法GetValueT将object Value安全地转型为目标类型。当前仓库中FunctionResult的实现保留了这一设计骨架并做了一处值得注意的演进Value属性被标记为internal见 FunctionResult.cs外部代码统一通过GetValueT()访问进一步强化了类型安全的访问入口。基础用法示例以下是 ADR 文档中的原始示例展示了字符串、复杂类型与流式三种场景// string var text (await kernel.RunAsync(function)).GetValuestring(); // complex type var myComplexType (await kernel.RunAsync(function)).GetValueMyComplexType(); // streaming var results (await kernel.RunAsync(function)).GetValueIAsyncEnumerableint(); await foreach (var result in results) { Console.WriteLine(result); }在当前仓库 API 形态下Kernel.RunAsync已演进为Kernel.InvokeAsync返回TaskFunctionResult见 Kernel.cs同样语义的代码可写为// 单函数调用直接返回 FunctionResult FunctionResult result await kernel.InvokeAsync(function); // string var text result.GetValuestring(); // complex type var myComplexType result.GetValueMyComplexType();单元测试 KernelTests.cs 给出了最朴素的验证路径var function KernelFunctionFactory.CreateFromMethod(() Result, Function1); var result await kernel.InvokeAsync(function); Assert.NotNull(result); Assert.Equal(Result, result.GetValuestring());转型失败时的行为设计文档明确规定当FunctionResult/KernelResult中存的是TypeA而调用方试图转型为TypeB时应抛出携带类型明细的InvalidCastException帮助调用方快速定位应当使用的目标类型。当前实现中这一契约被完整保留且转换逻辑大幅增强——GetValueT()不止做简单强转还内置了对KernelContent、ChatMessageContent列表、Microsoft.Extensions.AI.ChatResponse等聊天内容类型的自动转换分支例如Value为ChatMessageContent且目标为string时返回其ToString()Value为IReadOnlyListChatMessageContent且目标为ChatResponse/ChatMessage时自动取首条消息转换当目标类型不可转换时统一抛出InvalidCastException($Cannot cast {this.Value.GetType()} to {typeof(T)})FunctionResult.cs。从源码结构看这些分支主要是为了在向Microsoft.Extensions.AI抽象迁移的过渡期保持与既有KernelContent代码的兼容FunctionResult.cs属于实现细节层面的自然演化。四、元数据Metadata属性设计初衷为了让调用方了解函数执行得怎么样FunctionResult增加了Dictionarystring, object Metadata属性用于携带任何执行相关信息例如 token 用量、模型响应等且不依赖具体 AI 提供方。当前实现在 FunctionResult.cs 中Metadata的实际类型是IReadOnlyDictionarystring, object??可通过构造函数以可选参数注入FunctionResult.cspublic FunctionResult( KernelFunction function, object? value null, CultureInfo? culture null, IReadOnlyDictionarystring, object?? metadata null)ADR 文档中的原始访问示例var functionResult await function.InvokeAsync(context); Console.WriteLine(functionResult.Metadata[MyInfo]);当前仓库中原生函数返回带元数据结果的典型写法见测试 FunctionFromMethodTests.csvar kernel new Kernel(); var sut KernelFunctionFactory.CreateFromMethod((KernelFunction func) { return new FunctionResult(func, Full content result, metadata: new Dictionarystring, object?() { { key1, value1 }, { key2, value2 }, }); }); var result await sut.InvokeAsync(kernel); Assert.Equal(value1, result.Metadata[key1]); Assert.Equal(value2, result.Metadata[key2]);该测试还验证了一个细节原生函数返回的FunctionResult元数据在流式调用InvokeStreamingAsync时也会被传播到StreamingMethodContent.Metadata上说明Metadata并不局限于一次性调用而是贯穿同步/流式两种执行路径。其他附带属性除了Value、Metadata之外FunctionResult当前还包含以下成员可作为排障与观测的补充信息Function产生该结果的KernelFunction实例FunctionResult.csCulture执行该函数的 Kernel 所配置的文化信息默认CultureInfo.InvariantCultureFunctionResult.csValueTypeValue的实际运行时类型FunctionResult.csRenderedPrompt函数调用时实际渲染出的提示词文本FunctionResult.cs对排查提示词工程问题非常有用。五、多函数结果KernelResult.FunctionResults设计目标KernelResult包含IReadOnlyCollectionFunctionResult FunctionResults用于保留流水线中每个函数各自的结果同时FunctionResult上提供FunctionName与PluginName属性方便调用方从集合中按名字精确取回指定函数的结果。ADR 文档给出的示例var kernelResult await kernel.RunAsync(function1, function2, function3); var functionResult2 kernelResult.FunctionResults.First(l l.FunctionName Function2 l.PluginName MyPlugin); Assert.Equal(Result2, functionResult2.GetValuestring());在仓库中的对应物从当前源码结构看KernelFunction正是通过Name与PluginName提供这两个标识的PluginName默认可从函数元数据中读取KernelFunction.csName则由每个函数实现KernelFunction.cs且ToString()会输出PluginName.Name的完整形态KernelFunction.cs。这意味着调用方不仅能拿到流水线最后一个结果还能逐个审视每个函数产出了什么、占用了多少资源这正是 ADR 决策驱动中访问流水线中间函数结果诉求的直接体现。六、该决策对当前代码库的落地情况该 ADR2023-09-21 提出状态 accepteddeciders 为 shawncal 与 dmytrostruk的核心理念在当前代码库中已被完整吸收并持续演进FunctionResult已成为唯一标准结果类型KernelFunction.InvokeAsync返回TaskFunctionResultKernelFunction.csKernel.InvokeAsync两个重载同样返回TaskFunctionResultKernel.cs流式能力独立成通道Kernel.InvokeStreamingAsync返回IAsyncEnumerableStreamingKernelContentKernel.cs与 ADR 中支持流式的目标一脉相承内部上下文彻底退居幕后SKContext不再出现在对外返回类型中函数间信息传递由内部机制承担调用方只与FunctionResult交互测试充分覆盖单元测试对GetValueT、Metadata、多插件导入与调用等行为均有断言KernelTests.cs、FunctionFromMethodTests.cs可作为阅读实现与验证行为的参考入口。七、实践小结围绕如何正确消费函数执行结果可以总结出以下可直接落地的要点统一走GetValueT()无论目标是string、自定义复杂类型还是聊天内容类型都以泛型方式取回避免直接触碰内部Value利用Metadata观测执行细节在原生函数中通过构造函数注入metadata字典即可让调用方读取 token 用量、模型响应等自定义信息且该信息在流式路径同样可用按需精确取结果多函数流水线场景下通过FunctionResults结合FunctionName/PluginName定位特定函数的结果而不是只依赖最后一个返回值把SKContext留给内部对外 API 一律面向FunctionResult设计保持输入-输出模型的清晰与强类型化。参考资源架构决策记录docs/decisions/0011-function-and-kernel-result-types.md结果类型实现dotnet/src/SemanticKernel.Abstractions/Functions/FunctionResult.cs调用入口dotnet/src/SemanticKernel.Abstractions/Kernel.cs函数抽象dotnet/src/SemanticKernel.Abstractions/Functions/KernelFunction.cs行为验证测试dotnet/src/SemanticKernel.UnitTests/KernelTests.cs、dotnet/src/SemanticKernel.UnitTests/Functions/FunctionFromMethodTests.cs【免费下载链接】semantic-kernelIntegrate cutting-edge LLM technology quickly and easily into your apps项目地址: https://gitcode.com/GitHub_Trending/se/semantic-kernel创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/11 5:25:25

RVM多输入多输出回归:贝叶斯稀疏建模与不确定性量化

简介:本资源是一套基于MATLAB实现的相关向量机(RVM)多输入多输出(MIMO)回归建模方案,面向本科及以上层次的机器学习初学者、统计建模研究者及工程实践人员,适用于小样本非线性系统建模、传感器融…

2026/9/11 5:25:25

国产芯片替代实测:ST/TI/NXP对标验证与工程落地避坑指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 5:25:25

跨境电商动态定价系统:实时监控与利润优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 10:16:29

ML-KWS-for-MCU源码深度评测:边缘AI关键词唤醒在Cortex-M上的实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/11 10:16:28

51单片机+DS18B20+LabVIEW温度采集与上位机显示全攻略

简介:面向51单片机初学者、嵌入式爱好者以及LabVIEW上位机开发者,这份资源提供了一套基于STC单片机与DS18B20传感器的环境温度采集及上位机显示方案,解决从底层驱动、串口通信到上位机实时监测与数据存储的完整联动问题。压缩包内共2个文件&a…

2026/9/11 10:16:28

Context-Mode:智能体上下文调度引擎实战指南

1. 项目概述:Context-Mode 不是玄学,而是现代智能体系统里最务实的“上下文调度引擎” “context-mode”这个词最近在开发者社区里频繁冒头,尤其和 MCP、SQLite、FTS5、BM25 这几个词绑在一起出现——它既不是某个开源项目的官方命名&#xf…

2026/9/11 10:16:28

PoolFormer:用池化替代注意力的轻量图像分类模型

简介:本资源是一份基于PoolFormer架构的图像分类实战项目包,面向深度学习初学者与计算机视觉方向实践者,帮助快速掌握MetaFormer系列模型的核心思想与工程实现。资源完整复现了PoolFormer论文中以池化操作替代注意力机制的轻量级建模思路&…

2026/9/11 10:11:27

GPT-4o工具调用实战:构建可中断、可修正的智能体工作流

我不能按照您的要求生成关于“GPT-6 Astra”的博文内容。原因如下:事实层面严重失实:截至2024年7月,OpenAI 官方从未发布、命名或确认存在名为“GPT-6”或“Astra”的模型。所有公开信息显示,OpenAI 当前最新发布的旗舰模型为GPT-…

2026/9/10 16:39:38

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/10 11:16:38

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 12:32:02

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/10 15:19:50

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/10 15:49:53

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码