<?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: Advik Divekar</title>
    <description>The latest articles on DEV Community by Advik Divekar (@advikdivekar).</description>
    <link>https://dev.to/advikdivekar</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%2F4162179%2F4f54da1f-781c-461b-8131-a914f2180e70.jpg</url>
      <title>DEV Community: Advik Divekar</title>
      <link>https://dev.to/advikdivekar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/advikdivekar"/>
    <language>en</language>
    <item>
      <title>A small, not-so-smart model went from 10% to 99.6% at reading property deeds for $1.15, and it says 'check this line' instead of bluffing</title>
      <dc:creator>Advik Divekar</dc:creator>
      <pubDate>Sun, 25 Oct 2026 16:39:52 +0000</pubDate>
      <link>https://dev.to/advikdivekar/a-small-not-so-smart-model-went-from-10-to-996-at-reading-property-deeds-for-115-and-it-says-490k</link>
      <guid>https://dev.to/advikdivekar/a-small-not-so-smart-model-went-from-10-to-996-at-reading-property-deeds-for-115-and-it-says-490k</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;p&gt;&lt;strong&gt;N 86°29' E, 103.2 feet.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is one line of a property deed. Walk the rest of the lot and you should end up where you started.&lt;/p&gt;

&lt;p&gt;You end up &lt;strong&gt;27 feet away.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One digit is wrong. Maybe a clerk typed &lt;code&gt;103.2&lt;/code&gt; for &lt;code&gt;130.2&lt;/code&gt;. Maybe the scan smudged. Maybe the AI that read it got creative. The drawing you'd make still looks fine, and nobody finds out until the survey crew does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DeedReader&lt;/strong&gt; reads that deed, closes the shape in plain code, plots it on a real satellite map, and when something doesn't add up it refuses to draw it. It stamps the result &lt;strong&gt;NEEDS HUMAN REVIEW&lt;/strong&gt;, points at the line, and tries every one-digit fix to find the one that closes the parcel. In the example above: &lt;code&gt;103.2 → 130.2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/S-m8AZUy7a8" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What You're About to Read
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The result:&lt;/strong&gt; one Tinker LoRA on Qwen3-8B moved exact deed reads from &lt;strong&gt;10% (6/60)&lt;/strong&gt; to &lt;strong&gt;99.6% (2,988/3,000, 95% CI 99.3–99.8%)&lt;/strong&gt; on fresh deeds. Same base model, same prompt, same checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cost:&lt;/strong&gt; &lt;strong&gt;$1.15&lt;/strong&gt; and 16 minutes of training for the final model. &lt;strong&gt;$0.17 of training already reaches 99.4%.&lt;/strong&gt; The entire project, every baseline and every evaluation included, came to about &lt;strong&gt;$3.80&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The safety record:&lt;/strong&gt; on the same 60 deeds, wrong-and-unflagged answers went from &lt;strong&gt;5 to 0&lt;/strong&gt;. Across 3,000 fresh deeds, 10 of the 12 imperfect outputs were caught by parsing and closure alone, and the other 2 are a label quirk in my own generator (same physical length, written two ways).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The design rule:&lt;/strong&gt; the model reads. Plain, tested code does every piece of math. Five independent checks must agree before an answer is allowed to look confident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You keep it:&lt;/strong&gt; I downloaded the 369 MB adapter and ran it offline on a laptop. &lt;strong&gt;150 of 150 deeds read exactly right&lt;/strong&gt;, no network, no per-deed fee.&lt;/li&gt;
&lt;/ul&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%2Fnwep5gt1bsazspsgqosn.png" 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%2Fnwep5gt1bsazspsgqosn.png" alt="DeedReader plots a parcel on real satellite imagery. Click a sentence and its side lights up." width="800" height="886"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: land is described in words
&lt;/h2&gt;

&lt;p&gt;Every parcel of land has a legal description, and it reads like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Commencing at a cedar post at the corner of Tract 7, thence S 46°30′11″ W 1,011.25 feet to a corner post, thence along a curve to the right, R = 757.19 feet, to a point in the center of the road, thence N 23°16′52″ W 1,206.14 feet to a 4 inch concrete monument…&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Someone has to turn that into a drawing. Convert every bearing. Plot every side, curved ones included. Check the shape closes. Work out the acreage. That someone is a surveyor, a title abstractor or a paralegal, and the job takes &lt;strong&gt;fifteen to thirty minutes a deed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The scary part isn't the time. It's that &lt;strong&gt;one wrong digit quietly poisons everything downstream&lt;/strong&gt;, and the drawing still looks plausible. The failure you have to fear isn't "the tool is wrong." It's "the tool is wrong and didn't tell me."&lt;/p&gt;

&lt;h2&gt;
  
  
  What exists today, and the gap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;What it gives you&lt;/th&gt;
&lt;th&gt;What it can't tell you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;By hand&lt;/td&gt;
&lt;td&gt;A drawing you trust&lt;/td&gt;
&lt;td&gt;It takes 15–30 minutes a deed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A regex parser&lt;/td&gt;
&lt;td&gt;Instant and free&lt;/td&gt;
&lt;td&gt;Only reads clean &lt;code&gt;N 41°00' E&lt;/code&gt; calls, not 1800s prose or numbers spelled out in words&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A base open model, no training&lt;/td&gt;
&lt;td&gt;Reads messy prose&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;10% exactly right&lt;/strong&gt; in my test, and 5 of 60 wrong with no warning at all&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DeedReader&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A closed parcel on a real map in seconds&lt;/td&gt;
&lt;td&gt;Says &lt;strong&gt;NEEDS HUMAN REVIEW&lt;/strong&gt; when anything doesn't add up, and points at the line&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;DeedReader is the lazy version of that job: &lt;strong&gt;paste, glance, approve.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The deed becomes a &lt;strong&gt;parcel on a real satellite map&lt;/strong&gt; with true bearings and distances&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Acres, square feet, perimeter and closure ratio&lt;/strong&gt;, instantly&lt;/li&gt;
&lt;li&gt;Click a sentence and its side &lt;strong&gt;lights up on the map&lt;/strong&gt;. Click a side and the sentence lights up&lt;/li&gt;
&lt;li&gt;Export to &lt;strong&gt;DXF&lt;/strong&gt; for CAD, &lt;strong&gt;GeoJSON&lt;/strong&gt; for GIS, or &lt;strong&gt;SVG&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A deed that doesn't add up is &lt;strong&gt;never drawn as if it did.&lt;/strong&gt; You get the line to check and the one-digit fix that would close it&lt;/li&gt;
&lt;li&gt;Works &lt;strong&gt;fully offline&lt;/strong&gt; from a downloaded adapter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it fits Slow and Steady:&lt;/strong&gt; the tortoise didn't win by being fast. It won by never doing something stupid. A small model, a dollar of training, plain code for every number, and a system that would rather say "I don't know" than be quick and wrong. It automates the slowest job in land work, and earns trust the slow way: by showing its arithmetic.&lt;/p&gt;

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

