<?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: william freund</title>
    <description>The latest articles on DEV Community by william freund (@986036734).</description>
    <link>https://dev.to/986036734</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%2F4173730%2F57c0f6f7-641d-4fa8-870e-c2b4ccdc5e22.png</url>
      <title>DEV Community: william freund</title>
      <link>https://dev.to/986036734</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/986036734"/>
    <language>en</language>
    <item>
      <title>I Stopped Opening the Spreadsheet: Asking 19,426 Job Posts One Lazy Sentence</title>
      <dc:creator>william freund</dc:creator>
      <pubDate>Mon, 26 Oct 2026 01:00:02 +0000</pubDate>
      <link>https://dev.to/986036734/i-stopped-opening-the-spreadsheet-asking-19426-job-posts-one-lazy-sentence-2od4</link>
      <guid>https://dev.to/986036734/i-stopped-opening-the-spreadsheet-asking-19426-job-posts-one-lazy-sentence-2od4</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;em&gt;DEV Hacktoberfest Week 3 — "Slow and Steady". Built this week, from scratch, with an open-weight model (Gemma 3 1B, running locally).&lt;/em&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  The most boring week of my October
&lt;/h3&gt;

&lt;p&gt;Every year, China's national civil-service exam (国考) publishes its position table: &lt;strong&gt;19,426 rows&lt;/strong&gt; of departments, quotas, majors, degree requirements, locations, and footnotes. To find posts I could actually apply for, I spent a week scrolling, Excel-filtering, and re-checking constraints — degree, major, English certificates, party membership, grassroots experience, "remote western region" postings.&lt;/p&gt;

&lt;p&gt;With my AI assistant's help I got it down to &lt;strong&gt;23 genuinely eligible posts&lt;/strong&gt;. And then I noticed something: every remaining question I had was a one-liner.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;英语专业，不要四六级，招3人以上，太原的岗&lt;br&gt;
&lt;em&gt;English major, no CET-4/6 requirement, 3+ openings, in Taiyuan&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;招4个人的税务局岗&lt;br&gt;
&lt;em&gt;Tax bureau posts hiring 4 people&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;提供宿舍的岗&lt;br&gt;
&lt;em&gt;Posts that provide a dormitory&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each of those used to mean: open the spreadsheet, remember which column holds what, apply three filters, squint. So I built the laziest possible interface: &lt;strong&gt;type one sentence, get a ranked shortlist.&lt;/strong&gt;&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Meet CouchFilter 🛋️
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python couchfilter_cli.py &lt;span class="s2"&gt;"英语专业，不要四六级，招3人以上，太原的岗"&lt;/span&gt;

问：英语专业，不要四六级，招3人以上，太原的岗
（Gemma 本地解析）

命中 1 个岗（按招考人数排序）：
1. &lt;span class="o"&gt;[&lt;/span&gt;300110021004] 国家税务总局清徐县税务局｜一级行政执法员（四）｜招 3 人
   地点：山西省太原市清徐县｜备注：男性，在本单位最低服务年限为5年
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or open the tiny web UI and ask from the couch:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;python serve.py&lt;/code&gt; → &lt;a href="http://127.0.0.1:8000" rel="noopener noreferrer"&gt;http://127.0.0.1:8000&lt;/a&gt; — one input box, one button, ranked cards.&lt;/p&gt;

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

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

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

&lt;h3&gt;
  
  
  How it works (and where the model earns its keep)
&lt;/h3&gt;

&lt;p&gt;The pipeline is deliberately split in two:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fuzzy part → Gemma 3 1B (open weights), running locally via Ollama.&lt;/strong&gt;&lt;br&gt;
It turns one Chinese sentence into structured filters — a JSON object with location, minimum headcount, major, excluded terms, dormitory requirement, degree. Nothing leaves the machine; the position table never touches a cloud API.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exact part → plain Python.&lt;/strong&gt;&lt;br&gt;
Filters are applied deterministically over the spreadsheet, so every result is reproducible and every rejection comes with a reason ("只招 2 人（要 ≥3）", "备注未写提供宿舍").&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Why the split? A 1B model is great at understanding "招3人以上" means &lt;code&gt;min_headcount: 3&lt;/code&gt;, but I don't want it &lt;em&gt;deciding&lt;/em&gt; my career shortlist from vibes. The model translates; the code filters. If Ollama is down, a rule-based parser takes over and says so honestly.&lt;/p&gt;

&lt;p&gt;Ranking is laziness-first: more openings first (better odds per application), then everything else.&lt;/p&gt;

&lt;p&gt;Total new code: ~400 lines. Dependencies: &lt;code&gt;openpyxl&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt;, and a local model. The web UI is Python stdlib only.&lt;/p&gt;

