<?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: Moin105</title>
    <description>The latest articles on DEV Community by Moin105 (@moin105).</description>
    <link>https://dev.to/moin105</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%2F859116%2Fc8eb2ebd-7b0b-4ce4-a7cb-f0ed3b4486fc.jpeg</url>
      <title>DEV Community: Moin105</title>
      <link>https://dev.to/moin105</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/moin105"/>
    <language>en</language>
    <item>
      <title>A 4B model on my computer drafts freelance quotes. I tested it on 8 real client briefs.</title>
      <dc:creator>Moin105</dc:creator>
      <pubDate>Fri, 16 Oct 2026 06:54:51 +0000</pubDate>
      <link>https://dev.to/moin105/a-4b-model-on-my-computer-drafts-freelance-quotes-i-tested-it-on-8-real-client-briefs-19lc</link>
      <guid>https://dev.to/moin105/a-4b-model-on-my-computer-drafts-freelance-quotes-i-tested-it-on-8-real-client-briefs-19lc</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;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;A freelancer gets a vague client brief, guesses the hours, and finds out three weeks later the guess was wrong. briefquote makes that guess less of a guess, and the brief never leaves your computer.&lt;/p&gt;

&lt;p&gt;It splits the work between two open models. Gemma (&lt;code&gt;gemma3:4b&lt;/code&gt;, running locally through Ollama) reads the messy prose and extracts a structured scope: project type, deliverables, integrations, a 1 to 5 complexity rating, plus the questions to ask the client and the risks to price in. Six of those fields become one table row. TabPFN, a pretrained model for small tables, learns from your own past jobs and turns that row into an hours range, a price and an on-time probability. You get a Markdown quote draft to review before it goes out.&lt;/p&gt;

&lt;p&gt;On 8 real client briefs it returned valid output every time, and 3 were usable as a first draft without major edits. Most of this post is about that gap.&lt;/p&gt;

&lt;p&gt;Who would pay: freelancers who would rather not paste a client's brief into a hosted chatbot. Nobody has paid yet.&lt;/p&gt;

&lt;p&gt;One disclosure first: the demo's job history is 30 synthetic jobs, so its hours and prices show the pipeline working, not real-world accuracy. Every Gemma output in this post comes from a real run.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxyvlxi50usfh7pstj00.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmxyvlxi50usfh7pstj00.gif" alt="briefquote web UI: a real gemma3:4b run on the SaaS sample brief" width="800" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A real &lt;code&gt;gemma3:4b&lt;/code&gt; run on a CPU-only machine. The wait (about a minute) is shortened; the elapsed counter is genuine. Why the on-time figure shows 5% is explained in "The estimator" below.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Try it in your browser, nothing to install:&lt;/strong&gt; &lt;a href="https://briefquote-replay.vercel.app" rel="noopener noreferrer"&gt;briefquote replay&lt;/a&gt;. Pick one of three sample briefs to see real output. Nothing on the page calls a model; only the hourly-rate arithmetic recalculates. Gemma's output varies between runs: the replay shows 66.8 h for the SaaS brief, the GIF run 79.1 h, and another run 59.2 h.&lt;/p&gt;

