- Add run_ocr_llm_batch() — sends N images in a single vision API call
with structured JSON prompt, up to 20 images per batch
- Add _resize_for_llm() — downscales images to 1600px max dimension
before sending to LLM, reducing per-image token cost
- Update bulk_process() to pre-read all files and batch-OCR in one call
- Graceful fallback: if batch JSON parsing fails, retries individually
- Frontend shows llm_batch engine badge
Without batch: N photos = N API calls (each with full prompt overhead)
With batch: N photos = ceil(N/20) API calls + image downscaling savings
Adds optional LLM-based OCR as an alternative to Tesseract for reading
machine IDs from photos.
Backend (server.py):
- New run_ocr_llm() function calls OpenCode Go API (mimo-v2-omni model)
- Auto-falls back to Tesseract if API key missing or call fails
- Endpoints /api/analyze and /api/bulk-process accept ?ocr_engine=llm
query param (default: tesseract) and ?ocr_model for model override
- Configurable via env vars: OPENCODE_GO_API_KEY, LLM_OCR_MODEL
- Requires User-Agent: Hermes-Agent/1.0 header for OpenCode Go API
Frontend (static/index.html):
- Toggle checkbox 'Use LLM OCR' in the UI
- OCR engine badge shown in results (llm vs tesseract + model name)
- getOcrParams() helper appends ?ocr_engine=llm to API calls
Infrastructure:
- .gitignore for uploads/ directory
Closes: #2