首页
/ AutoGen.NET OpenAIChatAgent 实战:创建 OpenAI 聊天 Agent 并完成简单对话与流式回复

AutoGen.NET OpenAIChatAgent 实战:创建 OpenAI 聊天 Agent 并完成简单对话与流式回复

2026-09-04 16:46:33作者:冯梦姬Eddie

本文基于 AutoGen 仓库中 dotnet/website/articles/OpenAIChatAgent-simple-chat.md 教程展开,讲解如何在 .NET 端使用 AutoGen.OpenAI.OpenAIChatAgent 完成一次完整的“创建 Agent → 发送消息 → 接收回复 → 流式接收回复”流程。读完后你将掌握:OpenAIChatAgent 的构造参数与默认值、消息封包(MessageEnvelope)机制、SendAsyncGenerateStreamingReplyAsync 两条调用链的源码级实现细节,以及配套测试用例对行为的验证方式。

1. 依赖与适用前提

简单对话示例依赖以下 NuGet 包(见 AutoGen.OpenAI.csproj):

  • AutoGen.OpenAI:提供 OpenAIChatAgent,项目同时引用了 AutoGen.Core(Agent 核心抽象与消息类型)和 AutoGen.SourceGenerator(函数调用契约的源生成器,仅在涉及 function call 时发挥作用)。
  • OpenAI SDK(v2,包内以 $(OpenAISDKVersion) 统一版本):OpenAIChatAgentOpenAIClient / ChatClient 的薄封装,消息类型 ChatMessageChatCompletionStreamingChatCompletionUpdate 均来自该 SDK 的 OpenAI.Chat 命名空间。

一个重要的适用前提写在 csproj 的包描述中:如果你的项目仍依赖旧版 Azure.AI.OpenAI v1 SDK,应改用 AutoGen.OpenAI.V1(见 dotnet/src/AutoGen.OpenAI.V1),本文示例使用的是新版 OpenAI SDK 的 ChatClient

运行示例前需要设置环境变量 OPENAI_API_KEY,示例代码在缺少该变量时会直接抛出异常:

var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
    ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");

2. 引入命名空间

教程给出的第一步是导入所需命名空间(来自 OpenAICodeSnippet.csusing_statement 代码段):

using AutoGen.Core;
using AutoGen.OpenAI;
using AutoGen.OpenAI.Extension;

三个命名空间分别承担:AutoGen.Core 提供 IAgentIMessageMessageEnvelopeTextMessage 等核心抽象;AutoGen.OpenAI 提供 OpenAIChatAgent 本体;AutoGen.OpenAI.Extension 提供 RegisterMessageConnector() 等扩展方法。

3. 创建 OpenAIChatAgent 并发起第一次对话

完整的建 Agent + 对话示例(同上文件 create_openai_chat_agent 代码段):

var openAIKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
    ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
var modelId = "gpt-4o-mini";
var openAIClient = new OpenAIClient(openAIKey);

// 创建 OpenAI 聊天 Agent
var openAIChatAgent = new OpenAIChatAgent(
    chatClient: openAIClient.GetChatClient(modelId),
    name: "assistant",
    systemMessage: "You are an assistant that help user to do some tasks.");

// 构造用户消息并封装为 MessageEnvelope
var helloMessage = new UserChatMessage("Hello");
var chatMessageContent = MessageEnvelope.Create(helloMessage);

// 发送消息并接收回复
var reply = await openAIChatAgent.SendAsync(chatMessageContent);

// 回复类型是 MessageEnvelope<ChatCompletion>
ChatCompletion response = reply.As<MessageEnvelope<ChatCompletion>>().Content;

3.1 构造参数与默认值

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

参数 类型 默认值 说明
chatClient ChatClient(OpenAI SDK v2) 必填 实际调用 LLM 的客户端,由 openAIClient.GetChatClient(modelId) 绑定模型
name string 必填 Agent 名称,会写入回复消息封包的 from 字段
systemMessage string? "You are a helpful AI assistant" 系统提示词
temperature float? 构造选项时默认 0.7f 采样温度,见 OpenAIChatAgent.csCreateChatCompletionOptions
maxTokens int? 构造选项时默认 1024 单次生成最大 token 数
seed int? null 设置后可获得确定性输出
responseFormat ChatResponseFormat? null 设置为 JSON 格式时可启用 json mode
functions IEnumerable<ChatTool>? null 预注册的 ChatTool 集合

另外还有一个重载构造函数,接受完整的 ChatCompletionOptions 对象(OpenAIChatAgent.cs),可以一次性传入 TopPPresencePenaltyFrequencyPenaltyStopSequencesEndUserId 等全部完成选项,适合需要精细控制的场景。

3.2 支持的消息类型

类注释(OpenAIChatAgent.cs)明确了输入输出契约:

  • 输入MessageEnvelope<T>TChatMessage(OpenAI SDK 的聊天消息类型,如 UserChatMessageSystemChatMessage);
  • 输出:非流式返回 MessageEnvelope<ChatCompletion>;流式返回 MessageEnvelope<StreamingChatCompletionUpdate>

3.3 SendAsync 的底层调用链