&lt;p&gt;Try it on your own table:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
ollama pull gemma3:1b
python couchfilter_cli.py &lt;span class="s2"&gt;"你的问题"&lt;/span&gt; &lt;span class="nt"&gt;--table&lt;/span&gt; your-positions.xlsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any 国考-style table works if the column layout matches (the &lt;code&gt;C_*&lt;/code&gt; constants in &lt;code&gt;couchfilter.py&lt;/code&gt; are the whole schema).&lt;/p&gt;

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

&lt;p&gt;CouchFilter is built around an open-weight model, Gemma 3 1B, running locally via Ollama. Because the model runs locally, nothing leaves the machine and the position table never touches a cloud API. The model does the fuzzy language part, and deterministic code does the filtering, so every result is reproducible and every rejection comes with a reason. If Ollama is down, a rule-based parser takes over and says so honestly.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  The "slow and steady" philosophy
&lt;/h3&gt;

&lt;p&gt;The theme this week is &lt;em&gt;rewarding laziness&lt;/em&gt;, and I took it literally. The laziest query wins: no column names to memorize, no filter dialogs, no "wait, which sheet was it". The tool even tells you what it excluded and why, so you can loosen one constraint instead of starting over.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Built 2026-10-24 for DEV Hacktoberfest Week 3. The 23-post shortlist is public recruitment data; the week of manual screening that produced it is a story for another post.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>BlastRadius: Know What Breaks Before You Merge</title>
      <dc:creator>william freund</dc:creator>
      <pubDate>Sat, 17 Oct 2026 02:31:06 +0000</pubDate>
      <link>https://dev.to/986036734/blastradius-know-what-breaks-before-you-merge-8k8</link>
      <guid>https://dev.to/986036734/blastradius-know-what-breaks-before-you-merge-8k8</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;BlastRadius answers the question every developer dreads: "if I change this function, what breaks?"&lt;/p&gt;

&lt;p&gt;You point it at a Python repo. It parses the code into a graph (files, functions, classes; calls, imports, definitions), then runs real graph queries to find the blast radius of any proposed change: every caller, transitively, the files involved, the tests that cover it, the dependency chain, and the hot spots. Then a local open-weight model (Gemma, via Ollama) writes a change summary grounded in those graph results, plus which tests to run.&lt;/p&gt;

&lt;p&gt;Who would pay for it: indie developers and small teams who have been burned by "one-line fix, three-hour outage." Local single-repo scans are free; the business is a per-repo / small-team plan for hosted scans and team-wide impact reports.&lt;/p&gt;

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

&lt;p&gt;Watch the 37-second demo (real run on the bundled sample app): &lt;a href="https://github.com/986036734/blastradius/releases/download/v1.0.0/blastradius-demo.mp4" rel="noopener noreferrer"&gt;BlastRadius demo video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or run it yourself: clone the repo, follow the README quickstart, then &lt;code&gt;python -m blastradius demo&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://github.com/986036734/blastradius" rel="noopener noreferrer"&gt;https://github.com/986036734/blastradius&lt;/a&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FalkorDB&lt;/strong&gt; (open-source graph database) holds the code graph. All impact analysis is real Cypher: multi-hop reverse CALLS traversal for the blast radius, shortest path for the dependency chain, degree centrality for hot spots.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gemma&lt;/strong&gt; (Google's open-weight model) via &lt;strong&gt;Ollama&lt;/strong&gt;, running fully locally, writes the change summary. The prompt is grounded in the graph results — callers, files, tests, chain — and the graph results are authoritative: the summary is a draft for the developer to check, not gospel. (In testing, the 1B model occasionally garbles a detail, e.g. inventing a test filename; the 4B model is recommended for better fidelity.)&lt;/li&gt;
&lt;li&gt;Python stdlib &lt;code&gt;ast&lt;/code&gt; for parsing. No embeddings, no hosted APIs in the loop.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Your codebase is your most private asset, and your change history is your team's memory. A closed API would mean shipping both to someone else's server on every query, and paying per token for the privilege.&lt;/p&gt;

