首页
/ AutoGen.Net v0.2.0 版本解析:OpenAI 结构化输出、Azure.AI.OpenAI v2 迁移与 GPTAgent 弃用指南

AutoGen.Net v0.2.0 版本解析:OpenAI 结构化输出、Azure.AI.OpenAI v2 迁移与 GPTAgent 弃用指南

2026-09-06 17:01:52作者:裘晴惠Vivianne

AutoGen.Net v0.2.0 是 AutoGen(一个用于构建 Agentic AI 的编程框架).NET 端的重要版本:它引入了基于 JSON Schema 的 OpenAI 结构化输出(Structural Output)、将 AutoGen.OpenAI 包底层切换为 OpenAI .NET SDK v2,并正式弃用 GPTAgent。读完本文,你将掌握这三个变化的具体用法与迁移方式,并能对照仓库中的源码与示例验证每一项变更的实际落地情况。

版本总览

v0.2.0 的官方发布说明位于 0.2.0.md,内容可分为四类:

类别 变更 对应 PR/Issue
新特性 OpenAI 集成支持结构化输出格式(Structural Format Output) #3482
新特性 GenerateReplyOption 新增属性,允许在生成回复时覆盖结构化输出 schema #3436
Bug 修复 修复消息历史中包含多个不同 name 字段的 tool call 时报错(Error Code 500)的问题 #3437
改进 AutoGen.OpenAI 包改用 OpenAI v2.0 SDK;原 AutoGen.OpenAI 保留为 AutoGen.OpenAI.V1 供继续使用 Azure.AI.OpenAI v1 的用户 #3193
改进 GPTAgent 被弃用,改用 OpenAIChatAgent + OpenAIMessageConnector #3404
文档 新增使用 ollamaOpenAIChatAgent 进行 tool call 的详细文档 #3248

其中对开发者影响最大的是三项:结构化输出、OpenAI SDK v1 → v2 的包迁移、GPTAgent 弃用。下面逐一展开。

新特性一:OpenAI 结构化输出(Structural Output)

GenerateReplyOptions.OutputSchema 属性

v0.2.0 在核心消息生成选项 GenerateReplyOptions 中新增了 OutputSchema 属性(类型为 JsonSchema?),可以在每次调用 GenerateReplyAsync 时按调用粒度覆盖结构化输出 schema,而不必修改 Agent 本身的构造配置。该属性的定义见 IAgent.cs 中的 GenerateReplyOptions 类:

public JsonSchema? OutputSchema { get; set; }

完整的结构化输出示例

仓库中 Structural_Output.cs 提供了可直接运行的完整示例,演示了如何用 C# 类型自动生成 JSON Schema、将其作为输出约束传给 OpenAI,并把模型回复反序列化为强类型对象。

第一步:定义输出类型并生成 JSON Schema。 使用 JsonSchemaBuilder(来自 Json.Schema 库)从 Person 类构建 schema,类的特性([JsonPropertyName][Description][Required] 等)会被带入 schema 中,成为对模型的字段级约束:

var schemaBuilder = new JsonSchemaBuilder().FromType<Person>();
var schema = schemaBuilder.Build();

[Title("Person")]
public class Person
{
    [JsonPropertyName("name")]
    [Description("Name of the person")]
    [Required]
    public string Name { get; set; }

    [JsonPropertyName("age")]
    [Description("Age of the person")]
    [Required]
    public int Age { get; set; }

    [JsonPropertyName("city")]
    [Description("City of the person")]
    public string? City { get; set; }

    [JsonPropertyName("address")]
    [Description("Address of the person")]
    public string? Address { get; set; }

    [JsonPropertyName("hobbies")]
    [Description("Hobbies of the person")]
    public List<string>? Hobbies { get; set; }
}

注意类上的 [Title("Person")] 特性——后文会看到,它是 v0.2.0 中 OutputSchema 生效的硬性前提。

第二步:创建 Agent 并发起结构化回复。 Agent 通过 OpenAI v2 的 ChatClient 创建(详见后文迁移章节),并通过 GenerateReplyOptions.OutputSchema 传入 schema:

var apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY")
    ?? throw new Exception("Please set OPENAI_API_KEY environment variable.");
var openAIClient = new OpenAIClient(apiKey);
var openAIClientAgent = new OpenAIChatAgent(
    chatClient: openAIClient.GetChatClient("gpt-4o-mini"),
    name: "assistant",
    systemMessage: "You are a helpful assistant")
    .RegisterMessageConnector()
    .RegisterPrintMessage();

var prompt = new TextMessage(Role.User, """
    My name is John, I am 25 years old, and I live in Seattle.
    I like to play soccer and read books.
    """);
