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
+55
-9
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.
|
"""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,
|
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."""
|
tag)). Son katmanin cevabi sorulmadan akar. Beklerken SSE yorum satiri gider ki Codex akisi kopmus saymasin."""
|
||||||
|
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)
|
self._akis_basligi(resp, resp.status)
|
||||||
kalan, son_yazi = list(sira), time.time()
|
kalan, son_yazi, son_hata = list(sira), time.time(), ""
|
||||||
|
|
||||||
def w(b):
|
def w(b):
|
||||||
if b:
|
if b:
|
||||||
self.wfile.write(b"%x\r\n" % len(b) + b + b"\r\n"); self.wfile.flush()
|
self.wfile.write(b"%x\r\n" % len(b) + b + b"\r\n"); self.wfile.flush()
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
parcalar, okuyan = [], yarim.Izleyici("", "")
|
parcalar, okuyan, hata = [], yarim.Izleyici("", ""), resp is None
|
||||||
while True:
|
while not hata:
|
||||||
try:
|
try:
|
||||||
chunk = resp.read1(4096)
|
chunk = resp.read1(4096)
|
||||||
except (OSError, http.client.HTTPException) as e:
|
except (OSError, http.client.HTTPException) as e:
|
||||||
log(f"{tag} ust kaynak koptu (denetim tamponu, {sum(map(len, parcalar))} bayt): {type(e).__name__}: {e}")
|
log(f"{tag} katman denetimi: cevap yarida koptu, siradakine geciliyor ({type(e).__name__}: {e})")
|
||||||
self.close_connection = True
|
hata = True
|
||||||
return
|
break
|
||||||
if not chunk:
|
if not chunk:
|
||||||
break
|
break
|
||||||
parcalar.append(chunk)
|
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.
|
# Her adim Jev'e gider: yazi yoksa modelin bu adimda cagirdigi araclar sorulur.
|
||||||
metin = yazi or jev_denetim.komutlar(b"".join(parcalar))
|
metin = yazi or jev_denetim.komutlar(b"".join(parcalar))
|
||||||
gecmedi = False
|
gecmedi = False
|
||||||
if metin:
|
if hata:
|
||||||
|
gecmedi = True
|
||||||
|
elif metin:
|
||||||
t0 = time.time()
|
t0 = time.time()
|
||||||
puan = jev_denetim.sor(istek, metin, jev_denetim.anahtar())
|
puan = jev_denetim.sor(istek, metin, jev_denetim.anahtar())
|
||||||
if puan is None:
|
if puan is None:
|
||||||
@@ -922,13 +930,22 @@ class H(http.server.BaseHTTPRequestHandler):
|
|||||||
try:
|
try:
|
||||||
yeni = ac(ad)
|
yeni = ac(ad)
|
||||||
except Exception as e:
|
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:
|
if yeni is None:
|
||||||
break
|
break
|
||||||
resp, rewriter, tag = yeni
|
resp, rewriter, tag = yeni
|
||||||
log(f"{tag} katman denetimi: adim bu katmana verildi")
|
log(f"{tag} katman denetimi: adim bu katmana verildi")
|
||||||
if not kalan:
|
if not kalan:
|
||||||
return self._stream(resp, resp.status, tag, rewriter, izle, basliksiz=True)
|
return self._stream(resp, resp.status, tag, rewriter, izle, basliksiz=True)
|
||||||
|
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:
|
for chunk in parcalar:
|
||||||
if izle is not None:
|
if izle is not None:
|
||||||
izle.feed(chunk)
|
izle.feed(chunk)
|
||||||
@@ -938,7 +955,7 @@ class H(http.server.BaseHTTPRequestHandler):
|
|||||||
except (ConnectionAbortedError, BrokenPipeError, ConnectionResetError):
|
except (ConnectionAbortedError, BrokenPipeError, ConnectionResetError):
|
||||||
log(f"{tag} istemci baglantiyi kapatti (denetim tamponu)")
|
log(f"{tag} istemci baglantiyi kapatti (denetim tamponu)")
|
||||||
return
|
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):
|
def _stream(self, resp, status, tag, rewriter=None, izle=None, basliksiz=False):
|
||||||
if not basliksiz:
|
if not basliksiz:
|
||||||
@@ -1620,6 +1637,8 @@ class H(http.server.BaseHTTPRequestHandler):
|
|||||||
log(f"{tag} deneme {attempt}: HTTP {e.code} {errbody[:100]!r} -> tekrar")
|
log(f"{tag} deneme {attempt}: HTTP {e.code} {errbody[:100]!r} -> tekrar")
|
||||||
time.sleep(min(2 * attempt, 8)); continue
|
time.sleep(min(2 * attempt, 8)); continue
|
||||||
log(f"{tag} HTTP {e.code} {errbody[:200]!r}")
|
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):
|
if pencere.tasma_mi(etxt):
|
||||||
# Hedef "baglam sigmiyor" dedi: Codex'in tanidigi tasma hatasi olarak iletilir ve hedefin
|
# Hedef "baglam sigmiyor" dedi: Codex'in tanidigi tasma hatasi olarak iletilir ve hedefin
|
||||||
# bildirdigi gercek sinir ogrenilir (sonraki model listesinde pencere kuculur).
|
# 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:
|
if jev_sira and resp.status == 200:
|
||||||
return self._denetimli_akis(resp, tag, rewriter, izle, jev_istek, jev_sira, jev_ac)
|
return self._denetimli_akis(resp, tag, rewriter, izle, jev_istek, jev_sira, jev_ac)
|
||||||
return self._stream(resp, resp.status, tag, rewriter, izle)
|
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}"}})
|
self._send_json(503, {"error": {"message": f"bridge: hedef ulasilamadi {last}"}})
|
||||||
|
|
||||||
do_POST = _handle
|
do_POST = _handle
|
||||||
|
|||||||
@@ -241,6 +241,31 @@ class Akis(unittest.TestCase):
|
|||||||
self.assertEqual(self.opened, ["Katman-2", "Katman-3"])
|
self.assertEqual(self.opened, ["Katman-2", "Katman-3"])
|
||||||
self.assertEqual(self.sent(), self.cevap["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):
|
def test_unreachable_jev_keeps_the_answer(self):
|
||||||
self.puanlar = [None]
|
self.puanlar = [None]
|
||||||
body = sse("Bunu yapamam.")
|
body = sse("Bunu yapamam.")
|
||||||
|
|||||||
Reference in new issue
Block a user