Update ui/chat_engine.py
Browse files- ui/chat_engine.py +41 -4
ui/chat_engine.py
CHANGED
|
@@ -25,9 +25,10 @@ counts.
|
|
| 25 |
import random
|
| 26 |
import threading
|
| 27 |
import time
|
|
|
|
| 28 |
|
| 29 |
from ui.constants import SONIC_QUOTES
|
| 30 |
-
from ui.gpu import ON_ZEROGPU, vectorize_on_gpu
|
| 31 |
from ui.papers import resolve_and_download_pdf
|
| 32 |
from ui.sonic import SONIC_DATA_URI
|
| 33 |
|
|
@@ -48,6 +49,34 @@ def _quote_at(quotes, start):
|
|
| 48 |
return quotes[int((time.time() - start) // 4) % len(quotes)]
|
| 49 |
|
| 50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 51 |
# --- phase workers (touch no UI) -------------------------------------------
|
| 52 |
|
| 53 |
def _download_blocking(record: dict, holder: dict):
|
|
@@ -59,14 +88,21 @@ def _download_blocking(record: dict, holder: dict):
|
|
| 59 |
return
|
| 60 |
holder["pdf_path"] = pdf_path
|
| 61 |
except Exception as e:
|
| 62 |
-
|
|
|
|
| 63 |
|
| 64 |
|
| 65 |
def _vectorize_blocking(pdf_path: str, holder: dict):
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
try:
|
| 67 |
vectorize_on_gpu(pdf_path)
|
| 68 |
except Exception as e:
|
| 69 |
-
|
|
|
|
|
|
|
| 70 |
|
| 71 |
|
| 72 |
def _assemble_session(pdf_path: str) -> dict:
|
|
@@ -142,7 +178,8 @@ def prepare_chat_stream(record: dict):
|
|
| 142 |
try:
|
| 143 |
session = _assemble_session(pdf_path)
|
| 144 |
except Exception as e:
|
| 145 |
-
|
|
|
|
| 146 |
return
|
| 147 |
|
| 148 |
yield vec_loading_html(quotes[0], "Ready.", 100), True, session, None
|
|
|
|
| 25 |
import random
|
| 26 |
import threading
|
| 27 |
import time
|
| 28 |
+
import traceback
|
| 29 |
|
| 30 |
from ui.constants import SONIC_QUOTES
|
| 31 |
+
from ui.gpu import ON_ZEROGPU, cuda_state, vectorize_on_gpu
|
| 32 |
from ui.papers import resolve_and_download_pdf
|
| 33 |
from ui.sonic import SONIC_DATA_URI
|
| 34 |
|
|
|
|
| 49 |
return quotes[int((time.time() - start) // 4) % len(quotes)]
|
| 50 |
|
| 51 |
|
| 52 |
+
# --- error reporting --------------------------------------------------------
|
| 53 |
+
|
| 54 |
+
def describe_exception(e: BaseException) -> str:
|
| 55 |
+
"""Flatten a whole exception chain into one readable line.
|
| 56 |
+
|
| 57 |
+
`f"{type(e).__name__}: {e}"` is lossy the moment anything wraps anything,
|
| 58 |
+
and that is precisely what cost us a debugging session: ZeroGPU marshals a
|
| 59 |
+
worker-side failure back to the caller as a `gradio.exceptions.Error` whose
|
| 60 |
+
payload is just the *name* of the original class. The naive format rendered
|
| 61 |
+
that as the useless string
|
| 62 |
+
|
| 63 |
+
Couldn't read this paper: Error: 'RuntimeError'
|
| 64 |
+
|
| 65 |
+
— a wrapper around a wrapper, with the real traceback discarded. Walking
|
| 66 |
+
__cause__/__context__ keeps the causal chain, and the callers below print
|
| 67 |
+
the traceback too, since only that names the failing frame.
|
| 68 |
+
"""
|
| 69 |
+
parts: list[str] = []
|
| 70 |
+
seen: set[int] = set()
|
| 71 |
+
current: BaseException | None = e
|
| 72 |
+
while current is not None and id(current) not in seen:
|
| 73 |
+
seen.add(id(current))
|
| 74 |
+
text = str(current).strip()
|
| 75 |
+
parts.append(f"{type(current).__name__}: {text}" if text else type(current).__name__)
|
| 76 |
+
current = current.__cause__ or current.__context__
|
| 77 |
+
return " <- ".join(parts)
|
| 78 |
+
|
| 79 |
+
|
| 80 |
# --- phase workers (touch no UI) -------------------------------------------
|
| 81 |
|
| 82 |
def _download_blocking(record: dict, holder: dict):
|
|
|
|
| 88 |
return
|
| 89 |
holder["pdf_path"] = pdf_path
|
| 90 |
except Exception as e:
|
| 91 |
+
traceback.print_exc()
|
| 92 |
+
holder["error"] = f"Couldn't fetch this paper: {describe_exception(e)}"
|
| 93 |
|
| 94 |
|
| 95 |
def _vectorize_blocking(pdf_path: str, holder: dict):
|
| 96 |
+
# The decisive log line. If CUDA is already initialised *here*, in the
|
| 97 |
+
# parent, the ZeroGPU fork about to happen is already doomed — see the
|
| 98 |
+
# CUDA-VIRGINITY RULE in ui/gpu.py.
|
| 99 |
+
print(cuda_state("pre-gpu-call"), flush=True)
|
| 100 |
try:
|
| 101 |
vectorize_on_gpu(pdf_path)
|
| 102 |
except Exception as e:
|
| 103 |
+
traceback.print_exc()
|
| 104 |
+
print(cuda_state("post-gpu-failure"), flush=True)
|
| 105 |
+
holder["error"] = f"Couldn't read this paper: {describe_exception(e)}"
|
| 106 |
|
| 107 |
|
| 108 |
def _assemble_session(pdf_path: str) -> dict:
|
|
|
|
| 178 |
try:
|
| 179 |
session = _assemble_session(pdf_path)
|
| 180 |
except Exception as e:
|
| 181 |
+
traceback.print_exc()
|
| 182 |
+
yield fail(f"Couldn't prepare this paper for chat: {describe_exception(e)}")
|
| 183 |
return
|
| 184 |
|
| 185 |
yield vec_loading_html(quotes[0], "Ready.", 100), True, session, None
|