Spaces:
Running on Zero
A newer version of the Gradio SDK is available: 6.19.0
Chhaya: teaching a 4B model to be the eyes, not the doctor
Field notes from the Hugging Face Build Small Hackathon — Backyard AI track.
The person
Not a persona. A class of people you pass every day and never think about as patients: the auto driver whose right arm bakes in the window sun for ten hours, the delivery rider whose neck burns under the helmet line, the construction worker on a site that doesn't reschedule for a heat wave. They get the most sun exposure of anyone and the fewest skin checks. Heat waves are making the exposure worse every year.
The phone is the one tool they all already have. So the question was narrow: what can a small model do with one photo and thirty seconds, for someone who will never see a dermatologist?
The one design decision everything else followed
Early on it would have been easy to let the model do everything — look at the photo and tell the person what to drink, when to rest, whether to worry. That's also how you build something that confidently hallucinates a hydration schedule.
So we drew a hard line: the model is the eyes, the guidelines are the medicine.
- MedGemma-1.5-4B looks at the photo and returns a structured description — type, colour, borders, symmetry, texture, a concern level. That's all it's trusted with.
- Every medical number and action — litres per shift, ORS timing, the 12–3 pm shade window, when to call an ambulance — is curated, deterministic content from NDMA India heat guidance, WHO heat-health advice, and the Cancer Council's ABCDE criteria.
The model never invents medicine. When it's wrong, it's wrong about what a spot looks like — recoverable — not about what you should do — dangerous.
Three things that broke, and what they taught us
1. The model thinks out loud. First live test on ZeroGPU: the app fell back to demo mode. MedGemma-1.5 is a reasoning model — it emits a long Thought: … trace before the JSON, and our 600-token budget ran out mid-thought. Fix was two-part: raise the budget, and parse the last balanced {…} block carrying a concern key rather than the first. The reasoning trace often contains a draft JSON; you want the conclusion, not the scratch work.
2. Shared free GPUs run dry. Anonymous visitors burn ZeroGPU quota in about two requests. Silent degradation to demo mode looked like a bug. Now the app catches the quota error and shows a friendly "sign in to Hugging Face for more free quota" card. Honesty beats a mysterious downgrade.
3. Pretty isn't tasteful. The first UI was a generic clinical dashboard. Wrong audience. The rebuild — a warm sand-and-dusk palette, a hand-drawn sun-under-an-umbrella mascot, plain-language result cards — isn't decoration; it's the difference between something a tired worker actually opens and something that feels like a hospital form.
The fine-tune: from "describes skin" to "knows when to worry"
Sunny (the app that inspired this) fine-tuned MedGemma on Gemini's opinion of each image. We wanted the one medically-loaded field — concern — anchored to something harder.
So the training set joins two sources:
- ISIC-2024 lesion photos, with
concernmapped from biopsy ground truth (malignant → see a doctor). - Google's SCIN — real consumer phone photos with dermatologist labels, spanning Monk skin tones 1–7 (dermoscopy datasets skew light-skinned; our users don't).
1,406 examples, low deliberately downsampled so the model can't learn to default to "safe" — the one mistake a screening tool must never make. A low spot whose description shows the full ABCDE high-risk combo gets bumped to watch regardless of label. Cautious by construction.
The headline eval metric isn't accuracy — it's malignant recall: of the spots that truly need a doctor, how few did the model wave through as ordinary. That's the number that matters when the user is the only person who will ever look.
The numbers (141-image held-out test set)
| metric | base MedGemma | Chhaya-tuned (v2) |
|---|---|---|
| Valid JSON | 99.3% | 100% |
| Concern accuracy | 33.3% | 69.5% |
| Malignant recall | 0.936 | 0.83 |
| Output tokens/answer | 770 | 156 |
The fine-tune doubled accuracy and cut output to a fifth (the chain-of-thought preamble is gone — that's the 5× speed-up, live). One honest caveat: base's 0.94 malignant recall looks higher, but it's hollow — base reaches it by dumping 60% of all cases into "watch" (hence 33% accuracy). It's a hedge machine, not a safer tool. The tuned model commits to a real triage; we oversampled the "see-a-doctor" class to push its recall from 0.77 (v1) to 0.83 (v2), and the deterministic ABCDE backstop plus the always-on "see a doctor if…" card carry the residual risk — because the model is the eyes, and the guidelines are the safety net.
(Training: QLoRA on a frozen vision tower, 2 epochs, ~$6 of Modal credits total across v1+v2.)
What it is, and isn't
Chhaya is not a medical device and never diagnoses. It describes, it explains in plain words, and it points people toward care earlier than they'd have gone on their own. For someone who works in the sun and has never had a skin check, "this is worth showing a doctor" — arriving for free, in thirty seconds, on the phone already in their pocket — is the whole point.
— Built with Gradio on Hugging Face Spaces. Model: MedGemma-1.5-4B (≤4B, well under the 32B cap). Inspired by Sunny.