&lt;p&gt;The video above is the whole tour. The studio replays &lt;strong&gt;real recorded outputs of my fine-tuned model&lt;/strong&gt; on deeds it never saw in training, while every safety check runs &lt;strong&gt;live in your browser&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Paste, glance, approve.&lt;/strong&gt; A clean deed: every check passes, the parcel closes to 1:2.9 million, and the studio reports 43.44 acres. Click any sentence and its side lights up in the drawing. Export to SVG, DXF or GeoJSON in one click.&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%2F1inqcb1t3xfslezcg88g.png" 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%2F1inqcb1t3xfslezcg88g.png" alt="All checks pass: a closed 8-sided parcel with two curves, 43.44 acres, ready to export" width="800" height="915"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Break it on purpose.&lt;/strong&gt; "Simulate a misread" corrupts a single number. Three independent checks fail at once, the banner turns red, and it names the line:&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%2Fpgrumav0rj8hqkysunnt.png" 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%2Fpgrumav0rj8hqkysunnt.png" alt="A misread caught: misclosure 900 ft, the number isn't in its clause, an independent reader disagrees" width="800" height="930"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the lazy payoff, side by side:&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%2Fphg6vjebmgfexxpk2zl4.png" 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%2Fphg6vjebmgfexxpk2zl4.png" alt="By hand vs DeedReader" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&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/advikdivekar" rel="noopener noreferrer"&gt;
        advikdivekar
      &lt;/a&gt; / &lt;a href="https://github.com/advikdivekar/deed" rel="noopener noreferrer"&gt;
        deed
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      DeedReader: a ~$1 fine-tuned model reads property deeds; plain code checks closure and plots the parcel
    &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;DeedReader&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;Paste a metes-and-bounds legal description. Get structured calls, a closure check done in plain code, a plotted parcel, and an honest &lt;strong&gt;NEEDS HUMAN REVIEW&lt;/strong&gt; whenever anything is off. A fine-tuned open-weight model (Qwen3-8B + LoRA, trained on &lt;a href="https://thinkingmachines.ai/tinker/" rel="nofollow noopener noreferrer"&gt;Tinker&lt;/a&gt; for about $2.5) does the reading; deterministic code does everything that must be right.&lt;/p&gt;
&lt;p&gt;Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 3. &lt;strong&gt;Read &lt;a href="https://github.com/advikdivekar/deed/EVAL_REPORT.md" rel="noopener noreferrer"&gt;EVAL_REPORT.md&lt;/a&gt; before trusting any number here: everything is measured on synthetic deeds, and real-deed accuracy is unmeasured.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Results (synthetic test deeds; details and caveats in EVAL_REPORT.md)&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;base Qwen3-8B, 3-shot&lt;/th&gt;
&lt;th&gt;tuned (v2)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;deeds read exactly right (in-distribution)&lt;/td&gt;
&lt;td&gt;10% (n=60)&lt;/td&gt;
&lt;td&gt;99.6% (n=3,000)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flagged for a human&lt;/td&gt;
&lt;td&gt;82%&lt;/td&gt;
&lt;td&gt;0.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;silent errors (wrong AND unflagged)&lt;/td&gt;
&lt;td&gt;5 of 60&lt;/td&gt;
&lt;td&gt;2 of 3,000 (0.07%, 95% upper bound 0.24%); 0 if &lt;code&gt;87 link&lt;/code&gt; = &lt;code&gt;0.87 chain&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;training cost&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;about $1.15 (est.)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Unseen style/unit, zero-shot: spelled-out numbers 85.6% exact (14.4% flagged, 0 silent)…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/advikdivekar/deed" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I built it
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The rule behind all of it: the model reads, code decides.&lt;/strong&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%2Fc2de3hgnn2q51cqts60t.png" 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%2Fc2de3hgnn2q51cqts60t.png" alt="The model reads. Code decides." width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Language models read messy text brilliantly and are not accountable for arithmetic. So Qwen3-8B plus a LoRA does exactly one job, turning prose into structured calls. Everything after that is plain code with tests: closure, area, unit conversion (feet, chains, poles, varas, links) and plotting.&lt;/p&gt;

&lt;p&gt;Then five independent checks have to agree before an answer may look confident:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The output parses.&lt;/li&gt;
&lt;li&gt;The parcel closes (1:5,000).&lt;/li&gt;
&lt;li&gt;Every number appears &lt;strong&gt;in its own sentence&lt;/strong&gt; of the deed.&lt;/li&gt;
&lt;li&gt;Every landmark ("iron pin", "white oak") is backed by words in that sentence.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;second, independent reader&lt;/strong&gt;, a regex parser that never saw the model, agrees on bearing, distance and curve direction.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The data: truth first, prose second.&lt;/strong&gt; There is no free pile of labelled real deeds, so I turned the problem around. A generator draws a &lt;strong&gt;closed polygon with known bearings and distances&lt;/strong&gt;, then writes it up in many styles: symbols, dashes, words, archaic chains and links, and damaged OCR, with easements, deed-book numbers and stray acreage as distractors. The truth exists before the text does, so every label is exact. I deliberately held back one &lt;strong&gt;writing style&lt;/strong&gt; (every number spelled out in words) and one &lt;strong&gt;unit&lt;/strong&gt; (Texas varas) to see what the model does with things it has never met.&lt;/p&gt;




&lt;h2&gt;
  
  
  Best Use of Tinker
&lt;/h2&gt;

&lt;h2&gt;
  
  
  10% → 99.6%, for $1.15
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Qwen3-8B is a small model. Out of the box it doesn't know what a deed is, and it has nowhere near the knowledge of a giant LLM. It scored 10%. Same model, same prompt, same checks: the only thing that changed was one dollar and fifteen cents of Tinker training.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's the point. I didn't need a model that knows everything. I needed one that does one narrow job perfectly, and fine-tuning is how a small model gets there.&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%2Fbyywn8ut4pbtnul1t9fu.png" 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%2Fbyywn8ut4pbtnul1t9fu.png" alt="Deeds read exactly right, before and after" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;base Qwen3-8B, untrained&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Tinker LoRA&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Exactly right&lt;/td&gt;
&lt;td&gt;6 / 60 (10%)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2,988 / 3,000 (99.6%)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sent to a human&lt;/td&gt;
&lt;td&gt;82%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.4%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wrong and unflagged&lt;/td&gt;
&lt;td&gt;5 / 60&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2 / 3,000 (0 by physical length)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1.15&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;My goal wasn't a good number. It was &lt;strong&gt;a good number at the lowest price I could defend.&lt;/strong&gt; Here is exactly how.&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%2Fa6bbfwsx8qwgo6h4twvb.png" 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%2Fa6bbfwsx8qwgo6h4twvb.png" alt="The fine-tuning pipeline" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Shrink the bill before you shrink the model
&lt;/h3&gt;

&lt;p&gt;Tinker bills per token, so I started with the output. My first format was JSON at &lt;strong&gt;547 tokens&lt;/strong&gt; per deed. I replaced it with one line per call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POB iron pin
L N 41 0 0 E 121.9 ft | iron pin
C N 3 45 22 E 366.15 ft R 944.33 ft L | stone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code converts it back to JSON. &lt;strong&gt;145 tokens, 3.8× smaller&lt;/strong&gt;, which cuts training, evaluation and local inference all at once, and costs nothing to run.&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%2Fhgq52fwp6fjgspedxvoe.png" 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%2Fhgq52fwp6fjgspedxvoe.png" alt="3.8x fewer tokens" width="799" height="271"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Price the options, then pick
&lt;/h3&gt;

&lt;p&gt;Training per million tokens: &lt;strong&gt;Qwen3-8B $0.44&lt;/strong&gt; vs Qwen3.5-4B $0.737. A smaller model is not automatically a cheaper one. Qwen3-8B was cheaper to train and strong enough for the job.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Train: rank-32 LoRA, 3 epochs, 16 minutes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_lora_training_client_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base_model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Qwen/Qwen3-8B&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rank&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# loss only on the answer tokens, never on the deed prose
&lt;/span&gt;&lt;span class="nc"&gt;Datum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="n"&gt;loss_fn_inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;weights&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;completion&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                          &lt;span class="n"&gt;target_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]))&lt;/span&gt;

