首页
/ AutoGen.SemanticKernel 实战:用 SemanticKernelChatCompletionAgent 将 Semantic Kernel 对话代理接入 AutoGen 消息体系

AutoGen.SemanticKernel 实战:用 SemanticKernelChatCompletionAgent 将 Semantic Kernel 对话代理接入 AutoGen 消息体系

2026-09-04 10:29:15作者:董斯意

本文以 AutoGen .NET 的 AutoGen.SemanticKernel 组件为主线,完整讲解如何用五步创建一个基于 Semantic Kernel ChatCompletionAgentSemanticKernelChatCompletionAgent,并与其进行对话。读完本文,你将掌握:Kernel 与 ChatCompletionAgent 的构建方式、SemanticKernelChatMessageContentConnector 中间件的作用机制,以及从源码层面理解 AutoGen 内置消息类型(TextMessageImageMessageMultiModalMessage)与 Semantic Kernel ChatMessageContent 之间的双向转换规则与限制边界。

一、为什么需要 SemanticKernelChatCompletionAgent

如果你已经在项目中使用了 Microsoft Semantic Kernel,并希望把它现有的 ChatCompletionAgent 直接纳入 AutoGen 的多代理编排(如 GroupChat、Orchestrator),AutoGen.SemanticKernel 提供了内建支持:通过 SemanticKernelChatCompletionAgent 将 Semantic Kernel 的 ChatCompletionAgent 包装为 AutoGen 的 IAgent,从而复用 AutoGen 的消息、中间件与编排能力。

但有一个关键前提需要理解:默认情况下,SemanticKernelChatCompletionAgent 仅支持原始的 ChatMessageContent 类型,即要求消息为 IMessage<ChatMessageContent>。这一点从源码可以直接确认——在 SemanticKernelChatCompletionAgent.csProcessMessage 方法中,凡是不满足 IMessage<ChatMessageContent> 的消息都会被抛出 ArgumentException("Invalid message type")

private IEnumerable<ChatMessageContent> ProcessMessage(IEnumerable<IMessage> messages)
{
    return messages.Select(m => m switch
    {
        IMessage<ChatMessageContent> cmc => cmc.Content,
        _ => throw new ArgumentException("Invalid message type")
    });
}

因此,若要支持 AutoGen 的内置消息类型,如 TextMessageImageMessageMultiModalMessage,就需要把该代理注册到 SemanticKernelChatMessageContentConnector 之下。该 Connector 是一个中间件(同时实现 IMiddlewareIStreamingMiddleware),负责:

  • 在调用底层代理前,把 AutoGen 内置消息类型转换ChatMessageContent
  • 在收到回复后,把 ChatMessageContent 反向转换回 AutoGen 内置消息类型。

二、五步创建并对话 SemanticKernelChatCompletionAgent

完整的示例代码位于 Create_Semantic_Kernel_Chat_Agent.cs,以下按官方文档的步骤逐一拆解。

Step 1:添加 using 语句

using AutoGen.Core;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Agents;
  • AutoGen.Core 提供 IAgentTextMessageSendAsync/RegisterMiddleware 等扩展能力;
  • Microsoft.SemanticKernel 提供 Kernel 构建器与 ChatMessageContent
  • Microsoft.SemanticKernel.Agents 提供 Semantic Kernel 的 ChatCompletionAgent

Step 2:创建 Kernel

var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
var modelId = "gpt-3.5-turbo";
var kernel = Kernel.CreateBuilder()
    .AddOpenAIChatCompletion(modelId: modelId, apiKey: openAIKey)
    .Build();

示例从环境变量 OPENAI_API_KEY 读取密钥,并注册 gpt-3.5-turbo 作为 OpenAI 聊天模型。这里适用前提是已安装 Semantic Kernel 的 OpenAI 连接器包(Microsoft.SemanticKernel.Connectors.OpenAI)并设置好密钥环境变量;换用其他模型时,只需替换 AddXxxChatCompletion 对应的注册方法与 modelId

Step 3:创建 Semantic Kernel 的 ChatCompletionAgent

// The built-in ChatCompletionAgent from semantic kernel.
var chatAgent = new ChatCompletionAgent()
{
    Kernel = kernel,
    Name = "assistant",
    Description = "You are a helpful AI assistant",
};

注意 Name 并非可选装饰:从 SemanticKernelChatCompletionAgent.cs 的构造函数可以看到,若传入的 chatCompletionAgent.Name 为 null 会直接抛出 ArgumentNullException,因为包装后 AutoGen 侧的 Name 属性直接取自它:

public SemanticKernelChatCompletionAgent(ChatCompletionAgent chatCompletionAgent)
{
    this.Name = chatCompletionAgent.Name ?? throw new ArgumentNullException(nameof(chatCompletionAgent.Name));
    this._chatCompletionAgent = chatCompletionAgent;
}

Step 4:创建 SemanticKernelChatCompletionAgent 并注册消息 Connector

var messageConnector = new SemanticKernelChatMessageContentConnector();
var skAgent = new SemanticKernelChatCompletionAgent(chatAgent)
    .RegisterMiddleware(messageConnector) // register message connector so it support AutoGen built-in message types like TextMessage.
    .RegisterPrintMessage(); // pretty print the message to the console

这一步是本文的核心:

  • new SemanticKernelChatCompletionAgent(chatAgent) 完成包装;
  • .RegisterMiddleware(messageConnector) 注册 SemanticKernelChatMessageContentConnector,使代理能够收发 AutoGen 内置消息类型(如 TextMessage);
  • .RegisterPrintMessage() 是 AutoGen 的通用中间件,把消息以美观格式打印到控制台。

