Testiniz Pazartesi günü geçti: aynı girdi, aynı kod ve temperature=0. Salı günü ise siz hiçbir şeyi değiştirmeden başarısız oldu. Onaylama tam dize eşleşmesi arıyordu, model de aynı cevabı farklı biçimde ifade etti. Test kırmızı, ajan doğru çalışıyor ve artık ürün yerine test paketinizi hata ayıklıyorsunuz.
Bir dil modeli kullanan sistemlerde bu durum normaldir. Çıktı, istemeseniz de değişebilir. temperature=0 ayarlasanız bile çalıştırmalar arasında bayt düzeyinde özdeş yanıt garantisi yoktur. Bu yüzden testleri tam metne değil, değişmeyen sözleşmeye göre tasarlamanız gerekir. Bu yazı, yapay zeka ajanlarının üretimde neden bozulduğuna dair kılavuzumuzdaki üçüncü hata moduna odaklanır.
Neden temperature=0 belirleyici değildir?
Sıcaklık, modelin sonraki token'ı nasıl örneklediğini kontrol eder. Sıfırda model en olası token'ı seçer; bu da teoride yeniden üretilebilir görünür. Pratikte ise çıkarım altyapısı sonucu etkiler.
GPU'larda kayan noktalı işlemler ilişkilendirici değildir. Aynı sayıları farklı sırayla toplamak, son ondalık basamaklarda farklı sonuçlar üretebilir. Bu küçük fark, en yüksek olasılıklı token'ın değişmesine neden olabilir. İlk token değiştiğinde, devamındaki tüm çıktı da değişebilir.
Bu işlem sırası şunlara bağlı olabilir:
- Sağlayıcının istekleri nasıl toplu işlediği
- İsteğin hangi donanımda çalıştığı
- Dağıtılan çekirdek veya çıkarım kütüphanesi sürümü
- Çağrının yönlendirildiği bölge
- Model ağırlıklarının veya nicemleme yapılandırmasının değişmesi
vLLM üzerindeki bu uzun tartışma, sabit çekirdek ve temperature=0 kullanılsa bile bit düzeyinde yeniden üretilebilirliğin neden garanti olmadığını açıklar.
Özet: determinizm, API isteğinde ayarladığınız tek bir bayrak değildir. Tüm sunum yığınının özelliğidir.
Bu nedenle test varsayımınızı değiştirin:
- Yanlış varsayım: “Model tam olarak bu metni döndürmeli.”
- Doğru varsayım: “Model, sözleşmedeki yapıyı ve iş kurallarını karşılayan bir yanıt döndürmeli.”
Tam dize onaylamaları neden kararsız test üretir?
Şu test ilk çalıştırmada mantıklı görünebilir:
assert response == "Siparişinizin toplamı 42,00 $'dır."
Ancak model sonraki çalıştırmada aşağıdakini döndürürse test başarısız olur:
Toplamınız 42,00 $'a geliyor.
Yanıt doğru olduğu halde test kırmızıya döner.
Doğru yanıtta başarısız olan testler, hiç test olmamasından daha zararlıdır. Ekip zamanla bu testleri tekrar çalıştırmayı, başarısızlıkları görmezden gelmeyi ve gerçek regresyonları gürültü içinde kaçırmayı öğrenir. Kararsız testlerin nedenleri ve nasıl yayıldıkları bu yüzden önemlidir.
Tam dize eşleşmesi, snapshot veya metin farkı alma yaklaşımı genellikle sorunu çözmez. Testi, değişmesi en muhtemel katmana bağlamış olursunuz.
Bunun yerine yapıyı, türleri, sınırları ve iş kurallarını doğrulayın.
Tam metin yerine yapıyı ve anlamı doğrulayın
Bir destek ajanı geri ödeme onayını onlarca farklı şekilde yazabilir. Ancak geçerli her yanıt aynı temel bilgileri taşımalıdır:
- Geri ödeme miktarı
- Sipariş kimliği
- İşlem durumu
- Kullanıcıya gösterilmesi güvenli açıklama
Testlerinizin hedefi cümle yapısı değil, bu sözleşme olmalıdır.
Aşağıdaki stratejileri birlikte kullanın.
Yanıtı JSON şemasına göre doğrulayın
Ajanınız yapılandırılmış veri döndürüyorsa, önce bir JSON şeması tanımlayın. Ardından her yanıtı bu şemaya göre doğrulayın.
Örnek bir geri ödeme yanıtı:
{
"order_id": "ORD-12345",
"status": "refunded",
"amount": 42.0,
"currency": "USD",
"resolution": "Geri ödeme işlemi başlatıldı."
}
Bu yanıt için şema:
{
"type": "object",
"required": [
"order_id",
"status",
"amount",
"currency",
"resolution"
],
"properties": {
"order_id": {
"type": "string",
"pattern": "^ORD-[0-9]+$"
},
"status": {
"type": "string",
"enum": ["refunded", "pending", "denied"]
},
"amount": {
"type": "number",
"minimum": 0
},
"currency": {
"type": "string",
"enum": ["USD", "EUR", "TRY"]
},
"resolution": {
"type": "string",
"minLength": 1
}
},
"additionalProperties": false
}
Bu yaklaşım şu hataları yakalar:
- Modelin zorunlu alanı atlaması
- Sayı yerine dize döndürmesi
- Nesneyi yanlış iç içe yerleştirmesi
- Beklenen JSON yerine düz metin döndürmesi
- Geçersiz durum değeri üretmesi
Yanıt şemanızı Apidog'a yükleyerek canlı veya test yanıtlarını doğrulayabilirsiniz. Böylece hata mesajı, yüzlerce karakterlik metin farkı yerine bozuk alanı gösterir.
Araç çağrılarının şeklini ve hedefini doğrulayın
Ajan bir araç çağırdığında, çağrıyı üreten doğal dil açıklamasını değil, aracın kendisini test edin.
Her araç çağrısında üç soruyu yanıtlayın:
- Doğru araç seçildi mi?
- Doğru uç nokta veya hedef kullanıldı mı?
- Gönderilen yük araç şemasıyla eşleşiyor mu?
Örneğin bir rezervasyon ajanı şu çağrıyı üretiyorsa:
POST /reservations
Gönderilen yükü doğrulayın:
{
"date": "2025-06-20",
"guests": 2,
"customer_id": "CUS-1001"
}
Örnek kontroller:
assert tool_call["name"] == "create_reservation"
assert tool_call["method"] == "POST"
assert tool_call["path"] == "/reservations"
payload = tool_call["body"]
assert isinstance(payload["guests"], int)
assert payload["guests"] > 0
assert "date" in payload
assert "customer_id" in payload
assert "internal_reasoning" not in payload
Bu test, modelin “rezervasyonunuzu oluşturdum” veya “hemen rezervasyonunuzu hazırlıyorum” demesinden etkilenmez. Önemli olan, API sözleşmesine uygun isteği göndermesidir.
Bir ajanın API çağrılarını test etmeye yönelik uçtan uca yöntem, araç şemalarını yakalama ve bunlara göre onaylama sürecini ayrıntılı olarak ele alır.
Tam değer yerine sayısal aralık kullanın
Modelin ürettiği veya aktardığı sayılarda tam eşleşme yerine geçerli aralıkları doğrulayın.
Örneğin, bir alışveriş sepeti ajanının toplam tutarı hesapladığını düşünün. Her sepet için kesin rakamı test içinde sabitlemek yerine bilinen iş sınırlarını kullanın:
assert response["total"] >= 0
assert response["total"] <= cart_subtotal + max_shipping + max_tax
Bu kontroller şunları yakalar:
- Negatif toplam
- Mantıksız derecede yüksek toplam
- Dolu sepet için sıfır toplam
- Sayısal olmayan değer
Aynı yaklaşım şuralarda da kullanışlıdır:
- Güven skorları
- Öğe sayıları
- Token kullanımı
- Gecikme bütçeleri
- İndirim oranları
- Tahmini teslimat süreleri
Kural basit: Gerçek hata oluştuğunda başarısız olacak en geniş sınırı seçin.
Zorunlu alanları ve yasaklı alanları kontrol edin
İki basit kontrol, yüksek değer sağlar:
- Gerekli alanlar mevcut ve
nulldeğil mi? - Asla görünmemesi gereken alanlar yok mu?
Örnek:
required_fields = ["order_id", "status", "resolution"]
for field in required_fields:
assert field in response
assert response[field] is not None
forbidden_fields = ["internal_notes", "raw_prompt", "system_message"]:
assert field not in response
Bir destek ajanı müşteriye resolution alanını döndürmelidir. Ancak internal_notes, raw_prompt veya sistem mesajını asla döndürmemelidir.
Bu kontroller metinden bağımsızdır. Ayrıca modelin yararlı olmaya çalışırken gizli verileri sızdırmasına karşı düşük maliyetli bir güvenlik katmanı sağlar.
Serbest metinde anlamsal ve eşik kontrolleri kullanın
Bazı yanıtlar kaçınılmaz olarak düz metindir. Bu durumda tam eşleşme yerine ölçülebilir özellikleri kontrol edin.
Örnek:
assert order_id in response_text
assert len(response_text) <= 500
assert "şifre" not in response_text.lower()
assert "sistem mesajı" not in response_text.lower()
Kontrol edebileceğiniz özellikler:
- Girdi sipariş numarasının yanıt içinde bulunması
- Maksimum karakter veya kelime sınırı
- Yasaklı ifadelerin bulunmaması
- Beklenen bağlantının veya yönlendirmenin yer alması
- Gerekli açıklama veya uyarının mevcut olması
Gerçekten anlamsal yakınlığı ölçmeniz gerekiyorsa, yanıtı referans cevaba yerleştirme benzerliği ile karşılaştırabilir ve eşik belirleyebilirsiniz:
similarity = cosine_similarity(response_embedding, expected_embedding)
assert similarity >= 0.82
Ancak bu kontrolü hassas bir doğruluk kapısı olarak kullanmayın. Anlamsal benzerlik, konu dışına çıkan yanıtları yakalamada faydalıdır; ince iş mantığı hatalarını tek başına güvenilir biçimde yakalayamaz. Şema, tür, sınır ve güvenlik kontrolleriyle birlikte kullanın.
Tam snapshot yerine snapshot aralığı kullanın
Snapshot testleri tamamen bırakmanız gerekmez. Ancak serbest metni dondurmak yerine kararlı özelliklerin anlık görüntüsünü alın.
Örneğin şu yapı korunabilir:
{
"keys": ["amount", "currency", "order_id", "resolution", "status"],
"status_enum": ["refunded", "pending", "denied"],
"amount_range": [0, 10000]
}
Bu yaklaşım, aşağıdaki değişikliklerde testi başarısız kılar:
- Alanın kaldırılması
- Alan türünün değiştirilmesi
- Yeni ve beklenmeyen alan eklenmesi
- Enum dışı değer dönmesi
- Sayısal sınırın aşılması
Ancak resolution metnindeki eş anlamlı değişiklikler nedeniyle başarısız olmaz.
Durum ve bellek testi zorlaştırır
Yukarıdaki örnekler tek istek ve tek yanıt varsayar. Ajanlar genellikle konuşmalar arasında bellek taşır.
Durumlu bir ajanın yanıtı şunlara bağlıdır:
- Geçerli kullanıcı girdisi
- Önceki dönüşlerde saklanan bellek
- Araç çağrılarının sırası
- Alma veya arama sonuçlarının sıralaması
- Önceki dönüşlerde üretilen özetler
Bu nedenle aynı konuşma iki farklı çalıştırmada farklı sonuç verebilir. Bunun nedeni hem modelin belirsizliği hem de başlangıç durumunun değişmesidir.
Yapay zeka ajanı belleğinin nasıl çalıştığına dair açıklayıcı, bu durumun nerede tutulduğunu ve nasıl oluştuğunu ele alır.
Durumlu ajanları test ederken iki alışkanlık uygulayın.
1. Başlangıç durumunu sabitleyin
Her testten önce bellek ve konuşma durumunu bilinen bir başlangıç noktasına getirin.
def setup_test_agent():
agent.reset_memory()
agent.seed_memory({
"customer_id": "CUS-1001",
"active_order_id": "ORD-12345"
})
Böylece test başarısız olduğunda hem istemin hem belleğin aynı anda değişip değişmediğini tahmin etmek zorunda kalmazsınız.
2. Yoldan bağımsız değişmezleri doğrulayın
Ajanın hangi ara adımları attığından bağımsız olarak geçerli olması gereken kuralları test edin.
Örnekler:
assert employee_balance >= 0
assert reservation_count == 1
assert payment_attempts <= 3
assert final_state in {"confirmed", "cancelled", "needs_review"}
Bir uçuş rezervasyonu konuşması üç veya on dönüş sürebilir. Ancak tamamlandığında tam olarak bir rezervasyon oluşmalı ya da açık bir hata durumu dönmelidir.
Bağımlılıkları taklit ederek testleri tekrarlanabilir yapın
Canlı üçüncü taraf API'leri test ortamında ek rastgelelik üretir:
- Hız limiti uygularlar
- Verileri değişir
- Bakım veya kesinti yaşayabilirler
- Gecikmeleri farklılaşır
- Farklı hata yanıtları döndürebilirler
Tekrarlanabilir test için, ajanın davranışı dışındaki her şeyi sabitleyin.
Ajanın çağırdığı bağımlılıkları taklit edin ve sabit yanıtlar tanımlayın:
{
"payment_api": {
"receipt_id": "RCP-001",
"status": "paid",
"amount": 42.0
},
"search_api": {
"results": [
{"id": "DOC-1", "title": "İade politikası"},
{"id": "DOC-2", "title": "Teslimat bilgisi"},
{"id": "DOC-3", "title": "Sipariş takibi"}
]
}
}
Bu sayede:
- Ödeme API'si her seferinde aynı makbuzu döndürür.
- Arama API'si her seferinde aynı sonuçları döndürür.
- Testte değişen ana unsur, gözlemlemek istediğiniz ajan davranışı olur.
Taklitler ayrıca canlı ortamda üretmesi zor olan uç durumları zorlamanızı sağlar:
{
"error": "payment_provider_timeout",
"retry_after_seconds": 30
}
Ardından ajanın doğru davranışı gösterdiğini doğrulayabilirsiniz:
assert response["status"] == "needs_review"
assert "tekrar deneyin" in response["resolution"].lower()
Apidog ile ajan bağımlılıkları için kararlı mock yanıtları oluşturabilir, ardından bunları şema ve sözleşme kontrolleriyle birleştirebilirsiniz. Bu yaklaşım, daha geniş ajanlı yapay zeka testi uygulamasının temel parçalarından biridir.
Apidog nerede uyar, nerede uymaz?
Aracın sorumluluğunu doğru konumlandırın.
Apidog; API tasarımı, test ve mock platformudur. Bir ajan çerçevesi, model barındırıcısı, ajan çalışma zamanı veya muhakeme puanlama platformu değildir.
Apidog şunları yapmaz:
- Ajanınızı oluşturmaz
- Modelinizi barındırmaz
- Ajan adımlarını orkestre etmez
- Muhakeme zincirini değerlendirmez
Ancak ajanın konuştuğu API katmanında güçlüdür.
Bu yazıdaki kullanım alanları şunlardır:
-
API yanıtı sözleşmelerini doğrulamak
- JSON şeması
- Yanıt şekli
- Sayısal aralıklar
- Zorunlu alanlar
- Yasaklı alanlar
- Araç çağrısı yükleri
-
Ajan bağımlılıklarını mocklamak
- Sabit API yanıtları
- Kontrollü hata senaryoları
- Tekrarlanabilir entegrasyon testleri
Apidog'un doldurduğu boşluk budur: modeli değil, modelin ürettiği istek ve yanıtların sözleşmesini test etmek.
Sözleşmeyi test edin, kelimeleri değil
Belirsizlik, yapılandırma ile tamamen kaldırabileceğiniz bir hata değildir. Dil modeli çalıştırmanın doğal sonucudur ve temperature=0 bunu ortadan kaldırmaz.
Güvenilir ajanlar geliştiren ekipler, değişen metinle savaşmak yerine sabit kalan özellikleri test eder:
- Şema
- Alan türleri
- Yanıt şekli
- Sayısal aralıklar
- Zorunlu alanlar
- Yasaklı alanlar
- Araç çağrısı sözleşmeleri
- Durum değişmezleri
Bu yaklaşımı benimsediğinizde test paketiniz daha sessiz hale gelir: metin farklı ifade edildiğinde yeşil kalır, yalnızca sözleşme gerçekten bozulduğunda kırmızıya döner.
Bu hafta test paketinizdeki bir tam dize onaylamasını seçin. Onu bir şema doğrulaması, aralık kontrolü veya zorunlu/yasaklı alan kontrolü olarak yeniden yazın. Ardından ajanın bağımlılıklarını mocklayarak testi tekrarlanabilir hale getirin.
Top comments (0)