SendAsync 并不是 OpenAIChatAgent 自己的方法,而是 AgentExtension.cs 中定义在 IAgent 上的扩展方法:

  1. 传入 IMessage 时,SendAsync(agent, message, chatHistory) 先把可选的 chatHistory 追加进消息列表,再把 message 放在末尾,最后调用 agent.GenerateReplyAsync(messages)
  2. 传入 string 时,会自动包装成 new TextMessage(Role.User, message) 再走同一流程,这是多 Agent 对话(如 agent.SendAsync(receiver, "hello"))能直接收发字符串的原因。

GenerateReplyAsync 的实现(OpenAIChatAgent.cs)分为两步:

  • CreateChatMessagesOpenAIChatAgent.cs):把 IMessage 序列转换为 SDK 的 ChatMessage 序列,遇到非 ChatMessage 类型直接抛 ArgumentException如果消息列表中没有任何 SystemChatMessage,会自动把构造时传入的 systemMessage 拼到最前面——这就是为什么示例里只需传一条 "Hello" 用户消息,系统提示词也会生效;
  • CreateChatCompletionsOptionsOpenAIChatAgent.cs):合并构造时的 options 与调用时传入的 GenerateReplyOptions(含 TemperatureMaxTokenStopSequenceFunctionsOutputSchema,定义见 IAgent.cs),其中 TemperatureMaxToken 遵循“调用时参数优先于构造时参数”的覆盖规则,OutputSchema 会被转换为 ChatResponseFormat.CreateJsonSchemaFormat 以启用结构化输出。

最终调用 chatClient.CompleteChatAsync(chatHistory, settings, cancellationToken),并把结果包装为 new MessageEnvelope<ChatCompletion>(reply.Value, from: this.Name) 返回。

4. 使用 GenerateStreamingReplyAsync 进行流式聊天

教程指出的第二个能力:OpenAIChatAgent 通过 IAgent.GenerateStreamingReplyAsync(实际签名来自 IStreamingAgent,见 IStreamingAgent.cs)支持流式回复。示例代码(create_openai_chat_agent_streaming 代码段):

var streamingReply = openAIChatAgent.GenerateStreamingReplyAsync(new[] { chatMessageContent });

await foreach (var streamingMessage in streamingReply)
{
    // 每个流式片段是 MessageEnvelope<StreamingChatCompletionUpdate>
    streamingMessage.As<MessageEnvelope<StreamingChatCompletionUpdate>>().Content
        .Role.Should().Be(ChatMessageRole.Assistant);
}

实现细节(OpenAIChatAgent.cs)值得注意两点:

  1. 底层走 chatClient.CompleteChatStreamingAsync,每个 StreamingChatCompletionUpdate 被包装成 MessageEnvelope<StreamingChatCompletionUpdate> 逐个 yield return
  2. 流式响应只支持单 choice:若某个 update 的 ContentUpdate.Count > 1,会抛出 InvalidOperationException("Only one choice is supported in streaming response")。因此创建 ChatClient 时不要依赖多 choice 的流式返回。

5. 测试用例对行为的验证

仓库中的 OpenAIChatAgentTest.cs 用真实的(带条件跳过机制的)集成测试验证了本文描述的全部路径:

  • 第 51 行 openAIChatAgent.SendAsync(chatMessageContent) 验证非流式回复类型为 MessageEnvelope<ChatCompletion>
  • 第 59 行 openAIChatAgent.GenerateStreamingReplyAsync(new[] { chatMessageContent }) 验证流式回复类型为 MessageEnvelope<StreamingChatCompletionUpdate>
  • 第 254 行还演示了字符串重载 await openAIChatAgent.SendAsync("hello") 的简化写法。

测试与 OpenAICodeSnippet.cs 使用完全一致的 API 序列,可作为“最小可运行单元”的交叉印证。

6. 小结与常见坑

  • 消息类型必须匹配OpenAIChatAgent 只接受 ChatMessage 家族的封包消息;如果你希望直接收发 TextMessageMultiModalMessage 等 AutoGen 通用消息类型,需要在 Agent 上注册消息连接器(RegisterMessageConnector() 扩展,见 OpenAIAgentExtension.cs),这属于仓库中另一篇进阶文档的主题,本文不展开。
  • 默认值要心里有数:不传 temperature 时实际生效的是 0.7maxTokens1024(由 CreateChatCompletionOptions 静态方法注入),而构造函数参数本身默认是 null;两者差异在 OpenAIChatAgent.csOpenAIChatAgent.cs 中可以对照阅读。
  • 系统消息自动注入:只有当消息序列中不含 SystemChatMessage 时才会自动拼接 systemMessage,如果你想在多轮对话中临时替换系统提示词,直接在历史消息里放一条 SystemChatMessage 即可跳过自动注入逻辑。
  • 多 Agent 场景:基于 IAgentSendAsync / InitiateChatAsync 扩展(AgentExtension.cs),本文创建的单个 OpenAIChatAgent 可以直接参与 agent.SendAsync(receiver, "message") 形式的双 Agent 对话,无需改动构造方式。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
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
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384