Step 5:与代理对话

await skAgent.SendAsync("Hey tell me a long tedious joke");

SendAsyncIAgent 扩展方法,会向该代理发送一条用户文本消息并等待回复。由于注册了 RegisterPrintMessage(),请求与回复都会打印到控制台。

三、源码级解析:GenerateReplyAsync 的实际调用链

包装代理的回复流程在 SemanticKernelChatCompletionAgent.cs 中一目了然:

public async Task<IMessage> GenerateReplyAsync(IEnumerable<IMessage> messages, GenerateReplyOptions? options = null,
    CancellationToken cancellationToken = default)
{
    var agentThread = new ChatHistoryAgentThread(BuildChatHistory(messages));
    var reply = await _chatCompletionAgent
        .InvokeAsync(agentThread, cancellationToken: cancellationToken)
        .ToArrayAsync(cancellationToken: cancellationToken);

    return reply.Length > 1
        ? throw new InvalidOperationException("ResultsPerPrompt greater than 1 is not supported in this semantic kernel agent")
        : new MessageEnvelope<ChatMessageContent>(reply[0], from: this.Name);
}

从源码结构看,有三点值得注意:

  1. 历史重建方式:每次调用都会把 AutoGen 传入的 messages 序列化为 Semantic Kernel 的 ChatHistory,再放入 ChatHistoryAgentThread 中驱动 InvokeAsync。也就是说,对话上下文由 AutoGen 侧的消息列表完整承载;
  2. 只支持单结果:若 Semantic Kernel 侧配置导致单次提示返回多于一条结果(即 ResultsPerPrompt > 1),会抛出 InvalidOperationException
  3. 回复类型固定:返回值始终是 MessageEnvelope<ChatMessageContent>From 为代理名。这也是为什么默认只能处理 IMessage<ChatMessageContent> 的根因——而 Connector 正是为打通这一类型边界而设计。

四、SemanticKernelChatMessageContentConnector 的转换规则详解

Connector 实现位于 SemanticKernelChatMessageContentConnector.cs。它同时实现 IMiddleware(非流式)与 IStreamingMiddleware(流式)两个接口,双向转换逻辑可以概括为:

入站方向(AutoGen 消息 → ChatMessageContent)

ProcessMessage 方法中,消息按来源分为两条路径(见 L111-L128):

消息来源 角色映射规则 说明
IMessage<ChatMessageContent> 直接透传 已经是 SK 原生类型,无需转换
来自代理自身(m.From == agent.Name System 保留为 System;其余映射为 Assistant 即"自己说过话"的文本被视为助手侧历史
来自其他方 System 保留为 SystemTextMessage 映射为 User 第三方文本一律视为用户侧输入

对图片类消息,ProcessMessageForOthers 要求 ImageMessage 必须携带 Url 或可构造的 DataUri,否则抛出 "ImageMessage must have Url or DataUri"(见 L181-L198)。

出站方向(ChatMessageContent → AutoGen 消息)

PostProcessMessage 中(见 L80-L99):

  • TextContentTextMessage
  • ImageContent(携带 UriReadOnlyMemory<byte> 数据)→ ImageMessage
  • 若回复只包含单个内容项,直接返回该消息;若包含多项,则聚合为一个 MultiModalMessage 返回。

流式场景下,StreamingChatMessageContent 被转换为 TextMessageUpdate,且仅支持 ChoiceIndex == 0 的单选择响应(多 choice 会抛出异常)。

明确的限制边界(均可以直接在源码中验证):

  • MultiModalMessage 若来自代理自身(self),会抛出 InvalidOperationException,即 Semantic Kernel 侧不支持"来自自己的多模态历史";
  • 函数调用类消息(FunctionName/FunctionArguments)不被支持,会抛出异常;
  • 以上限制在 Connector 的 XML 文档注释中也被明确列出:支持的输入/回复类型为 TextMessageImageMessageMultiModalMessage(以及流式的 TextMessageUpdate)。

五、运行示例与注意事项

  • 示例工程位于 AutoGen.SemanticKernel.Sample.csproj,其中每个示例类(如 Create_Semantic_Kernel_Chat_Agent)都暴露了 RunAsync() 入口。从当前的 Program.cs 看,程序入口默认执行的是 Use_Kernel_Functions_With_Other_Agent.RunAsync();如果你想单独跑本文示例,把入口改为 await Create_Semantic_Kernel_Chat_Agent.RunAsync(); 即可(在本地环境操作,不需要修改本仓库)。
  • 运行前置条件:设置 OPENAI_API_KEY 环境变量;模型 gpt-3.5-turbo 仅为示例取值,可按需替换。
  • 若只需要与 Semantic Kernel 的原生 ChatMessageContent 交互、无需 AutoGen 内置消息类型,也可以不注册 Connector,直接使用 IMessage<ChatMessageContent> 与该代理通信。
  • 相关测试与周边实现可参考:SemanticKernelAgentTest.cs、包装的另一条路线 SemanticKernelAgent.cs,以及组件概览文档 AutoGen-SemanticKernel-Overview.md

六、小结

SemanticKernelChatCompletionAgent 让你可以用不到二十行代码,把 Semantic Kernel 中现成的 ChatCompletionAgent 接入 AutoGen 的代理体系;而 SemanticKernelChatMessageContentConnector 是打通两套消息类型的关键中间件。理解了它的角色映射规则(自身→Assistant、他方→User、System 保留)与不支持项(self 侧 MultiModalMessage、函数调用、多结果响应),你就能在实际工程中准确判断它适用于哪些场景,避免踩到类型转换的边界异常。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
980
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384