Yapay Zekâ Aracıları Uzun Süren Asenkron İşlemleri Nasıl Yönetmeli?
Bir aracı, video dönüştürme uç noktanızı çağırır. Uç nokta 202 Accepted ve bir iş kimliği döndürür. Sisteminizde 202 kodunun ne anlama geldiğini bilmeyen aracı, dönüştürmenin tamamlandığını varsayar ve henüz var olmayan dosyayı okumaya çalışan sonraki adıma geçer.
Uzun süren işlemler aracılarda üç tip soruna yol açar:
- Başarıyı çok erken bildirirler.
- Sıkı bir döngü içinde gereğinden fazla sorgulama yaparlar.
- İş kimliğini kaybedip devam eden işi unuturlar.
Senkron bir çağrının sözleşmesi basittir: isteği gönderir, beklersiniz ve yanıt alırsınız. Asenkron çağrı ise işlemi bir başlangıç ve bitiş olarak ikiye böler. Sorun, bu iki nokta arasındaki boşlukta ortaya çıkar.
Bu yazı; takip edilebilir bir asenkron sözleşmenin nasıl tasarlanacağını, sorgulamanın ne zaman yapılacağını, hangi durumda webhook kullanılacağını, araçların modele uygun biçimde nasıl yazılacağını ve yavaş ya da başarısız durumların nasıl test edileceğini açıklar.
Aracı hata kurtarma konusundaki rehberimiz API hatalarını ele alır. Bu yazı ise yavaş ama sonunda başarılı olan işlemlere odaklanır.
Aracılar asenkron işlemleri neden yanlış yönetir?
Modeller her 2xx yanıtını tamamlanmış kabul edebilir
202 Accepted, isteğin işlenmek üzere kabul edildiğini, ancak işlemin henüz tamamlanmamış olabileceğini belirtir.
Sıradan istek/yanıt trafiği üzerinde eğitilen modeller ise yanıt aksini açıkça söylemedikçe herhangi bir 2xx kodunu başarı ve tamamlanma olarak yorumlamaya eğilimlidir.
Sorgulama döngüleri pahalıdır
Aracı sorgulamayı kendi muhakeme döngüsü içinde yaparsa her kontrol:
- Yeni bir model sırası oluşturur.
- Önceki konuşma belirteçlerini tekrar kullanır.
- Bağlam ve bütçe tüketir.
Dört dakika süren bir iş için iki saniyede bir sorgulama yapmak 120 model sırası demektir. Bu yaklaşım, çalışma süresini ve bağlamı hızla tüketebilir. Araç yanıtlarını bağlam penceresinin dışında tutma rehberimizde bu birikimin neden beklenenden hızlı gerçekleştiğini açıklıyoruz.
İş kimlikleri konuşma içinde kaybolabilir
İş başlatan ve bir job_id döndüren araç, aracının ileride taşıması gereken bir durum oluşturur. Uzun konuşmalarda bu kimlik:
- Sıkıştırma sırasında kaybolabilir.
- Bağlamın ortasında gözden kaçabilir.
- Aracının devam eden bir işi olduğunu unutmasına neden olabilir.
Modelin yanlış yorumlayamayacağı yanıtlar tasarlayın
En etkili çözüm çoğu zaman mimari değil, açık ifadelerdir. Durum kodunuz ne olursa olsun yanıt gövdesi işlemin ne durumda olduğunu ve bundan sonra ne yapılması gerektiğini söylemelidir:
{
"status": "processing",
"job_id": "job_7f21c",
"message": "The transcode has STARTED and is NOT complete. Do not report success. Check status with getJobStatus(job_id) after at least 30 seconds.",
"poll_after_seconds": 30,
"estimated_duration_seconds": 240,
"status_url": "/v1/jobs/job_7f21c"
}
Bu, insan API tüketicisi için gereğinden fazla açık görünebilir. Ancak modeller, durum kodundan anlam çıkarmak yerine yanıt gövdesindeki doğrudan talimatları daha güvenilir biçimde takip eder.
Özellikle şu üç ayrıntı önemlidir:
- İşlemin tamamlanmadığını açıkça belirtmek.
- Kullanılması gereken sonraki aracı adlandırmak.
- Minimum bekleme süresini belirtmek.
Google'ın uzun süreli işlemler için hazırladığı AIP-151, done, error ve response alanlarını taşıyan tek bir Operation nesnesi önerir. Bu şekli kullanmak, tüm yavaş uç noktalar için tutarlı bir arayüz oluşturur. Bir aracı bir sorgulama düzenini öğrendiğinde aynı düzeni diğer işlemlerde de kullanabilir.
Durum yanıtını da açık tutun:
{
"job_id": "job_7f21c",
"status": "processing",
"done": false,
"progress_percent": 45,
"elapsed_seconds": 108,
"poll_after_seconds": 45,
"message": "Still processing. Do not proceed to the next step."
}
İşlem tamamlandığında sonuç küçükse yanıt içine ekleyin. Böylece aracının üçüncü bir çağrı yapması gerekmez:
{
"job_id": "job_7f21c",
"status": "succeeded",
"done": true,
"result": { "output_url": "https://cdn.example.com/out/7f21c.mp4", "duration_seconds": 372 }
}
Sorgulamayı modelin içinde değil, dışında yapın
En önemli uygulama kararı şudur: beklemeyi aracının muhakeme döngüsüne değil, araç sarmalayıcısına koyun.
import time
def start_and_await_transcode(client, source_url, max_wait=600):
job = client.post("/v1/transcode", json={"source_url": source_url}).json()
job_id = job["job_id"]
delay = job.get("poll_after_seconds", 5)
waited = 0
while waited < max_wait:
time.sleep(delay)
waited += delay
status = client.get(f"/v1/jobs/{job_id}").json()
if status.get("done"):
if status["status"] == "succeeded":
return {"status": "succeeded", "result": status["result"]}
return {"status": "failed", "error": status.get("error")}
delay = min(int(delay * 1.5), 60)
return {
"status": "timed_out",
"job_id": job_id,
"message": f"Still running after {max_wait}s. Job {job_id} continues in the background.",
}
Model açısından bu, biraz zaman alan ve nihai yanıt döndüren tek bir araç çağrısıdır:
- Bağlam içinde sorgulama döngüsü yoktur.
- Unutulabilecek bir iş kimliği yoktur.
- 120 ayrı model sırası oluşmaz.
- Geri çekilme mekanizması istek sayısını sınırlar.
- Üst sınır, takılı kalan işin sonsuza kadar beklemeyi sürdürmesini engeller.
Amazon'un jitter ile zaman aşımları, yeniden denemeler ve geri çekilme hakkındaki rehberi, bu değerleri ayarlamak için iyi bir referanstır.
Güvenli bir sarmalayıcı için iki kuralı uygulayın:
- Bekleme süresini her zaman sınırlayın.
- Zaman aşımında her zaman
job_iddöndürün.
Belirsiz sonuçlar döndürmeyin. succeeded, failed ve timed_out farklı durumlardır; modelin bu üç durumu ayırt edebilmesi gerekir.
Saatler süren işler için iki araç kullanın
İşler dakikalar yerine saatlerle ölçülüyorsa sarmalayıcı içinde sorgulama yapmak uygun değildir. Bu durumda:
- Bir araç işi başlatmalı.
- İkinci araç iş durumunu kontrol etmeli.
- Devam eden işler konuşma dışında kalıcı bir yerde saklanmalıdır.
En azından şu bilgileri kaydedin:
job_id- İlişkili görev
- Başlangıç zamanı
- Mevcut durum
Aracının her çalıştırmanın başında devam eden işler listesini okumasını sağlayın. Böylece durum, konuşma sıkıştırması nedeniyle kaybolmaz.
Webhook ne zaman daha iyi bir seçenektir?
Sorgulama basit ve her yerde çalışır. Webhook ise daha verimlidir, ancak daha fazla altyapı gerektirir. Ayrıntılı karşılaştırma için webhook ve sorgulama rehberimize bakabilirsiniz.
Sorgulama kullanın
Şu koşullarda sorgulama genellikle daha uygundur:
- İş birkaç saniye ile birkaç dakika arasında sürüyorsa.
- Aracı sonucu beklemeden ilerleyemiyorsa.
- Herkese açık bir webhook uç noktası barındıramıyorsanız.
Çoğu aracı iş yükü bu gruba girer.
Webhook kullanın
Şu koşullarda webhook tercih edin:
- İş saatler sürüyorsa.
- Aracı işi başlatıp devam edebiliyorsa.
- Aynı anda çok sayıda iş çalışıyor ve her birini sorgulamak maliyetliyse.
Webhook yaklaşımı şu bileşenleri gerektirir:
- Herkese açık bir alıcı.
- İmza doğrulama.
- Yeniden deneme işleme.
- Geri çağrı geldiğinde aracıyı uyandıracak bir mekanizma.
Sağlam webhook'lar tasarlama ve webhook imza doğrulama rehberlerimiz bu temel parçaları kapsar.
SSE ara seçeneği sunar
Sunucu tarafından gönderilen olaylarla ilerleme bilgisi akıtmak, istemci bağlantıyı açık tuttuğu için herkese açık bir webhook uç noktası olmadan push semantiği sağlar.
Bu yöntem, bir insanın süreci izlediği interaktif aracılar için uygundur. Uygulama ayrıntıları için SSE ile API yanıtlarını akışla gönderme rehberimize bakabilirsiniz.
Tamamlanma idempotent olmalıdır
Hangi yöntemi seçerseniz seçin, tamamlanma yolu idempotent olmalıdır.
- Webhook'lar yeniden denenebilir.
- Sorgulamalar yarışabilir.
- Aynı başarı bildirimi iki kez ulaşabilir.
Aynı sonucu iki kez gören bir aracı sonraki adımı iki kez başlatmamalıdır. Yapay zekâ aracıları için idempotentlik rehberimizde bunu güvenli hale getiren anahtarları açıklıyoruz.
Yalnızca hızlı yolu değil, yavaş yolu da test edin
Asenkron hatalar test ortamlarında kolayca gizlenir. Üretimde dört dakika süren bir iş yerel bir stub üzerinde 200 milisaniyede tamamlanabilir. Bu durumda aracı gerçek davranışı hiç görmez.
Aşağıdaki dört senaryoyu özellikle test edin.
1. Gerçekten yavaş iş
Durum uç noktasını ilk birkaç çağrıda processing, daha sonra succeeded döndürecek şekilde taklit edin.
Bu test şunları doğrular:
- Sarmalayıcı gerçekten sorgulama yapıyor.
- Geri çekilme uygulanıyor.
- İş sonunda doğru sonuç dönüyor.
Apidog'da yanıtı istek sayısına veya bir kontrol parametresine göre değiştiren bir mock kullanabilirsiniz. Böylece test her çalıştırmada aynı şekilde davranır.
2. Geç başarısız olan iş
Üç kez processing, ardından hata gövdesiyle birlikte failed döndürün.
Aracı, sorgulamanın tamamlanmasını işin başarısı olarak yorumlamamalı; hatayı açıkça bildirmelidir. Bu durum gözden kaçtığında sessiz veri kaybına yol açabilir.
3. Zaman aşımı
Mock sürekli processing döndürerek sarmalayıcının üst sınırını aşmalıdır.
Aracının:
- İstisna fırlatmadığını,
- Sahte bir başarı bildirmediğini,
-
timed_outdöndürdüğünü, -
job_iddeğerini koruduğunu
doğrulayın.
4. Yinelenen tamamlanma
Başarı bildirimini iki kez gönderin. Bunu bir webhook yeniden denemesi veya yarışan iki sorgulama ile simüle edebilirsiniz.
Aşağı akış adımının yalnızca bir kez çalıştığını doğrulayın.
Bu dört senaryoyu CI'da çalışacak şekilde kaydedin. Yeniden çalıştırmak düşük maliyetlidir ve şu regresyonları yakalar:
- Zaman aşımının kısaltılması.
- Hatanın yutulması.
- Yinelenen tamamlanmanın işlenmemesi.
- Geri çekilmenin kaldırılması.
Daha geniş yaklaşım için API sözleşme testi rehberimize bakabilirsiniz.
Kısmi sonuçlar için ayrı bir durum tanımlayın
Uzun işler çoğu zaman başarı ile başarısızlık arasında tamamlanır. Yalnızca iki durum kullanan bir model, kısmi başarıyı yanlış ifade etmeye zorlar.
Üçüncü durumu açıkça tanımlayın:
{
"job_id": "job_a11f",
"status": "completed_with_errors",
"done": true,
"summary": { "processed": 20000, "succeeded": 19860, "failed": 140 },
"errors_url": "/v1/jobs/job_a11f/errors?limit=50",
"message": "Import finished. 140 rows failed and were not written. Review errors before reporting success."
}
Bu yanıtta iki ayrıntı önemlidir:
- Sayılar satır içinde bulunur; aracının karar vermek için yeni bir çağrı yapması gerekmez.
- Hatalı satırlar, sınırlı sonuç döndüren bir URL'nin arkasındadır; 140 hata nesnesi bağlama gereksiz yere eklenmez.
Takılı kalan işi birinin görmesini sağlayın
Zaman aşımı yanıtı, iş kimliğiyle birlikte işin hâlâ devam ettiğini belirtir:
{
"status": "timed_out",
"job_id": "job_7f21c",
"message": "Still running after 600s. Job job_7f21c continues in the background."
}
Bu yanıt ancak doğru kişiye ulaştığında faydalıdır.
Aracı kendi hizmetinizse işi ekibinizin zaten izlediği kuyruğa yönlendirin. Aracı, atanmış görevleri çalıştıran bir kodlama ortamıysa platformun yürütme ve bildirim özelliklerini kullanın.
Sharkly gibi ortamlarda engellenmiş olarak biten bir çalıştırma, yürütme durumu ve sonucu ile görevin üzerinde kalır. Gelen Kutusu ise insan yanıtı veya incelemesi gerektiren öğeleri sıradan güncellemelerden ayırır.
Önemli olan kullandığınız araç değildir. “Hâlâ çalışıyor, daha sonra kontrol et” mesajının bir sahibi olmalıdır. Aksi halde sonuç “kimse kontrol etmedi” olur.
Kısa kontrol listesi
- Her yavaş uç nokta bir
job_id, durum URL'si ve işlemin tamamlanmadığını belirten açık bir mesaj döndürür. - Durum yanıtları, modelin yorumlaması gereken bir dize yerine boolean
donealanı taşır. - Sorgulama, üstel geri çekilme ve katı bir üst sınırla araç sarmalayıcısında yapılır.
- Zaman aşımı yanıtları, işin daha sonra takip edilebilmesi için
job_iddöndürür. -
succeeded,failedvetimed_outfarklı dönüş değerleridir. - Birkaç dakikadan uzun süren işler konuşmanın dışında kalıcı olarak kaydedilir.
- Sorgulama veya webhook ile gelen tamamlanma bildirimleri idempotent işlenir.
- Yavaş, geç başarısız olan, zaman aşımına uğrayan ve yinelenen tamamlanma senaryoları CI'da test edilir.
Yanıt sözleşmesini ve sarmalayıcıyı doğru tasarladığınızda uzun süreli işlemler aracılar için özel bir durum olmaktan çıkar. Aracı çağrıyı yapar, sarmalayıcı bekler ve modelin kolayca yorumlayabileceği tek bir sonuç döner.
Yavaş iş mock'larını testlerle birlikte oluşturmak için Apidog'u indirin.
Sıkça Sorulan Sorular
API, asenkron başlangıç için 202 mi yoksa 200 mü döndürmeli?
202 Accepted dürüst bir koddur ve standart istemcilere işlemin henüz tamamlanmamış olabileceğini bildirir. Ancak aracılar için yalnızca durum koduna güvenmeyin; modeller gövdeyi daha güvenilir biçimde takip eder. İkisini birlikte kullanın: 202 ve açık bir yanıt gövdesi.
Araç sarmalayıcısı pes etmeden önce ne kadar beklemeli?
Üst sınırı, uç noktanın gerçekçi en kötü durum süresinin biraz üzerine ayarlayın. Çoğu iş için bu süre iki ile on dakika arasındadır.
Bundan daha uzun bir bekleme, konuşma sırasını gereksiz yere açık tutar. Daha uzun işler için işi başlatan ve daha sonra kontrol eden ayrı araçlar kullanın.
Hangi sorgulama aralığını kullanmalıyım?
Sunucu poll_after_seconds ipucu veriyorsa bununla başlayın. Ardından yaklaşık 1.5 katsayısıyla geri çekilin ve aralığı yaklaşık 60 saniyede sınırlayın.
Her saniye sabit aralıklarla sorgulama yapmak gereksiz istek üretir ve oran limitlerini tetikleyebilir.
Aracı beklerken yararlı başka bir iş yapabilir mi?
Yalnızca yürütme ortamınız eşzamanlı araç çağrılarını destekliyorsa.
Destekleniyorsa:
- İşi başlatın.
- Bağımsız işi gerçekleştirin.
- Ardından ilk işin durumunu kontrol edin.
Eşzamanlılık desteklenmiyorsa engelleme yapan sarmalayıcı, elle yazılmış bir zamanlayıcıdan daha basit ve daha az hataya açıktır.
Aracının başarıyı erken iddia etmesini nasıl engellerim?
- Yanıt gövdesinde işlemin tamamlanmadığını açıkça yazın.
- Boolean
donealanı döndürün. - Tamamlama aracını sonucun görüneceği tek yer haline getirin.
- Başlangıç yanıtına sonuç eklemeyin.
Başlangıç yanıtı sonuç içermiyorsa modelin bunu başarı olarak bildirmesi zorlaşır.
Webhook'lar dizüstü bilgisayarda çalışan aracılar için çalışır mı?
Doğrudan çalışmaz; çünkü dizüstü bilgisayarda genellikle herkese açık bir uç nokta yoktur.
Geliştirme sırasında bir tünel kullanın. Webhook hizmetleriyle localhost API'lerini test etme rehberimiz bu yaklaşımı açıklar. Alternatif olarak, aracı adreslenebilir bir ortamda çalışana kadar sorgulamayı kullanın.
Daha fazla bilgi için çoklu aracı devri ve bağlam geçişi rehberimize de göz atabilirsiniz.


Top comments (0)