<?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: AMIT KUMAR SINHA</title>
    <description>The latest articles on DEV Community by AMIT KUMAR SINHA (@amit_sinha_2a6ee473012f2d).</description>
    <link>https://dev.to/amit_sinha_2a6ee473012f2d</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%2F4152107%2Ff13cc4ad-1229-4ca9-a735-f9446b4d7181.png</url>
      <title>DEV Community: AMIT KUMAR SINHA</title>
      <link>https://dev.to/amit_sinha_2a6ee473012f2d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amit_sinha_2a6ee473012f2d"/>
    <language>en</language>
    <item>
      <title>Vector : local code summariser</title>
      <dc:creator>AMIT KUMAR SINHA</dc:creator>
      <pubDate>Sun, 25 Oct 2026 16:07:11 +0000</pubDate>
      <link>https://dev.to/amit_sinha_2a6ee473012f2d/vector-local-code-summariser-1k63</link>
      <guid>https://dev.to/amit_sinha_2a6ee473012f2d/vector-local-code-summariser-1k63</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week3-2026-10-19"&gt;Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Everyone has opened an unfamiliar repo and spent the first hour just trying to work out what it does. Vector is my lazy answer to that hour.&lt;/p&gt;

&lt;p&gt;Vector is a local code summariser. Give it a file, a GitHub repo, or an entire project folder, and it tells you what the code is for before you read any of it. Every file gets a TL;DR, its purpose, key functions with line ranges, dependencies, and gotchas. For a whole project it also writes an overview: tech stack, architecture, a directory map, entry points, how to run it, and an ordered "start reading here" list.&lt;/p&gt;

&lt;p&gt;The laziest part is watch mode. Point Vector at a folder, edit a file, and a fresh summary shows up on its own a few seconds later. You never have to ask.&lt;/p&gt;

&lt;p&gt;It's for anyone who reads more code than they write: students inheriting a messy assignment, Hacktoberfest contributors landing in a new repo, and anyone who has ever said "wait, what does this module do?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://vector-frontend-dxot.onrender.com" rel="noopener noreferrer"&gt;https://vector-frontend-dxot.onrender.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/amitsinha-cell/vector.git" rel="noopener noreferrer"&gt;https://github.com/amitsinha-cell/vector.git&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The open pieces&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma 4 E4B&lt;/strong&gt; is the default model. I also use &lt;strong&gt;Gemma 4 E2B&lt;/strong&gt; as the light option and &lt;strong&gt;Qwen2.5-Coder 7B&lt;/strong&gt; as "deep mode."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama&lt;/strong&gt; runs inference locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tree-sitter&lt;/strong&gt; splits code by structure (functions, classes), not by size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI + SQLite (FTS5)&lt;/strong&gt; handle the backend, caching, history, and search.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;watchdog&lt;/strong&gt; powers the folder watcher.&lt;/li&gt;
&lt;li&gt;The frontend is React + Vite + TypeScript, started in Lovable. I built the backend with Antigravity, and the specs and design decisions were mine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;My hardware is the whole story.&lt;/strong&gt; I built and tested this on an HP Victus laptop with an RTX 4050 (6 GB VRAM, 50W TGP). That is not a big machine, and it shaped every decision:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Structure-aware chunking.&lt;/strong&gt; Small models get lost in long files. Vector parses the file, summarises each function or class, then rolls those up into a file-level summary. If parsing fails, it falls back to overlapping line windows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hierarchical project mode.&lt;/strong&gt; A whole folder will never fit in one context window. Vector summarises files, then directories, then the project. Only the top-ranked files (entry points, manifests, most-imported modules) get full LLM summaries. The rest get a one-line description built from their function and class names, with no model call at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache by content hash.&lt;/strong&gt; The cache key is the file's contents plus the model and prompt version. Re-uploading an unchanged folder returns almost instantly, so the GPU only works on what changed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One GPU queue.&lt;/strong&gt; Watcher jobs and manual requests never run at the same time on the same card.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema-checked output.&lt;/strong&gt; Every result is validated against a fixed JSON schema, with one repair retry before returning a partial result with a warning.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;What went wrong.&lt;/strong&gt; &lt;code&gt;gemma4:e4b&lt;/code&gt; is 6.6 GB on disk and my card has about 5 GB free, so part of it runs on CPU. I added a smaller-model retry and kept E2B one dropdown away.&lt;/p&gt;

