Kopru: secili model hata verirse siradaki katman yapar
Hata kodu, baglanamama ve yarida kopma da siradaki katmana gider. Siradakine gecilen adimda onceki cevap verilmez; son katman da acilamazsa onun kendi hatasi gider. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7547de1852
commit
06039b904d
2 files changed
+61
-15
No files matched your search
@@ -875,22 +875,28 @@ class H(http.server.BaseHTTPRequestHandler):
|
||||
"""Katman denetimi (jev_denetim.py): cevap istemciye verilmeden once tamami okunur ve Jev'e sorulur.
|
||||
Gecerse oldugu gibi verilir; gecmezse atilir ve ayni adimi siradaki katman yapar (ac(ad): (resp, rewriter,
|
||||
tag)). Son katmanin cevabi sorulmadan akar. Beklerken SSE yorum satiri gider ki Codex akisi kopmus saymasin."""
|
||||
self._akis_basligi(resp, resp.status)
|
||||
kalan, son_yazi = list(sira), time.time()
|
||||
if resp is None: # secili model hata verdi: cevabi yok, adimi siradaki katman yapar
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/event-stream")
|
||||
self.send_header("Transfer-Encoding", "chunked")
|
||||
self.end_headers()
|
||||
else:
|
||||
self._akis_basligi(resp, resp.status)
|
||||
kalan, son_yazi, son_hata = list(sira), time.time(), ""
|
||||
|
||||
def w(b):
|
||||
if b:
|
||||
self.wfile.write(b"%x\r\n" % len(b) + b + b"\r\n"); self.wfile.flush()
|
||||
try:
|
||||
while True:
|
||||
parcalar, okuyan = [], yarim.Izleyici("", "")
|
||||
while True:
|
||||
parcalar, okuyan, hata = [], yarim.Izleyici("", ""), resp is None
|
||||
while not hata:
|
||||
try:
|
||||
chunk = resp.read1(4096)
|
||||
except (OSError, http.client.HTTPException) as e:
|
||||
log(f"{tag} ust kaynak koptu (denetim tamponu, {sum(map(len, parcalar))} bayt): {type(e).__name__}: {e}")
|
||||
self.close_connection = True
|
||||
return
|
||||
log(f"{tag} katman denetimi: cevap yarida koptu, siradakine geciliyor ({type(e).__name__}: {e})")
|
||||
hata = True
|
||||
break
|
||||
if not chunk:
|
||||
break
|
||||
parcalar.append(chunk)
|
||||
@@ -901,7 +907,9 @@ class H(http.server.BaseHTTPRequestHandler):
|
||||
# Her adim Jev'e gider: yazi yoksa modelin bu adimda cagirdigi araclar sorulur.
|
||||
metin = yazi or jev_denetim.komutlar(b"".join(parcalar))
|
||||
gecmedi = False
|
||||
if metin:
|
||||
if hata:
|
||||
gecmedi = True
|
||||
elif metin:
|
||||
t0 = time.time()
|
||||
puan = jev_denetim.sor(istek, metin, jev_denetim.anahtar())
|
||||
if puan is None:
|
||||
@@ -922,23 +930,32 @@ class H(http.server.BaseHTTPRequestHandler):
|
||||
try:
|
||||
yeni = ac(ad)
|
||||
except Exception as e:
|
||||
log(f"{tag} katman denetimi: {ad} acilamadi ({type(e).__name__}: {str(e)[:120]})")
|
||||
govde = e.read().decode("utf-8", "replace") if hasattr(e, "read") else ""
|
||||
son_hata = f"{ad}: {e} {govde}".strip()
|
||||
log(f"{tag} katman denetimi: {ad} acilamadi ({son_hata[:300]})")
|
||||
if yeni is None:
|
||||
break
|
||||
resp, rewriter, tag = yeni
|
||||
log(f"{tag} katman denetimi: adim bu katmana verildi")
|
||||
if not kalan:
|
||||
return self._stream(resp, resp.status, tag, rewriter, izle, basliksiz=True)
|
||||
for chunk in parcalar:
|
||||
if izle is not None:
|
||||
izle.feed(chunk)
|
||||
w(rewriter.feed(chunk) if rewriter else chunk)
|
||||
if rewriter: w(rewriter.flush())
|
||||
if gecmedi:
|
||||
# Siradakine gecilen adimda onceki model bir sey soyleyemez: son katmanin kendi hatasi gider.
|
||||
log(f"{tag} katman denetimi: son katman da acilamadi, onun hatasi veriliyor")
|
||||
olay = {"type": "response.failed", "response": {"id": "resp_astrabridge_katman", "object": "response",
|
||||
"status": "failed", "output": [], "error": {"code": "katman_hatasi", "message": son_hata}}}
|
||||
w(b"event: response.failed\ndata: " + json.dumps(olay, ensure_ascii=False).encode("utf-8") + b"\n\n")
|
||||
else:
|
||||
for chunk in parcalar:
|
||||
if izle is not None:
|
||||
izle.feed(chunk)
|
||||
w(rewriter.feed(chunk) if rewriter else chunk)
|
||||
if rewriter: w(rewriter.flush())
|
||||
self.wfile.write(b"0\r\n\r\n"); self.wfile.flush()
|
||||
except (ConnectionAbortedError, BrokenPipeError, ConnectionResetError):
|
||||
log(f"{tag} istemci baglantiyi kapatti (denetim tamponu)")
|
||||
return
|
||||
log(f"{tag} bitti status={resp.status} {sum(map(len, parcalar))} bayt")
|
||||
log(f"{tag} bitti {'hata' if gecmedi else 'status=200'} {sum(map(len, parcalar))} bayt")
|
||||
|
||||
def _stream(self, resp, status, tag, rewriter=None, izle=None, basliksiz=False):
|
||||
if not basliksiz:
|
||||
@@ -1620,6 +1637,8 @@ class H(http.server.BaseHTTPRequestHandler):
|
||||
log(f"{tag} deneme {attempt}: HTTP {e.code} {errbody[:100]!r} -> tekrar")
|
||||
time.sleep(min(2 * attempt, 8)); continue
|
||||
log(f"{tag} HTTP {e.code} {errbody[:200]!r}")
|
||||
if jev_sira: # secili model hata verdi: adimi siradaki katman yapar
|
||||
return self._denetimli_akis(None, tag, rewriter, izle, jev_istek, jev_sira, jev_ac)
|
||||
if pencere.tasma_mi(etxt):
|
||||
# Hedef "baglam sigmiyor" dedi: Codex'in tanidigi tasma hatasi olarak iletilir ve hedefin
|
||||
# bildirdigi gercek sinir ogrenilir (sonraki model listesinde pencere kuculur).
|
||||
@@ -1651,6 +1670,8 @@ class H(http.server.BaseHTTPRequestHandler):
|
||||
if jev_sira and resp.status == 200:
|
||||
return self._denetimli_akis(resp, tag, rewriter, izle, jev_istek, jev_sira, jev_ac)
|
||||
return self._stream(resp, resp.status, tag, rewriter, izle)
|
||||
if jev_sira: # secili modele ulasilamadi: adimi siradaki katman yapar
|
||||
return self._denetimli_akis(None, tag, rewriter, izle, jev_istek, jev_sira, jev_ac)
|
||||
self._send_json(503, {"error": {"message": f"bridge: hedef ulasilamadi {last}"}})
|
||||
|
||||
do_POST = _handle
|
||||
|
||||
@@ -241,6 +241,31 @@ class Akis(unittest.TestCase):
|
||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3"])
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-3"])
|
||||
|
||||
def test_an_error_of_the_selected_model_goes_to_the_next_layer(self):
|
||||
self.h._denetimli_akis(None, "[1]", None, None, "yap", ["Katman-1", "Katman-2", "Katman-3", "Katman-4"], self.ac)
|
||||
self.assertEqual(self.opened, ["Katman-1"])
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-1"])
|
||||
|
||||
def test_an_answer_cut_midway_goes_to_the_next_layer(self):
|
||||
class Kopan(Yanit):
|
||||
def read1(self, n):
|
||||
if not self.parts:
|
||||
raise OSError("koptu")
|
||||
return self.parts.pop(0)
|
||||
self.h._denetimli_akis(Kopan(sse("yarim")), "[1]", None, None, "yap", ["Katman-2", "Katman-3", "Katman-4"], self.ac)
|
||||
self.assertEqual(self.opened, ["Katman-2"])
|
||||
self.assertEqual(self.sent(), self.cevap["Katman-2"])
|
||||
self.assertNotIn(b"yarim", self.h.wfile.getvalue())
|
||||
|
||||
def test_when_no_layer_opens_the_blocked_answer_is_not_delivered(self):
|
||||
self.puanlar = [{"ret": 0.9, "sart": 0.0}]
|
||||
self.cevap.update({"Katman-2": None, "Katman-3": None, "Katman-4": None})
|
||||
self.calistir(sse("Bunu yapamam."))
|
||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3", "Katman-4"])
|
||||
self.assertNotIn(b"yapamam", self.h.wfile.getvalue())
|
||||
self.assertIn(b"response.failed", self.sent())
|
||||
self.assertIn(b"Katman-4: acilamadi", self.sent()) # the last layer's own error reaches the user
|
||||
|
||||
def test_unreachable_jev_keeps_the_answer(self):
|
||||
self.puanlar = [None]
|
||||
body = sse("Bunu yapamam.")
|
||||
|
||||
Reference in new issue
Block a user