<?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: Duskel</title>
    <description>The latest articles on DEV Community by Duskel (@duskel).</description>
    <link>https://dev.to/duskel</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%2F4017462%2F90c2edba-3925-4c35-91f4-30b241f50d1b.jpg</url>
      <title>DEV Community: Duskel</title>
      <link>https://dev.to/duskel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/duskel"/>
    <language>en</language>
    <item>
      <title>RAG Chatbot Development for Small Business: What Actually Changed When We Swapped in Claude Sonnet 5</title>
      <dc:creator>Duskel</dc:creator>
      <pubDate>Mon, 06 Jul 2026 16:40:00 +0000</pubDate>
      <link>https://dev.to/duskel/rag-chatbot-development-for-small-business-what-actually-changed-when-we-swapped-in-claude-sonnet-5-34mj</link>
      <guid>https://dev.to/duskel/rag-chatbot-development-for-small-business-what-actually-changed-when-we-swapped-in-claude-sonnet-5-34mj</guid>
      <description>&lt;p&gt;Claude Sonnet 5 became the default free and Pro model on July 1. We had it running inside a client's retrieval pipeline four days later — not a toy demo, a production RAG chatbot for a small business client with about 40,000 support documents and a strict "don't make things up" requirement.&lt;/p&gt;

&lt;p&gt;Here's what actually changed, and what didn't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;The client came to us the way a lot of small businesses do when they want to hire a developer to build a RAG system on their own data: a pile of PDFs, a shared drive, and a support inbox getting the same 30 questions on repeat. No enterprise budget, no in-house ML team, just a real need to stop answering the same email every day.&lt;/p&gt;

&lt;p&gt;Our stack for this one is boring on purpose: pgvector for retrieval, a thin re-ranking step, and whatever LLM sits at the end answering with citations. That last part is a config value, not a rewrite. Swapping providers or model versions should be a one-line change. If it isn't, your architecture is the actual problem, not the model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;generationModel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anthropic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;claude-sonnet-5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// was claude-sonnet-4-6&lt;/span&gt;
  &lt;span class="na"&gt;maxTokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What got better
&lt;/h2&gt;

&lt;p&gt;Two things stood out in the first 48 hours of testing against our existing eval set (about 120 real support questions with known-good answers):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fewer confident wrong answers.&lt;/strong&gt; Sonnet 5 was noticeably more willing to say "the documents don't cover this" instead of blending two unrelated policy sections into something plausible-sounding. That's the failure mode that actually costs small businesses money — not the chatbot being unhelpful, but the chatbot being wrong with a straight face.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better use of retrieved context under pressure.&lt;/strong&gt; When we deliberately fed it 8-10 chunks instead of 3-4 (a common real-world scenario when queries are vague), the answer quality held up better than the previous model. Less "picks the first chunk and ignores the rest."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Latency was roughly flat. Cost per query was flat. Neither was the reason to move.&lt;/p&gt;

&lt;h2&gt;
  
  
  What didn't change
&lt;/h2&gt;

&lt;p&gt;The model swap did not fix bad chunking, and it did not fix a retrieval step that was already returning the wrong documents. We still spent most of our week on the boring stuff: chunk size, metadata filters, and re-ranking thresholds. That's the part of RAG chatbot development for small business clients that never makes it into vendor pitch decks, because it's not a feature you can screenshot.&lt;/p&gt;

&lt;p&gt;There's a real backlash brewing right now about AI-written code quality — a widely cited 153-million-line analysis this week shows duplication up roughly 4x and rising churn where teams lean hard on agents without review. We see the same pattern in RAG systems: teams swap in a shinier model and expect it to paper over a retrieval layer nobody actually designed. It won't. The model is maybe 20% of why a RAG chatbot hallucinates. The other 80% is what you feed it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The actual takeaway
&lt;/h2&gt;

&lt;p&gt;If your RAG pipeline is architected so the generation model is a config value, model releases are good news you can act on in days, not a migration project. If it's not — if "switch models" means touching prompt templates in six different files — that's worth fixing before you worry about which model is smartest this quarter.&lt;/p&gt;