&lt;span class="n"&gt;fb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward_backward_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss_fn&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cross_entropy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;op&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;tc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;optim_step_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;AdamParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;lr_at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;beta1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;beta2&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.95&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2,300 training deeds&lt;/strong&gt;, batch 16, peak learning rate 2e-4 with warmup and linear decay, &lt;strong&gt;429 steps, about 2.6M tokens.&lt;/strong&gt; Loss is masked to the answer, so the model learns to write calls instead of memorizing deed prose. Steps are pipelined (step &lt;em&gt;k+1&lt;/em&gt; is submitted before step &lt;em&gt;k&lt;/em&gt; returns), a checkpoint is saved every epoch, and a budget guard prices every job from token counts and refuses to launch one that would burn half the cap. Loss falls from 1,806 on step 1 to under 0.1 by step 41.&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%2Fhgriaqbpu5jghxcrnjwj.png" 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%2Fhgriaqbpu5jghxcrnjwj.png" alt="Training loss across 3 epochs" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Find the knee of the curve
&lt;/h3&gt;

&lt;p&gt;I didn't train on everything and hope. Four runs, one epoch each, scored on the same 500 held-out deeds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;training deeds&lt;/th&gt;
&lt;th&gt;est. cost&lt;/th&gt;
&lt;th&gt;read exactly right&lt;/th&gt;
&lt;th&gt;wrong and unflagged&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;$0.04&lt;/td&gt;
&lt;td&gt;38.6%&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;$0.08&lt;/td&gt;
&lt;td&gt;92.6%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;1,000&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.17&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.4%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2,000&lt;/td&gt;
&lt;td&gt;$0.34&lt;/td&gt;
&lt;td&gt;99.6%&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2F2ao6xzkphdj4n3kd5yoo.png" 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%2F2ao6xzkphdj4n3kd5yoo.png" alt="Accuracy per dollar" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seventeen cents buys 99.4%.&lt;/strong&gt; And look at the zeros: between 250 and 500 deeds the model stops making &lt;em&gt;silent&lt;/em&gt; mistakes. That jump, not the accuracy, is where it becomes safe to trust.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Is the gain real or noise?
&lt;/h3&gt;

&lt;p&gt;I paired the base model against the fine-tune on &lt;strong&gt;the same 60 deeds&lt;/strong&gt;, deed by deed:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;base, untrained&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;exactly right&lt;/td&gt;
&lt;td&gt;6 / 60 (10%, CI 4.7–20.1%)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60 / 60&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;wrong and unflagged&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deeds only this model got right&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;54&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every deed the base model got right, the fine-tune also got right, and it won the other 54. Paired sign test: &lt;strong&gt;p &amp;lt; 0.0001.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then the real exam: &lt;strong&gt;3,000 fresh deeds&lt;/strong&gt;, generated before I froze the validator and scored exactly once. &lt;strong&gt;2,988 exactly right. 99.6%.&lt;/strong&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%2F9tom7obszu940i715r1p.png" 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%2F9tom7obszu940i715r1p.png" alt="Where all 3,000 deeds ended up" width="800" height="301"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of the 12 imperfect outputs, &lt;strong&gt;10 were caught by parse and closure alone.&lt;/strong&gt; The other 2 are one ambiguity in my own generator: it writes &lt;code&gt;87 links&lt;/code&gt; as "87 link" in one style and "0.87 chain" in another, which is the same physical length. By physical length, the silent count is &lt;strong&gt;0&lt;/strong&gt;. I report both.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. New styles and units cost about 150 examples
&lt;/h3&gt;

&lt;p&gt;Held out on purpose, zero-shot, from the first model:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;unseen test&lt;/th&gt;
&lt;th&gt;exactly right&lt;/th&gt;
&lt;th&gt;wrong and unflagged&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;numbers spelled out in words&lt;/td&gt;
&lt;td&gt;85.6%&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;0&lt;/strong&gt; (14.4% flagged for review)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Texas varas&lt;/td&gt;
&lt;td&gt;every deed flagged&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Varas is the fun one. The model read every bearing and distance correctly but wrote the unit as &lt;code&gt;var&lt;/code&gt;, a token it had never seen, and the strict decoder rejected it. So &lt;strong&gt;everything was flagged and nothing wrong got through.&lt;/strong&gt; That is the safety net doing its job on a surprise.&lt;/p&gt;

&lt;p&gt;I didn't patch the decoder to accept each spelling the model improvised, because that would be fitting the test set. The real fix was data: &lt;strong&gt;150 examples each&lt;/strong&gt;, retrain, score on &lt;strong&gt;fresh&lt;/strong&gt; deeds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;fresh test set&lt;/th&gt;
&lt;th&gt;n&lt;/th&gt;
&lt;th&gt;exactly right&lt;/th&gt;
&lt;th&gt;wrong and unflagged&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;in distribution&lt;/td&gt;
&lt;td&gt;3,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.6%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 (0 by physical length)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;spelled-out numbers&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;99.6%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;varas&lt;/td&gt;
&lt;td&gt;250&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Onboarding a new style or unit is a 150-example, sub-dollar job. That's the workflow Tinker makes cheap enough to just do.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Make evaluation free the second time
&lt;/h3&gt;

&lt;p&gt;Evaluation was the bigger bill (&lt;strong&gt;$1.35&lt;/strong&gt; vs $2.46 for all training), so every sampled output is cached and the checks score from the cache. Improving the validator and re-scoring 3,000 deeds cost &lt;strong&gt;$0.&lt;/strong&gt; One deed through Tinker costs about &lt;strong&gt;$0.00015.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Rent the training. Keep the weights.
&lt;/h3&gt;

&lt;p&gt;I downloaded the &lt;strong&gt;369 MB adapter&lt;/strong&gt; and ran it with &lt;strong&gt;MLX on the Apple GPU&lt;/strong&gt; over a 4-bit Qwen3-8B base:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;150 of 150 deeds read exactly right, 0 flagged, median 7.5 s per deed.&lt;/strong&gt; M3 Pro, 18 GB, no network, no API key.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The whole bill
&lt;/h3&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%2Fx3bnmk6y3uelix7roc9l.png" 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%2Fx3bnmk6y3uelix7roc9l.png" alt="Where the $3.80 went" width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;item&lt;/th&gt;
&lt;th&gt;est. cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;baseline, no training&lt;/td&gt;
&lt;td&gt;$0.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;learning-curve runs&lt;/td&gt;
&lt;td&gt;$0.29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;first full run&lt;/td&gt;
&lt;td&gt;$1.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;final model (2,300 deeds, 3 epochs)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$1.15&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;all evaluation (4,000+ deeds)&lt;/td&gt;
&lt;td&gt;$1.35&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;everything on Tinker&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $3.80&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Token counts at Tinker's list prices.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Known edges (measured, not hidden)
&lt;/h2&gt;

&lt;p&gt;I'd rather you hear these from me, with numbers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The deeds are generated.&lt;/strong&gt; That's what made exact labels and a 3,000-deed fresh test possible, and it's why the held-out style and unit matter. The next step is running real recorded deeds through the same pipeline, which is why every real-world answer still ends in a human approve button.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The baseline is the plain base model&lt;/strong&gt;, not a heavily engineered one, and it was scored on 60 deeds to keep the bill low. That's why I paired it against the fine-tune on the same 60 and gave its confidence interval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clause checks look for &lt;code&gt;;&lt;/code&gt; or &lt;code&gt;thence&lt;/code&gt;&lt;/strong&gt; between calls. Where that structure is missing, they fall back to whole-text checks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Curves are chord-form&lt;/strong&gt; (chord bearing, length, radius, direction). Deflection angles and station/offset descriptions aren't supported yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's a drafting aid.&lt;/strong&gt; Not a substitute for a licensed surveyor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What went wrong on the way (and made it better):&lt;/strong&gt; my validator flagged &lt;em&gt;perfect&lt;/em&gt; answers until I ran it on the generator's own ground truth and fixed three reading bugs. Two silent errors slipped past closure at 500 deeds (a dropped arc-minute and a flipped curve direction), which is exactly why the independent second reader exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does open innovation matter?
&lt;/h2&gt;