&lt;p&gt;My favourite bug: the UI said "Ollama isn't running" while Ollama was fine. The real cause was a CORS preflight rejection. Vite had moved to port 8081 and the backend's allowlist didn't include it, so the browser never read &lt;code&gt;/health&lt;/code&gt;. The fix was easy, but the real lesson was that "backend unreachable" and "Ollama down" are different failures and the UI should say which one it is. It does now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Your code stays on your machine.&lt;/strong&gt; A code summariser is a poor fit for a closed API. People paste private, unreleased, or employer-owned code into it. With local models the code never leaves the laptop. The UI shows a "100% local" badge, and a hosted fallback exists only as an opt-in setting that is off by default, with a warning before any code is sent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Watch mode is only practical when inference is free.&lt;/strong&gt; An assistant that re-summarises every time you save a file would run up an API bill quickly. Locally, the only cost is electricity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Swapping models is a dropdown.&lt;/strong&gt; I could try Gemma 4 against Qwen2.5-Coder on my own files and pick per task. A closed API doesn't let me do that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It works offline.&lt;/strong&gt; Once the models are pulled, Vector needs no internet except for GitHub repo mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customising is possible.&lt;/strong&gt; Because the weights are open, I can fine-tune a small Gemma on code-summary pairs next. I've fine-tuned small Gemma models before, and that path is closed with a hosted API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where closed still wins.&lt;/strong&gt; Large frontier models write better summaries of huge, tangled files. For "tell me what this folder is about," a small local model with good chunking was good enough, and it was private.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;For example: "A 40-file project that took me about 120 minutes to understand by reading now takes 30 minutes, and the cached re-run takes 10 seconds."&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma:&lt;/strong&gt; Gemma 4 E4B and E2B are the core models.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub:&lt;/strong&gt; repo ingestion. [Keep this only if repo mode really uses the GitHub API or clones through GitHub.]&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>gemmachallenge</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>Trail bird journal v1</title>
      <dc:creator>AMIT KUMAR SINHA</dc:creator>
      <pubDate>Sat, 17 Oct 2026 19:05:52 +0000</pubDate>
      <link>https://dev.to/amit_sinha_2a6ee473012f2d/trail-bird-journal-v1-53g1</link>
      <guid>https://dev.to/amit_sinha_2a6ee473012f2d/trail-bird-journal-v1-53g1</guid>
      <description>&lt;p&gt;What I Built&lt;br&gt;
Trail Bird Journal is an offline bird-song journal that runs entirely on my phone. You tap Record (or upload a clip), an open bird-sound model names the species it hears, and the app writes a short field-journal entry and saves it with the audio. A second page keeps a growing life list of every bird you've identified.&lt;br&gt;
It is for the person who walks past a hundred birds a day and has never known their names, and especially for the places where birdwatching actually happens: trails, woods and wetlands where there is no signal. A cloud app is useless there. This one works with airplane mode on, and your recordings never leave the phone.&lt;br&gt;
The point is to get you outside and keep you standing still. The reward for listening is a name, an entry in your journal, and one more bird on the list.&lt;br&gt;
A real entry from my outdoor test:&lt;br&gt;
Date : 10/10/2026&lt;br&gt;
Place : Near an open ground&lt;br&gt;
Species recognised : rock dove&lt;/p&gt;

