通过


使用代理生成结构化输出

本教程步骤演示如何使用代理生成结构化输出,其中代理是在 Azure OpenAI 聊天完成服务上构建的。

重要

并非所有代理类型都支持结构化输出。 此步骤使用ChatClientAgent,后者支持结构化输出。

先决条件

有关先决条件和安装 NuGet 包,请参阅本教程中的 “创建并运行简单代理 ”步骤。

使用结构化输出创建代理

该系统在任何 ChatClientAgent 实现的基础上构建 IChatClientChatClientAgent 利用基础聊天客户端提供的结构化输出支持。

创建代理时,可以选择提供用于基础聊天客户端的默认 ChatOptions 实例。 此 ChatOptions 实例允许你选取首选 ChatResponseFormat实例。

有各种选项可供 ResponseFormat选择。

此示例创建一个代理,该代理以符合特定架构的 JSON 对象的形式生成结构化输出。

生成架构的最简单方法是定义一个类型,该类型表示要从代理输出的结构,然后使用 AIJsonUtilities.CreateJsonSchema 该方法从类型创建架构。

using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.AI;

public class PersonInfo
{
    public string? Name { get; set; }
    public int? Age { get; set; }
    public string? Occupation { get; set; }
}

JsonElement schema = AIJsonUtilities.CreateJsonSchema(typeof(PersonInfo));

然后,可以创建一个 ChatOptions 实例,该实例将此架构用于响应格式。

using Microsoft.Extensions.AI;

ChatOptions chatOptions = new()
{
    ResponseFormat = ChatResponseFormat.ForJsonSchema(
        schema: schema,
        schemaName: "PersonInfo",
        schemaDescription: "Information about a person including their name, age, and occupation")
};

创建代理时可以使用此 ChatOptions 实例。

using System;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using OpenAI;

AIAgent agent = new AzureOpenAIClient(
    new Uri("https://<myresource>.openai.azure.com"),
    new DefaultAzureCredential())
        .GetChatClient("gpt-4o-mini")
        .AsAIAgent(new ChatClientAgentOptions()
        {
            Name = "HelpfulAssistant",
            Instructions = "You are a helpful assistant.",
            ChatOptions = chatOptions
        });

警告

DefaultAzureCredential 对于开发来说很方便,但在生产中需要仔细考虑。 在生产环境中,请考虑使用特定凭据(例如), ManagedIdentityCredential以避免延迟问题、意外凭据探测以及回退机制的潜在安全风险。

现在,您只需使用可用于填充结构化输出的一些文本信息来启动代理。

var response = await agent.RunAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");

然后,可以使用响应对象上的PersonInfo 方法将代理的响应反序列化为Deserialize<T> 类。

var personInfo = response.Deserialize<PersonInfo>(JsonSerializerOptions.Web);
Console.WriteLine($"Name: {personInfo.Name}, Age: {personInfo.Age}, Occupation: {personInfo.Occupation}");

流式处理时,代理响应将作为一系列更新进行流式传输,并且只能在收到所有更新后反序列化响应。 在反序列化更新之前,必须将所有更新组合到单个响应中。

var updates = agent.RunStreamingAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
personInfo = (await updates.ToAgentResponseAsync()).Deserialize<PersonInfo>(JsonSerializerOptions.Web);

小窍门

有关完整的可运行示例,请参阅 .NET 示例

流式处理示例

小窍门

有关完整的可运行示例,请参阅 .NET 示例

本教程步骤演示如何使用代理生成结构化输出,其中代理是在 Azure OpenAI 聊天完成服务上构建的。

重要

并非所有代理类型都支持结构化输出。 与兼容的聊天客户端一起使用时,支持 Agent 结构化输出。

先决条件

有关先决条件和安装包,请参阅本教程中的 “创建并运行简单代理 ”步骤。

使用结构化输出创建代理

Agent 基于支持结构化输出的任何聊天客户端实现来构建。 使用 Agentresponse_format 参数来指定所需的输出架构。

创建或运行代理时,可以提供一个 Pydantic 模型来定义预期输出的结构。

根据底层聊天客户端的功能,各种响应格式都得到了支持。

此示例创建一个代理,该代理以符合 Pydantic 模型架构的 JSON 对象的形式生成结构化输出。