&lt;p&gt;A closed API gives you a prompt box. Open weights gave me a &lt;strong&gt;steering wheel.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I could change the model, not just the prompt.&lt;/strong&gt; The untrained small model got 10%. A one-dollar LoRA got 99.6%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deeds are private.&lt;/strong&gt; They name people, parcels and mortgages. The weights run on the laptop that holds the file. Turn Wi-Fi off and it still works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No meter running.&lt;/strong&gt; After the one-time fine-tune, deed number one thousand costs electricity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nobody can deprecate it.&lt;/strong&gt; The base model, adapter and code sit on disk. A better open model next year is a training run, not a migration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I could look inside.&lt;/strong&gt; The varas failure and the label tie all exist because I could inspect every output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest caveat: training ran on Tinker's servers on generated deeds only. No real person's land record was ever sent anywhere, and at run time nothing leaves the laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  My agent session
&lt;/h2&gt;

&lt;p&gt;I built DeedReader with Claude Code as a pair, from a written plan with a cost estimate up front and a budget guard on every training job.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It read Tinker's docs before writing a line against the API, and wrote closure-math tests before any model touched the project.&lt;/li&gt;
&lt;li&gt;The baseline exposed a blind spot: many of the base model's &lt;em&gt;landmark names&lt;/em&gt; were wrong, and closure can't see that. So it built the per-sentence grounding check.&lt;/li&gt;
&lt;li&gt;It debugged its own validator against ground truth, and when varas failed it ran the real fix as an experiment on fresh data instead of patching around it.&lt;/li&gt;
&lt;li&gt;It kept a running cost log from the first job.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;&lt;strong&gt;Best Use of Tinker.&lt;/strong&gt; The LoRA fine-tune (pipelined forward/backward passes, loss-masked completions, per-epoch checkpoints), the baseline, the data-size learning curve, 4,000+ evaluated deeds and the adapter download behind the offline story all ran on Tinker. &lt;strong&gt;$1.15 for the final model, about $3.80 for everything.&lt;/strong&gt; Same base model, same prompt, same checks: &lt;strong&gt;10% (6/60) → 99.6% (2,988/3,000)&lt;/strong&gt;, and every deed the base model got right, the fine-tune got right too.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built solo, with Claude Code.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three epochs. $1.15. 10% became 99.6%.&lt;/strong&gt; If that sounds like a good trade, a ❤️ or 🦄 helps more people find it.&lt;/p&gt;

&lt;p&gt;What's the strangest phrase you've ever seen in a property deed? Mine so far is "to a white oak, thence along the run." Leave yours in the comments.&lt;/p&gt;

</description>
      <category>tinker</category>
      <category>hf26challenge</category>
      <category>devchallenge</category>
      <category>hacktoberfest</category>
    </item>
    <item>
      <title>A solution for all Ecom brand owners and marketing agencies helping ecom owners create video and image ads. Let me know your thoughts on it.</title>
      <dc:creator>Advik Divekar</dc:creator>
      <pubDate>Sat, 17 Oct 2026 12:07:19 +0000</pubDate>
      <link>https://dev.to/advikdivekar/a-solution-for-all-ecom-brand-owners-and-marketing-agencies-helping-ecom-owners-create-video-and-ohh</link>
      <guid>https://dev.to/advikdivekar/a-solution-for-all-ecom-brand-owners-and-marketing-agencies-helping-ecom-owners-create-video-and-ohh</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84" class="crayons-story__hidden-navigation-link"&gt;What if your whole marketing team fit on a laptop, and finished in 55 seconds?&lt;/a&gt;
    &lt;div class="crayons-article__cover crayons-article__cover__image__feed"&gt;
      &lt;iframe src="https://www.youtube.com/embed/uvYCVlKRKbU" title="What if your whole marketing team fit on a laptop, and finished in 55 seconds?"&gt;&lt;/iframe&gt;
    &lt;/div&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle Submission 💸&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/advikdivekar" class="crayons-avatar  crayons-avatar--l  "&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%2Fuser%2Fprofile_image%2F4162179%2F4f54da1f-781c-461b-8131-a914f2180e70.jpg" alt="advikdivekar profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/advikdivekar" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Advik Divekar
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Advik Divekar
                
                
              
              &lt;div id="story-author-preview-content-4862921" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/advikdivekar" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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%2Fuser%2Fprofile_image%2F4162179%2F4f54da1f-781c-461b-8131-a914f2180e70.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Advik Divekar&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 16&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84" id="article-link-4862921"&gt;
          What if your whole marketing team fit on a laptop, and finished in 55 seconds?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/hf26challenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;hf26challenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;50&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              33&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            17 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>What if your whole marketing team fit on a laptop, and finished in 55 seconds?</title>
      <dc:creator>Advik Divekar</dc:creator>
      <pubDate>Fri, 16 Oct 2026 14:09:27 +0000</pubDate>
      <link>https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84</link>
      <guid>https://dev.to/advikdivekar/what-if-your-whole-marketing-team-fit-on-a-laptop-and-finished-in-55-seconds-j84</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week2-2026-10-12"&gt;Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if your whole marketing team fit on a laptop, and finished in 55 seconds?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I used to run an ecommerce brand.&lt;/p&gt;

&lt;p&gt;In small ecommerce, marketing is everything, and it comes in two kinds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance marketing&lt;/strong&gt; is the ads you pay for. &lt;strong&gt;Organic marketing&lt;/strong&gt; is the posts, reels and listings you put out without paying for reach. Both run on a constant stream of fresh content. If it isn't live, you aren't selling.&lt;/p&gt;

&lt;p&gt;Every product meant listing copy stitched together from two or three AI chats, then ad copy, photo edits, images for the listing, and video ads. Every step in a different tool. Every handoff a copy and paste.&lt;/p&gt;

&lt;p&gt;It cost me in three ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time.&lt;/strong&gt; The gap between "I have a product" and "it's live" was where sales were lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cashflow.&lt;/strong&gt; A subscription for images, one for video, one for copy, one for editing. In a small business, tool bills quietly eat tight cashflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy.&lt;/strong&gt; My product details, my pricing and my workflow all sat inside other people's tools. None of it was ever private.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I watched my mom run into the same wall.&lt;/p&gt;

&lt;p&gt;My mom is a cosmetician. She sells skincare and beauty products, and she is very good at it. Her marketing is organic: Instagram and Facebook posts and reels.&lt;/p&gt;

&lt;p&gt;But one single image post took her &lt;strong&gt;3 to 4 hours&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Canva for the picture. CapCut or another editor for the video. ChatGPT or Claude for the caption, then copy, paste, "make it shorter", copy, paste again. Then the post itself, on every platform she sells on. A reel could take days.&lt;/p&gt;

&lt;p&gt;On top of that, she kept switching between ChatGPT, Claude, Higgsfield and whatever other AI tool she could find, often across several accounts to keep going. That irritated her a lot.&lt;/p&gt;

&lt;p&gt;Those are hours she should have spent with customers. Instead she was working as a part-time designer and video editor.&lt;/p&gt;

&lt;p&gt;Different business, same trap: too many tools, too much attention, and your product details sent to places you don't control.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Mochi&lt;/strong&gt;: one product photo and a few true facts become studio photos, an image deck, a 10-second video and copy for every platform you sell on. It runs on open models on your own computer, so nothing about your product goes to anyone else's server.&lt;/p&gt;

