Erken erişim programına katıl
Agent'tan Düzyazı Değil Veri İsteyin
Blog
Mühendislik8 dk okuma

Agent'tan Düzyazı Değil Veri İsteyin

KA

Kerem Aksoy

Geliştirici Platformu Lideri, Botonom

Bir agent API'si üstüne kurulan her entegrasyon aynı yerden başlıyor: bir modelin yazdığı cümleye nişan almış bir düzenli ifade. İstediğiniz şekli tarif etmek o ayrıştırmayı ortadan kaldırıyor; arkasındaki tasarım kararları ise özelliğin kendisinden daha ilginç.

Entegrasyonunuz düzyazı istemiyor. Toplayabileceği bir sayı, dallanabileceği bir durum, döngüye sokabileceği bir liste istiyor. Bu haftaya kadar Botonom komut API'si ona bir paragraf veriyor, ayrıştırmayı size bırakıyordu.

Bir yapay zeka agent API'sinden yapılandırılmış veri almanın yolu, talimatla birlikte istediğiniz şekli göndermek ve tipli nesneyi düzyazının yanında geri okumaktır. Agent'ın kendi cevabı düzyazı kalmalıdır; insanın okuduğu ve dosyaları taşıyan şey odur. Nesne ise biten turun sizin şemanıza okunmasıyla üretilir. Bu yaklaşımın yerine geçtiği hata biçimi, cümleleri düzenli ifadeyle ayrıştırmaktır ve o yöntem yazdığınız gün değil, modelin bir cümleyi başka türlü kurduğu gün patlar.

Önceden bir çalışma neye benziyordu

POST /v1/agents/command işi baştan beri yapabiliyordu. Agent kendi persona'sı, yetenekleri ve izinleriyle headless çalışıyor, gereken araçları çağırıyor, dosya üretiyor. Cevap result_text içinde, insan için yazılmış olarak dönüyordu.

Dolayısıyla üstüne kurulan her entegrasyon, bir modelin yazdığı cümleye nişan almış bir düzenli ifadeyle başlıyordu. O ayrıştırma yazdığınız gün yanlış değil. Üç hafta sonra, agent aynı toplamı başka türlü ifade ettiğinde ve ifadeniz sessizce yanlış rakamı yakaladığında yanlış. Hiçbir şey hata fırlatmıyor. Sayı o günden sonra sadece yanlış.

Ne değişti

İstediğiniz şekli tarif ediyorsunuz ve aynı çalışma onu döndürüyor.

json
POST /v1/agents/command
{
  "agent_id": "<agent-uuid>",
  "instruction": "Bu ayın siparişlerini incele ve ciroyu özetle.",
  "schema": {
    "type": "object",
    "properties": {
      "toplam_ciro":    { "type": "number", "description": "adet x fiyat toplamı" },
      "en_yuksek_urun": { "type": "string", "description": "En çok ciro getiren ürünün adı" }
    },
    "required": ["toplam_ciro", "en_yuksek_urun"]
  }
}

command_status iki yarıyı birden taşıyor:

json
{
  "status": "completed",
  "result_text": "Bu ayın cirosu 27.400 TL; en çok Masa kazandırdı...",
  "output": { "toplam_ciro": 27400, "en_yuksek_urun": "Masa" },
  "output_error": null
}

Düzyazı yerinde duruyor. Panelde çalışmayı açan bir insanın okuduğu şey o; JSON'a yer açmak için onu kaldırmak, bir kitleyi diğeriyle takas etmek olurdu.

Nesne neden tura dayatılmıyor da turdan okunuyor

Akla gelen ilk uygulama, agent'ın kendi cevabını şemayla kısıtlamak. Bunu yapmadık ve sebebi yazılmaya değer, çünkü aynı şeyi kuran herkes için geçerli.

Bir agent turu tek bir tamamlama değil. Bir döngü: model araç çağırır, sonucu okur, yine çağırır ve sonunda bir cevap yazar. O cevabın üstünde üç şey oturuyor ve şema kısıtı üçüyle birden kavga ediyor.

