python-sdk/i18n/tr/pages/servers/structured-output.md

10 KiB
Raw Blame History

translation
sections tool
a838d57f003aed44
857d03886a0137ed
42d9efcb9f542867
2290ff08435b5573
e866c192e11d1c14
6cdbad079f7b47f0
d4b607372fb28b51
18dbf726ac45e0b7
c6f7d2a148aa49f4
c851964bb3301907
d715db6f8dccc9cc
ef86634aa70498a7
1

Yapılandırılmış çıktı

Düz bir str döndüren bir araç, sonucu iki kez üretir: content içinde metin olarak ve structured_content içinde {"result": "..."} olarak.

Bu sayfa o ikinci kanalla ilgili: nereden geldiği, alabileceği her biçim ve SDK'nın onu nasıl tutarlı tuttuğu.

Kısaca: dönüş türü açıklaması (annotation) çıktı şemasıdır. Onu zaten yazdınız.

Çıktı şeması

--8<-- "docs_src/structured_output/tutorial001.py"

Önemli olan satır imza: -> int.

Bu sayede SDK'nın tools/list sırasında gönderdiği araç, parametrelerinizden oluşturduğu girdi şemasının yanında (onu Araçlar sayfası anlatır) bir de output_schema taşır:

{
  "properties": {
    "result": {"title": "Result", "type": "integer"}
  },
  "required": ["result"],
  "title": "get_temperatureOutput",
  "type": "object"
}

Tek başına bir int JSON nesnesi değildir, bu yüzden SDK onu {"result": ...} içine sarar. Aracı çağırdığınızda iki kanal da dolar:

result.content             # [TextContent(text="17")]
result.structured_content  # {"result": 17}

Her skaler aynı sarmalayıcıyı alır: str, int, float, bool, bytes, None.

İki kanal

Neden aynı değer iki kez gönderiliyor?

  • content model içindir. Bir dil modeli metin okur; sonucun gördüğü tek kısmı budur.
  • structured_content, modelin içinde çalıştığı uygulama içindir: "17" geçen bir cümle değil, 17 isteyen kod.
  • output_schema ikisi arasındaki sözleşmedir ve araç daha hiç çağrılmadan yayımlanır.

Siz tek bir Python değeri döndürürsünüz. Üçünü de SDK doldurur.

Bir model döndürme

Biçimi bir Pydantic BaseModel olarak bildirin ve bir örneğini döndürün:

--8<-- "docs_src/structured_output/tutorial002.py"

Artık şema WeatherData'nın kendisi. Sarmalayıcı yok, result anahtarı yok:

{
  "properties": {
    "temperature": {"description": "Degrees Celsius.", "title": "Temperature", "type": "number"},
    "humidity": {"description": "Relative humidity, 0 to 1.", "title": "Humidity", "type": "number"},
    "conditions": {"title": "Conditions", "type": "string"}
  },
  "required": ["temperature", "humidity", "conditions"],
  "title": "WeatherData",
  "type": "object"
}

structured_content alan alan o nesnedir:

result.structured_content  # {"temperature": 16.2, "humidity": 0.83, "conditions": "Overcast"}

Model de dışarıda kalmaz. SDK aynı nesneyi content için JSON metnine serileştirir:

{
  "temperature": 16.2,
  "humidity": 0.83,
  "conditions": "Overcast"
}

temperature ve humidity üzerindeki Field(description=...) bilgisinin şemaya düştüğüne dikkat edin. Girdilerinizi tanımlayan aynı Field, çıktılarınızı da tanımlar.

!!! info FastAPI'nin response_model'ını kullandıysanız bunu zaten biliyorsunuz: bildirilen yanıt olarak bir Pydantic modeli, sizin yerinize serileştirilir ve belgelenir. Tek fark, burada bildirimin tamamının dönüş açıklaması olmasıdır.

Bir TypedDict

Her biçim bir sınıfı hak etmez. Bir TypedDict aynı şemayı üretir:

--8<-- "docs_src/structured_output/tutorial003.py"

TypedDict çalışma zamanında düz bir dict'tir; siz de onu oluşturup döndürürsünüz. Şema, doğrulama ve structured_content, BaseModel sürümüyle birebir aynıdır (TypedDict'te yeri olmayan açıklamalar hariç).

Bir dataclass

Dataclass'lar da çalışır; öznitelikleri tür ipucu taşıyan herhangi bir sıradan sınıf da öyle. SDK arka planda açıklamalardan bir Pydantic modeli oluşturur.

--8<-- "docs_src/structured_output/tutorial004.py"

Üç yazım, tek şema. Kod tabanınızda hangisi varsa onu kullanın.

Listeler

Bir list[...] de JSON nesnesi değildir, bu yüzden {"result": ...} sarmalayıcısını alır; öğe türünüz içinde bir $defs başvurusu olarak yer alır:

--8<-- "docs_src/structured_output/tutorial005.py"
{
  "$defs": {
    "WeatherData": {
      "properties": {
        "temperature": {"title": "Temperature", "type": "number"},
        "humidity": {"title": "Humidity", "type": "number"},
        "conditions": {"title": "Conditions", "type": "string"}
      },
      "required": ["temperature", "humidity", "conditions"],
      "title": "WeatherData",
      "type": "object"
    }
  },
  "properties": {
    "result": {"items": {"$ref": "#/$defs/WeatherData"}, "title": "Result", "type": "array"}
  },
  "required": ["result"],
  "title": "get_forecastOutput",
  "type": "object"
}