&lt;p&gt;Demo&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff342kvo2eu273nx81k8w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff342kvo2eu273nx81k8w.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj073q6pa342rrikfpcvi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj073q6pa342rrikfpcvi.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7szrohjmef2qxu7c4d5a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7szrohjmef2qxu7c4d5a.jpg" alt=" " width="800" height="2511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffgmyl3dexscflno4cf4k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffgmyl3dexscflno4cf4k.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvam57197u2g69ixr2idx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvam57197u2g69ixr2idx.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/amitsinha-cell" rel="noopener noreferrer"&gt;
        amitsinha-cell
      &lt;/a&gt; / &lt;a href="https://github.com/amitsinha-cell/Trail-Bird-Journal" rel="noopener noreferrer"&gt;
        Trail-Bird-Journal
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Trail Bird Journal&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An offline bird-song journal for your phone. Record or upload a clip, and the app identifies the birds with &lt;strong&gt;BirdNET&lt;/strong&gt; and writes a short field-journal entry. No internet, no cloud, no account. Built for the "Touch Grass" open-source AI challenge.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Browser page records audio (or you upload a file) and sends it to a local FastAPI server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ffmpeg&lt;/code&gt; converts it to 48 kHz mono WAV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BirdNET&lt;/strong&gt; (ONNX backend) lists the species it hears with confidence scores.&lt;/li&gt;
&lt;li&gt;The journal sentence is first built by plain Python from those detections, so it can only state what was detected. An optional small local LLM (&lt;strong&gt;Gemma 3 1B&lt;/strong&gt;, via llama.cpp) may rewrite it, and a validator rejects any rewrite that adds facts, so the template text is used instead.&lt;/li&gt;
&lt;li&gt;Each session is saved as a JSON file plus the audio clip. History and Birds Discovered pages…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/amitsinha-cell/Trail-Bird-Journal" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
Everything is in the repo: a FastAPI server, a small pipeline, and four hand-written pages with no frameworks and no CDN. No model weights are in the repo; the README says where to download them.&lt;br&gt;
How I Built It&lt;br&gt;
I built and ran all of it on an Android phone (iQOO Z9, 8 GB RAM) using Termux, a proot Ubuntu, and opencode as my coding agent.&lt;br&gt;
Browser page (phone)&lt;br&gt;
   -&amp;gt; FastAPI server (localhost, inside proot Ubuntu)&lt;br&gt;
        -&amp;gt; ffmpeg: any audio -&amp;gt; 48 kHz mono WAV&lt;br&gt;
        -&amp;gt; BirdNET (ONNX backend): species + confidence per 3-second window&lt;br&gt;
        -&amp;gt; journal.py: builds the entry text, optional LLM rewrite, validator&lt;br&gt;
        -&amp;gt; saves entries/.json and audio/.wav&lt;br&gt;
   -&amp;gt; optional: llama-server (native Termux) running Gemma 3 1B (Q4_K_M)&lt;br&gt;
Bird identification: BirdNET (Cornell Lab of Ornithology and Chemnitz University of Technology), run through its ONNX backend. It scores each 3-second window of the clip against thousands of species.&lt;br&gt;
Journal writer: Gemma 3 1B Instruct (4-bit GGUF) via llama.cpp, about 11 tokens per second on the phone.&lt;br&gt;
No training. The project wires two open models together and builds the safety net around them.&lt;br&gt;
The design rule that came out of the project: the language model never gets to know anything about birds. Plain Python builds a sentence from the detections, and the model may only rephrase it. That rule exists because of what went wrong, which is most of the story.&lt;br&gt;
Challenges, and what I changed

