Condividi tramite


Produzione di output strutturati con agenti

Questo passaggio dell'esercitazione illustra come produrre output strutturato con un agente, in cui l'agente è basato sul servizio Completamento chat OpenAI di Azure.

Importante

Non tutti i tipi di agente supportano l'output strutturato. Questo passaggio usa un oggetto ChatClientAgent, che supporta l'output strutturato.

Prerequisiti

Per i prerequisiti e l'installazione dei pacchetti NuGet, vedere il passaggio Creare ed eseguire un agente semplice in questa esercitazione.

Creare l'agente con output strutturato

Il ChatClientAgent è basato su una qualsiasi implementazione di IChatClient. ChatClientAgent usa il supporto per l'output strutturato fornito dal client di chat sottostante.

Quando si crea l'agente, è possibile fornire l'istanza predefinita ChatOptions da usare per il client di chat sottostante. Questa ChatOptions istanza consente di selezionare una preferenza ChatResponseFormat.

Sono disponibili varie opzioni per ResponseFormat :

Questo esempio crea un agente che produce output strutturato sotto forma di oggetto JSON conforme a uno schema specifico.

Il modo più semplice per produrre lo schema consiste nel definire un tipo che rappresenta la struttura dell'output desiderato dall'agente e quindi usare il AIJsonUtilities.CreateJsonSchema metodo per creare uno schema dal tipo .

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));

È quindi possibile creare un'istanza ChatOptions che usa questo schema per il formato di risposta.

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")
};

Questa ChatOptions istanza può essere usata durante la creazione dell'agente.

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
        });

Avviso

DefaultAzureCredential è utile per lo sviluppo, ma richiede un'attenta considerazione nell'ambiente di produzione. Nell'ambiente di produzione prendere in considerazione l'uso di credenziali specifiche ,ad esempio ManagedIdentityCredential, per evitare problemi di latenza, probe di credenziali indesiderate e potenziali rischi per la sicurezza dai meccanismi di fallback.

È ora possibile eseguire l'agente con alcune informazioni testuali che l'agente può usare per compilare l'output strutturato.

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

La risposta dell'agente può quindi essere deserializzata nella PersonInfo classe usando il Deserialize<T> metodo sull'oggetto risposta.

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

Quando si esegue lo streaming, la risposta dell'agente viene trasmessa come una serie di aggiornamenti ed è possibile deserializzare la risposta solo dopo che tutti gli aggiornamenti sono stati ricevuti. È necessario assemblare tutti gli aggiornamenti in una singola risposta prima di deserializzarlo.

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);

Esempio di streaming

Questo passaggio dell'esercitazione illustra come produrre output strutturato con un agente, in cui l'agente è basato sul servizio Completamento chat OpenAI di Azure.

Importante

Non tutti i tipi di agente supportano l'output strutturato. supporta l'output Agent strutturato quando usato con client di chat compatibili.

Prerequisiti

Per i prerequisiti e l'installazione dei pacchetti, vedere il passaggio Creare ed eseguire un agente semplice in questa esercitazione.

Creare l'agente con output strutturato

Il Agent è costruito su qualsiasi implementazione di client di chat che supporta l'output strutturato. Agent usa il response_format parametro per specificare lo schema di output desiderato.

Quando si crea o si esegue l'agente, è possibile fornire un modello Pydantic che definisce la struttura dell'output previsto.

Diversi formati di risposta sono supportati in base alle funzionalità client di chat sottostanti.

Questo esempio crea un agente che produce output strutturato sotto forma di oggetto JSON conforme a uno schema del modello Pydantic.

Prima di tutto, definire un modello Pydantic che rappresenta la struttura dell'output desiderato dall'agente:

from pydantic import BaseModel

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

È ora possibile creare un agente usando il client chat OpenAI di Azure:

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."
)

È ora possibile eseguire l'agente con alcune informazioni testuali e specificare il formato di output strutturato usando il response_format parametro :

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

La risposta dell'agente conterrà l'output strutturato nella value proprietà , accessibile direttamente come istanza del modello 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")

Quando si esegue lo streaming, agent.run(..., stream=True) restituisce un ResponseStream. Il finalizzatore predefinito del flusso gestisce automaticamente l'analisi dell'output strutturato, in modo da poter eseguire l'iterazione per gli aggiornamenti in tempo reale e quindi chiamare get_final_response() per ottenere il risultato analizzato:

# 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}")

Se non devi elaborare i singoli aggiornamenti in streaming, puoi saltare completamente l'iterazione: get_final_response() consumerà automaticamente il flusso.

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}")

Esempio completo

# 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())

Passaggi successivi