<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: sainikhil kilani</title>
    <description>The latest articles on DEV Community by sainikhil kilani (@sainikhil_kilani_9d4da26e).</description>
    <link>https://dev.to/sainikhil_kilani_9d4da26e</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3997059%2Fb2145888-2b7b-47d9-bf5a-73db763df84a.jpg</url>
      <title>DEV Community: sainikhil kilani</title>
      <link>https://dev.to/sainikhil_kilani_9d4da26e</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sainikhil_kilani_9d4da26e"/>
    <language>en</language>
    <item>
      <title>I gave my dataset CLI Gemma 4 eyes at a Hacktoberfest Hack Day: it read a scanned page on my laptop, no cloud</title>
      <dc:creator>sainikhil kilani</dc:creator>
      <pubDate>Sun, 25 Oct 2026 07:49:28 +0000</pubDate>
      <link>https://dev.to/sainikhil_kilani_9d4da26e/i-gave-my-dataset-cli-gemma-4-eyes-at-a-hacktoberfest-hack-day-it-read-a-scanned-page-on-my-3jfo</link>
      <guid>https://dev.to/sainikhil_kilani_9d4da26e/i-gave-my-dataset-cli-gemma-4-eyes-at-a-hacktoberfest-hack-day-it-read-a-scanned-page-on-my-3jfo</guid>
      <description>&lt;p&gt;I spent today at &lt;strong&gt;Hacktoberfest Hack Day Hyderabad x Kramer's Community&lt;/strong&gt; (an MLH Hack Day) working on &lt;a href="https://github.com/nikhil49023/Saara" rel="noopener noreferrer"&gt;Saara&lt;/a&gt;, my open-source, local-first CLI for building ML training datasets.&lt;/p&gt;

&lt;p&gt;The moment that made the day: I took a "scanned" PDF page with &lt;strong&gt;zero extractable text&lt;/strong&gt;, ran one command, and &lt;strong&gt;Gemma 4 running locally in Ollama on my laptop&lt;/strong&gt; read it back line for line, with nothing sent to the cloud.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;saara ingest pdf scan.pdf &lt;span class="nt"&gt;--provider&lt;/span&gt; ollama &lt;span class="nt"&gt;--model&lt;/span&gt; gemma4:latest &lt;span class="nt"&gt;--out&lt;/span&gt; ocr.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the real output (about a minute on a laptop GPU), every number intact.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: the model is the easy part
&lt;/h2&gt;

&lt;p&gt;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; &lt;strong&gt;it's the data.&lt;/strong&gt; And building training data today is broken in three ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Your most valuable knowledge is locked in documents that machines can't read.&lt;/strong&gt; 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 &lt;em&gt;nothing&lt;/em&gt; for those pages. The usual fix is to upload them to a paid cloud OCR API, which means &lt;strong&gt;sending private documents to someone else's server and paying per page.&lt;/strong&gt; For a student, a hospital, or a lab with confidential records, that's often a non-starter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Every training tool speaks a different language.&lt;/strong&gt; OpenAI fine-tuning wants one JSON shape, LLaMA-Factory and Axolotl want ShareGPT plus a registration file, Vertex AI wants &lt;code&gt;contents&lt;/code&gt; and &lt;code&gt;parts&lt;/code&gt;, 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Careless splits make your results lie.&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this matters now:&lt;/strong&gt; the gap between "I have an open model" and "I have a model that's good at &lt;em&gt;my&lt;/em&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Saara does
&lt;/h2&gt;

&lt;p&gt;One CLI for the whole path, running on &lt;strong&gt;local open-weight models&lt;/strong&gt; (Gemma 4 through Ollama, or vLLM), or hosted Gemma 4 through the Gemini API when you want it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;topics / web research / PDFs → ingest → generate → label → validate → distill → export
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--provider mock&lt;/code&gt; lets everything run offline for testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built today
&lt;/h2&gt;