&lt;p&gt;Running Gemma locally flips that: the graph and the model both live on your machine, your code never leaves the laptop, and the marginal cost of a query is ~$0 — which is exactly what makes a $5/mo-style price point work instead of a per-token meter. Open weights also mean you can swap models (1B on a laptop, 4B on a workstation) without rewriting anything. If Gemma disappeared tomorrow, the graph queries still work; if the graph disappeared, the model would be guessing. The open pieces are what make the product work.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Best Use of Gemma&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Touch Grass: an open-source AI agent that plans your way outside 🌿</title>
      <dc:creator>william freund</dc:creator>
      <pubDate>Fri, 09 Oct 2026 15:27:30 +0000</pubDate>
      <link>https://dev.to/986036734/touch-grass-an-open-source-ai-agent-that-plans-your-way-outside-46mn</link>
      <guid>https://dev.to/986036734/touch-grass-an-open-source-ai-agent-that-plans-your-way-outside-46mn</guid>
      <description>&lt;p&gt;&lt;em&gt;My submission for the Hacktoberfest Open-Source AI Challenge: Week 1 — "Touch Grass".&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The prompt was simple: build something with open-source AI at its core that gets people off the screen and into the world. So I built the smallest agent I could that does exactly that — you tell it where you are and how much time you have, and it plans a real outdoor micro-adventure: when to go, where to stand, what to look for, and what to do with your phone (spoiler: airplane mode).&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Touch Grass&lt;/strong&gt; is a tiny Python agent (~200 lines, one dependency). It runs a tool-using loop over any OpenAI-compatible chat endpoint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tools&lt;/strong&gt;: geocoding (OpenStreetMap), sunrise/sunset times, and a 12-hour weather outlook (Open-Meteo) — all free, keyless, open data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Brain&lt;/strong&gt;: any open-weight model behind an OpenAI-compatible API. The agent supports local Ollama for fully offline inference, or a hosted gateway. For this demo I ran it against a hosted open-weight model served over an OpenAI-compatible endpoint; swapping models is one environment variable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;: a concrete Markdown plan — time window, spot, timed steps, things to notice, a phone rule, and a rain check. No frameworks, no vendor SDKs. The whole thing is &lt;code&gt;requests&lt;/code&gt; + a loop.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Real run, tonight, no cherry-picking — asked for a 45-minute sunset walk with birding near Olympic Forest Park, Beijing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  Lakeside Light &amp;amp; Last Calls — Aohai, Olympic Forest Park
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When:&lt;/strong&gt; 17:05 → 17:50. Sunset is 17:46, so this window catches warm pre-sunset light and ends in the afterglow. Overcast, 21°C, 0% precipitation across the next 12 hours — dry and calm. Honest caveat: overcast may swallow the sun disc itself. That's fine — it's actually &lt;em&gt;better&lt;/em&gt; for birds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Where:&lt;/strong&gt; the east shore of Aohai lake, looking west across the water. Enter at the south gate, 8 minutes' walk to the shoreline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The plan:&lt;/strong&gt; timed steps from gate to shoreline birding (17:10–17:28), then 5 minutes north to a west-facing photo gap, shooting the afterglow 5–10 minutes &lt;em&gt;after&lt;/em&gt; official sunset.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Look for:&lt;/strong&gt; grey herons and great egrets in the shallows, little grebes and coots on open water, azure-winged magpies in the treeline, the lake going two-tone in the wind, early-October migrants in the willows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Leave the phone:&lt;/strong&gt; airplane mode in your pocket until 17:44 — the camera is the only phone use, and it starts when the light does.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Rain check:&lt;/strong&gt; not needed today. If the sky fully greys out, drop the sunset shot and walk the wetland boardwalk instead.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;What I like about this output: the agent actually &lt;em&gt;used&lt;/em&gt; its tools. It geocoded the park, pulled real sunset/weather data, and reasoned about it — noticing that overcast hurts the sunset photo but helps the birding, and adjusting the plan accordingly. That's the agent earning its keep, not just filling a template.&lt;/p&gt;

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

&lt;p&gt;This project only makes sense because it's open, in three concrete ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It can go where the trail goes.&lt;/strong&gt; A closed API means the agent dies the moment you lose signal. Open weights mean the same agent runs on a laptop with Ollama, fully offline — which is exactly where a "touch grass" tool needs to work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your location stays yours.&lt;/strong&gt; The agent's most sensitive input is where you are and when. With open models and open data sources, none of that has to travel to a server you don't control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It costs nothing to run and anyone can improve it.&lt;/strong&gt; The model is swappable, the data sources are free, the code is ~200 lines of MIT-licensed Python. A student, a hiking club, or a park ranger can fork it, point it at a newer open model next year, and it's better — no permission, no bill.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Closed models could generate the same &lt;em&gt;words&lt;/em&gt;. They couldn't give you the same &lt;em&gt;guarantees&lt;/em&gt;. For a tool whose whole job is getting you outside, offline and private aren't features — they're the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_BASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:11434/v1  &lt;span class="c"&gt;# or any OpenAI-compatible endpoint&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;qwen2.5:3b
python &lt;span class="nt"&gt;-m&lt;/span&gt; touchgrass.cli &lt;span class="nt"&gt;--place&lt;/span&gt; &lt;span class="s2"&gt;"your park here"&lt;/span&gt; &lt;span class="nt"&gt;--minutes&lt;/span&gt; 45 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--interests&lt;/span&gt; &lt;span class="s2"&gt;"birding, sunset photos"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/986036734/touch-grass" rel="noopener noreferrer"&gt;https://github.com/986036734/touch-grass&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I validated the plan logic against real data tonight; the agent geocoded, checked sunset and weather, and reasoned over them rather than filling a template.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Overall&lt;/li&gt;
&lt;/ul&gt;

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