var reply = await openAIClientAgent.GenerateReplyAsync(
    messages: [prompt],
    options: new GenerateReplyOptions
    {
        OutputSchema = schema,
    });

// 回复内容即为符合 schema 的 JSON,可直接反序列化
var person = JsonSerializer.Deserialize<Person>(reply.GetContent());

示例末尾还带有断言(person.Name.Should().Be("John") 等),验证模型返回的 JSON 完全落在 schema 约束之内。运行该示例需设置 OPENAI_API_KEY 环境变量。

源码层面:OutputSchema 是如何生效的

从源码结构看,OutputSchema 的消费逻辑位于新版 OpenAIChatAgent.csCreateChatCompletionsOptions 私有方法中:

if (options?.OutputSchema is not null)
{
    option.ResponseFormat = ChatResponseFormat.CreateJsonSchemaFormat(
        jsonSchemaFormatName: options.OutputSchema.GetTitle() ?? throw new ArgumentException("Output schema must have a title"),
        jsonSchema: BinaryData.FromObjectAsJson(options.OutputSchema),
        jsonSchemaFormatDescription: options.OutputSchema.GetDescription());
}

这里可以读出两个关键实现细节:

  1. schema 的 Title 是必需的。OpenAI v2 SDK 的 CreateJsonSchemaFormat 要求传入 jsonSchemaFormatName,源码直接用 options.OutputSchema.GetTitle() 填充,取不到会抛出 ArgumentException("Output schema must have a title")。这就是示例中 Person 类必须标注 [Title("Person")] 的原因。
  2. 它是"覆盖"语义OutputSchema 在每次请求时写入 ChatCompletionOptions.ResponseFormat,会覆盖构造 Agent 时通过 responseFormat 参数设置的格式(例如 JSON mode)。这与发布说明中"允许在生成回复时覆盖结构化输出 schema"的描述一致。

如果你熟悉 JSON mode,可以进一步参考仓库中的 OpenAIChatAgent-use-json-mode.md 了解 JSON mode 与结构化输出的关系;结构化输出(JSON Schema)是 JSON mode 的超集,能约束字段级结构。

新特性二与改进:AutoGen.OpenAI 切换到 OpenAI v2.0,原包保留为 AutoGen.OpenAI.V1

包结构变化

v0.2.0 之后,仓库中并存的两个 OpenAI 集成包分别是:

  • AutoGen.OpenAI:基于 OpenAI .NET SDK v2OpenAIClient / ChatClient / ChatMessage 等新类型),是新的默认包;
  • AutoGen.OpenAI.V1:保留基于 Azure.AI.OpenAI v1OpenAIClient / ChatCompletionsOptions / ChatRequestMessage 等旧类型)的实现,供尚未迁移的项目继续使用。

这一设计意味着升级是渐进的:新项目直接使用新 AutoGen.OpenAI,存量项目可先引用 AutoGen.OpenAI.V1 保持编译通过,再逐步迁移。

创建 OpenAIChatAgent 的前后对比

发布说明给出的迁移方式如下。

迁移前(v1 风格,OpenAIClient + 模型名字符串):

var openAIClient = new OpenAIClient(apiKey);
var openAIClientAgent = new OpenAIChatAgent(
            openAIClient: openAIClient,
            model: "gpt-4o-mini",
            // Other parameters...
            );

迁移后(v2 风格,直接传 ChatClient):

var openAIClient = new OpenAIClient(apiKey);
var openAIClientAgent = new OpenAIChatAgent(
            chatClient: openAIClient.GetChatClient("gpt-4o-mini"),
            // Other parameters...
            );

核心差异是:模型名从 Agent 构造参数下沉到了 SDK 的 ChatClient 层(openAIClient.GetChatClient("gpt-4o-mini")),Agent 只持有 ChatClient 实例。对照两个包中的 OpenAIChatAgent 构造函数可以印证这一点:

  • 新版 OpenAIChatAgent.csAutoGen.OpenAI):构造参数为 ChatClient chatClient,并额外支持 seedresponseFormatChatResponseFormat,设为 JSON 格式即启用 JSON mode)等可选参数;
  • 旧版 OpenAIChatAgent.csAutoGen.OpenAI.V1):构造参数为 OpenAIClient openAIClient + string modelName,选项类型为 v1 的 ChatCompletionsOptions

此外,新版 Agent 内部的消息转换、系统消息注入等逻辑(如 CreateChatMessages 在消息列表缺少 system 消息时自动补上构造时指定的 systemMessage)与 v1 包保持一致,迁移时对话行为不会改变。

