使用代理生成结构化输出

本教程步骤演示如何使用代理生成结构化输出,其中代理是在 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 AzureCliCredential())
        .GetChatClient("gpt-4o-mini")
        .CreateAIAgent(new ChatClientAgentOptions()
        {
            Name = "HelpfulAssistant",
            Instructions = "You are a helpful assistant.",
            ChatOptions = chatOptions
        });

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

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.ToAgentRunResponseAsync()).Deserialize<PersonInfo>(JsonSerializerOptions.Web);

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

重要

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

先决条件

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

使用结构化输出创建代理

ChatAgent 基于支持结构化输出的任何聊天客户端实现来构建。 使用 ChatAgentresponse_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()).create_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")

流式处理时,代理响应会以一系列更新的形式流式传输。 若要获取结构化输出,必须收集所有更新,然后访问最终的响应值:

from agent_framework import AgentRunResponse

# Get structured response from streaming agent using AgentRunResponse.from_agent_response_generator
# This method collects all streaming updates and combines them into a single AgentRunResponse
final_response = await AgentRunResponse.from_agent_response_generator(
    agent.run_stream(query, response_format=PersonInfo),
    output_format_type=PersonInfo,
)

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

后续步骤