<?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: utkarsh sonawane</title>
    <description>The latest articles on DEV Community by utkarsh sonawane (@utkarshsonawane67).</description>
    <link>https://dev.to/utkarshsonawane67</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%2F4175851%2Fb08e1b45-5029-47be-ac5d-038614493b14.png</url>
      <title>DEV Community: utkarsh sonawane</title>
      <link>https://dev.to/utkarshsonawane67</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/utkarshsonawane67"/>
    <language>en</language>
    <item>
      <title>I held a séance with dead programming languages — meet seance 👻</title>
      <dc:creator>utkarsh sonawane</dc:creator>
      <pubDate>Mon, 26 Oct 2026 20:44:33 +0000</pubDate>
      <link>https://dev.to/utkarshsonawane67/i-held-a-seance-with-dead-programming-languages-meet-seance-54jb</link>
      <guid>https://dev.to/utkarshsonawane67/i-held-a-seance-with-dead-programming-languages-meet-seance-54jb</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week4-2026-10-26"&gt;Hacktoberfest Open-Source AI Challenge Week 4: Ghost in the Machine&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;seance&lt;/strong&gt; is a small Python CLI that lets you ask a question and get an&lt;br&gt;
answer from the ghost of a long-dead programming language — COBOL (1959),&lt;br&gt;
FORTRAN (1957), BASIC (1964), or ALGOL (1958). Each spirit answers in its&lt;br&gt;
own voice: COBOL in formal ALL-CAPS divisions, FORTRAN in terse numerics&lt;br&gt;
and GOTOs, BASIC in friendly numbered lines, ALGOL in precise&lt;br&gt;
begin/end blocks.&lt;/p&gt;

&lt;p&gt;It takes the Week 4 theme two ways at once: it is spooky (a séance, on&lt;br&gt;
Halloween week), and it honors the past (the languages that built&lt;br&gt;
computing, remembered in their own words, in the spirit of Día de los&lt;br&gt;
Muertos).&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/sonawaneutkarsh/seance" rel="noopener noreferrer"&gt;https://github.com/sonawaneutkarsh/seance&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Real runs, offline mode, no model needed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cobol"&gt;&lt;code&gt;$ python3 -m seance "Will my code outlive me?" --spirit cobol --offline&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;spirit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COBOL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1959&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;speaks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kd"&gt;PROCEDURE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;DIVISION&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HAVE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;READ&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;YOUR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;QUERY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;HAVE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FILED&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;IT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;— "Will my code outlive me?" — echoes in the machine room.&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dead&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;formal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;procedural&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ALL-CAPS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divisions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="k"&gt;END&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;PROGRAM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;I&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mainframe&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;It&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;never&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sleeps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;[source: offline fallback (deterministic)]&lt;span class="w"&gt;
&lt;/span&gt;&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;$ python3 -m seance "Why did you disappear?" --spirit basic --offline
The spirit of BASIC (1964) speaks:
30 REM I HAVE BEEN WAITING SINCE 1984. ASK AWAY.
Your question — "Why did you disappear?" — echoes in the machine room.
The dead answer in friendly, numbered lines, eager to help.
GOTO 10. The loop closes. The loop always closes.