&lt;ol&gt;
&lt;li&gt;TensorFlow doesn't exist for my Python.
My proot Ubuntu ships Python 3.14. pip install birdnet-analyzer failed because it needs TensorFlow, which had no wheel for 3.14. The newer birdnet package also defaults to a TensorFlow backend, so that failed too. The fix was its ONNX backend (model version 3.0), which needs no TensorFlow at all. Open model formats let me route around a packaging dead end instead of giving up.&lt;/li&gt;
&lt;li&gt;A crash caused by a missing if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;".
BirdNET starts worker processes, and Python 3.14 re-imports the script in each one, so without the main guard everything died with an unhelpful "child process exited with exit code 1". The guard plus n_workers=1 (to keep RAM low) fixed it.&lt;/li&gt;
&lt;li&gt;Two tools disagreed about the same clip.
My first test clip scored Eurasian Skylark at 0.91, 0.95 and 0.90 across its three segments. A web bird-ID app said Daurian Redstart. BirdNET's top ten never included the redstart. I listened to it: a long, continuous, rising song, which matches a skylark, so I trusted the model whose scores I could see. The lesson is that every ID needs a confidence label, so the app now says "clearly identified", "likely" or "possibly, not certain" based on the score.&lt;/li&gt;
&lt;li&gt;My 1B model lied to me.
First test, I asked Gemma for "one fact about the bird". It told me skylarks nest "in the eaves of buildings". They nest on the ground in open fields. When I removed the fact request and tightened the prompt, it still invented things I never gave it: a "forest clearing" (the place was "unknown"), "bright yellow plumage", "a red bird", "a beautiful, melodic sound". On a noisy 80-second forest clip it simply repeated my prompt's format back at me. A 1B model copies the shape of whatever you show it and fills gaps with plausible fiction.
What worked:
Python decides everything factual (species, hedge words, segment counts).
Python writes the entry text itself. This is the default.
Gemma may rewrite it, but a validator rejects any rewrite that adds banned words (colors, habitats, behaviors), drops a species, or loses a "possibly" hedge.
If the rewrite fails validation, or the LLM isn't running, the app uses the template entry and labels it "template" instead of "local LLM".
So the bird ID is never the LLM's problem, and the LLM can't make the journal wrong.&lt;/li&gt;
&lt;li&gt;The counting bug: "23 of 3 segments".
On an 80-second clip with 27 windows, my summary said a nuthatch was "detected in 23 of 3 segments". The total was hard-coded from my 8-second test clip. I fixed it by counting unique start times, and later hit a cousin of the same bug: the template once printed "heard 3 of Alauda arvensis segments", where the scientific name had landed in the slot for the total. Small bugs, but a journal that states wrong numbers is worse than no journal. &lt;/li&gt;
&lt;li&gt;8 GB of RAM is not much.
llama-server, code-server and opencode together do not fit. Android killed sessions until I started working in phases: build with the editor and agent, then close them, then test with only BirdNET running, then add the LLM last. A 4-bit 1B model needs about 1 GB, BirdNET about the same, and the OS takes the rest.&lt;/li&gt;
&lt;li&gt;The agent wrote a frontend it never ran.
I used opencode to generate the backend and pages. The Python mostly worked. The browser side did not, because the agent had only checked syntax and never loaded a page. What went wrong:
Pages linked style.css instead of /static/style.css. Served at /capture, the browser asked for /style.css and got a 404.
The Play button was a plain link, so the browser downloaded a file named recording.wav.json containing {"detail":"Audio not found"}. The server looked for audio in one folder while the pipeline saved it in another.
Buttons did nothing. The forms were hidden with inline styles and the script that should show them never ran, so Skip and Continue just reloaded the page with a stray ?step=1 in the URL.
The server crashed at startup calling a helper that no longer existed.
Uploads failed with a 422 because the page sent the file under a different field name than the server declared.
I fixed these by hand with small patches, then replaced the capture page with a compact hand-written one, since patching on top of dead code wasn't working.&lt;/li&gt;
&lt;li&gt;The microphone, and a format BirdNET can't read.
Recording first failed with "Permission denied" because the browser stores mic permission per address and I was on 127.0.0.2 instead of localhost. Once the mic worked, the recording came back as WebM, which BirdNET cannot read. Rather than depend on ffmpeg inside proot, the page now decodes the recording in the browser, resamples it to 48 kHz mono, and uploads a real WAV, the same kind of file as my working uploads.
I took it outside
When and where: 10/10/2026, 9:43AM, near an open ground
Setup: phone in airplane mode, llama-server and the app running in Termux
Clips recorded: 4, each 8 sec
What it got right: rock dove
Airplane mode check: did everything work offline? yes
Why Does Open Innovation Matter?
It works where closed APIs can't. The places worth birdwatching have no signal. A hosted model would have meant a recording you can't process until you get home. Open weights and local inference mean the answer arrives while the bird is still singing.
Private by construction. Field recordings carry your location, your voice, and sometimes strangers' conversations. Nothing leaves the phone, so there is nothing to leak.
Swappable without permission. When TensorFlow had no build for my Python, I switched BirdNET to its ONNX backend and carried on. I can swap Gemma for another small model, or change the bird model, by changing one path.
Inspectable, so I could constrain it. Because I could see BirdNET's raw scores and run the LLM on my own hardware, I could find exactly where the 1B model made things up and build a validator around it. With a black-box API I could only have hoped the prompt held.
Free to run. No account, no key, no per-request cost, and no bill for walking around a pond for an hour.
Where open beat closed here was not raw quality (a large hosted model would write nicer sentences). It was availability, privacy, and the freedom to fix things myself.
Honest caveats: BirdNET's model weights are licensed for non-commercial use, so this project is a personal and educational one. The birdnet Python package itself is MIT-licensed. Gemma is open-weight under Google's terms of use, not an OSI open-source license.
Prize Categories
Goggle gemma&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>localmodels</category>
      <category>birdsound</category>
    </item>
    <item>
      <title>Trail Bird Journal</title>
      <dc:creator>AMIT KUMAR SINHA</dc:creator>
      <pubDate>Sat, 10 Oct 2026 17:26:35 +0000</pubDate>
      <link>https://dev.to/amit_sinha_2a6ee473012f2d/trail-bird-journal-1pj7</link>
      <guid>https://dev.to/amit_sinha_2a6ee473012f2d/trail-bird-journal-1pj7</guid>
      <description>&lt;p&gt;What I Built&lt;br&gt;
