barath19 OpenAI Codex commited on
Commit
988ede0
·
1 Parent(s): fa40826

fix: use MiniCPM-V-4.5 to resolve unsupported architecture on Space

Browse files

MiniCPM-V-4.6 has model_type 'minicpmv4_6' and requires transformers>=5.7.0,
which the Space's transformers 4.x can't load (ValueError: architecture not
recognized). Switch to MiniCPM-V-4.5 (model_type 'minicpmv'), which uses
trust_remote_code + model.chat() on transformers 4.x.

- redac/vision.py: MODEL_ID -> openbmb/MiniCPM-V-4_5; load/download weights
on CPU before entering the @spaces.GPU window so the 16GB download can't
exhaust the ZeroGPU time budget; deterministic decoding (sampling=False).
- requirements.txt: pin transformers>=4.49,<5; add timm.
- app.py: make local port configurable via GRADIO_SERVER_PORT (xray-anything
occupies 7860-7863).

Co-authored-by: OpenAI Codex <codex@openai.com>

Files changed (3) hide show
  1. app.py +5 -2
  2. redac/vision.py +11 -4
  3. requirements.txt +2 -1
app.py CHANGED
@@ -104,7 +104,7 @@ with gr.Blocks(title="Redac") as demo:
104
  with gr.Tab("Image"):
105
  gr.Markdown(
106
  "Upload a document or ID image. A local vision model "
107
- "(MiniCPM-V-4.6) extracts the fields, then Redac redacts them."
108
  )
109
  i_map = gr.State({})
110
  with gr.Row():
@@ -136,4 +136,7 @@ with gr.Blocks(title="Redac") as demo:
136
 
137
 
138
  if __name__ == "__main__":
139
- demo.launch(server_name="0.0.0.0", server_port=7860, theme=gr.themes.Soft())
 
 
 
 
104
  with gr.Tab("Image"):
105
  gr.Markdown(
106
  "Upload a document or ID image. A local vision model "
107
+ "(MiniCPM-V-4.5) extracts the fields, then Redac redacts them."
108
  )
109
  i_map = gr.State({})
110
  with gr.Row():
 
136
 
137
 
138
  if __name__ == "__main__":
139
+ import os
140
+
141
+ port = int(os.environ.get("GRADIO_SERVER_PORT", "7860"))
142
+ demo.launch(server_name="0.0.0.0", server_port=port, theme=gr.themes.Soft())
redac/vision.py CHANGED
@@ -1,9 +1,14 @@
1
- """Image -> text extraction with a local vision model (MiniCPM-V-4.6).
2
 
3
  Runs in-Space on ZeroGPU via the @spaces.GPU decorator. The model reads a
4
  document/ID image and returns the fields as plain text, which then flows
5
  through the same PII detection + redaction core as typed text.
6
 
 
 
 
 
 
7
  Local dev: set REDAC_MOCK=1 to skip the model entirely and return a canned
8
  extraction, so the Gradio UI runs on a laptop with no GPU.
9
  """
@@ -13,7 +18,7 @@ from __future__ import annotations
13
  import os
14
  from functools import lru_cache
15
 
16
- MODEL_ID = "openbmb/MiniCPM-V-4.6"
17
 
18
  EXTRACTION_PROMPT = (
19
  "You are a document data extractor. Read this image and transcribe ALL "
@@ -52,6 +57,7 @@ except Exception: # pragma: no cover - local fallback
52
 
53
  @lru_cache(maxsize=1)
54
  def _load_model():
 
55
  import torch
56
  from transformers import AutoModel, AutoTokenizer
57
 
@@ -67,10 +73,10 @@ def _load_model():
67
 
68
  @_gpu
69
  def _chat(image, prompt: str) -> str:
70
- model, tokenizer = _load_model()
71
  model = model.to("cuda")
72
  msgs = [{"role": "user", "content": [image, prompt]}]
73
- return model.chat(image=None, msgs=msgs, tokenizer=tokenizer)
74
 
75
 
76
  def extract_text_from_image(image, prompt: str | None = None) -> str:
@@ -79,4 +85,5 @@ def extract_text_from_image(image, prompt: str | None = None) -> str:
79
  return ""
80
  if _is_mock():
81
  return _MOCK_EXTRACTION
 
82
  return _chat(image.convert("RGB"), prompt or EXTRACTION_PROMPT).strip()
 
1
+ """Image -> text extraction with a local vision model (MiniCPM-V-4.5).
2
 
3
  Runs in-Space on ZeroGPU via the @spaces.GPU decorator. The model reads a
4
  document/ID image and returns the fields as plain text, which then flows
5
  through the same PII detection + redaction core as typed text.
6
 
7
+ MiniCPM-V-4.5 (model_type "minicpmv") uses trust_remote_code + model.chat()
8
+ and runs on transformers 4.x. The weights are downloaded/loaded on CPU
9
+ *before* entering the GPU window so the 16GB download can't blow the
10
+ ZeroGPU time budget; the GPU call only moves the model to CUDA and generates.
11
+
12
  Local dev: set REDAC_MOCK=1 to skip the model entirely and return a canned
13
  extraction, so the Gradio UI runs on a laptop with no GPU.
14
  """
 
18
  import os
19
  from functools import lru_cache
20
 
21
+ MODEL_ID = "openbmb/MiniCPM-V-4_5"
22
 
23
  EXTRACTION_PROMPT = (
24
  "You are a document data extractor. Read this image and transcribe ALL "
 
57
 
58
  @lru_cache(maxsize=1)
59
  def _load_model():
60
+ """Download + load weights on CPU. Cached. Called outside the GPU window."""
61
  import torch
62
  from transformers import AutoModel, AutoTokenizer
63
 
 
73
 
74
  @_gpu
75
  def _chat(image, prompt: str) -> str:
76
+ model, tokenizer = _load_model() # cached -> instant inside GPU window
77
  model = model.to("cuda")
78
  msgs = [{"role": "user", "content": [image, prompt]}]
79
+ return model.chat(image=None, msgs=msgs, tokenizer=tokenizer, sampling=False)
80
 
81
 
82
  def extract_text_from_image(image, prompt: str | None = None) -> str:
 
85
  return ""
86
  if _is_mock():
87
  return _MOCK_EXTRACTION
88
+ _load_model() # warm the cache on CPU before claiming the GPU
89
  return _chat(image.convert("RGB"), prompt or EXTRACTION_PROMPT).strip()
requirements.txt CHANGED
@@ -2,9 +2,10 @@ gradio==6.18.0
2
  gliner>=0.2.13
3
  torch
4
  torchvision
5
- transformers>=4.44
6
  accelerate
7
  sentencepiece
 
8
  pillow
9
  huggingface_hub
10
  spaces
 
2
  gliner>=0.2.13
3
  torch
4
  torchvision
5
+ transformers>=4.49,<5
6
  accelerate
7
  sentencepiece
8
+ timm
9
  pillow
10
  huggingface_hub
11
  spaces