Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Lernprogrammschritt erfahren Sie, wie Sie strukturierte Ausgaben mit einem Agent erstellen, wobei der Agent auf dem Azure OpenAI-Chatabschlussdienst basiert.
Von Bedeutung
Nicht alle Agenttypen unterstützen native strukturierte Ausgaben. Die ChatClientAgent unterstützt strukturierte Ausgaben, wenn sie mit kompatiblen Chat-Clients verwendet wird.
Voraussetzungen
Für Voraussetzungen und die Installation von NuGet-Paketen siehe den Schritt Erstellen und Ausführen eines einfachen Agenten in diesem Tutorial.
Definieren eines Typs für strukturierte Ausgaben
Definieren Sie zunächst einen Typ, der die Struktur der vom Agent gewünschten Ausgabe darstellt.
public class PersonInfo
{
public string? Name { get; set; }
public int? Age { get; set; }
public string? Occupation { get; set; }
}
Erstellen des Agents
Erstellen Sie eine ChatClientAgent mit dem Azure AI Projects Client.
using System;
using Azure.AI.Projects;
using Azure.Identity;
using Microsoft.Agents.AI;
AIAgent agent = new AIProjectClient(
new Uri("<your-foundry-project-endpoint>"),
new DefaultAzureCredential())
.AsAIAgent(
model: "gpt-4o-mini",
name: "HelpfulAssistant",
instructions: "You are a helpful assistant.");
Warnung
DefaultAzureCredential ist praktisch für die Entwicklung, erfordert aber sorgfältige Überlegungen in der Produktion. Berücksichtigen Sie in der Produktion die Verwendung bestimmter Anmeldeinformationen (z. B. ManagedIdentityCredential), um Latenzprobleme, unbeabsichtigte Abfragen von Anmeldeinformationen und potenzielle Sicherheitsrisiken durch Ausweichmechanismen zu vermeiden.
Strukturierte Ausgaben mit RunAsync<T>
Die RunAsync<T> Methode ist für die AIAgent Basisklasse verfügbar. Er akzeptiert einen generischen Typparameter, der den Typ der strukturierten Ausgabe angibt.
Dieser Ansatz gilt, wenn der strukturierte Ausgabetyp zur Kompilierungszeit bekannt ist und eine typierte Ergebnisinstanz erforderlich ist. Es unterstützt Grundtypen, Arrays und komplexe Typen.
AgentResponse<PersonInfo> response = await agent.RunAsync<PersonInfo>("Please provide information about John Smith, who is a 35-year-old software engineer.");
Console.WriteLine($"Name: {response.Result.Name}, Age: {response.Result.Age}, Occupation: {response.Result.Occupation}");
Strukturierte Ausgaben mit ResponseFormat
Strukturierte Ausgaben können konfiguriert werden, indem man die ResponseFormat-Eigenschaft bei AgentRunOptions zur Aufrufzeit oder bei der Agentinitialisierung festlegt, für Agents, die dies unterstützen, wie z. B. ChatClientAgent und den Foundry-Agent.
Dieser Ansatz ist anwendbar, wenn:
- Der Typ der strukturierten Ausgaben ist zur Kompilierungszeit nicht bekannt.
- Das Schema wird als unformatierter JSON-Code dargestellt.
- Strukturierte Ausgaben können nur zum Erstellungszeitpunkt des Agenten konfiguriert werden.
- Nur der unformatierte JSON-Text wird ohne Deserialisierung benötigt.
- Die Agentenzusammenarbeit kommt zum Einsatz.
Es stehen verschiedene Optionen zur ResponseFormat Verfügung:
- Eine integrierte ChatResponseFormat.Text Eigenschaft: Die Antwort wird im Klartext sein.
- Eine integrierte Eigenschaft: Die Antwort ist ein JSON-Objekt ChatResponseFormat.Json ohne ein bestimmtes Schema.
- Eine benutzerdefinierte ChatResponseFormatJson Instanz: Die Antwort ist ein JSON-Objekt, das einem bestimmten Schema entspricht.
Hinweis
Grundtypen und Arrays werden vom ResponseFormat Ansatz nicht unterstützt. Wenn Sie mit Grundtypen oder Arrays arbeiten müssen, verwenden Sie den RunAsync<T> Ansatz, oder erstellen Sie einen Wrappertyp.
// Instead of using List<string> directly, create a wrapper type:
public class MovieListWrapper
{
public List<string> Movies { get; set; }
}
using System.Text.Json;
using Microsoft.Extensions.AI;
AgentRunOptions runOptions = new()
{
ResponseFormat = ChatResponseFormat.ForJsonSchema<PersonInfo>()
};
AgentResponse response = await agent.RunAsync("Please provide information about John Smith, who is a 35-year-old software engineer.", options: runOptions);
PersonInfo personInfo = JsonSerializer.Deserialize<PersonInfo>(response.Text, JsonSerializerOptions.Web)!;
Console.WriteLine($"Name: {personInfo.Name}, Age: {personInfo.Age}, Occupation: {personInfo.Occupation}");
Die ResponseFormat kann auch mithilfe einer unformatierten JSON-Schemazeichenfolge angegeben werden, die nützlich ist, wenn kein entsprechender .NET Typ verfügbar ist, z. B. für deklarative Agents oder Schemas, die aus einer externen Konfiguration geladen werden:
string jsonSchema = """
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" },
"occupation": { "type": "string" }
},
"required": ["name", "age", "occupation"]
}
""";
AgentRunOptions runOptions = new()
{
ResponseFormat = ChatResponseFormat.ForJsonSchema(JsonElement.Parse(jsonSchema), "PersonInfo", "Information about a person")
};
AgentResponse response = await agent.RunAsync("Please provide information about John Smith, who is a 35-year-old software engineer.", options: runOptions);
JsonElement result = JsonSerializer.Deserialize<JsonElement>(response.Text);
Console.WriteLine($"Name: {result.GetProperty("name").GetString()}, Age: {result.GetProperty("age").GetInt32()}, Occupation: {result.GetProperty("occupation").GetString()}");
Strukturierte Ausgaben mit Streaming
Beim Streaming wird die Agent-Antwort als eine Reihe von Updates gestreamt, und Sie können die Antwort nur deserialisieren, nachdem alle Updates empfangen wurden. Sie müssen alle Updates in einer einzigen Antwort zusammenstellen, bevor Sie sie deserialisieren.
using System.Text.Json;
using Microsoft.Extensions.AI;
AIAgent agent = new AIProjectClient(
new Uri("<your-foundry-project-endpoint>"),
new DefaultAzureCredential())
.AsAIAgent(new ChatClientAgentOptions()
{
Name = "HelpfulAssistant",
ChatOptions = new()
{
ModelId = "gpt-4o-mini",
Instructions = "You are a helpful assistant.",
ResponseFormat = ChatResponseFormat.ForJsonSchema<PersonInfo>()
}
});
> [!WARNING]
> `DefaultAzureCredential` is convenient for development but requires careful consideration in production. In production, consider using a specific credential (e.g., `ManagedIdentityCredential`) to avoid latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
IAsyncEnumerable<AgentResponseUpdate> updates = agent.RunStreamingAsync("Please provide information about John Smith, who is a 35-year-old software engineer.");
AgentResponse response = await updates.ToAgentResponseAsync();
PersonInfo personInfo = JsonSerializer.Deserialize<PersonInfo>(response.Text)!;
Console.WriteLine($"Name: {personInfo.Name}, Age: {personInfo.Age}, Occupation: {personInfo.Occupation}");
Strukturierte Ausgaben mit Agenten ohne strukturierte Ausgabefunktionen
Einige Agents unterstützen keine strukturierten Ausgaben, entweder weil sie nicht Teil des Protokolls sind oder weil die Agents Sprachmodelle ohne strukturierte Ausgabefunktionen verwenden. Ein möglicher Ansatz besteht darin, einen benutzerdefinierten Dekorator-Agenten zu erstellen, der jedes AIAgent umschließt und einen zusätzlichen LLM-Aufruf über einen Chatclient verwendet, um die Textantwort des Agenten in strukturiertes JSON zu konvertieren.
Hinweis
Da dieser Ansatz von einem zusätzlichen LLM-Aufruf zum Transformieren der Antwort abhängt, reicht die Zuverlässigkeit möglicherweise nicht für alle Szenarien aus.
Eine Referenzimplementierung dieses Musters, die Sie an Ihre eigenen Anforderungen anpassen können, finden Sie im StructuredOutputAgent-Beispiel.
Tipp
In den .NET-Beispielen finden Sie vollständige ausführbare Beispiele.
Streamingbeispiel
Tipp
Sehen Sie die .NET-Beispiele für vollständige ausführbare Beispiele an.
In diesem Lernprogrammschritt erfahren Sie, wie Sie strukturierte Ausgaben mit einem Agent erstellen, wobei der Agent auf dem Azure OpenAI-Chatabschlussdienst basiert.
Von Bedeutung
Nicht alle Agenttypen unterstützen strukturierte Ausgaben. Die Agent unterstützt strukturierte Ausgaben, wenn sie mit kompatiblen Chatclients verwendet wird.
Voraussetzungen
Die erforderlichen Komponenten und die Installation von Paketen finden Sie im Schritt "Erstellen und Ausführen eines einfachen Agents " in diesem Lernprogramm.
Erstellen Sie einen Agenten mit strukturierten Ausgaben
Der Agent basiert auf jeder Chatclient-Implementierung, die strukturierte Ausgaben unterstützt.
Der Agent verwendet den response_format-Schlüssel im options-Verzeichnis, um das gewünschte Ausgabeschema festzulegen.
Wenn Sie den Agent ausführen, können Sie eine der folgenden Optionen angeben:
- Ein Pydantisches Modell, das die Struktur der erwarteten Ausgabe definiert.
- Eine JSON-Schemazuordnung (
dict), wenn Sie JSON analysieren möchten, ohne eine Modellklasse zu definieren.
Sie können das options Diktat zur Laufzeit über agent.run(..., options={"response_format": ...})das Diktat übergeben oder zur Agenterstellungszeit über das default_options Diktat festlegen.
Verschiedene Antwortformate werden basierend auf den zugrunde liegenden Chatclientfunktionen unterstützt.
Im ersten Beispiel wird ein Agent erstellt, der strukturierte Ausgaben in Form eines JSON-Objekts erzeugt, das einem Pydantischen Modellschema entspricht.
Definieren Sie zunächst ein Pydantisches Modell, das die Struktur der gewünschten Ausgabe aus dem Agent darstellt:
from pydantic import BaseModel
class PersonInfo(BaseModel):
"""Information about a person."""
name: str | None = None
age: int | None = None
occupation: str | None = None
Jetzt können Sie einen Agent mit dem Azure OpenAI-Chatclient erstellen:
import os
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import AzureCliCredential
# Create the agent using Azure OpenAI Chat Client
agent = OpenAIChatCompletionClient(
model=os.environ["AZURE_OPENAI_CHAT_COMPLETION_MODEL"],
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
credential=AzureCliCredential(),
).as_agent(
name="HelpfulAssistant",
instructions="You are a helpful assistant that extracts person information from text."
)
Jetzt können Sie den Agenten mit einigen textuellen Informationen ausführen und das strukturierte Ausgabeformat mithilfe des response_format Schlüssels im options Dict angeben.
response = await agent.run(
"Please provide information about John Smith, who is a 35-year-old software engineer.",
options={"response_format": PersonInfo},
)
Bei einem Pydantischen Modellantwortformat enthält die Agentantwort die strukturierten Ausgaben in der value Eigenschaft als Modellinstanz:
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")
Verwenden einer JSON-Schemazuordnung
Wenn Sie bereits über ein JSON-Schema als Python-Zuordnung verfügen, geben Sie das Schema direkt als response_format-Wert im options-Dict weiter. In diesem Modus enthält response.value den analysierten JSON-Wert (in der Regel ein dict oder list) anstelle einer Pydantic-Modellinstanz.
person_info_schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
"occupation": {"type": "string"},
},
"required": ["name", "age", "occupation"],
}
response = await agent.run(
"Please provide information about John Smith, who is a 35-year-old software engineer.",
options={"response_format": person_info_schema},
)
if response.value:
person_info = response.value
print(f"Name: {person_info['name']}, Age: {person_info['age']}, Occupation: {person_info['occupation']}")
Beim Streaming gibt agent.run(..., stream=True) ein ResponseStream zurück. Der eingebaute Finalizer des Datenstroms verarbeitet automatisch das Parsing der strukturierten Ausgaben, sodass Sie Echtzeitaktualisierungen durchlaufen können und dann get_final_response() aufrufen, um das analysierte Ergebnis abzurufen.
# 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}")
Die gleiche Regel gilt, wenn es sich um response_format eine JSON-Schemazuordnung handelt: final_response.value enthält analysiertes JSON anstelle einer Pydantischen Modellinstanz.
Wenn Sie keine einzelnen Streamingupdates verarbeiten müssen, können Sie die Iteration vollständig überspringen – get_final_response() verwendet automatisch den Datenstrom:
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}")
Vollständiges Beispiel
# Copyright (c) Microsoft. All rights reserved.
import asyncio
from agent_framework.openai import OpenAIChatClient
from pydantic import BaseModel
"""
OpenAI Responses Client with Structured Outputs Example
This sample demonstrates using structured outputs capabilities with OpenAI Responses Client,
showing Pydantic model integration for type-safe response parsing and data extraction.
"""
class OutputStruct(BaseModel):
"""A structured outputs model for testing purposes."""
city: str
description: str
async def non_streaming_example() -> None:
print("=== Non-streaming example ===")
agent = OpenAIChatClient().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 Outputs 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 = OpenAIChatClient().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 outputs parsed
result = await stream.get_final_response()
if structured_data := result.value:
print("Structured Outputs (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 Outputs ===")
await non_streaming_example()
await streaming_example()
if __name__ == "__main__":
asyncio.run(main())