Trail Bird Journal is an offline bird-song journal that runs entirely on my phone. You tap Record (or upload a clip), an open bird-sound model names the species it hears, and the app writes a short field-journal entry and saves it with the audio. A second page keeps a growing life list of every bird you've identified.&lt;br&gt;
It is for the person who walks past a hundred birds a day and has never known their names, and especially for the places where birdwatching actually happens: trails, woods and wetlands where there is no signal. A cloud app is useless there. This one works with airplane mode on, and your recordings never leave the phone.&lt;br&gt;
The point is to get you outside and keep you standing still. The reward for listening is a name, an entry in your journal, and one more bird on the list.&lt;br&gt;
A real entry from my outdoor test:&lt;br&gt;
Date : 10/10/2026&lt;br&gt;
Place : Near an open ground&lt;br&gt;
Species recognised : rock dove&lt;/p&gt;

&lt;p&gt;Demo&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff342kvo2eu273nx81k8w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff342kvo2eu273nx81k8w.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj073q6pa342rrikfpcvi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj073q6pa342rrikfpcvi.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7szrohjmef2qxu7c4d5a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7szrohjmef2qxu7c4d5a.jpg" alt=" " width="800" height="2511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffgmyl3dexscflno4cf4k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffgmyl3dexscflno4cf4k.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvam57197u2g69ixr2idx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvam57197u2g69ixr2idx.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Code&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/amitsinha-cell" rel="noopener noreferrer"&gt;
        amitsinha-cell
      &lt;/a&gt; / &lt;a href="https://github.com/amitsinha-cell/Trail-Bird-Journal" rel="noopener noreferrer"&gt;
        Trail-Bird-Journal
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Trail Bird Journal&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;An offline bird-song journal for your phone. Record or upload a clip, and the app identifies the birds with &lt;strong&gt;BirdNET&lt;/strong&gt; and writes a short field-journal entry. No internet, no cloud, no account. Built for the "Touch Grass" open-source AI challenge.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How it works&lt;/h2&gt;
&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Browser page records audio (or you upload a file) and sends it to a local FastAPI server.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ffmpeg&lt;/code&gt; converts it to 48 kHz mono WAV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BirdNET&lt;/strong&gt; (ONNX backend) lists the species it hears with confidence scores.&lt;/li&gt;
&lt;li&gt;The journal sentence is first built by plain Python from those detections, so it can only state what was detected. An optional small local LLM (&lt;strong&gt;Gemma 3 1B&lt;/strong&gt;, via llama.cpp) may rewrite it, and a validator rejects any rewrite that adds facts, so the template text is used instead.&lt;/li&gt;
&lt;li&gt;Each session is saved as a JSON file plus the audio clip. History and Birds Discovered pages…&lt;/li&gt;
&lt;/ol&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/amitsinha-cell/Trail-Bird-Journal" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;br&gt;
Everything is in the repo: a FastAPI server, a small pipeline, and four hand-written pages with no frameworks and no CDN. No model weights are in the repo; the README says where to download them.&lt;br&gt;
How I Built It&lt;br&gt;
I built and ran all of it on an Android phone (iQOO Z9, 8 GB RAM) using Termux, a proot Ubuntu, and opencode as my coding agent.&lt;br&gt;
Browser page (phone)&lt;br&gt;
   -&amp;gt; FastAPI server (localhost, inside proot Ubuntu)&lt;br&gt;
        -&amp;gt; ffmpeg: any audio -&amp;gt; 48 kHz mono WAV&lt;br&gt;
        -&amp;gt; BirdNET (ONNX backend): species + confidence per 3-second window&lt;br&gt;
        -&amp;gt; journal.py: builds the entry text, optional LLM rewrite, validator&lt;br&gt;
        -&amp;gt; saves entries/.json and audio/.wav&lt;br&gt;
   -&amp;gt; optional: llama-server (native Termux) running Gemma 3 1B (Q4_K_M)&lt;br&gt;
