{"slug": "i-stopped-asking-ai-to-count-now-it-catches-95-6-of-the-mistakes-in-crochet-on-a", "title": "I stopped asking AI to count. Now it catches 95.6% of the mistakes in crochet patterns, on a laptop", "summary": "A developer built StitchProof, a laptop-based tool that catches 95.6% (43/45) of stitch-count errors in crochet patterns by having a fine-tuned 4B open-weight model only read each row and translate it into a small program, while plain Python does all the arithmetic. The split approach followed a baseline in which an open-weight model shown 60 patterns with 45 hidden wrong rows found just 20 errors and flagged 78 correct rows, and a model 30 times larger still missed nearly half. The tool runs offline on a MacBook, shows the arithmetic behind each flag, and is aimed at designers who pay per pattern check while makers use it free.", "body_md": "*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle](https://dev.to/challenges/hacktoberfest-week2-2026-10-12)*\n\n**Round 5 says 31 stitches. You've counted three times. You keep getting 30.**\n\nSomewhere tonight, someone is pulling out an evening's work because of a number like that. They will blame their own hands. Sometimes they're right. Sometimes the pattern itself is wrong, and there's no way to tell which.\n\nSo I gave the job to an AI. I showed an open-weight model 60 crochet patterns with 45 wrong rows hidden in them and asked it to find the mistakes. It found 20. Along the way it flagged 78 rows that were perfectly fine. Then I tried a model 30 times bigger on some of the same patterns. It still missed almost half.\n\nThe problem wasn't crochet. The problem was that I was asking a language model to do arithmetic.\n\nSo I stopped. In StitchProof, the model only **reads** the pattern and turns each row into a tiny program. Plain Python does all the **counting**. With that split, and a 4B model fine-tuned on Tinker to do the reading, StitchProof caught **95.6% (43/45)** of the same mistakes, runs on a laptop with the Wi-Fi off, and shows the arithmetic behind every flag:\n\n*Rnd 5 says (31), but '(sc 3, inc) x6' uses 24 of 24 stitches and makes 30.*\n\nThis post is about crochet. The idea in it is for anyone who has watched an LLM confidently get a number wrong: **let the model translate, and let code count.**\n\n**StitchProof is a private tech editor for crochet patterns.**\n\nCrochet is bigger than it looks. Ravelry, the main home for knitters and crocheters, had [almost 9 million registered users](https://en.wikipedia.org/wiki/Ravelry) by 2020, and independent designers sell their patterns there and on Etsy as PDFs. Before a pattern goes on sale, many designers pay a human [tech editor](https://fiverr.com/mevlinngusickgo/tech-edit-your-crochet-pattern) to check every stitch count, because one wrong number in round 5 means every maker who buys it tears out their work.\n\nStitchProof does the stitch-math part of that job:\n\n| Who | What they do | What they get | \n|---|---|---|\n| **Designers** (would pay) | Paste a draft, open a `.txt` ,`.md` or`.pdf` , or photograph a printed page | Every row marked OK, ERROR, WARNING or CAN'T CHECK, the exact numbers behind each flag, a silhouette chart of the piece and a downloadable report | \n| **Makers** (free) | Type the stitches they had and paste the row they're stuck on | *\"The pattern says 31. These instructions make 30 from your 24 stitches. The pattern itself doesn't add up here, so it's not you.\"* | \n\n**The side hustle:** makers use it free, which is how designers hear about it. Designers pay per pattern check, or a small monthly fee if they publish often. A per-check price only works if each check costs nothing to run, which is exactly what a small local model gives me. (That's my business hypothesis, not a claim about revenue.)\n\n*The waits for the model and for Gemma are sped up 3x in the video. Everything you see runs on one MacBook.*\n\n**1. Start.** Paste a pattern, open a file, or photograph a printed page.\n\n**2. Check a pattern.** The sample has two deliberate mistakes. Rows are annotated in place as the model reads them, like a spellchecker. Select a row and the panel shows the stitches available, used, made and stated.\n\n**3. The second mistake.** Rnd 11 repeats `(sc 2, dec)` 5 times instead of 6, so it makes 15, not 18, and leaves 4 stitches unworked. StitchProof reports both problems.\n\nThe **silhouette** plots stitches per round. For amigurumi it traces the outline of the finished piece, so a mistake shows up as a spike or a dent, hatched and labelled.\n\n**4. Fix and check again.** Edit Rnd 5 and re-run. Unchanged rows come straight from a local cache, so only the edited row goes back to the model.\n\n**5. Light or dark.**\n\n**6. Printed patterns.** Plenty of patterns live in books and on paper. Drop in a photo and Gemma 4 transcribes it on your computer.\n\n**7. Review before checking.** The photo sits beside the editable transcription, so you can fix any misread before a single stitch is counted.\n\n**8. Stuck on a row.** The maker mode: one row, one plain answer.\n\n**A local tech editor for crochet patterns.**\nA small fine-tuned model reads every row. Plain code checks every stitch count. Nothing leaves your computer.\n\n[Demo video](https://github.com/HeetRanpura/stitchproof/docs/demo/stitchproof_demo.mp4) · [Results](https://github.com/HeetRanpura/stitchproof#results) · [How it works](https://github.com/HeetRanpura/stitchproof#how-it-works) · [Architecture](https://github.com/HeetRanpura/stitchproof#architecture) · [Run it](https://github.com/HeetRanpura/stitchproof#run-it-locally)\n\nYou've unravelled it twice. Is the pattern wrong, or are you?\n\nCrochet designers sell their patterns as PDFs on Etsy and Ravelry. Before publishing, many pay a human tech editor to check every single stitch count, because one wrong number in round 5 means hundreds of makers tearing out an evening's work. Errata are a fact of life.\n\nSo why not ask an AI? We tried. Given 60 test patterns and asked directly to find the rows whose counts are wrong, the open-weight Qwen3.5-4B caught **44.4% (20/45)** of the mistakes. Chatbots are famously bad at crochet. They \"count\" stitches they never counted.\n\n**StitchProof never asks**…\n\nMIT licensed. 149 Python tests, plus frontend tests, run in CI on every push. Every result in this post comes from files in [`eval/results/`](https://github.com/HeetRanpura/stitchproof/tree/main/eval/results), and every rate is shown with its count.\n\n**Built on open source:** Qwen3.5 (Qwen team), Gemma 4 (Google DeepMind), Tinker and `tinker-cookbook` (Thinking Machines), llama.cpp, Ollama, FastAPI and React. Full credits are in the [README](https://github.com/HeetRanpura/stitchproof#credits-and-license).\n\n`LineProgram` JSON object: work, increase, decrease, skip, \"to end\", turning chain, repeat, plus the row label and the stated count, `Rnds 6-9`. It reports `COUNT_MISMATCH`, `OVERFLOW`, `LEFTOVER`, `REPEAT_REMAINDER`, `NO_STATED_COUNT` or `CANT_CHECK`.\nThe model's instructions say it plainly ([`prompts.py`](https://github.com/HeetRanpura/stitchproof/blob/main/src/stitchproof/prompts.py)):\n\n```\n- Transcribe exactly. Never fix or compute counts. stated_count = the count\n  written (\"(18)\", \"[18 sts]\", \"- 18 st\", \"you should have 18\"), even if wrong.\n```\n\nAnd this is what \"counting\" looks like on the other side, straight from [`simulate.py`](https://github.com/HeetRanpura/stitchproof/blob/main/src/stitchproof/simulate.py). No model anywhere near it:\n\n``` php\ndef op(self, op: Op, tail: int = 0) -> None:\n    if isinstance(op, Work):          # \"sc 3\": 1 stitch into each of the next 3\n        self.take(op.n)\n        self.made += op.n\n    elif isinstance(op, IntoOne):     # \"inc\": 2 stitches into 1\n        self.take(1)\n        self.made += op.k\n    elif isinstance(op, Together):    # \"dec\": 2 stitches worked together into 1\n        self.take(op.k)\n        self.made += 1\n    ...\n```\n\nWhen the code can't be sure (lace, multi-size patterns, UK terms, short rows, a line the model couldn't read), the row says **CAN'T CHECK** with a reason. It never guesses. After a wrong row, the engine re-syncs to the designer's stated count, so one mistake is reported once instead of cascading down the whole pattern.\n\n`127.0.0.1`, fonts and icons are bundled, there's no telemetry, and uploaded photos are read from a temp file and deleted.`llama-server`, Metal), Ollama for Gemma 4, pypdf, Jinja2 and Matplotlib for reports.\n**No published patterns were used anywhere.** Real patterns are someone's copyrighted work, so every training example is generated by my own code:\n\n`shapes.py` builds pattern structures: spheres, tubes, cones, flat pieces, triangles, mixed stitches.`errors.py` seeds known mistakes (wrong stated count, wrong repeat count, wrong run length, wrong foundation chain, a repeat that doesn't divide \"around\"). Every seeded pattern is checked: the simulator must flag exactly the seeded rows.`render.py` writes the notation in many styles. `paraphrase.py` asks two teacher models on Tinker, `gpt-oss-120b` and `Qwen3.5-397B-A17B`, to rewrite some patterns in a natural designer's voice. Code then checks that every number and row label survived the rewrite.`ood.py` asks a third family, Training was a LoRA on `Qwen/Qwen3.5-4B` with `tinker-cookbook`'s supervised loop: rank 32, one epoch, 1,410 line examples, thinking disabled. Validation loss went from 0.303 to 0.0028.\n\n**The whole build cost US$1.62 of Tinker credit** ([costs.md](https://github.com/HeetRanpura/stitchproof/blob/main/eval/results/costs.md)):\n\n| Model on Tinker | Used for | US$ | \n|---|---|---|\n| Qwen3.5-4B | LoRA training (1 epoch + validation) | 1.018 | \n| Qwen3.5-4B | sampling for baselines, the fine-tuned eval, the export check | 0.359 | \n| Kimi-K2.6 | writing the out-of-generator test set | 0.099 | \n| Qwen3.5-397B-A17B | training-data rewrites | 0.084 | \n| gpt-oss-120b | training-data rewrites + the large-model baseline | 0.041 | \n| storage | checkpoints | 0.017 | \n| **Total** |  | **1.619** | \n\nFour approaches, the same eval sets, the same prompt and the same parser, at temperature 0:\n\n|  | A: base, asked directly | C: base + simulator | **D: StitchProof** | \n|---|---|---|---|\n| Held-out: errors caught | 44.4% (20/45) | 75.6% (34/45) | **95.6% (43/45)** | \n| Held-out: false alarms | 13.7% (78/571) | 42.6% (243/571) | **22.2% (127/571)** | \n| Other model family: errors caught | 61.1% (11/18) | 100.0% (18/18) | **100.0% (18/18)** | \n| Other model family: false alarms | 11.2% (23/205) | 50.7% (104/205) | **8.3% (17/205)** | \n| Other model family: whole pattern right | 32.0% (8/25) | 16.0% (4/25) | **80.0% (20/25)** | \n| Valid JSON (held-out) | 86.7% (52/60) | 78.0% (663/850) | **100.0% (850/850)** | \n| Stated count copied faithfully (held-out) | n/a | 67.4% (415/616) | **100.0% (616/616)** | \n\nWhat the table says, in plain words:\n\nAlmost all of D's false alarms on the held-out set come from **one notation it never saw**: `*sc, inc; rep from * 4 more times`, which means 5 repeats in total. The model writes 4. On rows in that style it raises false alarms on 97.5% (115/118) of clean rows, and it's also why D catches only 66.7% (4/6) of the wrong-repeat-count mistakes. On rows in the other three unseen styles, D parses 99.8% (466/467) exactly, with 2.7% (12/438) false alarms.\n\nI didn't retrain on that style, because that would be tuning on the test set. It goes into the next version's training templates, with fresh held-out styles to test against.\n\nPatterns are a designer's unreleased work, so the fine-tuned model had to run locally. I exported the LoRA with Tinker's weights API, converted it for llama.cpp and run it on a 4-bit base:\n\n| Disk | RAM | Load time | Per row (M4 MacBook) | Agreement with Tinker | \n|---|---|---|---|---|\n| 2.93 GB | 3.18 GB | 2.5 s | 2.36 s mean | **100.0% (50/50)** | \n\nOne gotcha worth sharing with anyone fine-tuning Qwen3.5 on Tinker:\n\nTinker trains the linear-attention Q, K and V projections as **separate** LoRAs, but Qwen3.5 stores them as **one fused** `in_proj_qkv` weight, so llama.cpp can't load the adapter as-is. An exact fused LoRA stacks the A matrices and puts the B matrices on a block diagonal ([`export.py`](https://github.com/HeetRanpura/stitchproof/blob/main/src/stitchproof/train/export.py)):\n\n```\nfor prefix, g in groups.items():\n    a = torch.cat([g[\"qA\"], g[\"kA\"], g[\"vA\"]], dim=0)            # rank r -> 3r\n    b = torch.block_diag(g[\"qB\"], g[\"kB\"], g[\"vB\"]) * 3.0       # llama.cpp scales by alpha / rank\n    out[f\"{prefix}.linear_attn.in_proj_qkv.lora_A.weight\"] = a.contiguous()\n    out[f\"{prefix}.linear_attn.in_proj_qkv.lora_B.weight\"] = b.to(g[\"qB\"].dtype).contiguous()\n```\n\nThe `* 3.0` matters: the fused LoRA has rank 3r, and llama.cpp divides by rank, so without it every update would be a third of what Tinker trained. The equivalence check (50 validation lines, same prompt and parser, local vs Tinker) is what proved the conversion exact.\n\nGemma 4 (`gemma4:e4b-it-qat` in Ollama) has one job: turn a photo of a printed pattern into text, locally. It never counts either. On 12 held-out patterns rendered as a clean scan and as a phone-style photo (slight rotation, uneven light, noise, JPEG):\n\n|  | Typed text | Scan → Gemma | Photo → Gemma | \n|---|---|---|---|\n| Numbers kept | n/a | 98.9% (357/361) | 98.1% (354/361) | \n| Errors caught, end to end | 100.0% (12/12) | 91.7% (11/12) | 100.0% (12/12) | \n| False alarms, end to end | 23.2% (22/95) | 25.3% (24/95) | 22.1% (21/95) | \n| Lines character-perfect | n/a | 50.3% (81/161) | 42.2% (68/161) | \n\nGemma keeps the numbers but likes to drop separators like \" - \". That's why the app always puts the photo next to the editable transcription before anything is checked.\n\nI wrote a spec with milestones and checkpoints, then built StitchProof with Claude Code against it, stopping at each checkpoint to review the counting rules, the baselines and the results before moving on. The spec is in the repo as [`SPEC.md`](https://github.com/HeetRanpura/stitchproof/blob/main/SPEC.md), and the counting rules are in [`CONVENTIONS.md`](https://github.com/HeetRanpura/stitchproof/blob/main/CONVENTIONS.md), each with its own test.\n\nEvery one of these would have been impossible, or worse, with a closed API:\n\nMy first user is a family member who sells handmade **hexagon cardigans and oversized patchwork sweaters on Etsy**, made from her own patterns.\n\nHer work shows why stitch math matters to a seller. A hexagon cardigan is dozens of identical motifs, each worked in rounds that have to land on the same count, and a patchwork sweater is panels that have to line up with their neighbours. One wrong number in her pattern doesn't cost one piece. It costs every motif made from it.\n\nShe ran StitchProof on one of her own patterns, on her own laptop. The pattern never left the machine, and it isn't in the training data or in any of the results above, which were all measured on generated patterns.\n\nHer patterns also show exactly where v1 stops. Hexagons with chain-space corners and sweaters written for several sizes come back as CAN'T CHECK today, so those two are first on the list below. **If you design or sell crochet pieces and have a draft you'd let me check, I'd love to hear from you in the comments.**\n\nI'm entering **Best Use of Tinker**, **Best Use of Gemma** and **Best Use of GitHub Copilot**.\n\nThe category asks for a fine-tune with a clear improvement over a baseline. StitchProof's case:\n\n`gemma4:e4b-it-qat` through Ollama, on the same laptop. The photo is read from a temp file and deleted.\nThe category includes automating your project with GitHub Actions. StitchProof uses two workflows:\n\n`Eval (synthetic sets)`): it runs approaches C and D on Tinker with a hard spending cap (`--max-usd 3` per run), writes the results table into the job summary and uploads the raw results as artifacts. It never touches the private `data/real/` folder.`CONVENTIONS.md`\n**Next:** support chain-space corners and multi-size patterns, since both show up in my first user's work; add the missing notation styles to training and test on fresh held-out ones; check more real drafts with designers; package the model for Ollama; and try the same translate, simulate, verify design on knitting.\n\nIf you crochet, design patterns, or just have opinions about LLMs and arithmetic, I'd love to hear what you think in the comments.", "url": "https://wpnews.pro/news/i-stopped-asking-ai-to-count-now-it-catches-95-6-of-the-mistakes-in-crochet-on-a", "canonical_source": "https://dev.to/heet_ranpura/i-stopped-asking-ai-to-count-now-it-catches-956-of-the-mistakes-in-crochet-patterns-on-a-laptop-1el0", "published_at": "2026-10-18 16:14:25+00:00", "updated_at": "2026-10-18 16:17:46.747836+00:00", "lang": "en", "topics": ["ai-tools", "large-language-models", "ai-agents"], "entities": ["StitchProof", "Tinker", "Gemma 4", "Ravelry", "Etsy", "Hacktoberfest"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/i-stopped-asking-ai-to-count-now-it-catches-95-6-of-the-mistakes-in-crochet-on-a", "markdown": "https://wpnews.pro/news/i-stopped-asking-ai-to-count-now-it-catches-95-6-of-the-mistakes-in-crochet-on-a.md", "text": "https://wpnews.pro/news/i-stopped-asking-ai-to-count-now-it-catches-95-6-of-the-mistakes-in-crochet-on-a.txt", "jsonld": "https://wpnews.pro/news/i-stopped-asking-ai-to-count-now-it-catches-95-6-of-the-mistakes-in-crochet-on-a.jsonld"}}