Spaces:
Running on Zero
Running on Zero
Codex Codex commited on
Commit ·
c1a5fb4
1
Parent(s): 3072bfd
Default extraction to the fine-tuned MiniCPM-V Hub checkpoint.
Browse filesPoint DEFAULT_HF_REPO at build-small-hackathon/blood-test-minicpmv-4_6-medreason so local runs and the Space use our MedReason SFT model without extra env vars.
Co-authored-by: Codex <chatgpt-codex-connector[bot]@users.noreply.github.com>
- DEPLOY.md +16 -10
- README.md +5 -3
- RUNBOOK.md +10 -8
- app.py +2 -2
- docs/MESSAGE_TO_DIMITRIS.md +2 -2
- docs/REMAINING_WORK.md +9 -13
- src/extraction/zerogpu_transformers.py +1 -3
- src/model_paths.py +4 -1
- tests/test_model_paths.py +42 -3
- train/modal_eval.py +4 -2
- train/modal_finetune.py +4 -4
DEPLOY.md
CHANGED
|
@@ -11,7 +11,7 @@ This workflow is intentionally fixed:
|
|
| 11 |
5. When the fine-tuned model is ready, replace only the model variables for the active lanes.
|
| 12 |
6. The llama.cpp lane is optional and must be enabled explicitly with environment variables.
|
| 13 |
|
| 14 |
-
Do not change this architecture unless the project intentionally gives up ZeroGPU.
|
| 15 |
|
| 16 |
## 1. Space Metadata
|
| 17 |
|
|
@@ -35,13 +35,17 @@ ZeroGPU is Gradio-only on Hugging Face. It is not available for Docker Spaces, w
|
|
| 35 |
|
| 36 |
## 2. Default Model Serving (Transformers)
|
| 37 |
|
| 38 |
-
The production Space path is the
|
| 39 |
|
| 40 |
```text
|
| 41 |
EXTRACTOR_BACKEND=transformers
|
| 42 |
-
ZEROGPU_MODEL_ID=
|
| 43 |
```
|
| 44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
The backend lives in:
|
| 46 |
|
| 47 |
```text
|
|
@@ -96,14 +100,14 @@ LLAMACPP_GGUF_REPO=openbmb/MiniCPM-V-4.6-gguf
|
|
| 96 |
LLAMACPP_MODEL_FILE=MiniCPM-V-4_6-Q4_K_M.gguf
|
| 97 |
```
|
| 98 |
|
| 99 |
-
## 4.
|
| 100 |
|
| 101 |
-
|
| 102 |
|
| 103 |
-
1. Upload the
|
| 104 |
-
2. Optionally convert/quantize
|
| 105 |
3. Keep the same Gradio + ZeroGPU architecture.
|
| 106 |
-
4.
|
| 107 |
|
| 108 |
```bash
|
| 109 |
ZEROGPU_MODEL_ID=<owner>/<fine-tuned-minicpm-v-transformers-repo>
|
|
@@ -112,6 +116,8 @@ LLAMACPP_MODEL_FILE=<fine-tuned-model>.gguf
|
|
| 112 |
LLAMACPP_MMPROJ_FILE=<mmproj-file>.gguf
|
| 113 |
```
|
| 114 |
|
|
|
|
|
|
|
| 115 |
Do not add model files to the Space git repo. Do not reintroduce Docker or `llama-server` for the ZeroGPU deployment.
|
| 116 |
|
| 117 |
## 5. Why This Architecture
|
|
@@ -122,9 +128,9 @@ This architecture keeps:
|
|
| 122 |
|
| 123 |
- Free ZeroGPU eligibility.
|
| 124 |
- No external hosted inference API calls.
|
| 125 |
-
- The
|
| 126 |
- An optional llama.cpp / GGUF lane for badges and fine-tuned GGUF deployment.
|
| 127 |
-
- A clean
|
| 128 |
|
| 129 |
## 6. Local Development
|
| 130 |
|
|
|
|
| 11 |
5. When the fine-tuned model is ready, replace only the model variables for the active lanes.
|
| 12 |
6. The llama.cpp lane is optional and must be enabled explicitly with environment variables.
|
| 13 |
|
| 14 |
+
Do not change this architecture unless the project intentionally gives up ZeroGPU. To swap models, change `ZEROGPU_MODEL_ID` (or `DEFAULT_HF_REPO` in `src/model_paths.py`) and optional `LLAMACPP_*` for the llama.cpp lane.
|
| 15 |
|
| 16 |
## 1. Space Metadata
|
| 17 |
|
|
|
|
| 35 |
|
| 36 |
## 2. Default Model Serving (Transformers)
|
| 37 |
|
| 38 |
+
The production Space path is the fine-tuned Transformers repo:
|
| 39 |
|
| 40 |
```text
|
| 41 |
EXTRACTOR_BACKEND=transformers
|
| 42 |
+
ZEROGPU_MODEL_ID=build-small-hackathon/blood-test-minicpmv-4_6-medreason
|
| 43 |
```
|
| 44 |
|
| 45 |
+
Hub: [build-small-hackathon/blood-test-minicpmv-4_6-medreason](https://huggingface.co/build-small-hackathon/blood-test-minicpmv-4_6-medreason)
|
| 46 |
+
|
| 47 |
+
`ZEROGPU_MODEL_ID` is optional when it matches the code default in `src/model_paths.py`. Use `openbmb/MiniCPM-V-4.6` only for base-model baselines.
|
| 48 |
+
|
| 49 |
The backend lives in:
|
| 50 |
|
| 51 |
```text
|
|
|
|
| 100 |
LLAMACPP_MODEL_FILE=MiniCPM-V-4_6-Q4_K_M.gguf
|
| 101 |
```
|
| 102 |
|
| 103 |
+
## 4. Swapping or Retraining the Model
|
| 104 |
|
| 105 |
+
To publish a newer fine-tune:
|
| 106 |
|
| 107 |
+
1. Upload the Transformers checkpoint to a Hugging Face model repo.
|
| 108 |
+
2. Optionally convert/quantize to GGUF (+ mmproj) for the llama.cpp lane.
|
| 109 |
3. Keep the same Gradio + ZeroGPU architecture.
|
| 110 |
+
4. Point extraction at the new repo:
|
| 111 |
|
| 112 |
```bash
|
| 113 |
ZEROGPU_MODEL_ID=<owner>/<fine-tuned-minicpm-v-transformers-repo>
|
|
|
|
| 116 |
LLAMACPP_MMPROJ_FILE=<mmproj-file>.gguf
|
| 117 |
```
|
| 118 |
|
| 119 |
+
Or update `DEFAULT_HF_REPO` in `src/model_paths.py` so local runs and the Space pick it up without an env override.
|
| 120 |
+
|
| 121 |
Do not add model files to the Space git repo. Do not reintroduce Docker or `llama-server` for the ZeroGPU deployment.
|
| 122 |
|
| 123 |
## 5. Why This Architecture
|
|
|
|
| 128 |
|
| 129 |
- Free ZeroGPU eligibility.
|
| 130 |
- No external hosted inference API calls.
|
| 131 |
+
- The fine-tuned Transformers runtime on ZeroGPU for PDF/image lab reports.
|
| 132 |
- An optional llama.cpp / GGUF lane for badges and fine-tuned GGUF deployment.
|
| 133 |
+
- A clean model swap by changing `ZEROGPU_MODEL_ID` / `DEFAULT_HF_REPO` and optional `LLAMACPP_*` variables.
|
| 134 |
|
| 135 |
## 6. Local Development
|
| 136 |
|
README.md
CHANGED
|
@@ -46,7 +46,7 @@ The knowledge graph is educational context, not diagnosis. The lab-provided refe
|
|
| 46 |
|
| 47 |
## Extraction Backends
|
| 48 |
|
| 49 |
-
The default path is **Transformers vision** (
|
| 50 |
|
| 51 |
| `EXTRACTOR_BACKEND` | Used for | PDF / image uploads |
|
| 52 |
|---|---|---|
|
|
@@ -123,9 +123,11 @@ Default Space variables:
|
|
| 123 |
|
| 124 |
```bash
|
| 125 |
EXTRACTOR_BACKEND=transformers
|
| 126 |
-
ZEROGPU_MODEL_ID=
|
| 127 |
```
|
| 128 |
|
|
|
|
|
|
|
| 129 |
Optional llama.cpp badge lane (not enabled in the default deployment):
|
| 130 |
|
| 131 |
```bash
|
|
@@ -136,7 +138,7 @@ LLAMACPP_MODEL_FILE=MiniCPM-V-4_6-Q4_K_M.gguf
|
|
| 136 |
LLAMACPP_MMPROJ_FILE=mmproj-model-f16.gguf
|
| 137 |
```
|
| 138 |
|
| 139 |
-
When
|
| 140 |
|
| 141 |
This workflow should not be changed back to Docker unless the project intentionally gives up ZeroGPU.
|
| 142 |
|
|
|
|
| 46 |
|
| 47 |
## Extraction Backends
|
| 48 |
|
| 49 |
+
The default path is **Transformers vision** with our fine-tuned [blood-test-minicpmv-4_6-medreason](https://huggingface.co/build-small-hackathon/blood-test-minicpmv-4_6-medreason) checkpoint (MiniCPM-V 4.6 + MedReason SFT). It handles PDFs, scans, and photos through the same document pipeline in `src/document_processing.py`.
|
| 50 |
|
| 51 |
| `EXTRACTOR_BACKEND` | Used for | PDF / image uploads |
|
| 52 |
|---|---|---|
|
|
|
|
| 123 |
|
| 124 |
```bash
|
| 125 |
EXTRACTOR_BACKEND=transformers
|
| 126 |
+
ZEROGPU_MODEL_ID=build-small-hackathon/blood-test-minicpmv-4_6-medreason
|
| 127 |
```
|
| 128 |
|
| 129 |
+
`ZEROGPU_MODEL_ID` is optional — the app defaults to the fine-tuned repo above. Override with `openbmb/MiniCPM-V-4.6` only for base-model experiments.
|
| 130 |
+
|
| 131 |
Optional llama.cpp badge lane (not enabled in the default deployment):
|
| 132 |
|
| 133 |
```bash
|
|
|
|
| 138 |
LLAMACPP_MMPROJ_FILE=mmproj-model-f16.gguf
|
| 139 |
```
|
| 140 |
|
| 141 |
+
When a new fine-tuned checkpoint is ready, replace `ZEROGPU_MODEL_ID` (or update `DEFAULT_HF_REPO` in `src/model_paths.py`) for the primary lane and the `LLAMACPP_*` variables for the optional GGUF lane. Do not commit model files to the Space git repo.
|
| 142 |
|
| 143 |
This workflow should not be changed back to Docker unless the project intentionally gives up ZeroGPU.
|
| 144 |
|
RUNBOOK.md
CHANGED
|
@@ -9,7 +9,7 @@ This replaced the Docker + `llama-server` path because ZeroGPU is only available
|
|
| 9 |
| Area | Current choice |
|
| 10 |
|---|---|
|
| 11 |
| Space SDK | `gradio` |
|
| 12 |
-
| Default extraction |
|
| 13 |
| ZeroGPU worker | `@spaces.GPU` in `src/extraction/zerogpu_transformers.py` |
|
| 14 |
| Optional llama.cpp lane | `EXTRACTOR_BACKEND=llamacpp-gpu` (+ `LLAMACPP_VISION=1` for PDF/images) |
|
| 15 |
| Transformers variables | `ZEROGPU_MODEL_ID`, `ZEROGPU_MAX_NEW_TOKENS`, `ZEROGPU_DOWNSAMPLE_MODE` |
|
|
@@ -25,7 +25,7 @@ Do not switch the Space back to Docker unless the project intentionally gives up
|
|
| 25 |
|
| 26 |
| Value | Behavior |
|
| 27 |
|---|---|
|
| 28 |
-
| `transformers` (default) |
|
| 29 |
| `auto`, `zerogpu`, `zero-gpu` | Same as `transformers` |
|
| 30 |
| `llamacpp-gpu`, `llama-champion` | GGUF through `llama-cpp-python` |
|
| 31 |
| `local`, `server` | Local `llama-server` HTTP backend |
|
|
@@ -36,10 +36,10 @@ Do not switch the Space back to Docker unless the project intentionally gives up
|
|
| 36 |
|
| 37 |
```bash
|
| 38 |
EXTRACTOR_BACKEND=transformers
|
| 39 |
-
ZEROGPU_MODEL_ID=
|
| 40 |
```
|
| 41 |
|
| 42 |
-
This is what the HF Space should use for PDF/image blood-test uploads.
|
| 43 |
|
| 44 |
### Optional llama.cpp path
|
| 45 |
|
|
@@ -115,7 +115,7 @@ Primary lane:
|
|
| 115 |
|
| 116 |
```bash
|
| 117 |
EXTRACTOR_BACKEND=transformers
|
| 118 |
-
ZEROGPU_MODEL_ID=
|
| 119 |
```
|
| 120 |
|
| 121 |
Optional llama.cpp lane:
|
|
@@ -130,12 +130,14 @@ No model files are committed to the Space repo.
|
|
| 130 |
|
| 131 |
## Fine-Tuned Model Swap
|
| 132 |
|
| 133 |
-
|
| 134 |
|
| 135 |
-
|
|
|
|
|
|
|
| 136 |
2. Optionally convert/quantize it to GGUF (+ mmproj) for the llama.cpp lane.
|
| 137 |
3. Keep the same Gradio architecture.
|
| 138 |
-
4.
|
| 139 |
|
| 140 |
```bash
|
| 141 |
ZEROGPU_MODEL_ID=<owner>/<fine-tuned-minicpm-v-transformers-repo>
|
|
|
|
| 9 |
| Area | Current choice |
|
| 10 |
|---|---|
|
| 11 |
| Space SDK | `gradio` |
|
| 12 |
+
| Default extraction | Fine-tuned MiniCPM-V 4.6 (`build-small-hackathon/blood-test-minicpmv-4_6-medreason`) |
|
| 13 |
| ZeroGPU worker | `@spaces.GPU` in `src/extraction/zerogpu_transformers.py` |
|
| 14 |
| Optional llama.cpp lane | `EXTRACTOR_BACKEND=llamacpp-gpu` (+ `LLAMACPP_VISION=1` for PDF/images) |
|
| 15 |
| Transformers variables | `ZEROGPU_MODEL_ID`, `ZEROGPU_MAX_NEW_TOKENS`, `ZEROGPU_DOWNSAMPLE_MODE` |
|
|
|
|
| 25 |
|
| 26 |
| Value | Behavior |
|
| 27 |
|---|---|
|
| 28 |
+
| `transformers` (default) | Fine-tuned MiniCPM-V through Transformers vision |
|
| 29 |
| `auto`, `zerogpu`, `zero-gpu` | Same as `transformers` |
|
| 30 |
| `llamacpp-gpu`, `llama-champion` | GGUF through `llama-cpp-python` |
|
| 31 |
| `local`, `server` | Local `llama-server` HTTP backend |
|
|
|
|
| 36 |
|
| 37 |
```bash
|
| 38 |
EXTRACTOR_BACKEND=transformers
|
| 39 |
+
ZEROGPU_MODEL_ID=build-small-hackathon/blood-test-minicpmv-4_6-medreason
|
| 40 |
```
|
| 41 |
|
| 42 |
+
This is what the HF Space should use for PDF/image blood-test uploads. The env var is optional when it matches `DEFAULT_HF_REPO` in `src/model_paths.py`.
|
| 43 |
|
| 44 |
### Optional llama.cpp path
|
| 45 |
|
|
|
|
| 115 |
|
| 116 |
```bash
|
| 117 |
EXTRACTOR_BACKEND=transformers
|
| 118 |
+
ZEROGPU_MODEL_ID=build-small-hackathon/blood-test-minicpmv-4_6-medreason
|
| 119 |
```
|
| 120 |
|
| 121 |
Optional llama.cpp lane:
|
|
|
|
| 130 |
|
| 131 |
## Fine-Tuned Model Swap
|
| 132 |
|
| 133 |
+
Current default: [build-small-hackathon/blood-test-minicpmv-4_6-medreason](https://huggingface.co/build-small-hackathon/blood-test-minicpmv-4_6-medreason).
|
| 134 |
|
| 135 |
+
To publish a newer checkpoint:
|
| 136 |
+
|
| 137 |
+
1. Upload the fine-tuned Transformers checkpoint to a Hugging Face model repo.
|
| 138 |
2. Optionally convert/quantize it to GGUF (+ mmproj) for the llama.cpp lane.
|
| 139 |
3. Keep the same Gradio architecture.
|
| 140 |
+
4. Update `DEFAULT_HF_REPO` in `src/model_paths.py` and/or:
|
| 141 |
|
| 142 |
```bash
|
| 143 |
ZEROGPU_MODEL_ID=<owner>/<fine-tuned-minicpm-v-transformers-repo>
|
app.py
CHANGED
|
@@ -210,7 +210,7 @@ def hero_hackathon_panel_html() -> str:
|
|
| 210 |
(
|
| 211 |
"🎯",
|
| 212 |
"Well-Tuned",
|
| 213 |
-
"MiniCPM-V was fine-tuned on Modal and published on Hugging Face for lab report extraction.",
|
| 214 |
),
|
| 215 |
(
|
| 216 |
"🎨",
|
|
@@ -276,7 +276,7 @@ def hero_attribution_html() -> str:
|
|
| 276 |
"Enabled with OpenBMB",
|
| 277 |
"OB",
|
| 278 |
"openbmb.png",
|
| 279 |
-
"MiniCPM-V-4.6 reads uploaded lab reports and extracts marker values, units, and status flags.",
|
| 280 |
),
|
| 281 |
(
|
| 282 |
"Modal",
|
|
|
|
| 210 |
(
|
| 211 |
"🎯",
|
| 212 |
"Well-Tuned",
|
| 213 |
+
"MiniCPM-V was fine-tuned on Modal with MedReason-style SFT and published on Hugging Face for lab report extraction.",
|
| 214 |
),
|
| 215 |
(
|
| 216 |
"🎨",
|
|
|
|
| 276 |
"Enabled with OpenBMB",
|
| 277 |
"OB",
|
| 278 |
"openbmb.png",
|
| 279 |
+
"Our fine-tuned MiniCPM-V-4.6 reads uploaded lab reports and extracts marker values, units, and status flags.",
|
| 280 |
),
|
| 281 |
(
|
| 282 |
"Modal",
|
docs/MESSAGE_TO_DIMITRIS.md
CHANGED
|
@@ -4,13 +4,13 @@ Hi Dimitris — here’s what’s left before submission. Full checklist for you
|
|
| 4 |
|
| 5 |
**Priority order:** custom model → copy pass → KB + videos (agents) → article → demo video.
|
| 6 |
|
| 7 |
-
1. **Custom model** —
|
| 8 |
2. **Copy** — Tighten hero, trace steps, and README; fix badge claims (Well-Tuned only after model swap).
|
| 9 |
3. **Knowledge graph** — Expand beyond 107 markers via `markers.py` + `expand_lab_knowledge_graph.py` (agent task).
|
| 10 |
4. **Videos** — Replace reused YouTube URLs with marker/category-specific explainers (agent task).
|
| 11 |
5. **Article** — Problem → architecture → fine-tune proof → limitations + Space link.
|
| 12 |
6. **Demo video** — Laytimely-style: AI voice + screen recording + background music; record after 1–2 are done.
|
| 13 |
|
| 14 |
-
**Current baseline:**
|
| 15 |
|
| 16 |
Ping me when the model is on the Space or if you want me on copy/KB review.
|
|
|
|
| 4 |
|
| 5 |
**Priority order:** custom model → copy pass → KB + videos (agents) → article → demo video.
|
| 6 |
|
| 7 |
+
1. **Custom model** — Fine-tuned repo is live on Hub and wired as the code default; confirm Space after redeploy, run `modal run train/modal_eval.py::compare` for before/after numbers.
|
| 8 |
2. **Copy** — Tighten hero, trace steps, and README; fix badge claims (Well-Tuned only after model swap).
|
| 9 |
3. **Knowledge graph** — Expand beyond 107 markers via `markers.py` + `expand_lab_knowledge_graph.py` (agent task).
|
| 10 |
4. **Videos** — Replace reused YouTube URLs with marker/category-specific explainers (agent task).
|
| 11 |
5. **Article** — Problem → architecture → fine-tune proof → limitations + Space link.
|
| 12 |
6. **Demo video** — Laytimely-style: AI voice + screen recording + background music; record after 1–2 are done.
|
| 13 |
|
| 14 |
+
**Current baseline:** App defaults to `build-small-hackathon/blood-test-minicpmv-4_6-medreason`; KG has 107 markers; only 2/13 real eval reports labeled; article and demo not started.
|
| 15 |
|
| 16 |
Ping me when the model is on the Space or if you want me on copy/KB review.
|
docs/REMAINING_WORK.md
CHANGED
|
@@ -12,7 +12,7 @@
|
|
| 12 |
|
| 13 |
| Area | Now |
|
| 14 |
|---|---|
|
| 15 |
-
| Space / app |
|
| 16 |
| Knowledge graph | 107 markers in `kb/cbc_knowledge_graph.json` |
|
| 17 |
| Marker videos | All 107 have `video_url`; ~44 unique YouTube IDs (many reused) |
|
| 18 |
| Real eval labels | 2/13 reports fully labeled in `eval/data/real/labels.jsonl` |
|
|
@@ -25,18 +25,14 @@
|
|
| 25 |
|
| 26 |
**Owner:** Dimitris (Modal + HF Space vars)
|
| 27 |
|
| 28 |
-
- [
|
| 29 |
-
- [
|
| 30 |
-
- [ ]
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
ZEROGPU_MODEL_ID=<fine-tuned-repo>
|
| 34 |
-
```
|
| 35 |
-
- [ ] Rebuild Space; test 2–3 PDFs from `eval/data/real/`
|
| 36 |
-
- [ ] Run before/after eval: `modal run train/modal_eval.py::compare --finetuned-id <repo>` → save `eval/before_after.json`
|
| 37 |
- [ ] *(Optional, Llama badge only)* GGUF via `scripts/convert_to_gguf.sh` + `LLAMACPP_VISION=1` vars (see `README.md`)
|
| 38 |
|
| 39 |
-
**Done when:** Space uses custom model; we have a before/after metric for the article.
|
| 40 |
|
| 41 |
---
|
| 42 |
|
|
@@ -47,7 +43,7 @@
|
|
| 47 |
**Edit:** `app.py` (hero, upload hints, status, disclaimers), `src/pipeline_trace.py` (step copy), `README.md` (Space card)
|
| 48 |
|
| 49 |
- [ ] One clear pitch: upload → extract → explain → prepare for clinician conversation
|
| 50 |
-
- [ ] Badge claims match reality (Well-Tuned
|
| 51 |
- [ ] Consistent “educational, not diagnosis” disclaimer
|
| 52 |
- [ ] Less dev jargon in user-facing text (“pipeline phase”, etc.)
|
| 53 |
- [ ] Align hero badges with hackathon criteria (OpenBMB, Modal, HF, off-grid)
|
|
@@ -124,7 +120,7 @@
|
|
| 124 |
|
| 125 |
## Submission checklist
|
| 126 |
|
| 127 |
-
- [
|
| 128 |
- [ ] Before/after eval documented
|
| 129 |
- [ ] Copy + badges accurate
|
| 130 |
- [ ] KG + videos polished
|
|
|
|
| 12 |
|
| 13 |
| Area | Now |
|
| 14 |
|---|---|
|
| 15 |
+
| Space / app | Fine-tuned Transformers (`build-small-hackathon/blood-test-minicpmv-4_6-medreason`) |
|
| 16 |
| Knowledge graph | 107 markers in `kb/cbc_knowledge_graph.json` |
|
| 17 |
| Marker videos | All 107 have `video_url`; ~44 unique YouTube IDs (many reused) |
|
| 18 |
| Real eval labels | 2/13 reports fully labeled in `eval/data/real/labels.jsonl` |
|
|
|
|
| 25 |
|
| 26 |
**Owner:** Dimitris (Modal + HF Space vars)
|
| 27 |
|
| 28 |
+
- [x] Fine-tuned Transformers repo on Hub: `build-small-hackathon/blood-test-minicpmv-4_6-medreason`
|
| 29 |
+
- [x] Code default in `src/model_paths.py` → `DEFAULT_HF_REPO`
|
| 30 |
+
- [ ] Confirm Space loads the model after redeploy (2–3 PDFs from `eval/data/real/`)
|
| 31 |
+
- [ ] Set HF Space variable if still on base model: `ZEROGPU_MODEL_ID=build-small-hackathon/blood-test-minicpmv-4_6-medreason` (optional when code default is deployed)
|
| 32 |
+
- [ ] Run before/after eval: `modal run train/modal_eval.py::compare` → save `eval/before_after.json`
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
- [ ] *(Optional, Llama badge only)* GGUF via `scripts/convert_to_gguf.sh` + `LLAMACPP_VISION=1` vars (see `README.md`)
|
| 34 |
|
| 35 |
+
**Done when:** Space uses custom model in production; we have a before/after metric for the article.
|
| 36 |
|
| 37 |
---
|
| 38 |
|
|
|
|
| 43 |
**Edit:** `app.py` (hero, upload hints, status, disclaimers), `src/pipeline_trace.py` (step copy), `README.md` (Space card)
|
| 44 |
|
| 45 |
- [ ] One clear pitch: upload → extract → explain → prepare for clinician conversation
|
| 46 |
+
- [ ] Badge claims match reality (Well-Tuned reflects live fine-tuned model)
|
| 47 |
- [ ] Consistent “educational, not diagnosis” disclaimer
|
| 48 |
- [ ] Less dev jargon in user-facing text (“pipeline phase”, etc.)
|
| 49 |
- [ ] Align hero badges with hackathon criteria (OpenBMB, Modal, HF, off-grid)
|
|
|
|
| 120 |
|
| 121 |
## Submission checklist
|
| 122 |
|
| 123 |
+
- [x] Custom model wired in code (`DEFAULT_HF_REPO`); [ ] confirm on live Space after deploy
|
| 124 |
- [ ] Before/after eval documented
|
| 125 |
- [ ] Copy + badges accurate
|
| 126 |
- [ ] KG + videos polished
|
src/extraction/zerogpu_transformers.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
"""ZeroGPU extraction backend using the
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
|
@@ -18,8 +18,6 @@ from src.openbmb_client import (
|
|
| 18 |
|
| 19 |
from src.model_paths import TransformersModelSource, resolve_transformers_model_source
|
| 20 |
|
| 21 |
-
DEFAULT_ZEROGPU_MODEL = "openbmb/MiniCPM-V-4.6"
|
| 22 |
-
|
| 23 |
|
| 24 |
class ZeroGPUTransformersExtractor:
|
| 25 |
"""Extractor backed by local or Hub MiniCPM-V Transformers weights."""
|
|
|
|
| 1 |
+
"""ZeroGPU extraction backend using the fine-tuned MiniCPM-V Transformers path."""
|
| 2 |
|
| 3 |
from __future__ import annotations
|
| 4 |
|
|
|
|
| 18 |
|
| 19 |
from src.model_paths import TransformersModelSource, resolve_transformers_model_source
|
| 20 |
|
|
|
|
|
|
|
| 21 |
|
| 22 |
class ZeroGPUTransformersExtractor:
|
| 23 |
"""Extractor backed by local or Hub MiniCPM-V Transformers weights."""
|
src/model_paths.py
CHANGED
|
@@ -6,7 +6,10 @@ import os
|
|
| 6 |
from dataclasses import dataclass
|
| 7 |
from pathlib import Path
|
| 8 |
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
| 10 |
|
| 11 |
|
| 12 |
@dataclass(frozen=True)
|
|
|
|
| 6 |
from dataclasses import dataclass
|
| 7 |
from pathlib import Path
|
| 8 |
|
| 9 |
+
# Fine-tuned MiniCPM-V 4.6 for lab extraction (MedReason SFT).
|
| 10 |
+
DEFAULT_HF_REPO = "build-small-hackathon/blood-test-minicpmv-4_6-medreason"
|
| 11 |
+
# Upstream OpenBMB base — eval baselines and training scripts.
|
| 12 |
+
BASE_HF_REPO = "openbmb/MiniCPM-V-4.6"
|
| 13 |
|
| 14 |
|
| 15 |
@dataclass(frozen=True)
|
tests/test_model_paths.py
CHANGED
|
@@ -4,7 +4,12 @@ from pathlib import Path
|
|
| 4 |
|
| 5 |
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
| 6 |
|
| 7 |
-
from src.model_paths import
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
|
| 9 |
|
| 10 |
def test_resolve_uses_hub_download_when_no_local_weights(monkeypatch):
|
|
@@ -18,10 +23,42 @@ def test_resolve_uses_hub_download_when_no_local_weights(monkeypatch):
|
|
| 18 |
lambda repo_id, hub_cache: None,
|
| 19 |
)
|
| 20 |
|
| 21 |
-
source = resolve_transformers_model_source(
|
| 22 |
assert source.local_files_only is False
|
| 23 |
assert source.origin == "hub-download"
|
| 24 |
-
assert source.model_id ==
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
|
| 27 |
def test_resolve_uses_local_dir_when_complete():
|
|
@@ -47,6 +84,8 @@ def test_is_transformers_model_dir_requires_weights():
|
|
| 47 |
|
| 48 |
if __name__ == "__main__":
|
| 49 |
test_resolve_uses_hub_download_when_no_local_weights()
|
|
|
|
|
|
|
| 50 |
test_resolve_uses_local_dir_when_complete()
|
| 51 |
test_is_transformers_model_dir_requires_weights()
|
| 52 |
print("test_model_paths: ok")
|
|
|
|
| 4 |
|
| 5 |
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
|
| 6 |
|
| 7 |
+
from src.model_paths import (
|
| 8 |
+
BASE_HF_REPO,
|
| 9 |
+
DEFAULT_HF_REPO,
|
| 10 |
+
is_transformers_model_dir,
|
| 11 |
+
resolve_transformers_model_source,
|
| 12 |
+
)
|
| 13 |
|
| 14 |
|
| 15 |
def test_resolve_uses_hub_download_when_no_local_weights(monkeypatch):
|
|
|
|
| 23 |
lambda repo_id, hub_cache: None,
|
| 24 |
)
|
| 25 |
|
| 26 |
+
source = resolve_transformers_model_source(DEFAULT_HF_REPO)
|
| 27 |
assert source.local_files_only is False
|
| 28 |
assert source.origin == "hub-download"
|
| 29 |
+
assert source.model_id == DEFAULT_HF_REPO
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def test_resolve_defaults_to_finetuned_repo(monkeypatch):
|
| 33 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 34 |
+
empty_models = Path(tmp) / "models"
|
| 35 |
+
empty_models.mkdir()
|
| 36 |
+
monkeypatch.setenv("BTE_MODELS_DIR", str(empty_models))
|
| 37 |
+
monkeypatch.setenv("HF_HOME", str(Path(tmp) / "hf"))
|
| 38 |
+
monkeypatch.delenv("ZEROGPU_MODEL_ID", raising=False)
|
| 39 |
+
monkeypatch.setattr(
|
| 40 |
+
"src.model_paths.latest_complete_snapshot",
|
| 41 |
+
lambda repo_id, hub_cache: None,
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
source = resolve_transformers_model_source()
|
| 45 |
+
assert source.model_id == DEFAULT_HF_REPO
|
| 46 |
+
assert source.origin == "hub-download"
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
def test_resolve_base_repo_for_eval_baseline(monkeypatch):
|
| 50 |
+
with tempfile.TemporaryDirectory() as tmp:
|
| 51 |
+
empty_models = Path(tmp) / "models"
|
| 52 |
+
empty_models.mkdir()
|
| 53 |
+
monkeypatch.setenv("BTE_MODELS_DIR", str(empty_models))
|
| 54 |
+
monkeypatch.setenv("HF_HOME", str(Path(tmp) / "hf"))
|
| 55 |
+
monkeypatch.setattr(
|
| 56 |
+
"src.model_paths.latest_complete_snapshot",
|
| 57 |
+
lambda repo_id, hub_cache: None,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
source = resolve_transformers_model_source(BASE_HF_REPO)
|
| 61 |
+
assert source.model_id == BASE_HF_REPO
|
| 62 |
|
| 63 |
|
| 64 |
def test_resolve_uses_local_dir_when_complete():
|
|
|
|
| 84 |
|
| 85 |
if __name__ == "__main__":
|
| 86 |
test_resolve_uses_hub_download_when_no_local_weights()
|
| 87 |
+
test_resolve_defaults_to_finetuned_repo()
|
| 88 |
+
test_resolve_base_repo_for_eval_baseline()
|
| 89 |
test_resolve_uses_local_dir_when_complete()
|
| 90 |
test_is_transformers_model_dir_requires_weights()
|
| 91 |
print("test_model_paths: ok")
|
train/modal_eval.py
CHANGED
|
@@ -5,7 +5,9 @@ field-level accuracy jump. The model runs through the same ZeroGPU/Transformers
|
|
| 5 |
uses (here `@spaces.GPU` is a no-op because the `spaces` package isn't installed, so generation
|
| 6 |
runs directly on the Modal GPU).
|
| 7 |
|
| 8 |
-
modal run train/modal_eval.py::compare
|
|
|
|
|
|
|
| 9 |
|
| 10 |
Writes eval/before_after.json locally with the base vs fine-tuned metrics.
|
| 11 |
"""
|
|
@@ -97,7 +99,7 @@ def eval_model(model_id: str, labels_rel: str = "eval/data/real/labels.jsonl") -
|
|
| 97 |
|
| 98 |
@app.local_entrypoint()
|
| 99 |
def compare(
|
| 100 |
-
finetuned_id: str,
|
| 101 |
base_id: str = "openbmb/MiniCPM-V-4.6",
|
| 102 |
labels_rel: str = "eval/data/real/labels.jsonl",
|
| 103 |
) -> None:
|
|
|
|
| 5 |
uses (here `@spaces.GPU` is a no-op because the `spaces` package isn't installed, so generation
|
| 6 |
runs directly on the Modal GPU).
|
| 7 |
|
| 8 |
+
modal run train/modal_eval.py::compare
|
| 9 |
+
|
| 10 |
+
modal run train/modal_eval.py::compare --finetuned-id build-small-hackathon/blood-test-minicpmv-4_6-medreason
|
| 11 |
|
| 12 |
Writes eval/before_after.json locally with the base vs fine-tuned metrics.
|
| 13 |
"""
|
|
|
|
| 99 |
|
| 100 |
@app.local_entrypoint()
|
| 101 |
def compare(
|
| 102 |
+
finetuned_id: str = "build-small-hackathon/blood-test-minicpmv-4_6-medreason",
|
| 103 |
base_id: str = "openbmb/MiniCPM-V-4.6",
|
| 104 |
labels_rel: str = "eval/data/real/labels.jsonl",
|
| 105 |
) -> None:
|
train/modal_finetune.py
CHANGED
|
@@ -170,7 +170,7 @@ def main(n: int = 2000, epochs: int = 1, lr: float = 2e-5, real_labels: str | No
|
|
| 170 |
print(f"\nLoRA adapters saved to Modal volume 'blood-test-adapters' at {path}")
|
| 171 |
print("Next: merge the adapter into the base model and push it to the Hub:")
|
| 172 |
print(" modal run train/modal_finetune.py::merge --repo-id <owner>/<model-name>")
|
| 173 |
-
print("then
|
| 174 |
|
| 175 |
|
| 176 |
@app.function(
|
|
@@ -183,7 +183,7 @@ def main(n: int = 2000, epochs: int = 1, lr: float = 2e-5, real_labels: str | No
|
|
| 183 |
def merge_and_push(repo_id: str, adapter_dir: str = "/adapters/minicpmv-lab-lora") -> str:
|
| 184 |
"""Merge the newest LoRA checkpoint into MiniCPM-V 4.6 and push the merged model to the Hub.
|
| 185 |
|
| 186 |
-
Deploy by setting ZEROGPU_MODEL_ID=<repo_id> on the Space
|
| 187 |
Requires a Modal secret named 'huggingface-secret' exposing HF_TOKEN with write access.
|
| 188 |
"""
|
| 189 |
import glob
|
|
@@ -227,5 +227,5 @@ def merge_and_push(repo_id: str, adapter_dir: str = "/adapters/minicpmv-lab-lora
|
|
| 227 |
@app.local_entrypoint()
|
| 228 |
def merge(repo_id: str, adapter_dir: str = "/adapters/minicpmv-lab-lora") -> None:
|
| 229 |
pushed = merge_and_push.remote(repo_id=repo_id, adapter_dir=adapter_dir)
|
| 230 |
-
print(f"\nDone.
|
| 231 |
-
print("
|
|
|
|
| 170 |
print(f"\nLoRA adapters saved to Modal volume 'blood-test-adapters' at {path}")
|
| 171 |
print("Next: merge the adapter into the base model and push it to the Hub:")
|
| 172 |
print(" modal run train/modal_finetune.py::merge --repo-id <owner>/<model-name>")
|
| 173 |
+
print("then update DEFAULT_HF_REPO in src/model_paths.py (or ZEROGPU_MODEL_ID on the Space).")
|
| 174 |
|
| 175 |
|
| 176 |
@app.function(
|
|
|
|
| 183 |
def merge_and_push(repo_id: str, adapter_dir: str = "/adapters/minicpmv-lab-lora") -> str:
|
| 184 |
"""Merge the newest LoRA checkpoint into MiniCPM-V 4.6 and push the merged model to the Hub.
|
| 185 |
|
| 186 |
+
Deploy by updating DEFAULT_HF_REPO in src/model_paths.py or setting ZEROGPU_MODEL_ID=<repo_id> on the Space.
|
| 187 |
Requires a Modal secret named 'huggingface-secret' exposing HF_TOKEN with write access.
|
| 188 |
"""
|
| 189 |
import glob
|
|
|
|
| 227 |
@app.local_entrypoint()
|
| 228 |
def merge(repo_id: str, adapter_dir: str = "/adapters/minicpmv-lab-lora") -> None:
|
| 229 |
pushed = merge_and_push.remote(repo_id=repo_id, adapter_dir=adapter_dir)
|
| 230 |
+
print(f"\nDone. Update DEFAULT_HF_REPO in src/model_paths.py to {pushed!r}")
|
| 231 |
+
print("(or set ZEROGPU_MODEL_ID on the Space), then redeploy.")
|