Bird identification: BirdNET (Cornell Lab of Ornithology and Chemnitz University of Technology), run through its ONNX backend. It scores each 3-second window of the clip against thousands of species.&lt;br&gt;
Journal writer: Gemma 3 1B Instruct (4-bit GGUF) via llama.cpp, about 11 tokens per second on the phone.&lt;br&gt;
No training. The project wires two open models together and builds the safety net around them.&lt;br&gt;
The design rule that came out of the project: the language model never gets to know anything about birds. Plain Python builds a sentence from the detections, and the model may only rephrase it. That rule exists because of what went wrong, which is most of the story.&lt;br&gt;
Challenges, and what I changed

&lt;ol&gt;
&lt;li&gt;TensorFlow doesn't exist for my Python.
My proot Ubuntu ships Python 3.14. pip install birdnet-analyzer failed because it needs TensorFlow, which had no wheel for 3.14. The newer birdnet package also defaults to a TensorFlow backend, so that failed too. The fix was its ONNX backend (model version 3.0), which needs no TensorFlow at all. Open model formats let me route around a packaging dead end instead of giving up.&lt;/li&gt;
&lt;li&gt;A crash caused by a missing if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;".
BirdNET starts worker processes, and Python 3.14 re-imports the script in each one, so without the main guard everything died with an unhelpful "child process exited with exit code 1". The guard plus n_workers=1 (to keep RAM low) fixed it.&lt;/li&gt;
&lt;li&gt;Two tools disagreed about the same clip.
My first test clip scored Eurasian Skylark at 0.91, 0.95 and 0.90 across its three segments. A web bird-ID app said Daurian Redstart. BirdNET's top ten never included the redstart. I listened to it: a long, continuous, rising song, which matches a skylark, so I trusted the model whose scores I could see. The lesson is that every ID needs a confidence label, so the app now says "clearly identified", "likely" or "possibly, not certain" based on the score.&lt;/li&gt;
&lt;li&gt;My 1B model lied to me.
First test, I asked Gemma for "one fact about the bird". It told me skylarks nest "in the eaves of buildings". They nest on the ground in open fields. When I removed the fact request and tightened the prompt, it still invented things I never gave it: a "forest clearing" (the place was "unknown"), "bright yellow plumage", "a red bird", "a beautiful, melodic sound". On a noisy 80-second forest clip it simply repeated my prompt's format back at me. A 1B model copies the shape of whatever you show it and fills gaps with plausible fiction.
What worked:
Python decides everything factual (species, hedge words, segment counts).
Python writes the entry text itself. This is the default.
Gemma may rewrite it, but a validator rejects any rewrite that adds banned words (colors, habitats, behaviors), drops a species, or loses a "possibly" hedge.
If the rewrite fails validation, or the LLM isn't running, the app uses the template entry and labels it "template" instead of "local LLM".
So the bird ID is never the LLM's problem, and the LLM can't make the journal wrong.&lt;/li&gt;
&lt;li&gt;The counting bug: "23 of 3 segments".
On an 80-second clip with 27 windows, my summary said a nuthatch was "detected in 23 of 3 segments". The total was hard-coded from my 8-second test clip. I fixed it by counting unique start times, and later hit a cousin of the same bug: the template once printed "heard 3 of Alauda arvensis segments", where the scientific name had landed in the slot for the total. Small bugs, but a journal that states wrong numbers is worse than no journal. &lt;/li&gt;
&lt;li&gt;8 GB of RAM is not much.
llama-server, code-server and opencode together do not fit. Android killed sessions until I started working in phases: build with the editor and agent, then close them, then test with only BirdNET running, then add the LLM last. A 4-bit 1B model needs about 1 GB, BirdNET about the same, and the OS takes the rest.&lt;/li&gt;
&lt;li&gt;The agent wrote a frontend it never ran.
I used opencode to generate the backend and pages. The Python mostly worked. The browser side did not, because the agent had only checked syntax and never loaded a page. What went wrong:
Pages linked style.css instead of /static/style.css. Served at /capture, the browser asked for /style.css and got a 404.
The Play button was a plain link, so the browser downloaded a file named recording.wav.json containing {"detail":"Audio not found"}. The server looked for audio in one folder while the pipeline saved it in another.
Buttons did nothing. The forms were hidden with inline styles and the script that should show them never ran, so Skip and Continue just reloaded the page with a stray ?step=1 in the URL.
The server crashed at startup calling a helper that no longer existed.
Uploads failed with a 422 because the page sent the file under a different field name than the server declared.
I fixed these by hand with small patches, then replaced the capture page with a compact hand-written one, since patching on top of dead code wasn't working.&lt;/li&gt;
&lt;li&gt;The microphone, and a format BirdNET can't read.
Recording first failed with "Permission denied" because the browser stores mic permission per address and I was on 127.0.0.2 instead of localhost. Once the mic worked, the recording came back as WebM, which BirdNET cannot read. Rather than depend on ffmpeg inside proot, the page now decodes the recording in the browser, resamples it to 48 kHz mono, and uploads a real WAV, the same kind of file as my working uploads.
I took it outside
When and where: 10/10/2026, 9:43AM, near an open ground
Setup: phone in airplane mode, llama-server and the app running in Termux
Clips recorded: 4, each 8 sec
What it got right: rock dove
Airplane mode check: did everything work offline? yes
Why Does Open Innovation Matter?
It works where closed APIs can't. The places worth birdwatching have no signal. A hosted model would have meant a recording you can't process until you get home. Open weights and local inference mean the answer arrives while the bird is still singing.
Private by construction. Field recordings carry your location, your voice, and sometimes strangers' conversations. Nothing leaves the phone, so there is nothing to leak.
Swappable without permission. When TensorFlow had no build for my Python, I switched BirdNET to its ONNX backend and carried on. I can swap Gemma for another small model, or change the bird model, by changing one path.
Inspectable, so I could constrain it. Because I could see BirdNET's raw scores and run the LLM on my own hardware, I could find exactly where the 1B model made things up and build a validator around it. With a black-box API I could only have hoped the prompt held.
Free to run. No account, no key, no per-request cost, and no bill for walking around a pond for an hour.
Where open beat closed here was not raw quality (a large hosted model would write nicer sentences). It was availability, privacy, and the freedom to fix things myself.
Honest caveats: BirdNET's model weights are licensed for non-commercial use, so this project is a personal and educational one. The birdnet Python package itself is MIT-licensed. Gemma is open-weight under Google's terms of use, not an OSI open-source license.
Prize Categories
Goggle gemma&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
      <category>majorleaguehacking</category>
    </item>
    <item>
      <title>Byte-Gemma: An Offline C++ Tutor That Asks Instead of Tells</title>
      <dc:creator>AMIT KUMAR SINHA</dc:creator>
      <pubDate>Sun, 04 Oct 2026 18:59:02 +0000</pubDate>
      <link>https://dev.to/amit_sinha_2a6ee473012f2d/byte-gemma-an-offline-c-tutor-that-asks-instead-of-tells-15ij</link>
      <guid>https://dev.to/amit_sinha_2a6ee473012f2d/byte-gemma-an-offline-c-tutor-that-asks-instead-of-tells-15ij</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;A fully offline C++ tutor that runs on a phone, built for [friend's name], who is learning C++ from scratch.&lt;/p&gt;