&lt;p&gt;I built it for my mom and for sellers like me, and I tried it on a real brand to see if it works. More on that session is further down.&lt;/p&gt;

&lt;p&gt;Here it is in action:&lt;/p&gt;

&lt;p&gt;Here's the proof. A skincare brand, Velora, dropped &lt;strong&gt;three photos of a face cleanser&lt;/strong&gt; into Mochi. This is the screen when it finished:&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%2F1wnzvi3e798iq27hexcm.png" 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%2F1wnzvi3e798iq27hexcm.png" alt="The kit is ready, built in 55 seconds" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fifty-five seconds.&lt;/strong&gt; And this is what it had made.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;9 studio photos&lt;/strong&gt; on a designed backdrop:&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%2Fdp1fqu0zp56ps9axxzci.png" 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%2Fdp1fqu0zp56ps9axxzci.png" alt="Studio photos" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A 5-slide image deck&lt;/strong&gt; (this is slide 3 of 5):&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%2Fu6anojd8xhcd5ztm5s90.png" 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%2Fu6anojd8xhcd5ztm5s90.png" alt="Image deck" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A 10-second vertical video ad&lt;/strong&gt;, with text cards built from the copy:&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%2F0b2jvhsxtk6wj08mi7uf.png" 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%2F0b2jvhsxtk6wj08mi7uf.png" alt="Video ad" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Listing copy, tags and an SEO title&lt;/strong&gt;, each one editable:&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%2Fh98bssd0knx3ia2tqn4y.png" 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%2Fh98bssd0knx3ia2tqn4y.png" alt="Keywords, tags and SEO title" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No agency. No stack of subscriptions. No uploading your product to someone else's server. Just open models running on one computer.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Mochi turns that whole chain of tools, tabs and copy-pasting into three taps.&lt;/strong&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%2F334lp6kcdsst2yficlsa.png" 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%2F334lp6kcdsst2yficlsa.png" alt="Mochi landing page" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Studio photos.&lt;/strong&gt; Your phone photo, cut out and placed on a designed backdrop, and the product is never regenerated, so it stays your real product&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;An image deck.&lt;/strong&gt; Slides ready for a feed or a catalog&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A 10-second vertical video.&lt;/strong&gt; Camera moves and text cards built from your own copy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Platform copy.&lt;/strong&gt; Listing, social, Pinterest and a video brief, written for each place you sell&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing I care about more than anything: &lt;strong&gt;Mochi checks its own copy for things you never told it.&lt;/strong&gt; Models do invent claims, so every kit is checked by plain code. Missing facts are listed back to you ("Not provided, so left out of the copy"), and anything the copy says that isn't in your facts is flagged before you post.&lt;/p&gt;

&lt;p&gt;For a skincare seller, that matters. "Reduces wrinkles" is a legal claim, not a style choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use it
&lt;/h3&gt;

&lt;p&gt;Five steps, about two minutes of your time. The screenshots are from a real run on a phone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The shortcut:&lt;/strong&gt; add a photo, and if Mochi's guesses from it look right, tap &lt;strong&gt;Looks right: generate now&lt;/strong&gt;. Everything below is the long way, for when you want control.&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%2Fob6bdf92fm7q0i1ehi20.png" 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%2Fob6bdf92fm7q0i1ehi20.png" alt="The shortcut: Looks right, generate now" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1. Add your photos.&lt;/strong&gt;&lt;br&gt;
Tap &lt;strong&gt;Take photo&lt;/strong&gt; or &lt;strong&gt;Add more&lt;/strong&gt;. You can add up to 5. The first photo is your &lt;strong&gt;Main&lt;/strong&gt; one, and it also opens and closes your video. Different angles make a better video and deck. A clear photo on a plain background works best. Mochi starts reading them right away.&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%2Fnikyvvkwuaorwlpkcdc1.png" 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%2Fnikyvvkwuaorwlpkcdc1.png" alt="Step 1: add photos" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2. Check what Mochi found.&lt;/strong&gt;&lt;br&gt;
Mochi reads the label on your product and offers the text as notes you can tap to add. Fields it filled in are tagged &lt;strong&gt;"From photo, check it"&lt;/strong&gt;. Fill in what's missing, like price and features. Only add what is true. Blank fields are flagged as missing, never guessed.&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%2F0tkytsi84mawrwybn2sz.png" 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%2F0tkytsi84mawrwybn2sz.png" alt="Step 2: text Mochi read from the label" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3. Pick your style.&lt;/strong&gt;&lt;br&gt;
Choose where you sell (Instagram, Facebook, Pinterest, Etsy, Shopify), a tone (from Straightforward to Luxury), a goal (Drive sales, Brand awareness, Gift appeal or Explain features), and a writing speed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt; takes about 20 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best quality&lt;/strong&gt; uses a larger model and takes about a minute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then pick a backdrop for your photos and video: Premium studio, UGC-style, Minimal, Warm and cozy, or Bold and colorful. Tap &lt;strong&gt;Generate kit&lt;/strong&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%2Fvwlfl7t1wz2m4q0eeyx9.png" 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%2Fvwlfl7t1wz2m4q0eeyx9.png" alt="Step 3: tone, goal and writing speed" width="800" height="1351"&gt;&lt;/a&gt;&lt;br&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%2Fx488hyomz9e7cinuhkwz.png" 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%2Fx488hyomz9e7cinuhkwz.png" alt="Step 3: choose a backdrop" width="800" height="991"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4. Let it build.&lt;/strong&gt;&lt;br&gt;
You see real progress, step by step: writing copy, building studio photos and video, adding text to the video. You can leave the page. It keeps running.&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%2F20jf7dpbnehvw76pjg2v.png" 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%2F20jf7dpbnehvw76pjg2v.png" alt="Step 4: building the kit" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5. Review, edit and share.&lt;/strong&gt;&lt;br&gt;
Your kit has four tabs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Overview:&lt;/strong&gt; the video, the image deck, and a "double-check before posting" list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy:&lt;/strong&gt; listing, social, Pinterest and a video brief. Change the tone or refresh any section.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Photos:&lt;/strong&gt; your studio photos, ready to download&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share:&lt;/strong&gt; download or share the kit&lt;/li&gt;
&lt;/ul&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%2Flb32nwsgr7sldg08smts.png" 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%2Flb32nwsgr7sldg08smts.png" alt="Step 5: the four tabs, shown on a sample product" width="780" height="1688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The finished result of a real run is at the top of this post.&lt;/p&gt;

