AutoGen.NET 图像对话实战:用 AutoGen.Gemini 让 Gemini 模型看懂图片
【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen
本文基于 AutoGen 仓库中的 图像对话文档 展开,完整讲解如何在 .NET 项目中通过AutoGen.Gemini包创建GeminiChatAgent,把本地图片作为ImageMessage发送给 Vertex AI 上的 Gemini 模型并获取文字描述。读完后你能掌握:安装配置、Agent 创建参数、图片消息的构造方式,以及图片在底层是如何被转换成 GeminiPart的完整链路。
前提条件
运行本示例需要在 Google Cloud 上拥有一个项目,并且该项目具备 Vertex AI API 的访问权限(对应文档中提到的 Vertex AI 要求)。示例代码通过环境变量GCP_VERTEX_PROJECT_ID读取 Google Cloud 项目 ID,运行前请先设置好该变量,否则示例会直接打印提示并退出:
var projectID = Environment.GetEnvironmentVariable("GCP_VERTEX_PROJECT_ID"); if (projectID is null) { Console.WriteLine("Please set GCP_VERTEX_PROJECT_ID environment variable."); return; }完整示例代码见 Image_Chat_With_Vertex_Gemini.cs。
Step 1:安装 AutoGen.Gemini
在项目中执行以下命令安装AutoGen.Gemini包:
dotnet add package AutoGen.GeminiStep 2:添加 using 语句
示例中需要引用AutoGen.Core,其中包含了ImageMessage、SendAsync等核心消息与扩展能力:
using AutoGen.Core;Step 3:创建 Gemini Agent
var geminiAgent = new GeminiChatAgent( name: "gemini", model: "gemini-1.5-flash-001", location: "us-east4", project: projectID, systemMessage: "You explain image content to user") .RegisterMessageConnector() .RegisterPrintMessage();这里调用了GeminiChatAgent面向 Vertex AI 的构造函数,各参数的含义可以从 GeminiChatAgent 的源码得到印证:
name:Agent 名称,本例为"gemini";model:模型 ID,本例使用"gemini-1.5-flash-001"。注意该构造函数内部会把它拼装成 Vertex 模型资源路径projects/{project}/locations/{location}/publishers/{provider}/models/{model}(默认provider为"google");project:Google Cloud 项目 ID;location:模型区域,例如"us-east4"。从源码看,它会被用来构造请求端点{location}-aiplatform.googleapis.com,见 VertexGeminiClient 中的PredictionServiceClientBuilder构建逻辑;systemMessage:系统指令,本例设定为 "You explain image content to user",让模型以"解释图片内容"为目标来回答。
在底层请求构建中(BuildChatRequest方法),系统指令会被放入Role = "system_instruction"的Content中,随GenerateContentRequest一并发送给模型。
链式调用部分:
RegisterMessageConnector():注册GeminiMessageConnector中间件,负责把 AutoGen 的消息体系与 Gemini 的请求/响应体系互相转换,定义见 GeminiAgentExtension.cs;RegisterPrintMessage():注册消息打印中间件,将收发到的消息输出到控制台,便于调试观察。
Step 4:把图片发送给 Gemini
var imagePath = Path.Combine("resource", "images", "background.png"); var image = await File.ReadAllBytesAsync(imagePath); var imageMessage = new ImageMessage(Role.User, BinaryData.FromBytes(image, "image/png")); var reply = await geminiAgent.SendAsync("what's in the image", [imageMessage]);逐行说明:
- 读取图片字节:
File.ReadAllBytesAsync把本地 PNG 文件读成字节数组。示例使用的图片位于样本项目的resource/images/background.png; - 构造 ImageMessage:
ImageMessage是 AutoGen.Core 中定义的消息类型,此处使用BinaryData构造器。该构造器要求两个约束(源码中显式校验):data不能为空,否则抛出ArgumentException("Data cannot be empty");data.MediaType必须提供(即BinaryData.FromBytes(image, "image/png")中的第二个参数),否则抛出ArgumentException("MediaType is needed for DataUri Images")。
- 发送消息:
SendAsync来自AutoGen.Core的 Agent 扩展,第一个参数是文字提问"what's in the image",第二个参数是一个IMessage数组,其中携带了Role.User角色的图片消息。也就是说,文字和图片会被打包在同一次请求中发给模型。
底层原理:图片是如何到达 Gemini 的
理解这条链路有助于排查图片无法识别、MIME 类型错误等问题。
1. 中间件入口。RegisterMessageConnector()注册的GeminiMessageConnector实现了IStreamingMiddleware,定义见 GeminiMessageConnector.cs。它接收ImageMessage后进入ProcessImageMessage方法,根据message.From是否等于当前 Agent 名判断角色:来自用户侧的消息映射为user,Agent 自身产出的映射为model。同时它提供strictMode选项——开启后,若图片消息以 model 角色出现(Gemini 不支持),会抛出InvalidOperationException("Image message is not supported as model role in Gemini.")。
2. 图片转 Part。核心是CreateImagePart方法,它按图片来源分两种情况生成 Gemini 协议的Part:
private Part CreateImagePart(ImageMessage message) { if (message.Url is string url) { return new Part { FileData = new FileData { FileUri = url, MimeType = message.MimeType } }; } else if (message.Data is BinaryData data) { return new Part { InlineData = new Blob { MimeType = message.MimeType, Data = ByteString.CopyFrom(data.ToArray()), } }; } else { throw new InvalidOperationException("Invalid ImageMessage, the data or url must be provided"); } }也就是说:
- 如果
ImageMessage基于URL构造,图片被封装为FileData(带FileUri和MimeType),由模型服务端按 URI 拉取; - 如果基于BinaryData构造(本文示例即属此类),字节会被拷贝进
Blob(InlineData),随请求体直接内联传输,同时携带 MimeType。
3. 消息序列约束。GeminiChatAgent.BuildChatRequest在组装请求时会执行 Gemini 多轮对话的规则校验:第一条消息必须来自user或function,最后一条也必须来自user或function,且同角色的连续消息会被合并为一条(合并Parts)。本示例中用户文字消息与图片消息分属不同 Part,最终以 user 角色一并送出。
4. 响应回转。模型返回后,GeminiMessageConnector的PostProcessMessage会校验响应必须恰好包含一个 candidate 且内容非空,然后把单条文本 Part 还原为TextMessage。因此示例可以用如下断言验证结果类型:
reply.Should().BeOfType<TextMessage>();使用 URL 传图的另一种方式
ImageMessage除了BinaryData构造器外,还支持 URL 构造器(见 ImageMessage.cs):
var imageMessage = new ImageMessage(Role.User, "https://example.com/photo.png");URL 构造器的行为细节:
- 传入
data:开头的Data URI时,会按data:[<mediatype>][;base64],<data>格式解析,格式不合法直接抛ArgumentException,并把 base64 解码为内联BinaryData; - 传入普通 URL 且未显式指定
mimeType时,会根据扩展名自动推断:.png→image/png、.jpg/.jpeg→image/jpeg、.gif→image/gif、.bmp→image/bmp、.webp→image/webp、.svg→image/svg+xml;无法识别扩展名时抛出ArgumentException("MimeType is required for ImageMessage"),此时必须显式传入 mimeType 参数。
从源码结构看,URL 方式的图片在连接器中走的是FileData分支,适合图片已有可访问地址(如 Google Cloud Storage 对象 URI)的场景,可以避免把大字节流塞进请求体。
小结
本文沿仓库文档 Image-chat-with-gemini.md 的四步流程(安装包 → using → 创建 Agent → 发送图片)完整落地了一个可运行的 Gemini 图像对话方案,并结合源码补充了三个文档未展开的关键点:
- Vertex 构造函数对
location、project、provider的实际用途(端点拼接与模型资源路径组装); ImageMessage两种构造方式(BinaryData / URL)对应的底层 Part 类型(InlineData/FileData)与 MimeType 校验规则;GeminiMessageConnector在请求前对图片消息的角色映射、strictMode 行为,以及对响应 candidate 的校验逻辑。
所有引用的实现文件均可在当前仓库中查阅:GeminiChatAgent.cs、GeminiMessageConnector.cs、VertexGeminiClient.cs、ImageMessage.cs 以及 示例代码。
【免费下载链接】autogenA programming framework for agentic AI项目地址: https://gitcode.com/GitHub_Trending/au/autogen
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考