&lt;p&gt;The real tool is a local web UI (&lt;code&gt;briefquote serve&lt;/code&gt;) bound to 127.0.0.1 with no external requests. Paste a brief, set your rate, and copy the Markdown quote.&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/Moin105" rel="noopener noreferrer"&gt;
        Moin105
      &lt;/a&gt; / &lt;a href="https://github.com/Moin105/briefquote" rel="noopener noreferrer"&gt;
        briefquote
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Local scope-and-quote tool for freelancers: Gemma via Ollama extracts a scope from a client brief, TabPFN estimates hours and price. DEV Hacktoberfest Open-Source AI Challenge Week 2.
    &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;briefquote&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/Moin105/briefquote/actions/workflows/tests.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/Moin105/briefquote/actions/workflows/tests.yml/badge.svg" alt="tests"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Live replay of real runs, nothing to install: &lt;a href="https://briefquote-replay.vercel.app" rel="nofollow noopener noreferrer"&gt;https://briefquote-replay.vercel.app&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Quote from a client brief without the brief leaving your laptop. Paste a client brief, and briefquote uses an open-weight model (Gemma, running locally through Ollama) to extract a structured scope as JSON: deliverables, tech stack, complexity, integrations, unknowns to ask the client, and risk flags.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why open-weight&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; client briefs often contain confidential business details. Nothing is sent to a third-party API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero per-call cost:&lt;/strong&gt; quote as many briefs as you like.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works offline:&lt;/strong&gt; once the model is pulled, no internet is needed.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Status&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Day 1:&lt;/strong&gt; brief-to-scope extraction. Done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Day 2:&lt;/strong&gt; TabPFN-based hour and price estimator trained on your past jobs (&lt;code&gt;data/past_jobs.csv&lt;/code&gt; is a &lt;strong&gt;synthetic&lt;/strong&gt; example dataset, not real client work; see &lt;code&gt;data/README.md&lt;/code&gt;), plus a client-ready Markdown quote. Done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Day 3:&lt;/strong&gt; local web UI (&lt;code&gt;briefquote serve&lt;/code&gt;). Done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TabPFN path:&lt;/strong&gt; verified on real model weights on…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Moin105/briefquote" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;MIT licensed. 76 tests run without Ollama, and CI runs them on Windows and Linux with Python 3.11 to 3.13. The one real-weights TabPFN test needs a Prior Labs key, so CI skips it; I ran it locally.&lt;/p&gt;

&lt;p&gt;Started October 14, 2026, inside the challenge window. Claude Code agents wrote the implementation; I directed and verified it, including running the real models.&lt;/p&gt;

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

&lt;p&gt;The pipeline extracts a scope from the brief, estimates hours and price, and renders the quote. Extraction is where a 4B model needs the most help.&lt;/p&gt;

&lt;p&gt;The JSON schema goes to Ollama in the &lt;code&gt;format&lt;/code&gt; field, constraining decoding to the right shape. Pydantic validates the result, and on failure the error goes back to the model once.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ScopeExtraction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json_schema_for_llm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_user_prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;brief&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_attempts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  &lt;span class="c1"&gt;# 2
&lt;/span&gt;    &lt;span class="n"&gt;raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SYSTEM_PROMPT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# sent as "format": schema
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ScopeExtraction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;strip_fences&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ValidationError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;base_prompt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;Your previous output was invalid: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Return only valid JSON.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a real run, trimmed from &lt;code&gt;examples/outputs/saas-dashboard.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"project_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"web"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"complexity"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"integrations_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"has_design_provided"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"client_timeline_days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"budget_mentioned_usd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6000.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"risk_flags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Client requesting additional bug fixes outside the initial scope - scope creep"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brief said "5 weeks" and "$6,000"; the model turned those into 35 and 6000.0 only after I changed the prompt, whose examples use those exact conversions. Tuning on the same three briefs I tested on proves little, so the real test below uses eight briefs the prompt never saw.&lt;/p&gt;

&lt;h3&gt;
  
  
  The first real run broke
&lt;/h3&gt;

&lt;p&gt;The agent-written tests passed against a fake client. Then I ran the real model on three demo briefs on a CPU-only Windows machine (AMD Ryzen 5 5600U, 15 GB RAM) at about 7 tokens per second.&lt;/p&gt;

&lt;p&gt;The original prompt failed on 2 of 3.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SaaS dashboard:&lt;/strong&gt; both attempts returned &lt;code&gt;complexity: 8&lt;/code&gt;, which my validator rejects above 5; the schema Ollama saw carried no such bound. It also left out the timeline and budget and listed field names as unknowns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shopify descriptions:&lt;/strong&gt; Ollama returned HTTP 500, "prediction aborted, token repeat limit reached". The model looped and the server killed it, reproducibly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dental bot (valid JSON, wrong content):&lt;/strong&gt; a WhatsApp bot labelled &lt;code&gt;mobile&lt;/code&gt;, complexity 1, for a job touching patient data and a third-party system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I made two rounds of prompt changes, with no structural code changes. The rules that mattered: &lt;code&gt;ai_automation&lt;/code&gt; for bots and LLM tools, &lt;code&gt;mobile&lt;/code&gt; only for native apps; complexity an integer from 1 to 5; lists capped at 8 short, non-repeating items (the abort did not recur in my run, though one run is not proof).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Brief&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;saas-dashboard&lt;/td&gt;
&lt;td&gt;invalid, complexity 8&lt;/td&gt;
&lt;td&gt;valid, 35 days and 6000.0 captured&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shopify-descriptions&lt;/td&gt;
&lt;td&gt;HTTP 500&lt;/td&gt;
&lt;td&gt;valid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dental-whatsapp-bot&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;mobile&lt;/code&gt;, complexity 1&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ai_automation&lt;/code&gt;, complexity 3&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After the second round, all three returned valid JSON, in 55 to 57 seconds each.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I fixed, and what is still wrong
&lt;/h3&gt;

