首页
/ AutoGen.NET 图像对话实战:用 OpenAIChatAgent 实现 ImageMessage 与 MultiModalMessage 视觉聊天

AutoGen.NET 图像对话实战:用 OpenAIChatAgent 实现 ImageMessage 与 MultiModalMessage 视觉聊天

2026-09-06 09:14:20作者:滕妙奇

本文基于 AutoGen.NET(dotnet 端 AutoGen)官方向导,讲解如何让一个 Agent 处理图片输入:以 OpenAIChatAgent(后端模型为 gpt-4o 系列)为例,完整走通安装 NuGet 包、创建视觉 Agent、构造 ImageMessage / MultiModalMessage 图像消息、以及通过 SendAsync 生成回复的全过程,并结合仓库源码剖析消息是如何被中间件转换成 OpenAI 图像请求的。读完后你能在自己的 .NET 项目中复制出可运行的“看图问答”代码,并理解 AutoGen 消息体系在多模态场景下的设计约束。

注意:要与 Agent 进行图像对话,Agent 背后的模型必须支持图像输入。官方文档给出的部分支持图像输入的模型列表包括:gpt-4o、gemini-1.5、llava、claude-3 等。本示例使用 gpt-4o 系列模型作为 Agent 的后端模型。

完整可运行的代码示例位于 Image_Chat_With_Agent.cs

Step 1: 安装 AutoGen 包

首先使用以下命令安装 AutoGen NuGet 包:

dotnet add package AutoGen

示例工程还引用了 AutoGen.OpenAI 相关包(提供 OpenAIChatAgent 及其扩展方法),运行前需要设置 OPENAI_API_KEY 环境变量。从 LLMConfiguration.cs 可以看到,示例通过 LLMConfiguration.GetOpenAIGPT4o_mini() 创建指向 gpt-4o-miniChatClient

public static ChatClient GetOpenAIGPT4o_mini()
{
    var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
        ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
    var modelId = "gpt-4o-mini";

    return new OpenAIClient(openAIKey).GetChatClient(modelId);
}

即:文档中笼统表述的“gpt-4o 模型”,在仓库当前示例代码里具体落地为 gpt-4o-mini,这是当前示例可运行的一套模型选择。

Step 2: 添加 using 语句

按照 示例源码,需要引入以下命名空间:

using AutoGen.Core;            // ImageMessage、MultiModalMessage、SendAsync 等核心类型
using AutoGen.OpenAI;          // OpenAIChatAgent
using AutoGen.OpenAI.Extension; // RegisterMessageConnector 扩展方法

Step 3: 创建 OpenAIChatAgent

创建 Agent 的核心代码(对应示例中 Create_Agent 代码块):

var gpt4o = LLMConfiguration.GetOpenAIGPT4o_mini();
var agent = new OpenAIChatAgent(
    chatClient: gpt4o,
    name: "agent",
    systemMessage: "You are a helpful AI assistant")
    .RegisterMessageConnector() // convert OpenAI message to AutoGen message
    .RegisterPrintMessage();

OpenAIChatAgent.cs 的构造函数签名看,OpenAIChatAgent 支持如下参数:

参数 类型 说明
chatClient ChatClient OpenAI SDK 的 ChatClient,模型选择由它决定
name string Agent 名称
systemMessage string? 系统消息,默认 "You are a helpful AI assistant"
temperature float? 采样温度,内部默认 0.7(见 CreateChatCompletionOptions
maxTokens int? 最大生成 token 数,内部默认 1024
seed int? 随机种子,设置后输出趋于确定性
responseFormat ChatResponseFormat? 设置为 JSON 格式可启用 json mode
functions IEnumerable<ChatTool>? 注册的工具函数

链式调用的两个扩展方法各司其职:

  • RegisterMessageConnector():注册 OpenAIChatRequestMessageConnector 中间件,负责把 AutoGen 的 IMessage(包括 ImageMessageMultiModalMessage)转换成 OpenAI 的 ChatMessage 请求,并把 OpenAI 的回复转换回 TextMessage / ToolCallMessage。见 OpenAIAgentExtension.cs
  • RegisterPrintMessage():注册打印中间件,在控制台输出对话内容,便于调试。见 PrintMessageMiddlewareExtension.cs

另外,OpenAIChatAgent 的 CreateChatMessages 逻辑显示:如果传入的消息中没有系统消息,且构造时指定了 systemMessage,系统消息会被自动前置到对话最前面——所以示例里不显式传 system message 也能生效。

Step 4: 构造图像消息

AutoGen 中构造图像消息有两种方式:ImageMessageMultiModalMessage。区别在于:ImageMessage 只携带单张图像;MultiModalMessage 允许把文本、图像等多种模态组合在一条消息中。

4.1 使用 ImageMessage 构造图像消息

对应示例 Prepare_Image_Input 代码块:

var backgoundImagePath = Path.Combine("resource", "images", "background.png");
var imageBytes = File.ReadAllBytes(backgoundImagePath);
var imageMessage = new ImageMessage(Role.User, BinaryData.FromBytes(imageBytes, "image/png"));

图片按相对路径 resource/images/background.png 读取。仓库中对应的测试图片资源位于 background.png,其他图像示例(如 Example05_Dalle_And_GPT4V.cs)也使用同一资源路径。

ImageMessage.cs 源码看,ImageMessage 提供了三个构造函数,覆盖三种图片来源:

  1. ImageMessage(Role role, string url, string? from = null, string? mimeType = null)
    • 支持普通 URL 或 data URI。data URI 必须形如 data:[<mediatype>][;base64],<data>,否则抛出 ArgumentException(见 ImageMessage.cs#L24-L37);
    • 普通 URL 场景下,若未显式传 mimeType,会按扩展名推断:.pngimage/png.jpg/.jpegimage/jpeg.gifimage/gif.bmpimage/bmp.webpimage/webp.svgimage/svg+xml;扩展名无法识别且不传 mimeType 时抛异常(见 ImageMessage.cs#L42-L55)。
  2. ImageMessage(Role role, Uri uri, ...):字符串 URL 构造函数的 Uri 版本。
  3. ImageMessage(Role role, BinaryData data, string? from = null):从二进制数据构造(本示例使用的方式)。注意 data 不能为空,且 data.MediaType 必须非空(即 BinaryData.FromBytes(bytes, "image/png") 中必须带上媒体类型),否则抛 ArgumentException(见 ImageMessage.cs#L66-L82)。

此外,ImageMessage 还提供 BuildDataUri() 方法,把 Data 编码为 data:<mimeType>;base64,... 形式的 data URI,供序列化与调试使用。

4.2 使用 MultiModalMessage 构造多模态消息

对应示例 Prepare_Multimodal_Input 代码块:

var textMessage = new TextMessage(Role.User, "what's in the picture");
var multimodalMessage = new MultiModalMessage(Role.User, [textMessage, imageMessage]);

MultiModalMessage.csValidate() 方法看,构造时会做两条强校验:

  • 子消息的 From 属性必须与聚合消息的 From 一致,否则抛 ArgumentException
  • 子消息只能是 TextMessageImageMessage,其他类型(如工具调用消息)不允许聚合进来。

仓库中还有一个多图像批量输入的实际用法可以参考 Example15_GPT4V_BinaryDataImageMessage.cs:它遍历 resource/images 目录下的所有图片,按扩展名映射媒体类型后逐个构造 ImageMessage,最后用 MultiModalMessage 打包成一条用户消息发给视觉 Agent——适合一次发多张图的场景。

Step 5: 生成响应

对应示例 Chat_With_Agent 代码块:

var reply = await agent.SendAsync("what's in the picture", chatHistory: [imageMessage]);
// or use multimodal message to generate reply
reply = await agent.SendAsync(multimodalMessage);

SendAsync 定义在 AgentExtension.cs,与单 Agent 交互相关的重载有两个:

  • SendAsync(this IAgent agent, IMessage? message = null, IEnumerable<IMessage>? chatHistory = null, CancellationToken ct = default):发送任意类型的 IMessage(本例中的 MultiModalMessage 走这条路径);
  • SendAsync(this IAgent agent, string message, IEnumerable<IMessage>? chatHistory = null, ...):字符串便捷重载,内部会包装成 TextMessage(Role.User, message)(见 AgentExtension.cs#L51-L60)。

两条路径的共同行为是:SendAsync 会把 chatHistory 排在前面、message 追加到末尾,合并成完整消息列表后调用 agent.GenerateReplyAsync(messages)(见 AgentExtension.cs#L21-L42)。因此“文字 + 图片”组合实际上有两种等价写法:

  1. 图片放在 chatHistory 里,当前问题用字符串参数发送:agent.SendAsync("what's in the picture", chatHistory: [imageMessage])
  2. 把文本和图像聚合进一条 MultiModalMessage 直接发送:agent.SendAsync(multimodalMessage)

回复默认是 TextMessage 类型(示例中用 reply.Should().BeOfType<TextMessage>() 做断言,见 示例源码)。

底层原理:图像消息如何变成 OpenAI 请求

理解上面两步写法能正常工作的关键,在于 RegisterMessageConnector() 注册的 OpenAIChatRequestMessageConnector 中间件。它在 ProcessIncomingMessages 中按类型分派:

  • ImageMessage(且 From 不是当前 Agent 自己)→ ProcessImageMessage:通过 ChatMessageContentPart.CreateImagePart(...) 构造图像内容项——若消息带 Url 则创建 URI 图像部分,否则用 Data + 媒体类型创建二进制图像部分,最终包装为一条 UserChatMessage(见 OpenAIChatRequestMessageConnector.cs#L265-L300);
  • MultiModalMessageProcessMultiModalMessage:遍历子消息,TextMessage 转文本部分、ImageMessage 转图像部分,合并成一条多部分 UserChatMessage
  • 回复方向:ChatCompletion 中的文本内容被转换回 TextMessage,工具调用则转换回 ToolCallMessagePostProcessChatCompletions,见 OpenAIChatRequestMessageConnector.cs#L153-L206)。

由此可以得到几条实践约束:

  • ImageMessage / MultiModalMessageFrom 不能等于 Agent 名称(即“助手自己发出图像”不被支持),中间件会直接抛 ArgumentException
  • ImageMessage 必须二选一携带 UrlData,且二进制数据必须带媒体类型,这与构造函数校验一致;
  • MultiModalMessage 只能聚合 TextMessageImageMessage,无法混入工具消息等其他类型;
  • 中间件支持 strictMode 构造参数:开启后遇到不支持的消息类型会抛异常,默认关闭时静默忽略(见 OpenAIChatRequestMessageConnector.cs#L34-L37)。

运行前提与扩展阅读

  • 运行前提:设置 OPENAI_API_KEY 环境变量;使用支持图像输入的视觉模型(gpt-4o 系列等);图像资源按相对路径 resource/images/background.png 放置在工作目录下。
  • 换用其他后端模型实现同样的图像对话,可参考:
  • 更多消息类型的定义可查阅 AutoGen.Core/Message 目录下的 TextMessageImageMessageMultiModalMessageToolCallMessage 等源文件。
登录后查看全文
热门项目推荐
相关项目推荐