Ajanlarla Yapılandırılmış Çıktılar Üretme

Bu öğretici adımında, Azure OpenAI Sohbet Tamamlama hizmetine dayalı bir ajanla yapılandırılmış çıkışların nasıl üretileceği gösterilmektedir.

Önemli

Tüm aracı türleri yapılandırılmış çıkışları yerel olarak desteklemez. , ChatClientAgent uyumlu sohbet istemcileriyle kullanıldığında yapılandırılmış çıkışları destekler.

Önkoşullar

Önkoşullar ve NuGet paketlerini yükleme için bu öğreticideki Basit bir aracı oluşturma ve çalıştırma adımına bakın.

Yapılandırılmış çıkışlar için bir tür tanımlama

İlk olarak, aracıdan istediğiniz çıkışın yapısını temsil eden bir tür tanımlayın.

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

Aracıyı oluşturma

Azure AI Projeleri İstemcisi'ni kullanarak bir ChatClientAgent oluşturun.

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

Uyarı

DefaultAzureCredential geliştirme için uygundur ancak üretimde dikkatli bir şekilde dikkate alınması gerekir. Üretimde gecikme sorunları, istenmeyen kimlik bilgisi yoklama ve geri dönüş mekanizmalarından kaynaklanan olası güvenlik risklerini önlemek için belirli bir kimlik bilgisi (ör ManagedIdentityCredential. ) kullanmayı göz önünde bulundurun.

RunAsync<T ile yapılandırılmış çıkışlar>

RunAsync<T> yöntemi temel sınıfta kullanılabilirAIAgent. Yapılandırılmış çıkış türünü belirten genel bir tür parametresi kabul eder. Bu yaklaşım, yapılandırılmış çıkış türü derleme zamanında bilindiğinde ve türlenmiş bir sonuç örneğine ihtiyaç duyulduğunda geçerlidir. İlkelleri, dizileri ve karmaşık türleri destekler.

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

ResponseFormat ile yapılandırılmış çıkışlar

Yapılandırılmış çıkışlar, ResponseFormat özelliği, AgentRunOptions veya Foundry Aracısı gibi destekleyen aracılar için çağırma zamanında veya aracı başlatma zamanında ayarlanarak yapılandırılabilir.

Bu yaklaşım şu durumlarda geçerlidir:

  • Yapılandırılmış çıkış türü derleme zamanında bilinmemektedir.
  • Şema ham JSON olarak temsil edilir.
  • Yapılandırılmış çıkışlar yalnızca aracı oluşturma zamanında yapılandırılabilir.
  • Seri hale getirme olmadan yalnızca ham JSON metni gereklidir.
  • Aracılar arası işbirliği kullanılır.

için ResponseFormat çeşitli seçenekler mevcuttur:

Uyarı

Özdeğerler ve diziler, ResponseFormat yaklaşımı tarafından desteklenmez. Temel öğeler veya dizilerle çalışmanız gerekiyorsa yaklaşımı kullanın RunAsync<T> veya bir sarmalayıcı türü oluşturun.

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

ResponseFormat ham JSON şema dizesi kullanılarak da belirtilebilir. Bu, dış yapılandırmadan yüklenen bildirim temelli aracılar veya şemalar gibi karşılık gelen .NET türü olmadığında kullanışlıdır:

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

Akış ile yapılandırılmış çıkışlar

Akış yapılırken, ajan yanıtı bir dizi güncelleştirme olarak iletilir ve ancak tüm güncellemelere ulaşıldıktan sonra yanıt seri durumdan çıkartılabilir. Seri durumdan çıkarmadan önce tüm güncellemeleri tek bir yanıt içinde birleştirmeniz gerekir.

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

Yapılandırılmış çıkış özelliklerine sahip olmayan aracılarla yapılandırılmış çıkışlar

Bazı aracılar, yapılandırılmış çıkışları yerel olarak desteklemez, çünkü bunlar protokolün parçası değildir veya aracılar yapılandırılmış çıkış özellikleri olmadan dil modellerini kullanır. Olası bir yaklaşım, herhangi bir AIAgent'yi sarmalayan ve bir sohbet istemcisi aracılığıyla ek bir LLM çağrısı kullanarak aracının metin yanıtını yapılandırılmış JSON'a dönüştüren özel bir dekoratör aracı oluşturmaktır.

Uyarı

Bu yaklaşım yanıtı dönüştürmek için ek bir LLM çağrısına bağlı olduğundan, güvenilirliği tüm senaryolar için yeterli olmayabilir.

Bu deseni kendi gereksinimlerinize uyarlayabileceğiniz bir referans uygulaması için StructuredOutputAgent örneğine bakın.

Tip

Çalıştırılabilir örneklerin tamamı için .NET örnekleri bakın.

Akış örneği

Tip

Çalıştırılabilir örneklerin tamamı için .NET örnekleri bakın.

Bu öğretici adımında, Azure OpenAI Sohbet Tamamlama hizmetine dayalı bir ajanla yapılandırılmış çıkışların nasıl üretileceği gösterilmektedir.

Önemli

Tüm aracı türleri yapılandırılmış çıkışları desteklemez. , Agent uyumlu sohbet istemcileriyle kullanıldığında yapılandırılmış çıkışları destekler.