Cevabın taşıdığıŞema kısıtının ona yaptığı
Araç döngüsüSon mesaja uygulanan yanıt biçimi, modelin araç çağırmayı sürdürme serbestisini geri çeker
Medya işaretleriGrafik ve dosyalar cevap metnindeki işaretlerle iliştirilir, bir JSON nesnesinin onları koyacak yeri yoktur
PersonaHer agent'ın bir sesi, dil kuralı ve düzyazı üreten davranış kuralları vardır

Bu yüzden tur hiç dokunulmadan koşuyor, ikinci ve çok daha küçük bir geçiş biten turu istenen şekle okuyor. Agent, siz yapı istemeden önce nasıl davranıyorsa aynen öyle davranıyor. Nesne istemek aldığınız şeyi değiştiriyor, agent'ın yaptığını değil.

Bedeli komut başına bir ek model çağrısı: küçük bir model, kısa bir girdi. Karşılığında iki yarı da bozulmuyor; insan düzyazıyı, kod veriyi alıyor.

Şema göndermezseniz ne alıyorsunuz

schema alanını boş bırakmak sizi cümle ayrıştırmaya geri döndürmüyor. Çalışma yine bir nesne döndürüyor, standart bir zarfla:

AlanAnlamı
resultok, partial, needs_input, refused veya failed
summaryTek cümle, talimatınızın dilinde
follow_upAgent'ın sizden hâlâ ihtiyaç duyduğu şey, yoksa null
actionsGerçekten kullandığı yetenekler
filesÜrettiği dosyalar

Zarf bilerek küçük. Her çağıranın sorduğu dört soruyu cevaplıyor ve başka bir şey yapmıyor: oldu mu, tek cümlede ne oldu, ne yaptı, ne çıktı. Daha büyük bir varsayılan, modeli kimsenin okumadığı alanları doldurmaya davet ederdi.

Asıl mesele şu: uç, birileri istemeyi hatırladığında değil, varsayılan olarak programlanabilir.

Modele hiç sorulmayan iki alan

actions ve files modelin yazdığı alanlar değil. Turun kendisinden hesaplanıyor.

Bu bilinçli bir çizgi ve bize göre özelliğin en işe yarar fikri. Hangi araçların koştuğu, platformun zaten elinde olan bir olgu. Hangi dosyaların üretildiği, istemcinin ekrana bastığı işaretlerde kayıtlı. Modelden zaten sahip olduğu olguları tekrar etmesini istemek, iki araç çağıran bir çalışmanın üç diye raporlanma yoludur; yüklenemeyen bir dosyanın "eklendi" diye anlatılma yolu da aynı.

Bu yüzden modele yalnızca gerçekten dilsel olan kısımlar soruluyor: bir özet, bir sonuç kelimesi, bekleyen bir şey varsa o. Kontrol edilebilir olan her şey sorulmuyor, kontrol ediliyor.

O ayrımdan bir ayrıntı. Agent'ın kendi çalışma hafızası aracı actions listesinden süzülüyor. Üretimde en çok çağrılan araç odur; bırakılsaydı çağıranın gerçekten önemsediği iki çağrıyı ev işlerinin altına gömerdi.

"Zorunlu değil" null demek, ve bu bilinçli

Katı yapılandırılmış çıktının, elle yazılmış hiçbir şemada bulunmayan iki şartı var: her nesne additionalProperties: false bildirmeli ve her alan required içinde geçmeli. İlk canlı denememiz tam da buna takıldı ve çoğu geliştiricinin hiç okumaması gereken bir hata verdi:

text
Invalid schema for response_format: 'additionalProperties' is required to be supplied and to be false.

Bunu çağırana yıkmak basit bir özelliği tatsız hale getirirdi, o yüzden şemayı platform normalize ediyor. required dışında bıraktığınız alan, zorunlu ama null olabilir hale geliyor.

Yan etkisi çözümün kendisinden iyi çıktı. Zorunlu işaretlemediğiniz alan output içinde her zaman var ve çalışma onu üretmediyse null. "Alan yok mu, null mı" ayrımını hiç yapmıyorsunuz, çünkü ikisinden yalnızca biri var.

