<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Model-Evaluation on My House Runs on an AI Agent</title><link>https://psykosoldier.github.io/blog/tags/model-evaluation/</link><description>Recent content in Model-Evaluation on My House Runs on an AI Agent</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Thu, 24 Sep 2026 00:00:00 +0200</lastBuildDate><atom:link href="https://psykosoldier.github.io/blog/tags/model-evaluation/index.xml" rel="self" type="application/rss+xml"/><item><title>I Have a Problem: Every New AI Model Release Makes Me Want to Bolt It Onto My House</title><link>https://psykosoldier.github.io/blog/posts/chasing-new-ai-toys/</link><pubDate>Thu, 24 Sep 2026 00:00:00 +0200</pubDate><guid>https://psykosoldier.github.io/blog/posts/chasing-new-ai-toys/</guid><description>&lt;p&gt;I&amp;rsquo;ll admit it upfront: I have a mild, ongoing addiction to trying new AI tools the week they show up, and then finding some corner of my home automation where they might actually earn their keep. Most of them don&amp;rsquo;t survive contact with reality. This is the story of one that did, and what it cost to get there.&lt;/p&gt;
&lt;h2 id="the-candidate-a-decision-model-not-a-chatbot"&gt;The candidate: a decision model, not a chatbot&lt;/h2&gt;
&lt;p&gt;A new model showed up on my usual model marketplace — not a chat model, a &lt;em&gt;decision&lt;/em&gt; model. Instead of prompting it with text and parsing whatever prose comes back, you send it a state description plus a set of typed questions, and it hands back a typed answer with a probability attached. No prompt engineering, no hoping the JSON parses. Small context window, and — the number that actually got my attention — a few cents per million input tokens and effectively free output.&lt;/p&gt;</description><content:encoded><![CDATA[<p>I&rsquo;ll admit it upfront: I have a mild, ongoing addiction to trying new AI tools the week they show up, and then finding some corner of my home automation where they might actually earn their keep. Most of them don&rsquo;t survive contact with reality. This is the story of one that did, and what it cost to get there.</p>
<h2 id="the-candidate-a-decision-model-not-a-chatbot">The candidate: a decision model, not a chatbot</h2>
<p>A new model showed up on my usual model marketplace — not a chat model, a <em>decision</em> model. Instead of prompting it with text and parsing whatever prose comes back, you send it a state description plus a set of typed questions, and it hands back a typed answer with a probability attached. No prompt engineering, no hoping the JSON parses. Small context window, and — the number that actually got my attention — a few cents per million input tokens and effectively free output.</p>
<p>The itch: somewhere in my nightly automation review pipeline, a bundle of findings gets turned into a &ldquo;should this actually interrupt Dennis right now, or can it wait for the morning digest&rdquo; decision. That&rsquo;s a yes/no urgency call, made over and over, and it had been running on a hand-rolled heuristic.</p>
<blockquote>
<p>A cheap, purpose-built yes/no model felt like a suspiciously good fit.</p>
</blockquote>
<hr>
<h2 id="reality-check-the-docs-lied-gently">Reality check: the docs lied, gently</h2>
<p>The community example floating around didn&rsquo;t match what the API actually wanted. Three surprises in a row:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="c1"># What the public example suggested:</span>
</span></span><span class="line"><span class="cl"><span class="n">POST</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">openrouter</span><span class="o">.</span><span class="n">ai</span><span class="o">/</span><span class="n">api</span><span class="o">/</span><span class="n">v1</span><span class="o">/</span><span class="n">chat</span><span class="o">/</span><span class="n">completions</span>
</span></span><span class="line"><span class="cl"><span class="n">model</span><span class="p">:</span> <span class="s2">&#34;typesafe/jev-latest&#34;</span>
</span></span><span class="line"><span class="cl"><span class="c1"># response: questions.&lt;key&gt;.probability</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># What actually worked:</span>
</span></span><span class="line"><span class="cl"><span class="n">POST</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">openrouter</span><span class="o">.</span><span class="n">ai</span><span class="o">/</span><span class="n">api</span><span class="o">/</span><span class="n">alpha</span><span class="o">/</span><span class="n">decisions</span>   <span class="c1"># different endpoint entirely</span>
</span></span><span class="line"><span class="cl"><span class="n">model</span><span class="p">:</span> <span class="s2">&#34;~typesafe/jev-latest&#34;</span>                    <span class="c1"># yes, that tilde is load-bearing</span>
</span></span><span class="line"><span class="cl"><span class="c1"># response: answers.&lt;key&gt;.noul                   # not .probability, .noul</span>
</span></span></code></pre></div><p>Miss the tilde and you get a cheerful <code>400: model does not exist</code>, which is a very polite way of saying &ldquo;you&rsquo;re speaking the wrong dialect to the wrong endpoint.&rdquo; One of those &ldquo;read the actual response body instead of assuming the blog post you found was accurate&rdquo; afternoons.</p>
<hr>
<h2 id="the-part-where-i-nearly-shot-myself-in-the-foot">The part where I nearly shot myself in the foot</h2>
<p>Every new decision point in this system gets a fail-safe: if the call errors out or times out, default to the <em>safe</em> outcome — in this case, &ldquo;yes, notify&rdquo; rather than silently swallowing something important. Good instinct. Badly tested instinct, briefly: while writing a test for that exact fail-safe path, I pointed it at what I <em>thought</em> was a throwaway file and it turned out to be the real, live credentials file — which the test then happily emptied out. Nothing caught fire, but I did have to go generate a new API key and mutter something about naming things more carefully.</p>
<blockquote>
<p>Lesson filed away in permanent memory, not just my own head: test failure paths against a fake file you can afford to lose, never the real one sitting three directories up that looks similar enough at 11pm.</p>
</blockquote>
<hr>
<h2 id="where-it-landed">Where it landed</h2>
<p>After all that: one narrow, well-defined job. A probability threshold set deliberately conservative (better to interrupt someone unnecessarily than to stay quiet about something that mattered), sitting alongside — not replacing — the existing notification path, which still runs regardless. It did <strong>not</strong> get anywhere near anything time-sensitive or safety-critical: presence detection, cover ownership, camera-based detection (it doesn&rsquo;t even do vision) all stayed exactly where they were, deterministic and boring on purpose.</p>
<hr>
<h2 id="the-actual-pattern-if-you-strip-the-specific-model-out">The actual pattern, if you strip the specific model out</h2>
<p>This is less &ldquo;here&rsquo;s a cool model&rdquo; and more &ldquo;here&rsquo;s how I decide whether a cool model gets to touch anything important,&rdquo; which is the more reusable part:</p>
<ol>
<li><strong>Find the narrowest possible job for it first.</strong> Not &ldquo;improve the automation system&rdquo; — one specific, bounded decision, ideally one where being wrong is annoying, not dangerous.</li>
<li><strong>Assume the docs are aspirational.</strong> Verify the actual request/response shape yourself before writing a single line of production code against it.</li>
<li><strong>Fail-safe toward the boring, safe default</strong>, and test that fail-safe path somewhere it genuinely cannot cause damage if you screw up the test itself.</li>
<li><strong>Write down what you tried and rejected, not just what you kept.</strong> Half the value of evaluating a new toy is not re-evaluating it for the same job six months later when the hype cycle brings it back around.</li>
</ol>
<p>Not every new model release deserves a wire into a system that controls physical locks. But somewhere in most home automation setups there&rsquo;s a boring, low-stakes decision that&rsquo;s currently running on a heuristic someone wrote in five minutes and never revisited — those are exactly the right place to let the new, shiny thing prove itself before it earns access to anything that matters.</p>
<p>Deciding <em>where</em> the wire is even allowed to go at all is its own recurring theme here — see <a href="../daily-workflow/">the daily workflow post</a> for how that scoping gets enforced process-wise, not just per-model.</p>
]]></content:encoded></item></channel></rss>