Önkoşullar

Önkoşullar ve paketleri yükleme için bu öğreticideki Basit bir aracı oluşturma ve çalıştırma adımına bakın.

Ajanı yapılandırılmış çıktı ile oluştur

, Agent yapılandırılmış çıkışları destekleyen tüm sohbet istemcisi uygulamalarının üzerine kurulmuştur. Agent istenen çıkış şemasını belirtmek için response_format anahtarını options sözlükte kullanır.

Aracıyı çalıştırırken şunları sağlayabilirsiniz:

  • Beklenen çıkışın yapısını tanımlayan bir Pydantic modeli.
  • JSON'un model sınıfı tanımlamadan ayrıştırılmasını istediğinizde JSON şema eşlemesi (dict).

Sözlüğü options çalışma zamanında agent.run(..., options={"response_format": ...}) aracılığıyla geçirebilir veya default_options sözlüğü aracılığıyla ajan oluşturma zamanında ayarlayabilirsiniz.

Temel alınan sohbet istemcisi özelliklerine göre çeşitli yanıt biçimleri desteklenir.

İlk örnek, Pydantic model şemasına uyan bir JSON nesnesi biçiminde yapılandırılmış çıkışlar üreten bir aracı oluşturur.

İlk olarak, aracıdan istediğiniz çıkışın yapısını temsil eden bir Pydantic modeli tanımlayın:

from pydantic import BaseModel

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

Artık Azure OpenAI Sohbet İstemcisi'ni kullanarak bir aracı oluşturabilirsiniz:

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

Artık aracıyı bazı metin bilgileriyle çalıştırabilir ve response_format anahtarını kullanarak options sözlükte yapılandırılmış çıkışlar biçimini belirtebilirsiniz.

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

Pydantic model yanıt formatı için, ajan yanıtı, yapılandırılmış çıkışları bir model örneği olarak value özelliğinde içerir.

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

JSON şema eşlemesi kullanma

Python eşlemesi olarak bir JSON şemanız zaten varsa, bu şemayı doğrudan response_format diktesindeki options değeri olarak geçirin. Bu modda, response.value Pydantic model örneği yerine ayrıştırılmış JSON değerini (genellikle dict a veya list) içerir.

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

Akış yaparken agent.run(..., stream=True) bir ResponseStream döndürür. Akışın yerleşik sonlandırıcısı, yapılandırılmış çıkışları ayrıştırmayı otomatik olarak işler, böylece gerçek zamanlı güncellemeler için yineleyebilirsiniz ve ardından ayrıştırılmış sonucu elde etmek için get_final_response() çağrısını yapabilirsiniz.

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

Aynı kural bir JSON şema eşlemesi olduğunda response_format da geçerlidir: final_response.value Pydantic model örneği yerine ayrıştırılmış JSON içerir.

Tek tek akış güncelleştirmelerini işlemeniz gerekmiyorsa yinelemeyi tamamen atlayabilirsiniz; get_final_response() akışı otomatik olarak kullanır:

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

Tam örnek

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

Yapılandırılmış çıkış

Go aracıları, agent.WithStructuredOutput seçeneği aracılığıyla yapılandırılmış çıktıyı destekler. Go yapısı tanımladığınızda çerçeve JSON şemasını otomatik olarak oluşturur ve yanıtın özetini geri alır.

Çıkış türünü tanımlama

type PersonInfo struct {
    Name       string `json:"name"`
    Age        int    `json:"age"`
    Occupation string `json:"occupation"`
}

Yapılandırılmış çıkış talep et

Ajanı çağırmak ve yanıtı ayrıştırmak için genel amaçlı bir yardımcı kullanın:

import (
    "context"
    "fmt"

    "github.com/microsoft/agent-framework-go/agent"
)

func runFor[T any](ctx context.Context, a *agent.Agent, message string, opts ...agent.Option) (T, error) {
    var v T
    opts = append(opts, agent.WithStructuredOutput(&v), agent.Stream(false))
    for _, err := range a.RunText(ctx, message, opts...) {
        if err != nil {
            return v, err
        }
    }
    return v, nil
}

person, err := runFor[PersonInfo](ctx, a,
    "Please provide information about John Smith, who is a 35-year-old software engineer.")
fmt.Println("Name:", person.Name)
fmt.Println("Age:", person.Age)

Aracı düzeyinde yanıt biçimini belirtme

Ayrıca, aracı yapılandırmasında yanıt biçimini ayarlayarak tüm çalıştırmaların yapılandırılmış çıkış üretmesini sağlayabilirsiniz:

import "github.com/microsoft/agent-framework-go/agent/format/jsonformat"

a := foundryprovider.NewAgent(endpoint, token, foundryprovider.ModelDeployment(model), foundryprovider.AgentConfig{
    Instructions: "You are a helpful assistant.",
    Config: agent.Config{
        RunOptions: []agent.Option{
            agent.WithResponseFormat(jsonformat.MustFor[PersonInfo]()),
        },
    },
})

Tip

Tam bir çalıştırılabilir örnek için bkz. tam örnek .

Sonraki Adımlar