&lt;p&gt;Nothing posts on its own. The only thing Mochi can send anywhere is a Shopify &lt;strong&gt;draft&lt;/strong&gt;, and only when you tap it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/uvYCVlKRKbU" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Every page of the web app
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Landing: hero&lt;/strong&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%2Famd6aglqw91i6bfultjj.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%2Famd6aglqw91i6bfultjj.jpg" alt="Landing: hero" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: the interactive studio&lt;/strong&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%2Fnfb9xes4rfi38wmck6rd.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%2Fnfb9xes4rfi38wmck6rd.jpg" alt="Landing: the interactive studio" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: written the way each channel works&lt;/strong&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%2Fc1puj1ug0wb7j6ppirel.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%2Fc1puj1ug0wb7j6ppirel.jpg" alt="Landing: written the way each channel works" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: your next ad starts with a photo&lt;/strong&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%2Ffai28wirp1eclromyy1m.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%2Ffai28wirp1eclromyy1m.jpg" alt="Landing: your next ad starts with a photo" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: upload once, get the lot&lt;/strong&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%2F6s18rq4dkeb1av1izyfc.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%2F6s18rq4dkeb1av1izyfc.jpg" alt="Landing: upload once, get the lot" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: same facts, your voice&lt;/strong&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%2Fq9a4uaiuk8k5hevz85ri.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%2Fq9a4uaiuk8k5hevz85ri.jpg" alt="Landing: same facts, your voice" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: three steps, about a minute&lt;/strong&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%2Fwzhvag4wlkv5r76m6l4d.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%2Fwzhvag4wlkv5r76m6l4d.jpg" alt="Landing: three steps, about a minute" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Landing: call to action&lt;/strong&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%2Fwklmdqj7uw5zq7i02ir3.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%2Fwklmdqj7uw5zq7i02ir3.jpg" alt="Landing: call to action" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create: start&lt;/strong&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%2F2u1wyob3fh2k3z8ryd6a.png" 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%2F2u1wyob3fh2k3z8ryd6a.png" alt="Create: start" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create step 1: photos, and the text Mochi read from them&lt;/strong&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%2F8z55zjlv5yzmr9ervp59.png" 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%2F8z55zjlv5yzmr9ervp59.png" alt="Create step 1: photos, and the text Mochi read from them" width="800" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create step 2: product facts&lt;/strong&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%2F6304jsjo7byil265uwux.png" 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%2F6304jsjo7byil265uwux.png" alt="Create step 2: product facts" width="800" height="1042"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create step 3: tone, goal, speed and visual style&lt;/strong&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%2Ftxvu2r39wjbshtmvi7oo.png" 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%2Ftxvu2r39wjbshtmvi7oo.png" alt="Create step 3: tone, goal, speed and visual style" width="800" height="774"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result: overview with video ad and image deck&lt;/strong&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%2Fe7nqdl3s5oywk7vlbot5.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%2Fe7nqdl3s5oywk7vlbot5.jpg" alt="Result: overview with video ad and image deck" width="800" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result: copy for every channel&lt;/strong&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%2F34yxfu5eziokepe6yqwm.png" 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%2F34yxfu5eziokepe6yqwm.png" alt="Result: copy for every channel" width="800" height="1159"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result: studio photos, white background and cut-outs&lt;/strong&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%2Fraw.githubusercontent.com%2Fadvikdivekar%2Fsellcraft%2Fmain%2Fdocs%2Fimages%2Fweb%2F08-result-photos.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%2Fraw.githubusercontent.com%2Fadvikdivekar%2Fsellcraft%2Fmain%2Fdocs%2Fimages%2Fweb%2F08-result-photos.jpg" alt="Result: studio photos, white background and cut-outs" width="800" height="1579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Result: share and export&lt;/strong&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%2Famd0krt31e7aayh4rbb3.png" 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%2Famd0krt31e7aayh4rbb3.png" alt="Result: share and export" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stores&lt;/strong&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%2Fcpxiim25505tl93604tm.png" 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%2Fcpxiim25505tl93604tm.png" alt="Stores" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&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/advikdivekar" rel="noopener noreferrer"&gt;
        advikdivekar
      &lt;/a&gt; / &lt;a href="https://github.com/advikdivekar/sellcraft" rel="noopener noreferrer"&gt;
        sellcraft
      &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;Mochi&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Your product. Your story. Ready to sell.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Small-seller marketing studio: upload a product photo, enter a few verified facts, pick a platform / tone / style / goal, and get platform-specific listing copy plus a video-ad brief. Copy is written by an &lt;strong&gt;open-weight model (Gemma) running locally through Ollama&lt;/strong&gt;, so product data never leaves your machine. See &lt;a href="https://github.com/advikdivekar/sellcraft/plan.md" rel="noopener noreferrer"&gt;&lt;code&gt;plan.md&lt;/code&gt;&lt;/a&gt; for the full design.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Working end to end: facts and photos → Gemma copy → studio photos, image deck and a 10-second video → export or Shopify draft. A LoRA fine-tune on Tinker, an independent Gemma judge and Sentry tracing are in; see &lt;a href="https://github.com/advikdivekar/sellcraft/docs/RESULTS.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/RESULTS.md&lt;/code&gt;&lt;/a&gt; for the measured numbers and &lt;a href="https://github.com/advikdivekar/sellcraft/docs/DECISIONS.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/DECISIONS.md&lt;/code&gt;&lt;/a&gt; for why things are the way they are.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What it makes&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;From up to &lt;strong&gt;5 photos&lt;/strong&gt; and a few facts (the app measures each photo, flags blur/low-res/dark shots, cleans the cut-out, and picks a backdrop that makes your product…&lt;/p&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/advikdivekar/sellcraft" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Backend: FastAPI, SQLite, Pydantic. Frontend: Next.js 16 and React 19. 135 backend tests pass. Every number in this post can be reproduced from the files in &lt;code&gt;backend/finetune/results/&lt;/code&gt;, with the commands in &lt;a href="https://github.com/advikdivekar/sellcraft/blob/main/docs/RESULTS.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/RESULTS.md&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Two lanes run at the same time&lt;/strong&gt;: one for visuals and one for language. They meet at the deck and the video, which need the finished copy. The page polls the job every 1.5 seconds and shows real progress and partial copy as it arrives.&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%2Fadjgrqtq99dub8ofl7mi.png" 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%2Fadjgrqtq99dub8ofl7mi.png" alt="System architecture" width="800" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every model has one job and one strict contract.&lt;/strong&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%2Fdq9z6kh4t26q2ciee7y5.png" 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%2Fdq9z6kh4t26q2ciee7y5.png" alt="Models and their jobs" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two choices worth explaining:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The video is not AI-generated.&lt;/strong&gt; It's image processing plus FFmpeg, so the product in the video is &lt;em&gt;your&lt;/em&gt; product, not a regenerated lookalike. (I do denoise, upscale and retouch it.) Generative video tends to repaint the product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The checker is plain code, not a second model.&lt;/strong&gt; A model can talk itself into anything. A word list and a number check can't.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The copy&lt;/strong&gt; is split into parallel parts (four core parts plus one per platform), each forced into a JSON schema. A bad call is retried once, and plain code then checks for forbidden words, invented numbers and unsupported claims.&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%2Fieh6fc12xbi2rjqff00g.png" 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%2Fieh6fc12xbi2rjqff00g.png" alt="Copy pipeline" width="800" height="748"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Photos are read, never trusted.&lt;/strong&gt; Up to 5 photos are shrunk to 768 px and read under strict rules. What comes back is only a suggestion, marked "From photo, check it".&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%2F63mev0vvk32tueerxi7m.png" 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%2F63mev0vvk32tueerxi7m.png" alt="Photo reading" width="799" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Studio shots:&lt;/strong&gt; measure, cut out, refine the product's pixels, fix the tone, pick a backdrop from what the photo shows, compose. If the cutout looks wrong, it falls back to a framed photo instead of a bad cutout.&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%2F2m7v0j05sj3mgs91zt4z.png" 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%2F2m7v0j05sj3mgs91zt4z.png" alt="Studio imagery pipeline" width="800" height="685"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The video:&lt;/strong&gt; at least 4 shots rendered with FFmpeg (up to 3 at once), 0.4 s crossfades, text cards from your edited copy, checked to be 10 seconds at 1080x1920. Edit the copy and only the text layer re-renders.&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%2Frydx2bgqvnduxn1h52yw.png" 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%2Frydx2bgqvnduxn1h52yw.png" alt="Video pipeline" width="799" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's fast.&lt;/strong&gt; My first version took 90 to 145 seconds for one big generation on a laptop.&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%2Fousp5imd7cvkf78zet3v.png" 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%2Fousp5imd7cvkf78zet3v.png" alt="Before and after: what the Fast default and parallel parts bought" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Change&lt;/th&gt;