&lt;p&gt;Most AI tools hand over the answer, and my friend ended up copy-pasting code without understanding it. Byte-Gemma is a fine-tuned Gemma 3 1B that teaches Socratically. It stays under ~100 words, praises one thing you got right, and asks one guiding question. It runs locally on Android, so it works without internet or an API bill.&lt;/p&gt;

&lt;p&gt;Slash commands control how much help you get:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Behaviour&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/explain&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Concept via analogy, tiny example, one question&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/debug&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only the first hint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/hint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A more specific hint, no full solution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/solution&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full fix, explanation, practice question&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/review&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One thing done right, the key issue, you fix it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/quiz&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One question, waits for your answer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdsie0cg8mz7hcyydodd8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdsie0cg8mz7hcyydodd8.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rp73xazch66qe9uvh0g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2rp73xazch66qe9uvh0g.jpg" alt=" " width="800" height="1778"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Model: &lt;a href="https://huggingface.co/99Amit99/byte_v2-gemma-3-1b-it-v2-GGUF/tree/main" rel="noopener noreferrer"&gt;https://huggingface.co/99Amit99/byte_v2-gemma-3-1b-it-v2-GGUF/tree/main&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repo: &lt;a href="https://github.com/amitsinha-cell/byte_v2.git" rel="noopener noreferrer"&gt;https://github.com/amitsinha-cell/byte_v2.git&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Base:&lt;/strong&gt; Gemma 3 1B (open weights), fine-tuned and quantized to Q4_K_M GGUF.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data:&lt;/strong&gt; [~300] examples generated with Gemma 4 as a teacher via the Gemini API. Validation scripts filtered out low-quality outputs, and I merged in cleaned examples from my friend's real coding mistakes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime:&lt;/strong&gt; llama.cpp-based, with PocketPal/Termux on Android.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A pivot:&lt;/strong&gt; My first version was a gamified "Byte" persona. Testing showed it wasn't teaching well, so I rebuilt it around Socratic tutoring.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Evaluation (and what failed)
&lt;/h2&gt;