&lt;p&gt;We're a founder-led software studio, not a faceless agency, and we test new model releases against real client pipelines because that's the only way to know if they matter. If you're trying to hire a developer to build a RAG system on your own data — a small business, not an enterprise budget — see how we scope it at &lt;a href="https://duskel.com/services" rel="noopener noreferrer"&gt;duskel.com/services&lt;/a&gt; or write to &lt;a href="mailto:hello@duskel.com"&gt;hello@duskel.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>RAG Chatbot Development for B2B: Why We Stopped Hard-Coding One LLM Vendor</title>
      <dc:creator>Duskel</dc:creator>
      <pubDate>Mon, 06 Jul 2026 14:39:26 +0000</pubDate>
      <link>https://dev.to/duskel/rag-chatbot-development-for-b2b-why-we-stopped-hard-coding-one-llm-vendor-4f8j</link>
      <guid>https://dev.to/duskel/rag-chatbot-development-for-b2b-why-we-stopped-hard-coding-one-llm-vendor-4f8j</guid>
      <description>&lt;h2&gt;
  
  
  The pipeline that broke on a Tuesday
&lt;/h2&gt;

&lt;p&gt;In June 2026, Anthropic's Claude was pulled from availability for 20 days in several regions under export-control rules. If you'd built a client's RAG chatbot with a single hard-coded call to &lt;code&gt;anthropic.messages.create()&lt;/code&gt;, that client's support bot went dark. Not because the model got worse. Because the vendor got yanked.&lt;/p&gt;

&lt;p&gt;We run a small studio building RAG systems for B2B clients, several of them outside the US, and that's the exact scenario we now design against. Not as a hypothetical — as something that already happened to teams who didn't plan for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most RAG chatbot builds get the wrong thing right
&lt;/h2&gt;

&lt;p&gt;When an agency pitches a "RAG chatbot development" project, the demo is always the same: embed some docs, wire up a vector store, call one model, done. It answers questions well in the sales call. Nobody stress-tests what happens when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the vendor changes pricing overnight&lt;/li&gt;
&lt;li&gt;the vendor's API gets export-restricted in the client's country&lt;/li&gt;
&lt;li&gt;the vendor deprecates the model you built prompts around&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We treat the LLM call as the &lt;em&gt;least&lt;/em&gt; stable part of the stack, and design everything else so swapping it out is a config change, not a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we actually build
&lt;/h2&gt;

&lt;p&gt;A thin provider interface sits between the retrieval layer and the model call. Retrieval, chunking, reranking, and citation logic never touch a vendor SDK directly.&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
 &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nb"&gt;NotImplementedError&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ClaudeProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;context&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;anthropic_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LongCatProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LLMProvider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
 &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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="n"&gt;context&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;longcat_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;

&lt;span class="c1"&gt;# swap providers via config, not a redeploy
&lt;/span&gt;&lt;span class="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PROVIDER_REGISTRY&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LLM_PROVIDER&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's not clever. That's the point — boring abstractions are the ones that survive a vendor outage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open-weight models changed the calculus
&lt;/h2&gt;

&lt;p&gt;LongCat-2.0 shipped this month under a full MIT license — no regional restrictions, free to fine-tune and redistribute. For a foreign client who just watched a US-origin model vanish for three weeks, that's not a curiosity, it's a fallback path. We're not saying drop Claude — Sonnet 5, out since June 30, is genuinely the sharpest agentic model we've used in production, and it's still our default for reasoning-heavy retrieval. We're saying don't let one vendor be a single point of failure for a client's support desk or internal knowledge base.&lt;/p&gt;

&lt;h2&gt;
  
  
  The trust gap nobody's pricing in
&lt;/h2&gt;

&lt;p&gt;There's a stat going around this week: 84% of developers now use AI coding tools, but only 29% trust the output unsupervised. We see the same split with RAG specifically — clients love what a demo can do, then ask "what happens when it's wrong in front of a customer?" The honest answer is: it will be, occasionally, and your architecture needs a human review step and a citation trail, not just a bigger prompt.&lt;/p&gt;

&lt;p&gt;That's the part of AI RAG system integration for small business that gets skipped when the pitch is all demo and no failure mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means if you're scoping one
&lt;/h2&gt;

&lt;p&gt;If you're evaluating a RAG chatbot development agency for B2B work, ask two questions before you ask about accuracy: what happens when the model vendor changes terms, and can you point the same pipeline at a different model without touching retrieval code. If the answer is "we'd rebuild it," you're buying a demo, not a system.&lt;/p&gt;

&lt;p&gt;We've been building this vendor-flexible pattern into every RAG engagement lately, partly because it's good architecture, partly because the last month proved it isn't optional for clients operating outside the US.&lt;/p&gt;

&lt;p&gt;If you're scoping something like this, &lt;a href="https://duskel.com/services" rel="noopener noreferrer"&gt;duskel.com/services&lt;/a&gt; has how we approach it, or just email &lt;a href="mailto:hello@duskel.com"&gt;hello@duskel.com&lt;/a&gt; and tell us what you're building.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>webdev</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