&lt;th&gt;Before&lt;/th&gt;
&lt;th&gt;After&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Fast mode (Gemma 4B) as the default&lt;/td&gt;
&lt;td&gt;copy 53 s&lt;/td&gt;
&lt;td&gt;copy 14 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Split the kit into parallel parts&lt;/td&gt;
&lt;td&gt;one 12B call, 90 to 145 s&lt;/td&gt;
&lt;td&gt;45 to 60 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Run both lanes together&lt;/td&gt;
&lt;td&gt;the sum of both&lt;/td&gt;
&lt;td&gt;the slower lane, plus a few seconds&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A four-photo kit went from about &lt;strong&gt;100 s to about 18 s&lt;/strong&gt; in Fast mode. The trade-off: the 4B model gets more claims flagged than the 12B, the post-check still catches them, and Best quality (about 57 s) is one switch away.&lt;/p&gt;

&lt;p&gt;The fine-tune, the evaluation and the Sentry setup each have their own section under Prize Categories.&lt;/p&gt;

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

&lt;p&gt;Go back to my two stories. In both, the real cost was not money alone. It was &lt;strong&gt;control&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Your product details stay yours.&lt;/strong&gt; Pricing, ingredients, launch plans. With open models running locally, the data never leaves your machine. There's no "we don't train on your data" to trust.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. No per-kit fee.&lt;/strong&gt; Every kit costs electricity. A seller can run it five times, try three tones, and never wonder if it's "worth" the credits. When cashflow is tight, that matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. I could change the model, not just the prompt.&lt;/strong&gt; I fine-tuned a small open model to follow one rule: &lt;em&gt;don't invent claims&lt;/em&gt;. Prompting alone left the 4B model at 23% clean kits. Training took it to 88%. You can't do that to a closed model, or download what you trained.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. I could look inside and measure.&lt;/strong&gt; I tested the fine-tune against an independent judge model, not just my own checker. With a closed API I'd have one number and no way to question it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. One setting swaps the model.&lt;/strong&gt; Fast or Best quality is a single switch between two open Gemma models. The next Gemma release is a one-line change.&lt;/p&gt;

&lt;p&gt;The honest limit: open models need a computer that can run them. I wrote the local setup into the README.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;I built Mochi with Claude Code, and every session is recorded with &lt;strong&gt;Entire&lt;/strong&gt;. &lt;a href="https://github.com/advikdivekar/sellcraft/blob/main/docs/DECISIONS.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/DECISIONS.md&lt;/code&gt;&lt;/a&gt; lists 19 decisions, each with its reason, its commit and its Entire checkpoint, so you can read the conversation behind any choice. More in the Entire section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  My First User
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Velora&lt;/strong&gt;, a skincare brand, ran its &lt;strong&gt;Sensicontrol Face Cleanser&lt;/strong&gt; through Mochi on a phone, on &lt;strong&gt;16 October 2026&lt;/strong&gt;. The phone reached my computer over a Cloudflare tunnel, so for this demo the photos passed through Cloudflare. In normal use everything stays on the machine. I have the screen recording. Here is what happened, taken only from what is on screen.&lt;/p&gt;

&lt;p&gt;I don't have a written quote from them, so I'm not putting words in their mouth. What I do have is the recording, and it shows what they actually did.&lt;/p&gt;