[source: offline fallback (deterministic)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;seance/spirits.py&lt;/code&gt; — the four spirits and the deterministic fallback&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seance/ollama_client.py&lt;/code&gt; — minimal stdlib Ollama client&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seance/__main__.py&lt;/code&gt; — the CLI: summon, list spirits, offline mode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tests/test_seance.py&lt;/code&gt; — 9 tests, all passing (Ollama mocked)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The question goes to &lt;strong&gt;Gemma, running locally through Ollama&lt;/strong&gt;, prompted&lt;br&gt;
to answer in the chosen spirit's voice. No accounts, no API keys, no&lt;br&gt;
question leaves your machine. And because a séance should work with the&lt;br&gt;
lights off, there is an honest offline fallback: when no model is&lt;br&gt;
reachable, lines are picked by hashing (spirit, question), so the same&lt;br&gt;
question always summons the same answer — and the reply always labels&lt;br&gt;
its source, so a fallback is never passed off as AI.&lt;/p&gt;

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

&lt;p&gt;The whole project only works because the pieces are open. Gemma is an&lt;br&gt;
open-weight model I can run on my own laptop, so communing with the past&lt;br&gt;
does not mean uploading my questions to someone else's server — and the&lt;br&gt;
dead languages themselves are the original open inheritance: ALGOL's&lt;br&gt;
ideas live on in nearly every language used today precisely because they&lt;br&gt;
were shared, not locked away. A closed model behind an API could vanish&lt;br&gt;
tomorrow and take the séance with it; a local open-weight model and a&lt;br&gt;
stdlib-only codebase will still answer in ten years. The past, kept&lt;br&gt;
open, stays reachable.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma — Gemma (via local Ollama) powers the AI séances.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Tags: #devchallenge #hf26challenge&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>I built a sloth that cleans my Downloads folder — meet slothsort 🦥</title>
      <dc:creator>utkarsh sonawane</dc:creator>
      <pubDate>Mon, 19 Oct 2026 22:10:01 +0000</pubDate>
      <link>https://dev.to/utkarshsonawane67/i-built-a-sloth-that-cleans-my-downloads-folder-meet-slothsort-4nik</link>
      <guid>https://dev.to/utkarshsonawane67/i-built-a-sloth-that-cleans-my-downloads-folder-meet-slothsort-4nik</guid>
      <description>&lt;h1&gt;
  
  
  I built a sloth that cleans my Downloads folder — meet slothsort 🦥
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the Hacktoberfest Open-Source AI Challenge: Week 3 — Slow and Steady.&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;slothsort&lt;/strong&gt; is a small Python CLI that tidies a messy folder for you. Point it at your Downloads directory — you know the one, with &lt;code&gt;Q3-budget-final-FINAL.xlsx&lt;/code&gt; living next to &lt;code&gt;screenshot 2026-10-19.png&lt;/code&gt; and an installer from 2024 — and it sorts everything into tidy category folders: Documents, Images, Videos, Audio, Archives, Installers, Code, and friends.&lt;/p&gt;

&lt;p&gt;The twist: the sorting decisions are made by &lt;strong&gt;Gemma, running locally through Ollama&lt;/strong&gt;. No accounts, no API keys, no filenames leaving your machine. And because sloths plan for every contingency, there's an honest offline fallback — when no model is reachable, deterministic extension rules do the sorting instead of an error message.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/sonawaneutkarsh/slothsort" rel="noopener noreferrer"&gt;https://github.com/sonawaneutkarsh/slothsort&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Here's a real run — offline mode, on a folder of 12 genuinely messy files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python3 -m slothsort /tmp/messy-desk --offline
slothsort would move 12 file(s):

  [Archives]
    backup-2024.zip
    font-pack.zip
  [Audio]
    podcast-ep12.mp3
  [Documents]
    meeting-notes.txt
    todo.md
  [Images]
    grandma-recipe-scan.jpg
    screenshot 2026-10-19.png
  [Installers]
    installer-v2.4.1.exe
  [Other]
    app-debug.log
  [Presentations]
    slides-pitch-deck.pptx
  [Spreadsheets]
    Q3-budget-final-FINAL.xlsx
  [Videos]
    vacation-clip.mov

Nothing moved (dry run). Re-run with --yes to apply, or --undo to revert the last run.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's the whole pitch: &lt;strong&gt;one command, zero decisions, twelve files filed.&lt;/strong&gt; The dry run is the default — slothsort shows you the plan and moves nothing until you say &lt;code&gt;--yes&lt;/code&gt;. Changed your mind afterward? &lt;code&gt;--undo&lt;/code&gt; puts every file back exactly where it was.&lt;/p&gt;

&lt;p&gt;With Ollama running (&lt;code&gt;ollama pull gemma3&lt;/code&gt;, then drop the &lt;code&gt;--offline&lt;/code&gt; flag), filenames the rules don't recognize get classified by the model instead — &lt;code&gt;app-debug.log&lt;/code&gt; stops landing in &lt;code&gt;Other&lt;/code&gt; and gets filed where it actually belongs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The architecture is deliberately boring, in the good way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Scan.&lt;/strong&gt; Lists the files in your folder (top level by default; &lt;code&gt;--recursive&lt;/code&gt; descends but never re-sorts folders it already created).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Classify.&lt;/strong&gt; Each filename goes to &lt;code&gt;localhost:11434&lt;/code&gt; — Ollama, plain HTTP, stdlib only. Default model is &lt;code&gt;gemma3&lt;/code&gt;. The model must reply with &lt;em&gt;exactly one&lt;/em&gt; category name; anything else — a sentence, an invented category, an empty reply — is rejected and the extension rules take over. The model never gets to invent folders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preview.&lt;/strong&gt; Dry-run prints the full plan grouped by folder. Nothing moves until &lt;code&gt;--yes&lt;/code&gt;. Laziness, but make it safe.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply + undo.&lt;/strong&gt; Moves are collision-safe (a second &lt;code&gt;a.pdf&lt;/code&gt; becomes &lt;code&gt;a (2).pdf&lt;/code&gt;, never overwritten), and every run writes a &lt;code&gt;.slothsort-manifest.json&lt;/code&gt; so &lt;code&gt;--undo&lt;/code&gt; reverses the whole thing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full test suite (19 tests, &lt;code&gt;python -m unittest discover -s tests&lt;/code&gt;) covers the extension bands, model-reply validation, fallback behavior, plan building, collision handling, the apply/undo round-trip, the CLI, and the Ollama HTTP layer with mocks — no server needed to verify.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lazy payoff
&lt;/h2&gt;

&lt;p&gt;The challenge asked for the lazy payoff, so here are the numbers from the demo above: &lt;strong&gt;12 files → 9 folders, 1 command, 0 decisions made, 0 files deleted, and a one-command undo&lt;/strong&gt; if I don't like where anything landed. The dreaded "I'll organize Downloads this weekend" task now takes eleven seconds, most of which is reading the preview.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open innovation matters for this build
&lt;/h2&gt;

&lt;p&gt;This project only makes sense &lt;em&gt;because&lt;/em&gt; the AI is open:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your filenames are personal data.&lt;/strong&gt; A cloud API sorting your Downloads folder would see every bank statement, medical form, and half-written novel title you own. With local inference, none of it leaves your machine — there is no trust decision to make, which is exactly the point of automating something this personal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free forever.&lt;/strong&gt; Sorting files is precisely the kind of tiny automation a per-token API would make silly to pay for. Open weights make the lazy option the free option: set it up once, nap forever. No accounts, no keys, no subscriptions to babysit — very on-brand for Sloth Day.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Models are swappable, not load-bearing.&lt;/strong&gt; Don't like Gemma's filing instincts? &lt;code&gt;--model llama3.2&lt;/code&gt; and you're done — no code changes, no renegotiating with a vendor. The deterministic core (extension rules, preview, collision handling, undo) stays identical no matter which weights you plug in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A closed model could file your PDFs. It couldn't do any of the three things above. That's the whole argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do next
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;--watch&lt;/code&gt; mode that tidies new downloads as they land, content sniffing (so &lt;code&gt;app-debug.log&lt;/code&gt; is classified by what's inside it, not its name), and per-folder rules you can teach it once ("always put screenshots in Images/Screenshots"). All doable without touching the core.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — Gemma (via Ollama) is the default classifier; the prompt design, strict reply validation, and model-swap architecture are built around it.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built October 19, 2026 for the Hacktoberfest Week 3 DEV Challenge ("Slow and Steady"). Tags: #devchallenge #hf26challenge&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>I Fine-Tuned a 4B Model to Write Etsy Listings That Actually Rank</title>
      <dc:creator>utkarsh sonawane</dc:creator>
      <pubDate>Tue, 13 Oct 2026 00:49:47 +0000</pubDate>
      <link>https://dev.to/utkarshsonawane67/i-fine-tuned-a-4b-model-to-write-etsy-listings-that-actually-rank-pej</link>
      <guid>https://dev.to/utkarshsonawane67/i-fine-tuned-a-4b-model-to-write-etsy-listings-that-actually-rank-pej</guid>
      <description>&lt;h1&gt;
  
  
  I Fine-Tuned a 4B Model to Write Etsy Listings That Actually Rank
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;An open-weights side hustle: turning rough seller notes into optimized Etsy titles, descriptions, and tags — and proving the fine-tune beats the base model.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Every Etsy seller knows the feeling. You have created something wonderful — a hand-poured candle, a vintage tee, a printable wall art — and now you have to describe it on Etsy. Title: 140 characters to encompass every search term a buyer can think of. Description: persuasive but easy to scan. Tags: 13 carefully chosen terms, each one a bet on how strangers search.&lt;/p&gt;

&lt;p&gt;Most sellers either stuff keywords until the title reads like a ransom note, or write something poetic that no search algorithm will ever find. I kept thinking: this is a narrow, well-defined text task with tons of examples floating around. It's exactly the kind of thing a small fine-tuned model should be good at.&lt;/p&gt;

&lt;p&gt;So for DEV's Hacktoberfest Week 2 challenge (theme: Side Hustle), I built &lt;strong&gt;ListCraft&lt;/strong&gt; — an Etsy listing optimizer powered by a LoRA fine-tune of Qwen3.5-4B on Tinker, Thinking Machines' fine-tuning API. Paste in rough notes about your product; get back an optimized title, description, and tags. And critically: I measured whether the fine-tune actually helped, instead of just assuming it did.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why fine-tune instead of just prompting?
&lt;/h2&gt;

&lt;p&gt;The honest answer: I wanted to find out if it matters. A base instruction model can already write a decent product description. But Etsy's format has sharp edges — titles need to land in a 120-140 character sweet spot, keyword phrases are pipe-separated, and you need exactly 13 tags. These are conventions a model won't reliably follow from a prompt alone, and stuffing all of it into a system prompt eats context on every single call.&lt;/p&gt;

&lt;p&gt;Fine-tuning bakes the format in. The bet: a 4B model with the format burned into its weights beats a much larger prompted model at this specific job — and it's cheap enough to serve that a real side hustle could afford it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data
&lt;/h2&gt;

&lt;p&gt;I used the public &lt;code&gt;listybox-etsy-listing-parquet&lt;/code&gt; dataset (536 real listing pairs), split 90/10 with seed 42 → &lt;strong&gt;483 training pairs, 53 held out for eval&lt;/strong&gt;. Each pair maps rough seller notes (product concept, themes, audience, use cases) to a finished listing.&lt;/p&gt;

&lt;p&gt;One important note: the source dataset declares no license, so I'm &lt;strong&gt;not redistributing the data&lt;/strong&gt;. The repo ships the code, the eval protocol, and a rebuild script — anyone can download the source dataset themselves and reproduce everything. Open science shouldn't need a lawyer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Training on Tinker (including the run that collapsed)
&lt;/h2&gt;

&lt;p&gt;Tinker is Thinking Machines' fine-tuning API — you bring a script, it brings the GPUs. I trained Qwen3.5-4B with LoRA rank 32, Adam at 1e-4, batch size 4, for 2 epochs. Total cost: a few dollars of a $10 credit.&lt;/p&gt;

&lt;p&gt;Here's what most write-ups don't tell you: my first training run produced a collapsed model. The loss decreased to ~3e-5, which sounded great until I sampled from it and got infinite repetitions of a single token ("izingizingizing..."). The problem was in how I'd constructed my datum — Tinker's &lt;code&gt;cross_entropy&lt;/code&gt; doesn't shift labels internally, and I'd fed it unshifted sequences, so the model learned the identity mapping: predict the current token. A perfect loss on a meaningless task.&lt;/p&gt;

&lt;p&gt;I caught it by reading Tinker's cookbook source, fixed the shift (&lt;code&gt;model_input=toks[:-1]&lt;/code&gt;, &lt;code&gt;target_tokens=toks[1:]&lt;/code&gt;), and retrained from scratch. The healthy run went 1.17 → 0.36 mean NLL, smooth, no collapse. Lesson relearned: a loss curve that looks too good is usually lying to you. Sample early, sample often.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does the fine-tune actually help? (measured, not vibes)
&lt;/h2&gt;

&lt;p&gt;On the 53 held-out listings, base model vs. fine-tuned, greedy decoding:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Base Qwen3.5-4B&lt;/th&gt;
&lt;th&gt;Fine-tuned&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Keyword coverage&lt;/td&gt;
&lt;td&gt;0.77&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.93&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Titles in 120–140 char sweet spot&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;83%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean title length&lt;/td&gt;
&lt;td&gt;2,591 chars&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;136 chars&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keyword phrases per title&lt;/td&gt;
&lt;td&gt;1.2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;4.0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outputs with a TAGS section&lt;/td&gt;
&lt;td&gt;0%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The base model doesn't just underperform — it fails at the task structurally. Zero-shot, it rambles for thousands of characters and never emits the tag section. The fine-tuned model learned the format cold.&lt;/p&gt;

&lt;p&gt;Then the blind test: I had Qwen3-8B judge base vs. fine-tuned outputs without knowing which was which, on title SEO, description quality, and tag relevance. The fine-tuned model won 35 of 44 overall judgments (5 for base, 4 ties). It swept title SEO 42–2 and tags 41–2. Descriptions were essentially tied (20–24) — the fine-tune learned Etsy's format, not better prose, and I'm not going to pretend otherwise.&lt;/p&gt;

&lt;p&gt;And the honest caveat: the fine-tuned model over-generates tags — about 66 per listing vs. 13 in the references. It learned the shape of a tag list but not when to stop. That's a real limitation, and it's the next thing I'd fix (a length penalty or stop-sequence tuning).&lt;/p&gt;

&lt;h2&gt;
  
  
  The demo
&lt;/h2&gt;

&lt;p&gt;There's a Gradio demo in the repo with a side-by-side view: type (or pick a preloaded example of) rough seller notes, and see the base model's rambling output next to the fine-tuned model's structured listing. That comparison &lt;em&gt;is&lt;/em&gt; the pitch — it's the clearest possible demonstration of what the fine-tune bought.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;demo
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; ../requirements.txt
python app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why open innovation matters here
&lt;/h2&gt;

&lt;p&gt;Everything in this project is open: the base model weights (Apache 2.0), the training and eval scripts, the metrics, the failure story. Tinker itself is built around open-weight models. A year ago, fine-tuning a model for a niche task like this would have meant either a big GPU bill or a closed API that could change under you. Now a student can do it on a $10 credit in an afternoon, measure the improvement rigorously, and hand the whole thing to someone else to reproduce.&lt;/p&gt;

&lt;p&gt;That's the side hustle thesis, too. The moat for a tool like ListCraft was never the model — it's the workflow, the eval, the understanding of what Etsy sellers actually need. Open weights commoditize the intelligence; the product is everything around it. If I were turning this into a real business tomorrow, I'd start with the sellers, not the model card.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fix tag over-generation (stop sequences / length penalties)&lt;/li&gt;
&lt;li&gt;Try a larger rank or full fine-tune to see if description quality moves&lt;/li&gt;
&lt;li&gt;Talk to actual Etsy sellers (the genuine first user this project deserves)&lt;/li&gt;
&lt;li&gt;Package it as a real hosted tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/sonawaneutkarsh/listcraft" rel="noopener noreferrer"&gt;https://github.com/sonawaneutkarsh/listcraft&lt;/a&gt; — code, eval protocol, and reproduction instructions are all public. The $10 of Tinker credit bought something I couldn't have gotten from prompting: a small model that reliably does one job well — and the receipts to prove it.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tags: &lt;code&gt;#devchallenge&lt;/code&gt; &lt;code&gt;#hf26challenge&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>I built a hiking guide that runs on a laptop with no internet — meet trailbrief</title>
      <dc:creator>utkarsh sonawane</dc:creator>
      <pubDate>Sat, 10 Oct 2026 20:25:55 +0000</pubDate>
      <link>https://dev.to/utkarshsonawane67/i-built-a-hiking-guide-that-runs-on-a-laptop-with-no-internet-meet-trailbrief-12e7</link>
      <guid>https://dev.to/utkarshsonawane67/i-built-a-hiking-guide-that-runs-on-a-laptop-with-no-internet-meet-trailbrief-12e7</guid>
      <description>&lt;h2&gt;
  
  
  What I built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;trailbrief&lt;/strong&gt; is a small Python CLI that writes you a personalized hiking briefing. You tell it the trail — name, distance, elevation gain, location, season, your experience level — and it hands back a practical plan: an overview, a pacing plan, a season-aware pack list, watch-outs, and a Leave No Trace reminder.&lt;/p&gt;

&lt;p&gt;The twist: the briefing is written by &lt;strong&gt;Gemma, running locally through Ollama&lt;/strong&gt;. No accounts, no API keys, no data leaving your machine. And because the whole point is getting &lt;em&gt;outside&lt;/em&gt;, there's a proper offline fallback — when no model is reachable (read: you're already on the trail with zero bars), a built-in template engine still produces a genuinely useful briefing instead of an error message.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/sonawaneutkarsh/trailbrief" rel="noopener noreferrer"&gt;https://github.com/sonawaneutkarsh/trailbrief&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Here's a real run — offline mode, since I don't have a GPU farm in my dorm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; trailbrief &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"Ricketts Glen Falls Trail"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--distance&lt;/span&gt; 7.2 &lt;span class="nt"&gt;--elevation&lt;/span&gt; 1200 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="s2"&gt;"Benton, PA"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--season&lt;/span&gt; fall &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--experience&lt;/span&gt; intermediate &lt;span class="nt"&gt;--offline&lt;/span&gt;

&lt;span class="c"&gt;# Trail Briefing: Ricketts Glen Falls Trail&lt;/span&gt;
&lt;span class="k"&gt;*&lt;/span&gt;Benton, PA · 7.2 mi · 1,200 ft gain · Fall · Moderate&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;## Overview&lt;/span&gt;
A moderate day out: 7.2 miles and 1,200 ft of gain asks &lt;span class="k"&gt;for &lt;/span&gt;steady pacing and a real lunch stop. Expect about 4.2 hours of moving &lt;span class="nb"&gt;time&lt;/span&gt;, plus stops.

&lt;span class="c"&gt;## Pacing plan&lt;/span&gt;
Start no later than 8 AM — with 4.2 hours of moving &lt;span class="nb"&gt;time &lt;/span&gt;plus breaks, you want a buffer before dark.

&lt;span class="c"&gt;## Pack list&lt;/span&gt;
- Insulating mid-layer — temps swing 20°F+ through the day
- Headlamp with fresh batteries &lt;span class="o"&gt;(&lt;/span&gt;shorter days sneak up on you&lt;span class="o"&gt;)&lt;/span&gt;
- Bright colors — it&lt;span class="s1"&gt;'s hunting season in many areas

## Watch-outs
Daylight is the constraint: sunset comes early and temperatures drop fast once the sun dips. Leaf-covered rocks are slippery.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Ollama running (&lt;code&gt;ollama pull gemma3&lt;/code&gt;, then drop the &lt;code&gt;--offline&lt;/code&gt; flag), the same inputs go to the model instead — with a twist I'll get to below.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The architecture is deliberately boring, in the good way:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic core.&lt;/strong&gt; Difficulty and moving time are computed from your numbers with a Naismith-style rule (2 mph + 30 min per 1,000 ft of gain). No vibes, just arithmetic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grounded prompt.&lt;/strong&gt; Those computed numbers are baked into the prompt, and the model is explicitly told to use them and &lt;em&gt;not invent trail features, facilities, or water sources&lt;/em&gt;. This is the part most "AI hiking apps" get wrong — a chatbot happily hallucinating a water fountain at mile 6 is how people get hurt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local inference.&lt;/strong&gt; The prompt goes to &lt;code&gt;localhost:11434&lt;/code&gt; — Ollama, plain HTTP, stdlib only. Default model is &lt;code&gt;gemma3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Honest fallback.&lt;/strong&gt; Model unreachable? The template engine takes over with season-aware packing (fall gets headlamp + hunter-orange reminders, winter gets microspikes), elevation-aware safety notes, and experience-level tips.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The full test suite (12 tests, &lt;code&gt;python -m unittest discover -s tests&lt;/code&gt;) covers the difficulty bands, prompt grounding, fallback content, and the Ollama HTTP layer with mocks — no server needed to verify.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open innovation matters for this build
&lt;/h2&gt;

&lt;p&gt;This project only makes sense &lt;em&gt;because&lt;/em&gt; the AI is open:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It works where the internet doesn't.&lt;/strong&gt; A cloud API can't brief you on a ridgeline with no signal. A 3–9B open-weight model on your laptop can. The "touch grass" theme isn't decoration here — offline capability is the entire point, and only open weights make it possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your location stays yours.&lt;/strong&gt; Where you hike is personal data. With local inference, your trail plans never touch a server you don't control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run.&lt;/strong&gt; No per-token billing for a hobby tool you use twice a month. The economics of a closed API would kill this project; open weights make it free forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Models are swappable, not load-bearing.&lt;/strong&gt; Don't like Gemma's briefing style? &lt;code&gt;--model llama3.2&lt;/code&gt; and you're done — no code changes, no renegotiating with a vendor. The deterministic core (difficulty math, grounding, fallback) stays identical no matter which weights you plug in.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A closed model could write a prettier paragraph. It couldn't do any of the four things above. That's the whole argument.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do next
&lt;/h2&gt;

&lt;p&gt;Trailhead weather overlays, GPX import so distance/elevation come from the file instead of your memory, and a &lt;code&gt;--compare&lt;/code&gt; mode that briefs the same trail with two models side by side. All doable without touching the core.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Gemma&lt;/strong&gt; — Gemma (via Ollama) is the default briefing engine; the prompt, grounding strategy, and model-swap design are built around it.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Built October 10, 2026 for the Hacktoberfest Week 1 DEV Challenge ("Touch Grass"). Tags: #devchallenge #hf26challenge&lt;/em&gt;&lt;/p&gt;

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