AutoGen.NET:通过 SemanticKernelChatMessageContentConnector 让 SemanticKernelAgent 支持更多内置消息类型
2026/9/5 20:40:03 网站建设 项目流程

AutoGen.NET:通过 SemanticKernelChatMessageContentConnector 让 SemanticKernelAgent 支持更多内置消息类型

【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen

在 AutoGen.NET(.NET 版 AutoGen)中,SemanticKernelAgent 原生的消息通道只认一种类型:来自 Semantic Kernel 的ChatMessageContent(即IMessage<ChatMessageContent>)。当你的对话系统中同时存在 AutoGen 内置消息(如TextMessageImageMessageMultiModalMessage)时,如何让它们与 Semantic Kernel Agent 无缝互通?本文基于官方文档 SemanticKernelAgent-support-more-messages 并结合仓库源码,完整讲解如何通过注册SemanticKernelChatMessageContentConnector中间件扩展 Agent 的消息兼容性:包括支持的消息类型清单、完整可运行代码、双向转换的底层实现细节,以及当前版本尚不支持的消息类型与验证方式。

一、SemanticKernelAgent 的默认消息限制

SemanticKernelAgent是基于Microsoft.SemanticKernelKernel对象构建的流式 Agent(实现IStreamingAgent接口)。它接收IEnumerable<IMessage>作为输入,内部通过BuildChatHistory将消息列表拼装为 Semantic Kernel 的ChatHistory

关键限制体现在它的消息处理逻辑中。从 SemanticKernelAgent.cs 的ProcessMessage方法可以看到:

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

也就是说,只有IMessage<ChatMessageContent>能通过类型匹配,任何 AutoGen 内置消息类型(TextMessageImageMessage等)传入都会直接抛出ArgumentException: Invalid message type。Agent 类注释(SemanticKernelAgent.cs)也明确说明:入站/回复消息均为IMessage<ChatMessageContent>,流式回复为IMessage<StreamingChatMessageContent>;"要支持更多 AutoGen 内置IMessage,请注册SemanticKernelChatMessageContentConnector"。

默认用法下,你需要用MessageEnvelope.CreateChatMessageContent包装成IMessage<ChatMessageContent>再发送,回复同样以MessageEnvelope<ChatMessageContent>形式返回。这是 AutoGen 与 Semantic Kernel 之间的"窄通道"。

二、SemanticKernelChatMessageContentConnector:双向消息转换器

SemanticKernelChatMessageContentConnector是解决上述限制的核心组件,位于 Middleware/SemanticKernelChatMessageContentConnector.cs。它的职责是双向转换

  • 入站(Inbound):把调用方发来的 AutoGen 内置消息转换为ChatMessageContent,再包上MessageEnvelope<ChatMessageContent>传给底层 Agent;
  • 出站(Outbound):把 Agent 返回的ChatMessageContent(流式场景为StreamingChatMessageContent)转换回 AutoGen 内置消息类型返回给调用方。

从类型声明看,它同时实现了IMiddlewareIStreamingMiddleware两个接口(SemanticKernelChatMessageContentConnector.cs),因此同步SendAsync与流式GenerateStreamingReplyAsync两条链路都能走转换逻辑——这是它与普通单一中间件的重要区别。

支持的消息类型清单

根据文档与中间件源码,当前阶段转换器的支持范围如下:

方向支持的消息类型说明
入站TextMessageRole映射为 System/User/Assistant
入站ImageMessage需带 URL 或可构造 Data URI 的二进制数据
入站MultiModalMessage内部元素仅支持TextMessageImageMessage
出站(非流式)TextMessage/ImageMessage/MultiModalMessage单内容项返回单条消息,多内容项打包为MultiModalMessage
出站(流式)TextMessageUpdate流式增量文本更新
不支持ToolCallMessage/ToolCallResultMessage函数调用类消息,当前版本尚未支持

此外,IMessage<ChatMessageContent>本身会被直接透传(原样解包),因此注册连接器后,原有 Semantic Kernel 风格的用法依然兼容。

三、注册方式与完整可运行示例

注册操作通过扩展方法RegisterMessageConnector()完成,定义在 Extension/SemanticKernelAgentExtension.cs:

public static MiddlewareStreamingAgent<SemanticKernelAgent> RegisterMessageConnector( this SemanticKernelAgent agent, SemanticKernelChatMessageContentConnector? connector = null) { if (connector == null) { connector = new SemanticKernelChatMessageContentConnector(); } return agent.RegisterStreamingMiddleware(connector); }

该扩展方法有两个重载(分别接收SemanticKernelAgentMiddlewareStreamingAgent<SemanticKernelAgent>),连接器实例可以缺省——不传时自动new一个默认实例;返回值是注册了流式中间件的新 Agent 实例(AutoGen 的中间件机制采用"注册即返回新 Agent"的不可变风格)。