&lt;p&gt;Three code fixes followed: an aborted generation retries once with a higher repeat penalty (tested only with mocked responses); output is forced to UTF-8, since redirected Windows output used a legacy code page and produced invalid JSON; and the 1 to 5 bound went into the JSON schema itself, after which the next real SaaS run came back valid with complexity 3.&lt;/p&gt;

&lt;p&gt;Valid is not good. Complexity was 3 for all three briefs, so the rating barely discriminates. Some unknowns are padding ("What is the client's experience with CSV files?").&lt;/p&gt;

&lt;h3&gt;
  
  
  Then I tried real briefs
&lt;/h3&gt;

&lt;p&gt;The three samples were AI-written and I tuned the prompt on them, so I wanted real client briefs the prompt had never seen. I took 8 public job posts from a freelance marketplace, stripped names, emails, phone numbers and URLs, and did not republish the texts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Measure&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Briefs run&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Valid output&lt;/td&gt;
&lt;td&gt;8 of 8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usable as a first draft without major edits&lt;/td&gt;
&lt;td&gt;3 of 8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median time per brief (CPU)&lt;/td&gt;
&lt;td&gt;63.5 s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three more needed real edits to type, unknowns and risks. Two dropped half the scope; both listed many separate deliverables. That is the expensive failure for a quoting tool: deliverable count feeds the estimator, so missing scope becomes an underquote. The failures were omission, label mistakes and filler, not fabrication: zero clear invented deliverables or technologies, one mild. Data work was labelled &lt;code&gt;ai_automation&lt;/code&gt; three times. Quoted client sentences showed up as risk flags in 4 of 8 briefs, and one fill-in-the-blank template line was read as a real 7-day timeline. Estimates clustered between $1,450 and $3,900 regardless of scope, which fits a history of only 30 synthetic jobs.&lt;/p&gt;

&lt;p&gt;The check also found a bug in my setup. Ollama's default context window silently cut a 3,811-word stress input (one real brief repeated five times) to 2,051 tokens, with no warning. The client now raises &lt;code&gt;num_ctx&lt;/code&gt; automatically for long briefs, up to 32,768 tokens, and errors clearly beyond that. After the fix, a synthetic 3,728-word input was read in full: 5,472 prompt tokens. Briefs under 700 words keep Ollama's defaults.&lt;/p&gt;

&lt;p&gt;My verdict on a 4B model: a checklist and clarifying-question generator that works best on short, clear briefs. It drops scope on long, structured ones and still needs a human reading the brief. Full report: &lt;a href="https://github.com/Moin105/briefquote/blob/main/docs/real-brief-check.md" rel="noopener noreferrer"&gt;https://github.com/Moin105/briefquote/blob/main/docs/real-brief-check.md&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The estimator
&lt;/h3&gt;

&lt;p&gt;TabPFN is a pretrained transformer for small tabular datasets, so it can learn from 20 or 30 past jobs instead of thousands. briefquote fits its regressor for hours and price, using the quantile output (10th, 50th and 90th percentile) as the range, and its classifier for the on-time chance. It runs on CPU with real weights (&lt;code&gt;tabpfn-v3.5&lt;/code&gt;, package &lt;code&gt;tabpfn&lt;/code&gt; 9.2.0). Without TabPFN, a k=5 nearest-neighbour baseline runs, and the quote says which.&lt;/p&gt;

