A privacy-first, fully-local web app for analyzing blood work results. Upload a lab PDF, extract structured markers with a local Ollama LLM, store results in SQLite, and view insights and trends.
cp .env.example .env
npm install
npm run db:pushnpm run db:backupCreates a timestamped copy of data/app.db under data/backups/.
npm run dev- Web UI: http://localhost:5173
- API: http://localhost:3001
npm run build
npm start- App: http://localhost:3001 (API and web UI on one port)
npm run verifyRuns TypeScript type-checking (tsc --noEmit) and unit tests (canned graders only — no Ollama calls).
Panel and trend Level 1 live scoring hit your local Ollama model and are not part of npm test / npm run verify. Requires Ollama running and OLLAMA_MODEL set (via .env or --model). Use --suite panel|trend|all (default all).
npm run test:live-eval -- --suite panel --model gemma4:26b
npm run test:live-eval -- --suite trend --model gemma4:26b
npm run test:live-eval -- --model qwen3.6:27b --timeout-ms 1200000
npm run test:live-eval -- --suite panel --model gemma4:26b-mlx --trials 3On failure, the suite logs failing assertion ids and the raw model answer for each case. --trials / -k (or LOCALLAB_LIVE_EVAL_TRIALS) repeats the full suite for pass^k; default is 1 (baselines / compares). Ship gate uses 3.
- Baseline (one model; suite
panel,trend, orall→ two files): ask Cursor with thebaseline-live-evalsskill, e.g. “baseline trend on gemma4:26b” or “baseline all on gemma4:26b-mlx”. Reports go toevals/baselines/. - Compare (same suite, multiple models): ask with
compare-live-evals, e.g. “compare trend live evals against gemma4:26b and medgemma1.5:latest” (suite defaults to panel if omitted). Reports go toevals/comparisons/.
Both report dirs are gitignored by default; force-add only when committing a decision record.
Do not ship a LocalLab chat model default or prompt change unless panel Level 1 and trend Level 1 both clear pass^k (start k = 3) on that exact model tag.
npm run test:live-eval -- --suite panel --model gemma4:26b-mlx --trials 3
npm run test:live-eval -- --suite trend --model gemma4:26b-mlx --trials 3Ask Cursor with the ship-gate-live-evals skill. Gate tag must match .env OLLAMA_MODEL (local default: gemma4:26b-mlx); document any one-line override in the PR. Do not average suites, skip a suite, or ship on pass@1 folklore.
| Variable | Default | Description |
|---|---|---|
OLLAMA_URL |
http://localhost:11434 |
Ollama API base URL |
OLLAMA_TIMEOUT_MS |
0 |
Idle timeout while streaming Ollama tokens; 0 disables the limit |
OLLAMA_MODEL |
— | Model for live evals (npm run test:live-eval); override with --model |
LOCALLAB_LIVE_EVAL |
0 |
Keep 0 for normal use; test:live-eval sets this to 1 |
LOCALLAB_LIVE_EVAL_TIMEOUT_MS |
900000 |
Per-case live-eval timeout in ms; override with --timeout-ms |
LOCALLAB_LIVE_EVAL_TRIALS |
1 |
Independent full-suite repeats for pass^k; override with --trials / -k (ship gate: 3) |
PORT |
3001 |
Express API port |
Choose a model from the web UI before uploading or generating insights.
