Saara CLI 加入 Gemma 4 本機 OCR,讀取掃描 PDF 並支援 8 種訓練資料格式匯出
I gave my dataset CLI Gemma 4 eyes at a Hacktoberfest Hack Day: it read a scanned page on my laptop, no cloud
開發者在 Hacktoberfest Hack Day 為開源資料集 CLI Saara 加入 Gemma 4 本機掃描 PDF OCR,並加入多格式匯出與按文件分組切分功能。本機模式透過 Ollama 將掃描頁面轉成文字,文件不會離開電腦;匯出涵蓋 8 種格式,分組切分則避免同一文件的頁面同時進入訓練集與測試集。
I spent today at Hacktoberfest Hack Day Hyderabad x Kramer's Community (an MLH Hack Day) working on Saara, my open-source, local-first CLI for building ML training datasets.
The moment that made the day: I took a "scanned" PDF page with zero extractable text, ran one command, and Gemma 4 running locally in Ollama on my laptop read it back line for line, with nothing sent to the cloud.
saara ingest pdf scan.pdf --provider ollama --model gemma4:latest --out ocr.jsonl
Solar Energy Field Notes
Panel efficiency: 21.4 percent at noon.
Battery storage: 13.5 kWh, two units.
Inverter rated at 5 kW continuous.
Next inspection: 12 November 2026.
That's the real output (about a minute on a laptop GPU), every number intact.
The problem: the model is the easy part
Open-weight models like Gemma 4 are now free to download and good enough to fine-tune for your own use case. What stops most students, researchers and small teams isn't the model; it's the data. And building training data today is broken in three ways:
1. Your most valuable knowledge is locked in documents that machines can't read. Course notes, lab records, research papers, field reports, old archives: so much of it lives in scanned PDFs with no text layer. Ordinary text extraction returns nothing for those pages. The usual fix is to upload them to a paid cloud OCR API, which means sending private documents to someone else's server and paying per page. For a student, a hospital, or a lab with confidential records, that's often a non-starter.
2. Every training tool speaks a different language. OpenAI fine-tuning wants one JSON shape, LLaMA-Factory and Axolotl want ShareGPT plus a registration file, Vertex AI wants contents and parts, TRL's DPO trainer wants prompt/chosen/rejected pairs. People write one-off conversion scripts for each, and every one is a place to silently lose rows or corrupt tool calls.
3. Careless splits make your results lie. If pages from the same document end up in both your training and test sets, your model looks better than it is. You find out only after you've shipped it.
Why this matters now: the gap between "I have an open model" and "I have a model that's good at my problem" is a data gap. Whoever can turn their own documents into clean, honest training data, privately and cheaply, gets to benefit from open AI. Everyone else is stuck with generic models and cloud bills. That's the gap Saara closes.
What Saara does
One CLI for the whole path, running on local open-weight models (Gemma 4 through Ollama, or vLLM), or hosted Gemma 4 through the Gemini API when you want it:
topics / web research / PDFs → ingest → generate → label → validate → distill → export
--provider mock lets everything run offline for testing.
What I built today
Honesty first: Saara existed before today as a basic dataset CLI (v1.6.9). Everything below was added at the Hack Day, and it's all in the diff.
1. Gemma 4 vision OCR for scanned PDFs (solves problem 1). If a page has a text layer, Saara reads it directly. If it doesn't (a scan), Saara renders the page to an image and asks Gemma 4 to transcribe it, either locally (--provider ollama, so documents never leave your machine) or through the Gemini API (--provider gemini, using the official google-genai SDK). The bug I was proudest to catch: the Ollama provider was silently dropping the image, so "local OCR" only worked on paper. Now it's fixed and covered by tests.
2. An export engine for 8 training formats (solves problem 2). One command converts a dataset to OpenAI chat, ShareGPT (LLaMA-Factory/Axolotl), Alpaca, ChatML, Vertex AI/Gemini, DPO pairs, plain text, or Saara's own format:
saara export data.jsonl --to jsonl --schema sharegpt \
--split train=0.9,test=0.1 --group-by metadata.source --out exports/llamafactory
It writes the shards, a dataset_info.json that LLaMA-Factory can register directly, a Hugging Face dataset card, and a manifest with sha256 checksums. Rows a format can't represent (tool calls in Alpaca, for example) are dropped and counted with a reason, never silently lost.
3. Leak-free splits (solves problem 3). --group-by splits by group (for example by source document), not by row, so pages of the same document never land in both train and test. The manifest even reports how many groups leaked (it should be 0).
4. Consent-gated local Gemma 4 setup. saara models setup reads your RAM, VRAM and disk, recommends Gemma 4 E2B, E4B or 12B (about 4.6, 6.6 or 8 GB), and never downloads without asking.
5. Real bug fixes. A plain pip install saara-ai crashed at startup (a missing core dependency). Parquet export crashed on empty fields. And DPO "rejected" answers were one hard-coded refusal sentence, which teaches a model to avoid saying "I don't know". They now use real negatives.
The impact
- Privacy by default. A scanned page goes from image to clean text to training data without leaving your laptop: no upload, no per-page bill, no third party holding your documents.
- Hours of glue code become one command. The same dataset exports to whichever trainer you pick, with checksums and a dataset card so it's reproducible and shareable.
- Results you can trust. Group-aware splits and counted drops mean your evaluation measures what you think it measures.
- Open AI for everyone, not just big labs. It runs on a student laptop with free, open-weight Gemma 4. That's what this year's Hacktoberfest theme, "AI belongs to everyone", means to me in practice.
What is not done (on purpose, stated plainly)
-
I did not fine-tune Gemma today. I built a pipeline (
experiments/saara-gemma/) to fine-tune Gemma 4 E4B for OCR, text cleaning and tool use on public datasets only. It has leak-free splits and paired-bootstrap evaluation against base Gemma. But it has only been tested on a tiny random-weight model with Gemma 4's architecture. No real training run, results or weights exist yet. I spun up a GPU, then decided a rushed run would be worse than an honest "not yet". - The Gemini API path is covered by tests with mocked responses. I had no API key at the venue, so I demo the local Ollama path live instead.
How I built it, and what I learned
I built this by directing AI coding agents (Claude Code and Antigravity), and I've disclosed that on the submission. My job was deciding what to build, and then checking every claim against the code. That second part taught me the most:
- AI-written code needs an audit, not a vibe check. Our own docs said "local Gemma 4 OCR" while the code dropped the image; said model downloads were 1.6 GB when Ollama's real image is 4.6 GB; and one prize answer implied the model was trained. We fixed every one before judging.
- Split by document, not by row. Otherwise near-identical pages leak from train into test and your evaluation lies to you.
- Gemma 4 is genuinely multimodal at laptop scale. An open-weight model reading a page image locally is a real alternative to paid OCR APIs for private documents.
Try it
pip install 'saara-ai[all]'
saara wizard # guided, interactive
saara --help # quick start included
- Repo (MIT): https://github.com/nikhil49023/Saara
- PyPI: https://pypi.org/project/saara-ai/1.8.1/
- Good first issues are open if you want to add an export format or a provider.
Further reading that shaped this
- 📄 "I replaced a $50/month OCR API with Gemma 4's native vision (4B model, local, free)" by stephen_sebastian_c85ea2b: https://dev.to/stephen_sebastian_c85ea2b/i-replaced-a-50month-ocr-api-with-gemma-4s-native-vision-4b-model-local-free-heres-the-1p97
- 🤖 "How I Built an Autonomous Dataset Generator with CrewAI + Ollama" by robopilingui: https://dev.to/robopilingui/how-i-built-an-autonomous-dataset-generator-with-crewai-ollama-72-hour-run-1065-entries-2280
Built at Hacktoberfest Hack Day Hyderabad x Kramer's Community. Thanks to the organizers and MLH.
來源:DEV Community · dev.to