&lt;p&gt;On the hand-written sample scope, the baseline said 95 h (48.8 to 112 h) and TabPFN said 91.9 h (80.1 to 102.4 h). A tighter range is not a more accurate one: on synthetic history this shows only that the plumbing works.&lt;/p&gt;

&lt;p&gt;The on-time figure taught me the most. In my synthetic history, all 12 jobs with unclear requirements ran late or were cancelled, against 17 of 18 clear ones delivered on time, and TabPFN learned exactly that rule: flipping only &lt;code&gt;has_clear_requirements&lt;/code&gt; moves the raw probability from 97.6% to 4.0%. Gemma marked all three sample briefs as unclear, so every demo quote shows 5%, the floor of the 5 to 95 percent clamp. TabPFN is faithful to the history it is given, which is the argument for fitting it on your own.&lt;/p&gt;

&lt;p&gt;Real weights also caught a bug: the recommended price ($4,250) sat above its own ceiling ($4,050), because floor and ceiling ignored the rate-based half of the blend. All three now use the same blend, so floor &amp;lt;= recommended &amp;lt;= ceiling by construction ($3,700, $4,250, $4,700 at $40/h).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Two kinds of private data stay on the computer.&lt;/strong&gt; A client brief is confidential, and pasting it into a hosted service decides on the client's behalf. A freelancer's job history is sensitive too: rates, clients, and the jobs that ran late. Here both stay local: Gemma reads the brief and TabPFN fits the history on the same machine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Owning the runtime cuts both ways.&lt;/strong&gt; Running the models myself put every knob in my hands: the JSON schema for constrained decoding, the context window, the retry repeat penalty, and the model (&lt;code&gt;--model&lt;/code&gt; swaps it). It also meant I inherited a default that silently cut a long input to 2,051 tokens, where hosted APIs typically return an error. Open means the defaults are yours, including the ones you did not know about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open weights are not always open for business.&lt;/strong&gt; TabPFN's weights are licensed for non-commercial use only; a commercial license comes from Prior Labs. So briefquote keeps a nearest-neighbour baseline with no ML dependencies (&lt;code&gt;--no-tabpfn&lt;/code&gt;) that anyone selling quotes can use with no license question. briefquote's own code is MIT.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it cost: speed and judgement.&lt;/strong&gt; About a minute per brief on CPU, and a 4B model that drops scope on long briefs. In return there is no per-call fee, and it works offline once the models are downloaded (TabPFN's weights need a one-time free Prior Labs sign-in and license). I did not run a hosted model on the same briefs, so I cannot say how much quality the privacy cost.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gemma&lt;/strong&gt; (&lt;code&gt;gemma3:4b&lt;/code&gt;, local through Ollama, CPU only): the reading half. It turns an unstructured brief into the structured scope and the six-field row the estimator needs, with schema-constrained JSON, Pydantic validation and one corrective retry. Tested on 3 sample and 8 real briefs; failure modes are in the repo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TabPFN&lt;/strong&gt; (&lt;code&gt;tabpfn-v3.5&lt;/code&gt;, real weights, local CPU): the prediction half. The regressor's quantiles give the hours range and feed the price range, and the classifier gives the on-time probability, both fitted on the freelancer's own past jobs (30 synthetic rows in the demo). A note for Prior Labs: the browser login crashed on Windows with &lt;code&gt;WinError 10038&lt;/code&gt; because its prompt calls &lt;code&gt;select&lt;/code&gt; on stdin; an API key in &lt;code&gt;TABPFN_TOKEN&lt;/code&gt; worked.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Should a newbie dive into fullstack development or has to specialize one front end or backend ?</title>
      <dc:creator>Moin105</dc:creator>
      <pubDate>Mon, 13 Jun 2022 10:46:42 +0000</pubDate>
      <link>https://dev.to/moin105/should-a-newbie-dive-into-fullstack-development-or-has-to-specialize-one-front-end-or-backend--1i2l</link>
      <guid>https://dev.to/moin105/should-a-newbie-dive-into-fullstack-development-or-has-to-specialize-one-front-end-or-backend--1i2l</guid>
      <description>&lt;p&gt;Should a newbie dive into fullstack development or has to specialize one front end or backend ? if yes then will golang be best option for backend (except node js)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