首先,定义一个 Pydantic 模型,该模型表示要从代理输出的结构:

from pydantic import BaseModel

class PersonInfo(BaseModel):
    """Information about a person."""
    name: str | None = None
    age: int | None = None
    occupation: str | None = None

现在可以使用 Azure OpenAI 聊天客户端创建代理:

from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential

# Create the agent using Azure OpenAI Chat Client
agent = AzureOpenAIChatClient(credential=AzureCliCredential()).as_agent(
    name="HelpfulAssistant",
    instructions="You are a helpful assistant that extracts person information from text."
)

现在,可以使用一些文本信息运行代理,并使用 response_format 参数指定结构化输出格式:

response = await agent.run(
    "Please provide information about John Smith, who is a 35-year-old software engineer.",
    response_format=PersonInfo
)

代理响应将包含属性中的 value 结构化输出,该输出可以直接作为 Pydantic 模型实例进行访问:

if response.value:
    person_info = response.value
    print(f"Name: {person_info.name}, Age: {person_info.age}, Occupation: {person_info.occupation}")
else:
    print("No structured data found in response")

流式处理时, agent.run(..., stream=True) 返回一个 ResponseStream。 流的内置终结器会自动处理结构化输出的解析,使您可以进行实时更新的迭代,然后调用 get_final_response() 来获取解析结果。

# Stream updates in real time, then get the structured result
stream = agent.run(query, stream=True, options={"response_format": PersonInfo})
async for update in stream:
    print(update.text, end="", flush=True)

# get_final_response() returns the AgentResponse with the parsed value
final_response = await stream.get_final_response()

if final_response.value:
    person_info = final_response.value
    print(f"Name: {person_info.name}, Age: {person_info.age}, Occupation: {person_info.occupation}")

如果不需要处理单个流更新,可以完全跳过迭代 — get_final_response() 将自动消费流:

stream = agent.run(query, stream=True, options={"response_format": PersonInfo})
final_response = await stream.get_final_response()

if final_response.value:
    person_info = final_response.value
    print(f"Name: {person_info.name}, Age: {person_info.age}, Occupation: {person_info.occupation}")

完整示例

# Copyright (c) Microsoft. All rights reserved.

import asyncio

from agent_framework.openai import OpenAIResponsesClient
from pydantic import BaseModel

"""
OpenAI Responses Client with Structured Output Example

This sample demonstrates using structured output capabilities with OpenAI Responses Client,
showing Pydantic model integration for type-safe response parsing and data extraction.
"""


class OutputStruct(BaseModel):
    """A structured output for testing purposes."""

    city: str
    description: str


async def non_streaming_example() -> None:
    print("=== Non-streaming example ===")

    agent = OpenAIResponsesClient().as_agent(
        name="CityAgent",
        instructions="You are a helpful agent that describes cities in a structured format.",
    )

    query = "Tell me about Paris, France"
    print(f"User: {query}")

    result = await agent.run(query, options={"response_format": OutputStruct})

    if structured_data := result.value:
        print("Structured Output Agent:")
        print(f"City: {structured_data.city}")
        print(f"Description: {structured_data.description}")
    else:
        print(f"Failed to parse response: {result.text}")


async def streaming_example() -> None:
    print("=== Streaming example ===")

    agent = OpenAIResponsesClient().as_agent(
        name="CityAgent",
        instructions="You are a helpful agent that describes cities in a structured format.",
    )

    query = "Tell me about Tokyo, Japan"
    print(f"User: {query}")

    # Stream updates in real time using ResponseStream
    stream = agent.run(query, stream=True, options={"response_format": OutputStruct})
    async for update in stream:
        if update.text:
            print(update.text, end="", flush=True)
    print()

    # get_final_response() returns the AgentResponse with structured output parsed
    result = await stream.get_final_response()

    if structured_data := result.value:
        print("Structured Output (from streaming with ResponseStream):")
        print(f"City: {structured_data.city}")
        print(f"Description: {structured_data.description}")
    else:
        print(f"Failed to parse response: {result.text}")


async def main() -> None:
    print("=== OpenAI Responses Agent with Structured Output ===")

    await non_streaming_example()
    await streaming_example()


if __name__ == "__main__":
    asyncio.run(main())

后续步骤