r0mant1c commited on
Commit
163f769
·
1 Parent(s): 31f3123

Fall back from Transformers to llama.cpp

Browse files
README.md CHANGED
@@ -51,7 +51,8 @@ This is the active deployment path.
51
 
52
  With `EXTRACTOR_BACKEND=auto`, the app checks CUDA availability at runtime. If CUDA is visible, it
53
  uses the official OpenBMB MiniCPM-V 4.6 Transformers path. If CUDA is not visible, it falls back to
54
- the CPU `llama.cpp` GGUF path. The deterministic knowledge-graph enrichment and UI rendering stay
 
55
  in normal Gradio/Python code.
56
 
57
  This workflow should not be further changed back to Docker unless the project intentionally gives up
 
51
 
52
  With `EXTRACTOR_BACKEND=auto`, the app checks CUDA availability at runtime. If CUDA is visible, it
53
  uses the official OpenBMB MiniCPM-V 4.6 Transformers path. If CUDA is not visible, it falls back to
54
+ the CPU `llama.cpp` GGUF path. If the CUDA worker fails, `auto` retries with CPU llama.cpp unless
55
+ `AUTO_FALLBACK_TO_LLAMACPP=0`. The deterministic knowledge-graph enrichment and UI rendering stay
56
  in normal Gradio/Python code.
57
 
58
  This workflow should not be further changed back to Docker unless the project intentionally gives up
RUNBOOK.md CHANGED
@@ -24,7 +24,7 @@ Do not switch the Space back to Docker unless the project intentionally gives up
24
 
25
  `EXTRACTOR_BACKEND`:
26
 
27
- - `auto`: uses the Transformers backend when `torch.cuda.is_available()` is true; otherwise uses the CPU llama.cpp backend.
28
  - `llamacpp-gpu`: force the GGUF llama.cpp backend.
29
  - `zerogpu` / `transformers`: force the OpenBMB Transformers backend.
30
  - `api`: hosted OpenBMB endpoint for development fallback only.
 
24
 
25
  `EXTRACTOR_BACKEND`:
26
 
27
+ - `auto`: uses the Transformers backend when `torch.cuda.is_available()` is true; otherwise uses the CPU llama.cpp backend. If the Transformers worker fails, it retries with CPU llama.cpp unless `AUTO_FALLBACK_TO_LLAMACPP=0`.
28
  - `llamacpp-gpu`: force the GGUF llama.cpp backend.
29
  - `zerogpu` / `transformers`: force the OpenBMB Transformers backend.
30
  - `api`: hosted OpenBMB endpoint for development fallback only.
src/extraction/auto.py CHANGED
@@ -2,6 +2,8 @@
2
 
3
  from __future__ import annotations
4
 
 
 
5
  from src.extraction.base import Extractor
6
  from src.extraction.llamacpp_gpu import LlamaCppGPUExtractor
7
  from src.extraction.zerogpu_transformers import ZeroGPUTransformersExtractor
@@ -15,7 +17,20 @@ class AutoExtractor:
15
  self._selected: Extractor | None = None
16
 
17
  def extract(self, file_path: str, max_pages: int = 3):
18
- return self._backend().extract(file_path, max_pages=max_pages)
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
  def _backend(self) -> Extractor:
21
  if self._selected is None:
@@ -32,6 +47,10 @@ def cuda_available() -> bool:
32
  except Exception:
33
  return False
34
 
 
 
 
 
35
  try:
36
  return bool(torch.cuda.is_available())
37
  except Exception:
 
2
 
3
  from __future__ import annotations
4
 
5
+ import os
6
+
7
  from src.extraction.base import Extractor
8
  from src.extraction.llamacpp_gpu import LlamaCppGPUExtractor
9
  from src.extraction.zerogpu_transformers import ZeroGPUTransformersExtractor
 
17
  self._selected: Extractor | None = None
18
 
19
  def extract(self, file_path: str, max_pages: int = 3):
20
+ backend = self._backend()
21
+ try:
22
+ return backend.extract(file_path, max_pages=max_pages)
23
+ except Exception as exc:
24
+ if not isinstance(backend, ZeroGPUTransformersExtractor) or not _fallback_enabled():
25
+ raise
26
+
27
+ print(
28
+ "[Blood Test Explainer] CUDA Transformers backend failed; "
29
+ f"falling back to CPU llama.cpp. Inner error: {type(exc).__name__}: {exc}",
30
+ flush=True,
31
+ )
32
+ self._selected = LlamaCppGPUExtractor()
33
+ return self._selected.extract(file_path, max_pages=max_pages)
34
 
35
  def _backend(self) -> Extractor:
36
  if self._selected is None:
 
47
  except Exception:
48
  return False
49
 
50
+
51
+ def _fallback_enabled() -> bool:
52
+ return os.getenv("AUTO_FALLBACK_TO_LLAMACPP", "1").strip().lower() not in {"0", "false", "no"}
53
+
54
  try:
55
  return bool(torch.cuda.is_available())
56
  except Exception:
src/extraction/zerogpu_transformers.py CHANGED
@@ -143,31 +143,37 @@ def _run_zerogpu_generation(
143
  ) -> str:
144
  import torch
145
 
146
- processor, model = _get_model(model_id)
147
- inputs = processor.apply_chat_template(
148
- messages,
149
- tokenize=True,
150
- add_generation_prompt=True,
151
- return_dict=True,
152
- return_tensors="pt",
153
- downsample_mode=downsample_mode,
154
- max_slice_nums=9,
155
- ).to(model.device)
156
-
157
- with torch.inference_mode():
158
- generated_ids = model.generate(
159
- **inputs,
160
  downsample_mode=downsample_mode,
161
- max_new_tokens=max_new_tokens,
162
- do_sample=False,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  )
164
-
165
- generated_ids_trimmed = [
166
- out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids, strict=False)
167
- ]
168
- output_text = processor.batch_decode(
169
- generated_ids_trimmed,
170
- skip_special_tokens=True,
171
- clean_up_tokenization_spaces=False,
172
- )
173
- return str(output_text[0]).strip() if output_text else ""
 
143
  ) -> str:
144
  import torch
145
 
146
+ try:
147
+ processor, model = _get_model(model_id)
148
+ inputs = processor.apply_chat_template(
149
+ messages,
150
+ tokenize=True,
151
+ add_generation_prompt=True,
152
+ return_dict=True,
153
+ return_tensors="pt",
 
 
 
 
 
 
154
  downsample_mode=downsample_mode,
155
+ max_slice_nums=9,
156
+ ).to(model.device)
157
+
158
+ with torch.inference_mode():
159
+ generated_ids = model.generate(
160
+ **inputs,
161
+ downsample_mode=downsample_mode,
162
+ max_new_tokens=max_new_tokens,
163
+ do_sample=False,
164
+ )
165
+
166
+ generated_ids_trimmed = [
167
+ out_ids[len(in_ids) :] for in_ids, out_ids in zip(inputs.input_ids, generated_ids, strict=False)
168
+ ]
169
+ output_text = processor.batch_decode(
170
+ generated_ids_trimmed,
171
+ skip_special_tokens=True,
172
+ clean_up_tokenization_spaces=False,
173
  )
174
+ return str(output_text[0]).strip() if output_text else ""
175
+ except Exception as exc:
176
+ raise RuntimeError(
177
+ "OpenBMB Transformers generation failed on the CUDA/ZeroGPU lane. "
178
+ f"Inner error: {type(exc).__name__}: {exc}"
179
+ ) from exc