下面是官方示例工程 SemanticKernelCodeSnippet.cs 中的完整代码(对应文档引用的register_semantic_kernel_chat_message_content_connector代码块):

var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY") ?? throw new Exception("Please set OPENAI_API_KEY environment variable."); var modelId = "gpt-3.5-turbo"; var builder = Kernel.CreateBuilder() .AddOpenAIChatCompletion(modelId: modelId, apiKey: openAIKey); var kernel = builder.Build(); // create a semantic kernel agent var semanticKernelAgent = new SemanticKernelAgent( kernel: kernel, name: "assistant", systemMessage: "You are an assistant that help user to do some tasks."); // Register the connector middleware to the kernel agent var semanticKernelAgentWithConnector = semanticKernelAgent .RegisterMessageConnector(); // now semanticKernelAgentWithConnector supports more message types IMessage[] messages = [ MessageEnvelope.Create(new ChatMessageContent(AuthorRole.User, "Hello")), new TextMessage(Role.Assistant, "Hello", from: "user"), new MultiModalMessage(Role.Assistant, [ new TextMessage(Role.Assistant, "Hello", from: "user"), ], from: "user"), ]; foreach (var message in messages) { var reply = await semanticKernelAgentWithConnector.SendAsync(message); // SemanticKernelChatMessageContentConnector will convert the reply message to TextMessage reply.Should().BeOfType<TextMessage>(); }

运行前提:需要设置OPENAI_API_KEY环境变量;项目需引用AutoGen.SemanticKernelMicrosoft.SemanticKernel等 NuGet 包(仓库 Directory.Packages.props 中当前锁定的 Semantic Kernel 稳定版为 1.45.0)。这段代码展示了三种入站消息混用:ChatMessageContent信封消息(透传)、AutoGenTextMessage、AutoGenMultiModalMessage,且回复统一被转换器还原为 AutoGen 的TextMessage

对比:未注册连接器时的基线用法

同一示例文件中的CreateSemanticKernelAgentAsync(SemanticKernelCodeSnippet.cs)演示了不注册连接器时的用法:只能发送IMessage<ChatMessageContent>,回复需用reply.As<MessageEnvelope<ChatMessageContent>>().Content解包;流式则通过GenerateStreamingReplyAsync拿到MessageEnvelope<StreamingChatMessageContent>。两段示例放在一起,可以直观看到连接器带来的能力差异。

四、转换逻辑源码剖析

4.1 入站转换:区分"自己发的"与"别人发的"

中间件的ProcessMessage(SemanticKernelChatMessageContentConnector.cs)按m.From == agent.Name把消息分为两类分别处理,这决定了 AutoGen 的Role到 Semantic KernelAuthorRole的映射规则:

  • 来自 Agent 自身ProcessMessageForSelf,即消息在对话历史中是 Agent 自己之前的回复):Role.SystemAuthorRole.System,其余一律 →AuthorRole.Assistant
  • 来自其他参与者ProcessMessageForOthers,即用户或第三方 Agent):Role.SystemAuthorRole.System,其余一律 →AuthorRole.User
  • ImageMessage(他人):优先使用message.Url构造ImageContent(new Uri(...));若无 URL 但持有二进制Data,则调用BuildDataUri()生成 base64 Data URI 再包装为ImageContent;两者皆无时抛出InvalidOperationException: ImageMessage must have Url or DataUriImageMessage的 Data URI 构造与 MIME 类型推断逻辑见 ImageMessage.cs(支持 png/jpg/jpeg/gif/bmp/webp/svg 等扩展名自动推断);
  • MultiModalMessage(他人):遍历内部Content,逐项转换为TextContentImageContent后装入ChatMessageContentItemCollection,打包为单条AuthorRole.User消息;
  • MultiModalMessage(自己):明确抛出InvalidOperationException("MultiModalMessage is not supported in the semantic kernel if it's from self.")——即 Agent 自己历史中的多模态消息暂不支持回放;
  • 旧版Message类型(已标记[Obsolete])仍有兼容分支,但其中携带函数调用字段(FunctionName/FunctionArguments)的消息会抛出 "Function call is not supported" 异常。

不支持的类型一律抛InvalidOperationException("unsupported message type, only support TextMessage, ImageMessage, MultiModalMessage and Message."),错误信息直接给出了支持清单,排错成本很低。

4.2 出站转换:按内容项数量选择消息类型