İki günlük bir tahmin istediğinizde structured_content, {"result": [{...}, {...}]} olur. content ise öğe başına bir tane olmak üzere iki TextContent bloğuna dönüşür: liste, model için tek bir dizge olarak dökülmek yerine düzleştirilir.

tuple[...], union'lar ve Optional[...] aynı şekilde sarılır.

Sözlükler

dict[str, ...] zaten bir JSON nesnesi olan tek generic türdür, bu yüzden sarılmaz:

--8<-- "docs_src/structured_output/tutorial006.py"
{
  "additionalProperties": {"type": "number"},
  "title": "get_temperaturesDictOutput",
  "type": "object"
}
result.structured_content  # {"London": 16.2, "Reykjavik": 4.4}

Anahtarlar str olmalıdır. Bir dict[int, float] JSON nesnesi olamaz, bu yüzden {"result": ...} sarmalayıcısına geri düşer.

Doğrulama

output_schema belgeleme değildir. Fonksiyonunuz ne döndürürse döndürsün, sunucudan çıkmadan önce ona göre doğrulanır.

Değeri elle oluşturduğunuz sürece bunu fark etmezsiniz: Pydantic, WeatherData'nızın bir WeatherData olduğundan zaten emin olmuştur. Bunu, verinin sizin denetlemediğiniz bir yerden geldiği gün fark edersiniz:

--8<-- "docs_src/structured_output/tutorial007.py"

Açıklama WeatherData vaat ediyor. Üst servisin yanıtı humidity göndermeyi bırakmış.

!!! check get_weather'ı çağırdığınızda istemciye sessizce yarı boş bir nesne vermez. Çağrı başarısız olur ve hatanın ilk satırları alanın adını verir:

```text
Error executing tool get_weather: 1 validation error for WeatherData
humidity
  Field required [type=missing, input_value={'temperature': 16.2, 'conditions': 'Overcast'}, input_type=dict]
```

Bu metin, `is_error=True` ile araç sonucu olarak geri döner; böylece model, var olmayan bir hava
durumunu kendinden emin biçimde okumak yerine çağrının başarısız olduğunu bilir.

Bu arada, -> WeatherData bir araçtan düz bir dict döndürmek sorun değil. json.loads'un ürettiği tam olarak buydu. Doğrulama Python türüne değil, değere uygulanır.

Devre dışı bırakma

Bazen dönüş açıklaması protokol için değil, tür denetleyiciniz içindir. structured_output=False geçirin; araç yalnızca metin üretir:

--8<-- "docs_src/structured_output/tutorial008.py"

output_schema yok, sarmalama yok, doğrulama yok. structured_content None'dır ve content döndürdüğünüz dizgedir.

Tersi olan structured_output=True, otomatik algılamayı bir zorunluluğa çevirir: dönüş türü şema üretemeyen bir araç, metne geri düşmek yerine içe aktarma anında istisna fırlatır.

Tür ipucu olmayan bir sınıf

İstemeden yapılandırılmamış sonuca varmanın bir yolu vardır: gövdesinde hiç açıklama olmayan bir sınıf döndürmek.

--8<-- "docs_src/structured_output/tutorial009.py"

Station, name ve online değerlerini __init__ içinde atar, ama sınıf hiçbir şey bildirmez. SDK sınıf açıklamalarını okur, hiçbir şey bulamaz ve vazgeçer.

!!! warning Sessizce vazgeçer. output_schema None'dır, structured_content None'dır ve modelin okuduğu metin nesnenin repr'idir:

```text
"<server.Station object at 0x7f539d75b230>"
```

Hata yok, uyarı yok, işe yaramaz bir araç. Açıklamaları sınıf gövdesine taşıyın ya da
`structured_output=True` geçirin; bu, modül içe aktarıldığı anda durumu kesin bir hataya çevirir:
`Function get_station: return type <class 'server.Station'> is not serializable for structured output`.

!!! tip Tam denetim mi gerekiyor (CallToolResult'ı kendiniz oluşturmak ya da uygulamanın görüp modelin göremediği bir _meta eklemek)? Bunun yeri Düşük seviyeli Server.

Özet

  • Dönüş türü açıklaması çıktı şemasıdır. tools/list içinde output_schema olarak yayımlanır.
  • Skalerler, listeler, tuple'lar ve union'lar {"result": ...} içine sarılır. Modeller, TypedDict'ler, dataclass'lar, açıklamalı sınıflar ve dict[str, ...] zaten nesnedir ve oldukları gibi kalırlar.
  • Her sonuç hem content (metin, model için) hem de structured_content (veri, uygulama için) taşır.
  • Döndürdüğünüz şey şemaya göre doğrulanır. Uyuşmazlık bozuk bir sonuç değil, bir araç hatasıdır.
  • structured_output=False bir aracı devre dışı bırakır. Tür ipucu olmayan bir sınıf sessizce devre dışı kalır; buna dikkat edin.

Artık bir aracın geri söyleyebileceği her şeye hâkimsiniz. Sırada ikinci ilkel yapı var: Kaynaklar.