&lt;p&gt;Honesty first: &lt;strong&gt;Saara existed before today&lt;/strong&gt; as a basic dataset CLI (v1.6.9). Everything below was added at the Hack Day, and it's all in &lt;a href="https://github.com/nikhil49023/Saara/compare/02a547a...v1.8.1" rel="noopener noreferrer"&gt;the diff&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Gemma 4 vision OCR for scanned PDFs (solves problem 1).&lt;/strong&gt; 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 &lt;strong&gt;locally&lt;/strong&gt; (&lt;code&gt;--provider ollama&lt;/code&gt;, so documents never leave your machine) or through the Gemini API (&lt;code&gt;--provider gemini&lt;/code&gt;, using the official &lt;code&gt;google-genai&lt;/code&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. An export engine for 8 training formats (solves problem 2).&lt;/strong&gt; 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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;saara &lt;span class="nb"&gt;export &lt;/span&gt;data.jsonl &lt;span class="nt"&gt;--to&lt;/span&gt; jsonl &lt;span class="nt"&gt;--schema&lt;/span&gt; sharegpt &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--split&lt;/span&gt; &lt;span class="nv"&gt;train&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.9,test&lt;span class="o"&gt;=&lt;/span&gt;0.1 &lt;span class="nt"&gt;--group-by&lt;/span&gt; metadata.source &lt;span class="nt"&gt;--out&lt;/span&gt; exports/llamafactory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It writes the shards, a &lt;code&gt;dataset_info.json&lt;/code&gt; 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 &lt;strong&gt;dropped and counted with a reason&lt;/strong&gt;, never silently lost.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Leak-free splits (solves problem 3).&lt;/strong&gt; &lt;code&gt;--group-by&lt;/code&gt; 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).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Consent-gated local Gemma 4 setup.&lt;/strong&gt; &lt;code&gt;saara models setup&lt;/code&gt; reads your RAM, VRAM and disk, recommends Gemma 4 E2B, E4B or 12B (about 4.6, 6.6 or 8 GB), and &lt;strong&gt;never downloads without asking&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Real bug fixes.&lt;/strong&gt; A plain &lt;code&gt;pip install saara-ai&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  The impact
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy by default.&lt;/strong&gt; A scanned page goes from image to clean text to training data &lt;strong&gt;without leaving your laptop&lt;/strong&gt;: no upload, no per-page bill, no third party holding your documents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hours of glue code become one command.&lt;/strong&gt; The same dataset exports to whichever trainer you pick, with checksums and a dataset card so it's reproducible and shareable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Results you can trust.&lt;/strong&gt; Group-aware splits and counted drops mean your evaluation measures what you think it measures.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open AI for everyone, not just big labs.&lt;/strong&gt; 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is &lt;em&gt;not&lt;/em&gt; done (on purpose, stated plainly)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I did not fine-tune Gemma today.&lt;/strong&gt; I built a pipeline (&lt;code&gt;experiments/saara-gemma/&lt;/code&gt;) 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".&lt;/li&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I built it, and what I learned
&lt;/h2&gt;

&lt;p&gt;I built this by &lt;strong&gt;directing AI coding agents&lt;/strong&gt; (Claude Code and Antigravity), and I've disclosed that on the submission. My job was deciding what to build, and then &lt;strong&gt;checking every claim against the code&lt;/strong&gt;. That second part taught me the most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI-written code needs an audit, not a vibe check.&lt;/strong&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split by document, not by row.&lt;/strong&gt; Otherwise near-identical pages leak from train into test and your evaluation lies to you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 is genuinely multimodal at laptop scale.&lt;/strong&gt; An open-weight model reading a page image locally is a real alternative to paid OCR APIs for private documents.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="s1"&gt;'saara-ai[all]'&lt;/span&gt;
saara wizard          &lt;span class="c"&gt;# guided, interactive&lt;/span&gt;
saara &lt;span class="nt"&gt;--help&lt;/span&gt;          &lt;span class="c"&gt;# quick start included&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Repo (MIT): &lt;a href="https://github.com/nikhil49023/Saara" rel="noopener noreferrer"&gt;https://github.com/nikhil49023/Saara&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;a href="https://pypi.org/project/saara-ai/1.8.1/" rel="noopener noreferrer"&gt;https://pypi.org/project/saara-ai/1.8.1/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Good first issues are open if you want to add an export format or a provider.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Further reading that shaped this
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📄 "I replaced a $50/month OCR API with Gemma 4's native vision (4B model, local, free)" by stephen_sebastian_c85ea2b: &lt;a href="https://dev.to/stephen_sebastian_c85ea2b/i-replaced-a-50month-ocr-api-with-gemma-4s-native-vision-4b-model-local-free-heres-the-1p97"&gt;https://dev.to/stephen_sebastian_c85ea2b/i-replaced-a-50month-ocr-api-with-gemma-4s-native-vision-4b-model-local-free-heres-the-1p97&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🤖 "How I Built an Autonomous Dataset Generator with CrewAI + Ollama" by robopilingui: &lt;a href="https://dev.to/robopilingui/how-i-built-an-autonomous-dataset-generator-with-crewai-ollama-72-hour-run-1065-entries-2280"&gt;https://dev.to/robopilingui/how-i-built-an-autonomous-dataset-generator-with-crewai-ollama-72-hour-run-1065-entries-2280&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Built at Hacktoberfest Hack Day Hyderabad x Kramer's Community. Thanks to the organizers and MLH.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>mlhacks</category>
      <category>hacktoberfest</category>
      <category>gemma</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