回复方向由PostProcessMessage(IMessage<ChatMessageContent>)(SemanticKernelChatMessageContentConnector.cs)完成:

  • TextContentTextMessage(Role.Assistant, ...)
  • ImageContent(带UriReadOnlyMemory<byte>二进制)→ImageMessage
  • 转换后的内容项若只有 1 个,直接返回该单条消息;否则打包为MultiModalMessage(Role.Assistant, items, ...)——这解释了为何多模态回复会自动升级类型;
  • 遇到其他KernelContent子类型抛Unsupported content type

流式回复走PostProcessMessage(IMessage<StreamingChatMessageContent>):校验ChoiceIndex必须为 0(多 choice 抛异常),然后把每个增量块包装为TextMessageUpdate(Role.Assistant, content, from)TextMessageUpdate的定义见 TextMessage.cs,它与TextMessage的区别在于Content可为空且用于增量累积。

4.3 为什么这样设计

AutoGen 的消息模型以IMessage接口为统一抽象,各后端(OpenAI、Ollama、Gemini、Semantic Kernel 等)有自己的原生消息类型。连接器中间件本质上是"适配器":让上层编排代码(如 GroupChat)只操作 AutoGen 原生消息,而由中间件屏蔽后端的类型差异。这一"注册中间件即扩展能力"的模式在 AutoGen.NET 的中间件体系中是通用设计,SemanticKernelChatMessageContentConnector只是 Semantic Kernel 后端的具体实现。

五、测试用例中的行为验证

SemanticKernelAgentTest.cs 提供了对上述能力的端到端验证(基于 Azure OpenAI,需AZURE_OPENAI_API_KEYAZURE_OPENAI_ENDPOINTAZURE_OPENAI_DEPLOY_NAME环境变量):

  • SemanticKernelChatMessageContentConnectorTestAsync(测试代码):注册连接器后,对ChatMessageContent信封、TextMessageMultiModalMessage三种入站消息逐一SendAsync,断言回复均为TextMessageFrom == "assistant";随后用同样的消息列表验证流式路径,断言每个增量块都是TextMessageUpdate。这与本文第三节的示例完全对应;
  • SemanticKernelPluginTestAsync还验证了注册连接器后 Kernel 插件(函数)仍可正常工作:向 Kernel 注入GetWeatherAsync插件函数并发送"What is the weather in Seattle?",断言回复包含 "seattle" 与 "sunny"——说明连接器只转换消息通道,不影响 Kernel 自身通过ToolCallBehavior.AutoInvokeKernelFunctions(见 SemanticKernelAgent.cs 的默认设置)完成的函数调用闭环;
  • SkChatCompletionAgentChatMessageContentConnectorTestAsync则展示了同一连接器也可用于SemanticKernelChatCompletionAgent(包装 Semantic KernelChatCompletionAgent的 另一种封装),通过.RegisterMiddleware(new SemanticKernelChatMessageContentConnector())注册,行为一致。

需要说明:这些测试标注了[ApiKeyFact(...)],属于依赖密钥的集成测试;仓库只读环境下你主要参考其断言逻辑即可。

六、限制与注意事项

  1. 函数调用消息暂不支持ToolCallMessageToolCallResultMessage无法通过该连接器传递,携带函数调用信息的旧式Message也会抛出 "Function call is not supported" 异常。如果你需要在 Semantic Kernel Agent 上使用 AutoGen 侧的函数调用编排,当前应从源码结构看只能依赖 Kernel 原生插件机制(ToolCallBehavior.AutoInvokeKernelFunctions),而非 AutoGen 的ToolCallMessage通道;
  2. 多模态消息不能来自 Agent 自身:对话历史中 Agent 自己产生的MultiModalMessage会直接抛异常,回放多轮多模态历史时需注意这一点;
  3. 仅支持单一 choice:非流式场景ResultsPerPrompt > 1与流式场景ChoiceIndex > 0均会抛异常,这与 Semantic Kernel 后端配置相关;
  4. 注册返回新实例RegisterMessageConnector()基于 AutoGen 的中间件机制返回新的MiddlewareStreamingAgent<SemanticKernelAgent>,原 Agent 实例的消息行为不变,请在后续代码中使用返回的新实例。

七、小结

当 Semantic Kernel Agent 需要融入 AutoGen 的多 Agent 编排体系时,注册SemanticKernelChatMessageContentConnector是打通消息模型的唯一推荐路径:一行RegisterMessageConnector()即可让TextMessageImageMessageMultiModalMessage等 AutoGen 内置消息在入站时转为ChatMessageContent、出站时还原为 AutoGen 消息(流式场景还原为TextMessageUpdate),且同步/流式两条链路同时生效。实现细节可在 SemanticKernelChatMessageContentConnector.cs 中逐方法核对,行为验证可参考 SemanticKernelAgentTest.cs,完整可运行示例见 SemanticKernelCodeSnippet.cs。

【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询