Şema, gerçeklikle yapılmış bir sözleşme değil

output null olabilir. Olduğunda output_error sebebini söylüyor ve çalışma yine completed, düzyazı cevabı da yerinde. Doldurulamayan bir şekil başarısız bir iş değildir; çalışmayı düşürmek, agent'ın gerçekten yaptığı işi çöpe atmak olurdu.

Desteklenen alt küme bilerek küçük: string, number, integer, boolean, array, object, en fazla elli alan, beş seviye derinlik. Fazlası istek anında ve yolu söylenerek reddediliyor:

text
400 SCHEMA_INVALID
schema is not supported: properties.when: unsupported type "date"

Kabul edilip sessizce yok sayılan bir şema, reddedilenden kötüdür: sorunu çalışmanın yanlış ucunda öğrenirsiniz.

Kendi ilk testimizde yaptığımız hata

product_count diye bir alan istedik ve açıklamasını yazmadık. Çalışma 18 döndürdü. Tabloda üç ürün ve on sekiz adet vardı; alan adının iki okuması da savunulabilir.

Bir alandaki description insanlar için dokümantasyon değil. Agent'ın okuduğu talimat. Tek cümle meseleyi kapatırdı:

json
"product_count": {
  "type": "integer",
  "description": "KAÇ FARKLI ürün geçiyor, satılan adet değil"
}

Dikkatli bir meslektaşın iki türlü okuyabileceği bir alan adı, yeterince çok çalışmada agent tarafından iki türlü de okunur. Alanı adlandırmak işin yarısı; onunla ne kastettiğinizi söylemek diğer yarısı.

Bu nereye oturuyor

Komut ucu zaten yazılımın bir agent'ı sürme yoluydu. Bu, diğer yarıyı kapatıyor: yazılım artık cevabı düzyazıdan tahmin etmeden okuyabiliyor. Varsayılan zarf ve doğrulama kuralları dahil tam sözleşme API dokümantasyonunda.

Görmenin en hızlı yolu bir tane göndermek: API Playground kendi anahtarınızla kendi agent'ınıza gerçek bir komut yolluyor ve schema alanı istek gövdesinde düzenlenmeyi bekliyor.

Sık sorulan sorular

Şema istemek agent'ın davranışını değiştirir mi?

Hayır. Tur önce ve değişmeden koşuyor, nesne biten turdan okunuyor. Aynı araçlar, aynı cevap, aynı dosyalar. Kısıtlı yanıt yerine ikinci geçiş olarak kurulmasının sebebi tam da bu.

Agent şemamı dolduramazsa ne olur?

output null döner ve output_error sebebini açıklar. Çalışma yine tamamlanır, result_text agent'ın cevabını taşımaya devam eder. Şekil oturmadı diye iş kaybetmezsiniz.

Her isteğe şema göndermeli miyim?

Yalnızca cevabı kodunuzun okuduğu yerlerde. Çıktısını bir insanın okuduğu bir çalışma için varsayılan zarf zaten daha iyisini yapıyor: hiçbir şey tasarlamadan işin olup olmadığını ve ne yapıldığını söylüyor.

Kısıtlı otonomi ile kullanabilir miyim?

Evet. Cevabın şekli ile agent'ın aksiyon alma izni birbirinden bağımsız iki ayardır. Yazabilen ama aksiyon alamayan bir çalışma da yapılandırılmış cevabını aynı şekilde döndürür.

Nesne, metin cevabın yerine mi geçiyor?

Hayır, birlikte geliyorlar. Biri çalışmayı okuyan insan için, diğeri sizin kodunuz için; ikisi de her zaman var.

Şemanın boyut sınırı var mı?

Elli alan ve beş seviye derinlik. İkisine de yaklaşıyorsanız, talimat genelde iki iş birden yapıyordur ve iki şekille iki komuta bölmek daha iyidir.

AI çalışanlarınız işe başlamaya hazırSiz işe almaya hazır mısınız?

Kredi kartı gerekmez5 dakikada kurulumİstediğiniz zaman iptal