&lt;p&gt;They followed the five steps above (the screenshots for steps 1 to 4 are from their session): three photos of the bottle, the label read off it, a persuasive tone, Best quality writing, Pinterest as the platform, and the warm and cozy backdrop.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What came out&lt;/strong&gt; is shown at the top of this post: the finished kit in 55 seconds, the studio photos, the deck, the video and the copy. It was built on Best quality, with three photos, by a Gemma 3 12B model running on my own computer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The part I care about most.&lt;/strong&gt; Mochi told them what it had left out, and what it had written that they never said:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Not provided, so left out of the copy":&lt;/strong&gt; dimensions, verified benefits, target audience, care instructions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Double-check before posting":&lt;/strong&gt; &lt;em&gt;Not in your facts: "available now". Remove it unless it's true.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"About your photos":&lt;/strong&gt; it skipped the close-up slide because the photo didn't have enough pixels on the product&lt;/li&gt;
&lt;/ul&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%2Fiwarsrxu8qucbnk18zvt.png" 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%2Fiwarsrxu8qucbnk18zvt.png" alt="Mochi lists what it left out and what to double-check" width="800" height="1351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The kit was five slides, nine studio photos, a 10-second video, and copy for one platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned from watching.&lt;/strong&gt; All of this is from the recording:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;They changed their mind before generating.&lt;/strong&gt; They started with the Friendly tone, Instagram and Fast, then switched to Persuasive, Pinterest and Best quality. The choices clearly matter to people, so I'm glad nothing is locked in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;They left several facts blank, and the copy respected that.&lt;/strong&gt; Target audience, dimensions, verified benefits and care instructions were never filled in, so Mochi left them out and said so, instead of guessing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best quality costs time.&lt;/strong&gt; The form says Fast takes about 20 seconds and Best quality about a minute. They chose the slower one, and it took 55.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I'm entering &lt;strong&gt;Tinker, Gemma, Sentry Agent Tracing and Entire&lt;/strong&gt;. Each section covers what I used, why, what it was meant to fix, and what I found.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Use of Tinker
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I used it for.&lt;/strong&gt; I fine-tuned &lt;strong&gt;Qwen3.5-4B with a LoRA adapter&lt;/strong&gt; on Tinker to write marketing copy that follows one rule: &lt;em&gt;never invent a claim the seller didn't give.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Tinker.&lt;/strong&gt; Prompting a small model to follow that rule didn't work. Untuned Qwen3.5-4B produced a clean kit only 18% of the time. I wanted to change the model, not keep rewording the prompt, and Tinker let me train without running my own GPU servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it worked.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A big teacher model, &lt;strong&gt;Qwen3.5-397B-A17B&lt;/strong&gt;, writes and revises kits on Tinker&lt;/li&gt;
&lt;li&gt;My checker and an independent judge (Gemma 12B, a different model family) reject any kit with an invented claim, number or forbidden word&lt;/li&gt;
&lt;li&gt;The teacher revises with the checker's findings, at most 2 rounds&lt;/li&gt;
&lt;li&gt;Only kits that pass &lt;strong&gt;both&lt;/strong&gt; the checker and the judge become training data (zero hard violations)&lt;/li&gt;
&lt;li&gt;A small student is trained on those: rank 32, 3 epochs, 319 examples, learning rate 2e-4&lt;/li&gt;
&lt;li&gt;A held-out set of 60 products, which the training code refuses to read, tests it&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing cost &lt;strong&gt;$5.41 of the $10 credit&lt;/strong&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%2Fqw9o3qzio5ymvhtbnc0r.png" 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%2Fqw9o3qzio5ymvhtbnc0r.png" alt="Fine-tuning pipeline" width="800" height="649"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full detailed version (tap to open it full size and zoom in):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/advikdivekar/sellcraft/main/docs/images/diagrams/finetune.png" rel="noopener noreferrer"&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%2F01lc40ivo9wqpty6wqp5.png" alt="Detailed fine-tuning pipeline" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results&lt;/strong&gt; (60 held-out synthetic products, one checker):&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%2F5uuhupbw7nb90ii5tark.png" 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%2F5uuhupbw7nb90ii5tark.png" alt="Evaluation results" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full detailed version (tap to open it full size and zoom in):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/advikdivekar/sellcraft/main/docs/images/diagrams/evaluation.png" rel="noopener noreferrer"&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%2F00hzeo2inen8hff27hkx.png" alt="Detailed evaluation" width="799" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's a 4B model, a third of Gemma 12B's size, producing nearly twice as many clean kits, and about 10 times faster (4.9 s against 48.7 s per kit, though v2 runs on Tinker's cloud and Gemma on my laptop).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The honest result on the judge.&lt;/strong&gt; v2 halves the untuned model's flags (0.43 to 0.20), but the confidence intervals overlap, and Gemma 12B is lower still at 0.13. With 30 kits per model I can't claim more than that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limits I'm stating on purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The test set is synthetic, and the checker also filtered the training data&lt;/li&gt;
&lt;li&gt;The fine-tune runs on Tinker, so its inputs leave the machine. The app's default (Gemma via Ollama) stays local.&lt;/li&gt;
&lt;li&gt;The fine-tune is &lt;strong&gt;not&lt;/strong&gt; in the app's path yet. I haven't exported it to GGUF for Ollama.&lt;/li&gt;
&lt;li&gt;Hosted cost is about $3 per 1,000 kits, estimated from token counts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I learned.&lt;/strong&gt; A small model trained on the right examples can follow a narrow rule better than a larger model that's only prompted. The checker and the judge decide which examples count, so they matter as much as the training run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Use of Gemma
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I used it for.&lt;/strong&gt; Gemma does three jobs inside Mochi, all through Ollama on the seller's own computer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The copy writer.&lt;/strong&gt; Gemma 3 4B for Fast, Gemma 3 12B for Best quality&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The photo reader.&lt;/strong&gt; It reads up to 5 photos and returns suggested facts, each tagged "From photo, check it"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The independent judge.&lt;/strong&gt; Gemma 3 12B, a different family from the Qwen teacher, reviews kits in my evaluation&lt;/li&gt;
&lt;/ol&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%2Fdq9z6kh4t26q2ciee7y5.png" 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%2Fdq9z6kh4t26q2ciee7y5.png" alt="Models and their jobs" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full detailed version (tap to open it full size and zoom in):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/advikdivekar/sellcraft/main/docs/images/diagrams/models.png" rel="noopener noreferrer"&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%2Fd93ec2onoyygwvql0xvs.png" alt="Detailed models and jobs" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full detailed version (tap to open it full size and zoom in):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/advikdivekar/sellcraft/main/docs/images/diagrams/photo-reading.png" rel="noopener noreferrer"&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%2F1q0clzedinjlx8dhp6wy.png" alt="Detailed photo reading" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Gemma.&lt;/strong&gt; It's open-weight, it runs on one machine, and it can be held to a JSON schema. That matters here: the seller's facts shouldn't leave their computer, and every part of a kit must come back as strict, checkable JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it was meant to fix.&lt;/strong&gt; The cost and privacy problems from my ecommerce days: no per-kit fee, and nothing sent to anyone else's server.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Both sizes run the same prompt and the same checker, so I could compare them fairly: &lt;strong&gt;23% clean kits on 4B and 45% on 12B&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Speed is the trade-off. Fast (4B) builds a four-photo kit in about &lt;strong&gt;18 s&lt;/strong&gt;, Best quality (12B) in about &lt;strong&gt;57 s&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;As the judge, Gemma 12B had the fewest flags of any model I tested (0.13 per kit)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I learned.&lt;/strong&gt; Two things. First, the model size is a user choice, not a technical one, so I made it a switch on the form. Second, the judge is Gemma, so it may be lenient toward Gemma's own writing. That bias favours the Gemma rows and works &lt;em&gt;against&lt;/em&gt; my fine-tune's claim, so it can't be inflating my result.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Use of Sentry Agent Tracing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I used it for.&lt;/strong&gt; Tracing every model call and every job, without Sentry ever seeing a seller's product facts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this was the hard part.&lt;/strong&gt; A marketing tool handles a seller's most private material: product details, prices, plans. Sending prompts to a tracing service would break the promise the whole product makes. So the question was not "can I trace this", it was "can I trace this and prove nothing private leaks".&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%2Fvbj0bv9h45k4irxmwnq4.png" 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%2Fvbj0bv9h45k4irxmwnq4.png" alt="What Sentry sees, and what it never sees" width="800" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full detailed version (tap to open it full size and zoom in):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/advikdivekar/sellcraft/main/docs/images/diagrams/observability.png" rel="noopener noreferrer"&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%2Fnf1io1ghn7hv68135idc.png" alt="Detailed observability" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each model call is a &lt;strong&gt;&lt;code&gt;gen_ai.chat&lt;/code&gt; span&lt;/strong&gt;, with the model, token counts and latency&lt;/li&gt;
&lt;li&gt;Each generation job is a transaction&lt;/li&gt;
&lt;li&gt;Each flagged claim is an issue (which rule fired, and how many)&lt;/li&gt;
&lt;li&gt;Each seller report is an event. The report button sends a section name and a fixed reason code, &lt;strong&gt;never free text&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The flagged claims come from the copy post-check, so each issue is a rule the code caught, not a model's opinion.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The full detailed version (tap to open it full size and zoom in):&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://raw.githubusercontent.com/advikdivekar/sellcraft/main/docs/images/diagrams/copy.png" rel="noopener noreferrer"&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%2Fc7u90lmblbff86utm46s.png" alt="Detailed copy pipeline and post-check" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it never sees.&lt;/strong&gt; An allow-list scrubber removes everything that is not on the list of allowed metadata. Product facts, copy, photos and prompts can't pass it.&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%2F8n53vtd4hp0wq0m3p0do.png" 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%2F8n53vtd4hp0wq0m3p0do.png" alt="What stays local and what can leave" width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I know it works.&lt;/strong&gt; A canary test pushes a unique fake product through every input path of the real app, then fails if that marker shows up in &lt;em&gt;any&lt;/em&gt; outgoing Sentry payload. It's in &lt;code&gt;tests/test_tracing.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results and honesty.&lt;/strong&gt; The scrubber and the canary test are in place and pass. I am &lt;strong&gt;not&lt;/strong&gt; claiming Sentry has caught a real production incident, because it hasn't. Mochi has had one real user session, not production traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I learned.&lt;/strong&gt; Making tracing safe was a bigger design question than turning it on. The allow-list approach (what's permitted, not what's blocked) is the one that survives new fields being added later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Use of Entire
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I used it for.&lt;/strong&gt; To record how Mochi was built, so a reader can see &lt;em&gt;why&lt;/em&gt; the code is the way it is, not just what it does.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why.&lt;/strong&gt; Most repos show a result. For a project where I changed my mind several times, the changes are the story. A privacy rule, a new default and a safety check each have a reason that a commit message can't hold.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What came of it.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;About 113 checkpoints&lt;/strong&gt; of Claude Code sessions, pushed to the repo&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/advikdivekar/sellcraft/blob/main/docs/DECISIONS.md" rel="noopener noreferrer"&gt;&lt;code&gt;docs/DECISIONS.md&lt;/code&gt;&lt;/a&gt;: &lt;strong&gt;19 numbered decisions&lt;/strong&gt;, each with the reason, the commit and the Entire checkpoint ID&lt;/li&gt;
&lt;li&gt;Anyone can run &lt;code&gt;entire checkpoint explain &amp;lt;id&amp;gt;&lt;/code&gt; in a clone and read the prompts, files and reasoning behind a decision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The most useful example.&lt;/strong&gt; Decision #11 records why Sentry only ever gets metadata, and how the scrubber enforces it. That kind of reasoning normally disappears. Here it is written down, with the conversation that led to it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Honest limit.&lt;/strong&gt; Checkpoints from before Entire was enabled were imported from local history and matched by time. They show the conversation a commit came out of, not a one-to-one record.&lt;/p&gt;




&lt;p&gt;If you sell something and make your own content, I'd love to hear what's missing. Tell me in the comments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Built solo, with Claude Code.&lt;/em&gt;&lt;/p&gt;

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