&lt;p&gt;My friend and I compared Byte-Gemma against stock Gemma 3 1B on struct vs class, pointers vs references, and multithreading. My first attempt gave only Byte-Gemma the tutoring system prompt, which made the result meaningless. So I re-ran it with &lt;strong&gt;the identical system prompt, runtime, and questions for both models&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where Byte-Gemma won: following the tutoring rules.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;6 of 6 replies stayed under 100 words (about 66 words on average for first replies). The stock model went over in 3 of 3 (131 to 214 words).&lt;/li&gt;
&lt;li&gt;Byte-Gemma asked exactly one question per reply. Stock Gemma asked three in the struct/class test and ended others with "Does that make sense?".&lt;/li&gt;
&lt;li&gt;Speed per token was about the same (about 6.4 vs 6.7 tok/s), but replies about 2.7x shorter mean much shorter waits on a phone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Where it fell short: accuracy.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every Byte-Gemma reply had at least one error, and at least 4 of its 6 code snippets were broken (assigning &lt;code&gt;"Red"&lt;/code&gt; to an &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;* = 12;&lt;/code&gt;, &lt;code&gt;Car&amp;lt;Car&amp;gt;&lt;/code&gt;, and a "multithreading" example that never creates a thread).&lt;/li&gt;
&lt;li&gt;It never stated the real struct/class difference (default access), and it wrongly said references can't access an object directly.&lt;/li&gt;
&lt;li&gt;With one-word replies like "classes" or "structure", it said "You are right" and then invented that objects are created "using the &lt;code&gt;&amp;lt;iostream&amp;gt;&lt;/code&gt; header". A tutor that agrees with a confused student and adds a wrong fact is the failure I most want to avoid.&lt;/li&gt;
&lt;li&gt;Stock Gemma had errors too (calling a reference "not an alias", a class with an accidentally private constructor), but its multithreading explanation was sound and its pointer example was correct.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Subjective scores: Byte-Gemma 5.5/10, stock Gemma 4/10. Byte-Gemma's lead is smaller than my first run suggested, and it comes from teaching format, not knowledge. Caveats: one run per prompt, 6 Byte-Gemma replies vs 3 stock replies, no follow-up turns for stock Gemma, and code judged by reading rather than compiling.&lt;/p&gt;

&lt;p&gt;Neither model is reliable enough to teach unsupervised. Next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compile every code block in the training data and reject anything that doesn't build.&lt;/li&gt;
&lt;li&gt;Add multi-turn examples where the student answers with one word and the tutor checks it instead of agreeing.&lt;/li&gt;
&lt;li&gt;Re-run the comparison with fixed temperature and seed, including follow-ups for both models.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Offline:&lt;/strong&gt; The tutor runs on a phone with no connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable:&lt;/strong&gt; I could change the model's behavior through fine-tuning, not just prompting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free:&lt;/strong&gt; No per-token cost for a student project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transparent:&lt;/strong&gt; My friend could audit the model, find its errors, and show me where it was wrong. Testing against the base model with the same prompt is also what showed me the fine-tune changed its behavior more than its knowledge.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;p&gt;Google Gemma&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
      <category>hacktoberfest</category>
    </item>
  </channel>
</rss>