改进:GPTAgent 弃用与迁移

弃用声明

发布说明宣布 GPTAgent 被弃用,推荐改用 OpenAIChatAgent + OpenAIMessageConnector(即 RegisterMessageConnector() 扩展)。源码中这一弃用是显式标注的,GPTAgent.cs 第 30 行带有:

[Obsolete("Use OpenAIChatAgent instead")]
public class GPTAgent : IStreamingAgent

使用它的工程在编译时会收到弃用警告。

迁移方式

Before:

var agent = new GPTAgent(...);

After:

var agent = new OpenAIChatAgent(...)
    .RegisterMessageConnector();

RegisterMessageConnector() 的作用是把 OpenAIChatAgent 收发的 SDK 消息类型(如 ChatCompletion)转换为 AutoGen 核心消息类型(TextMessageToolCallMessage 等),使其能与其他 Agent 在 AutoGen.Core 的消息体系中互通。

源码佐证:GPTAgent 本就是一层薄包装

GPTAgent.cs 的构造逻辑看,GPTAgent 内部正是按迁移后的形态实现的:

_innerAgent = new OpenAIChatAgent(openAIClient, name, modelName, systemMessage, temperature, maxTokens, seed, responseFormat, functions)
    .RegisterMessageConnector();

if (functionMap is not null)
{
    var functionMapMiddleware = new FunctionCallMiddleware(functionMap: functionMap);
    _innerAgent = _innerAgent.RegisterStreamingMiddleware(functionMapMiddleware);
}

也就是说,GPTAgent 除了从 AzureOpenAIConfig / OpenAIConfig 中解析出 OpenAIClient 和模型名(见 GPTAgent.cs 的 config 分支)以及可选地挂载 FunctionCallMiddleware 外,行为完全等价于 OpenAIChatAgent(...).RegisterMessageConnector()。因此迁移是"去掉配置对象解析这一层间接",语义不变;functionMap 参数对应的行为则需要在迁移后通过中间件自行挂载。

Bug 修复:多工具调用导致的 500 错误

v0.2.0 修复了消息历史中包含多个不同 name 字段的 tool call 时抛错的问题(#3437)。该问题属于消息连接器在将历史 ToolCallMessage 还原为 OpenAI 请求消息时的兼容性缺陷。如果你此前在多轮函数调用场景(如 ReAct 循环、工具编排)中遇到过请求失败,升级到 v0.2.0 即可消除;仓库中的 OpenAIChatAgent-use-function-call.mdFunction-call-with-ollama-and-litellm.md 分别覆盖了 OpenAI 与 ollama/LiteLLM 场景下的 tool call 用法,与本次新增的文档条目(#3248)对应。

迁移检查清单

结合发布说明与源码,从 v0.1.x 升级到 v0.2.0 建议按以下顺序操作:

  1. 确认目标包:新代码引用 AutoGen.OpenAI(v2 SDK);若必须暂留 v1,改为引用 AutoGen.OpenAI.V1,避免包名与 SDK 版本错配。
  2. 替换 GPTAgent:全局搜索 new GPTAgent(,按上文 Before/After 模式替换为 OpenAIChatAgent(...).RegisterMessageConnector();若原先传了 functionMap,迁移后以 RegisterStreamingMiddleware(new FunctionCallMiddleware(functionMap: ...)) 等价挂载。
  3. 调整 OpenAIChatAgent 构造:把"客户端 + 模型名"改为"客户端.GetChatClient(模型名)",并核对 responseFormat 类型变化(v1 的 ChatCompletionsResponseFormat → v2 的 ChatResponseFormat)。
  4. (可选)启用结构化输出:为需要强类型返回的 Agent 添加 JsonSchema 约束,调用时通过 GenerateReplyOptions.OutputSchema 传入;务必确保 schema 带 Title(如 [Title("Person")]),否则会抛出 ArgumentException
  5. 验证工具调用回归:在多 tool call 的对话历史场景中跑一遍回归用例,确认 #3437 修复生效。

小结

v0.2.0 的主线是"向 OpenAI .NET SDK v2 全面对齐":结构化输出让 GenerateReplyOptions.OutputSchema 成为每次调用级、schema 驱动的回复约束;包拆分(AutoGen.OpenAI / AutoGen.OpenAI.V1)为 v1 用户保留了平滑过渡通道;GPTAgent 的弃用则让消息连接器(RegisterMessageConnector)成为标准用法。三者的代码级证据均可在 AutoGen.OpenAI 源码AutoGen.OpenAI.V1 源码结构化输出示例 中直接对照验证。

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

项目优选

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