<?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: Anushka Shukla</title>
    <description>The latest articles on DEV Community by Anushka Shukla (@anushka_shukla_c2605dfa90).</description>
    <link>https://dev.to/anushka_shukla_c2605dfa90</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%2F3976224%2F33a498b3-5467-4203-ac47-f8f65565d9c5.png</url>
      <title>DEV Community: Anushka Shukla</title>
      <link>https://dev.to/anushka_shukla_c2605dfa90</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anushka_shukla_c2605dfa90"/>
    <language>en</language>
    <item>
      <title>Building an LLM Router with Jev: A Practical Approach</title>
      <dc:creator>Anushka Shukla</dc:creator>
      <pubDate>Sun, 11 Oct 2026 16:19:58 +0000</pubDate>
      <link>https://dev.to/anushka_shukla_c2605dfa90/building-an-llm-router-with-jev-a-practical-approach-jpd</link>
      <guid>https://dev.to/anushka_shukla_c2605dfa90/building-an-llm-router-with-jev-a-practical-approach-jpd</guid>
      <description>&lt;p&gt;When building applications with LLMs, using one model for everything is a reasonable starting point.&lt;/p&gt;

&lt;p&gt;But not every request needs the same level of reasoning.&lt;/p&gt;

&lt;p&gt;Converting a list into JSON is very different from debugging a race condition in a distributed system. Sending both requests to an expensive model might work, but it may not be the most efficient approach.&lt;/p&gt;

&lt;p&gt;What if we could evaluate a request first and then choose an appropriate model?&lt;/p&gt;

&lt;p&gt;That is the idea behind &lt;strong&gt;LLM routing with Jev&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore a practical architecture for routing requests between model tiers, implementing fallback logic in Python, and measuring whether the approach actually improves costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The architecture
&lt;/h2&gt;

&lt;p&gt;Imagine an application with three model tiers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Route&lt;/th&gt;
&lt;th&gt;Best suited for&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;small&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Simple, repetitive tasks&lt;/td&gt;
&lt;td&gt;JSON formatting, field extraction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;standard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Everyday requests&lt;/td&gt;
&lt;td&gt;Summaries, editing, general questions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;advanced&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Complex reasoning&lt;/td&gt;
&lt;td&gt;Difficult debugging, system design&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The routing pipeline looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Request
     |
     v
Jev Evaluation
     |
     v
Application Routing Policy
     |
     v
Selected LLM
     |
     v
Response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is the separation of responsibilities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Jev&lt;/strong&gt; evaluates the request and provides structured decision outputs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The application&lt;/strong&gt; decides how to interpret those outputs, applies routing rules, checks availability, and handles fallbacks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The selected LLM&lt;/strong&gt; performs the actual task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation makes the routing policy easier to test and modify independently of the model provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Understanding the routing decision
&lt;/h2&gt;

&lt;p&gt;Jev supports typed questions such as &lt;code&gt;choice&lt;/code&gt;, &lt;code&gt;score&lt;/code&gt;, and &lt;code&gt;noul&lt;/code&gt;. These can be used to represent decision-making logic with a shared state and defined options or rubrics.&lt;/p&gt;

&lt;p&gt;For the application example below, imagine we normalize the evaluation result into this structure:&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;"winner"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"small"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"distribution"&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;span class="nl"&gt;"small"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.92&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"standard"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.06&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"advanced"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.02&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;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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This JSON is an illustrative application-level representation, not a claim about Jev's exact SDK response format. Map the actual documented output into your application's own schema.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;winner&lt;/code&gt; is the leading route.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;distribution&lt;/code&gt; contains the normalized scores associated with the available choices.&lt;/li&gt;
&lt;li&gt;The application's routing policy uses the winning option's score to decide whether to accept the result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conceptually:&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;routing_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;winner&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A threshold can help the application decide when to accept a routing decision.&lt;/p&gt;

&lt;p&gt;For example, a threshold of &lt;code&gt;0.80&lt;/code&gt; means the policy accepts a winning score of at least &lt;code&gt;0.80&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; mean the selected LLM has an 80% chance of answering correctly. That interpretation would require empirical calibration and validation.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Implementing the routing policy in Python
&lt;/h2&gt;

&lt;p&gt;Let's assume the application has already normalized the evaluation result into the structure shown above.&lt;/p&gt;

&lt;p&gt;We also maintain a dictionary of configured model routes:&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;available_routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;provider-small-model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;provider-standard-model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advanced&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;provider-advanced-model&lt;/span&gt;&lt;span class="sh"&gt;"&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;p&gt;The model identifiers are placeholders. Replace them with the identifiers supported by your LLM provider.&lt;/p&gt;

&lt;p&gt;Now, let's implement route selection with explicit fallback handling.&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;

&lt;span class="n"&gt;ROUTING_THRESHOLD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.80&lt;/span&gt;
&lt;span class="n"&gt;DEFAULT_FALLBACK_ROUTE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;choose_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&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;Any&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&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="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;fallback_route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DEFAULT_FALLBACK_ROUTE&lt;/span&gt;&lt;span class="p"&gt;,&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Select a configured route from normalized decision output.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;No LLM routes are configured.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;fallback_route&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Configured fallback route &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;fallback_route&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; is unavailable.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;winner&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;distribution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;distribution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&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;fallback_route&lt;/span&gt;

    &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;distribution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;winner&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="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;winner&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="k"&gt;else&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;valid_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;valid_score&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;ROUTING_THRESHOLD&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;winner&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;available_routes&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;winner&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fallback_route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's what this implementation does:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checks that at least one model route is configured.&lt;/li&gt;
&lt;li&gt;Verifies that the designated fallback exists.&lt;/li&gt;
&lt;li&gt;Accepts the winning route only when its score meets the threshold and the route is available in the configuration.&lt;/li&gt;
&lt;li&gt;Uses the configured fallback when the decision is missing, invalid, or below the threshold.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Notice that the function does not silently select an arbitrary model if the fallback is missing. It raises an error instead.&lt;/p&gt;

&lt;p&gt;In production, you should also validate the entire normalized input schema and handle provider health, rate limits, timeouts, user permissions, and model-specific constraints.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. What happens when the decision is ambiguous?
&lt;/h2&gt;

&lt;p&gt;Consider two illustrative cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case A: No route meets the threshold
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;small:     0.20
standard:  0.35
advanced:  0.45
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The leading option is &lt;code&gt;advanced&lt;/code&gt;, but its score is below the configured threshold of &lt;code&gt;0.80&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Under our example policy, the application selects the configured fallback.&lt;/p&gt;

&lt;p&gt;If the fallback is &lt;code&gt;standard&lt;/code&gt;, the request goes to &lt;code&gt;standard&lt;/code&gt;. If &lt;code&gt;advanced&lt;/code&gt; is explicitly configured as the fallback, it goes to &lt;code&gt;advanced&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The choice is determined by the application's policy, not by silently assuming that the leading option is always suitable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Case B: One route clearly leads
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;small:     0.94
standard:  0.05
advanced:  0.01
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;small&lt;/code&gt; meets the threshold. The application selects it if the route is configured.&lt;/p&gt;

&lt;p&gt;These examples illustrate the mechanics of the routing policy. They do not establish how accurately Jev classifies real requests. That needs to be measured using representative evaluation data.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Connecting the policy to an application
&lt;/h2&gt;

&lt;p&gt;The orchestration layer can remain separate from the routing function.&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;def&lt;/span&gt; &lt;span class="nf"&gt;handle_request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Application-specific integration:
&lt;/span&gt;    &lt;span class="c1"&gt;# Normalize the documented Jev output first.
&lt;/span&gt;    &lt;span class="n"&gt;decision&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;evaluate_with_jev&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;route&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;choose_route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;decision&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;fallback_route&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;model_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;available_routes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;route&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;model_client&lt;/span&gt;&lt;span class="p"&gt;.&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;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user_prompt&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;p&gt;&lt;code&gt;evaluate_with_jev&lt;/code&gt; and &lt;code&gt;model_client.generate&lt;/code&gt; are placeholders for your actual integration. This is an architectural example, not a drop-in implementation for a specific SDK.&lt;/p&gt;

&lt;p&gt;Keeping evaluation, routing, and dispatch separate has a practical benefit: changing the model provider or adjusting the routing policy does not require rewriting the entire request-handling pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Does LLM routing actually save money?
&lt;/h2&gt;

&lt;p&gt;Not necessarily.&lt;/p&gt;

&lt;p&gt;The routing step introduces additional computation and latency. A smaller model may also produce an inadequate answer, leading to retries or escalation to a larger model.&lt;/p&gt;

&lt;p&gt;To evaluate the trade-off, compare three approaches using the same representative dataset:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;What it measures&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Always use the advanced model&lt;/td&gt;
&lt;td&gt;Baseline quality, cost, and latency&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use a simple rule-based router&lt;/td&gt;
&lt;td&gt;Whether basic routing is sufficient&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use Jev-based routing&lt;/td&gt;
&lt;td&gt;Whether decision-based routing improves the trade-off&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Track these metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Total cost:&lt;/strong&gt; Include the routing step, model calls, retries, and escalations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task success rate:&lt;/strong&gt; Measure whether the response meets task-specific correctness criteria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End-to-end latency:&lt;/strong&gt; Measure the full request lifecycle, not just the final LLM call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback rate:&lt;/strong&gt; Measure how often the routing policy falls back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality by task category:&lt;/strong&gt; Ensure that savings on simple tasks do not come at the expense of difficult ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful first step is to run the router in &lt;strong&gt;shadow mode&lt;/strong&gt;. Continue serving requests through the existing pipeline while evaluating proposed routes in the background. Compare the decisions against actual task outcomes before introducing automated routing into live traffic.&lt;/p&gt;

&lt;p&gt;The metric I'd pay most attention to is &lt;strong&gt;cost per successfully completed task&lt;/strong&gt;, rather than cost per token alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;LLM routing offers a way to match model capability to request complexity. But the router is only one part of the system.&lt;/p&gt;

&lt;p&gt;A robust implementation needs a clearly defined routing policy, explicit fallback behavior, endpoint validation, and benchmarks that include both cost and output quality.&lt;/p&gt;

&lt;p&gt;Jev provides an interesting approach to structured decision-making in this architecture. Whether it produces meaningful savings depends on the workload and the results of the evaluation.&lt;/p&gt;

&lt;p&gt;I'd benchmark it against a single-model baseline and a simple rule-based router before making any claims about cost reduction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@shuklaanushka2024/jev-ai-for-the-decisions-software-makes-every-day-9f3797dfb7c8?postPublishedType=initial" rel="noopener noreferrer"&gt;Why this kind of decision model could be useful — Medium&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://lnkd.in/ghbGFczm" rel="noopener noreferrer"&gt;How Jev's inputs and outputs fit into an application — DEV.to&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jevmodel.org/use-cases/ai-routing/" rel="noopener noreferrer"&gt;Jev LLM Routing Overview&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>jev</category>
      <category>jevrouting</category>
      <category>llm</category>
      <category>llmrouting</category>
    </item>
    <item>
      <title># Where Jev Fits in an Application</title>
      <dc:creator>Anushka Shukla</dc:creator>
      <pubDate>Wed, 30 Sep 2026 19:06:56 +0000</pubDate>
      <link>https://dev.to/anushka_shukla_c2605dfa90/-where-jev-fits-in-an-application-36je</link>
      <guid>https://dev.to/anushka_shukla_c2605dfa90/-where-jev-fits-in-an-application-36je</guid>
      <description>&lt;p&gt;Suppose you’re building a service that receives customer support tickets. Before assigning a ticket, your code needs to answer two questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Which team should handle it?&lt;/li&gt;
&lt;li&gt;Does it need urgent attention?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could ask a language model to write an assessment and then parse its response. &lt;strong&gt;Jev&lt;/strong&gt;, TypeSafe AI’s decision model, offers another interface: send it the ticket as &lt;code&gt;state&lt;/code&gt;, define the questions and their answer types, and receive structured answers.&lt;/p&gt;

&lt;p&gt;For example, you might define the team as a &lt;strong&gt;Choice&lt;/strong&gt; between &lt;code&gt;billing&lt;/code&gt;, &lt;code&gt;technical&lt;/code&gt;, and &lt;code&gt;sales&lt;/code&gt;. Urgency could be a &lt;strong&gt;Noul&lt;/strong&gt;, Jev’s probability-based answer to a yes-or-no question. Jev also supports &lt;strong&gt;Score&lt;/strong&gt; questions for placing something on a defined scale.&lt;/p&gt;

&lt;p&gt;The flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ticket + defined questions
           ↓
          Jev
           ↓
Choice and probability-based answers
           ↓
Your application decides what to do
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your application still owns the rules. It might assign a ticket automatically when the team choice is clear, or put it in a review queue when the result is uncertain. Jev supplies a judgment; your code decides how much to trust it.&lt;/p&gt;

&lt;p&gt;That separation is useful when the inputs vary too much for a few &lt;code&gt;if&lt;/code&gt; statements, but the possible actions are known in advance. Think ticket routing, document classification, content review, or deciding which tool an AI agent should call next.&lt;/p&gt;

&lt;p&gt;There’s a limit to keep in mind: structured output guarantees a usable &lt;em&gt;shape&lt;/em&gt;, not a correct judgment. I would test it against real examples, track mistakes, and keep human review for decisions where errors matter.&lt;/p&gt;

&lt;p&gt;TypeSafe AI’s &lt;a href="https://docs.typesafe.ai/introduction/quickstart" rel="noopener noreferrer"&gt;quickstart&lt;/a&gt; shows the request format and a working example if you want to try it.&lt;/p&gt;

</description>
      <category>jev</category>
      <category>llm</category>
      <category>automaton</category>
      <category>ai</category>
    </item>
    <item>
      <title>LLM Wiki: A Smarter Alternative to RAG</title>
      <dc:creator>Anushka Shukla</dc:creator>
      <pubDate>Tue, 09 Jun 2026 14:56:16 +0000</pubDate>
      <link>https://dev.to/anushka_shukla_c2605dfa90/llm-wiki-a-smarter-alternative-to-rag-4dm2</link>
      <guid>https://dev.to/anushka_shukla_c2605dfa90/llm-wiki-a-smarter-alternative-to-rag-4dm2</guid>
      <description>&lt;p&gt;Every developer I know has the same problem.&lt;br&gt;
You read a great article. You save it. You take notes. You bookmark three more links. A month later, you need that knowledge again and you're starting from scratch, re-reading the same things, rediscovering what you already knew.&lt;br&gt;
So you do what every sensible developer does: you build a RAG pipeline.&lt;br&gt;
You chunk your documents. You embed them. You set up a vector database. You wire up a retrieval layer. Three days later, you have a system that answers questions from your documents sort of. Sometimes the chunks are too small. Sometimes the wrong document gets retrieved. Sometimes the answer is technically correct but misses the point entirely.&lt;br&gt;
And the worst part? The system learns nothing. Every query starts from zero.&lt;br&gt;
There's a better way. Andrej Karpathy co-founder of OpenAI, former Director of AI at Tesla published a deceptively simple idea in April 2026 that's been quietly spreading through the developer community ever since.&lt;br&gt;
He calls it the LLM Wiki.&lt;/p&gt;

&lt;p&gt;What's Wrong with RAG?&lt;br&gt;
Before I explain LLM Wiki, let me be fair to RAG. It's not bad. For large enterprise document stores thousands of PDFs, legal contracts, customer records RAG is the right tool. It scales in ways that other approaches can't.&lt;br&gt;
But most developers aren't building enterprise search engines. They're trying to get an AI to work intelligently with their knowledge their notes, their research, their team's documentation.&lt;br&gt;
And for that use case, RAG has a fundamental flaw: it's stateless.&lt;br&gt;
Every time you ask a question, the system re reads your raw documents from scratch. It retrieves chunks. It answers. It forgets. The next question, same thing. There's no accumulation. No synthesis. No memory of what it figured out last time.&lt;br&gt;
It's like hiring a brilliant researcher who reads your entire library before answering every single question and then immediately forgets everything when you ask the next one.&lt;/p&gt;

&lt;p&gt;The LLM Wiki Pattern&lt;br&gt;
Karpathy's insight is almost embarrassingly simple once you hear it.&lt;br&gt;
Instead of querying raw documents over and over, you have an LLM compile your sources into a structured wiki of plain Markdown files once. From then on, you query the compiled wiki, not the raw sources.&lt;br&gt;
Think of it like this:&lt;/p&gt;

&lt;p&gt;"Obsidian is the IDE, the LLM is the programmer, the wiki is the codebase."&lt;br&gt;
— Andrej Karpathy&lt;/p&gt;

&lt;p&gt;Your raw documents are source material. The LLM reads them and produces clean, structured, interlinked pages one per concept. Like Wikipedia, but for your personal knowledge.&lt;br&gt;
When you have a new source, you add it and run the compilation again. The LLM updates the relevant pages, adds new ones, and notes any contradictions. The wiki grows. The knowledge compounds.&lt;/p&gt;

&lt;p&gt;What a Wiki Page Looks Like&lt;br&gt;
Here's an example of what the LLM produces a page for the concept "vector embeddings":&lt;br&gt;
markdown# Vector Embeddings&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type:&lt;/strong&gt; Concept&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Related:&lt;/strong&gt; [[RAG]], [[Semantic Search]], [[Neural Networks]]&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Vector embeddings are numerical representations of text that capture semantic &lt;br&gt;
meaning. Similar concepts produce vectors that are close together in space.&lt;/p&gt;

&lt;h2&gt;
  
  
  How They Work
&lt;/h2&gt;

&lt;p&gt;Text is passed through a model which outputs a list of numbers the embedding. &lt;br&gt;
These numbers encode the meaning of the text in a way that allows mathematical &lt;br&gt;
comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where They're Used
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;RAG pipelines (retrieving relevant document chunks)&lt;/li&gt;
&lt;li&gt;Semantic search engines&lt;/li&gt;
&lt;li&gt;Recommendation systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Embeddings from different models aren't compatible&lt;/li&gt;
&lt;li&gt;Quality degrades on very long texts&lt;/li&gt;
&lt;li&gt;Require a vector database to query at scale&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[[Attention Is All You Need Vaswani et al.]]&lt;/li&gt;
&lt;li&gt;[[OpenAI Embeddings Documentation]]
Clean. Structured. Cross-referenced. Written once, queryable forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RAG vs LLM Wiki: A Direct Comparison&lt;br&gt;
RAGLLM WikiLearns over time? No YesInfrastructure neededVector DB + embeddings + retrieval pipelineA text editorQuery costHigh re reads docs every timeLow reads structured wikiCross-source synthesisWeakStrongBest forMillions of documentsPersonal / team knowledge&lt;/p&gt;

&lt;p&gt;How to Try It in 30 Minutes&lt;br&gt;
You don't need to write any code to try this. Here's the simplest possible version:&lt;br&gt;
Step 1 — Gather your sources&lt;br&gt;
Create a folder. Drop in 3–5 Markdown or text files articles you've saved, notes you've taken, documentation you reference often.&lt;br&gt;
Step 2 — Compile the wiki&lt;br&gt;
Open Claude.ai, upload your files, and paste this prompt:&lt;br&gt;
Read these documents and create structured Markdown wiki pages for the key &lt;br&gt;
concepts. For each concept, write a summary, list related concepts using &lt;br&gt;
[[wikilinks]], and note the source. Output each page as a separate code block.&lt;br&gt;
Step 3 — Save and query&lt;br&gt;
Copy the generated pages into a folder. Open it in Obsidian (free). Now ask questions against your wiki instead of your raw documents.&lt;br&gt;
That's it. No vector database. No embedding model. No retrieval pipeline. Just Markdown files and an LLM.&lt;/p&gt;

&lt;p&gt;When to Stick with RAG&lt;br&gt;
LLM Wiki isn't a replacement for RAG in every situation. Use RAG when:&lt;/p&gt;

&lt;p&gt;You have thousands of documents the wiki would become too large for a context window&lt;br&gt;
Your documents update constantly real time data needs real time retrieval&lt;br&gt;
You need exact citation RAG can point to the precise chunk; a wiki synthesizes across sources&lt;/p&gt;

&lt;p&gt;For everything else personal research, team knowledge bases, project documentation, learning notes the LLM Wiki pattern is simpler, cheaper, and produces better answers.&lt;/p&gt;

&lt;p&gt;The Bigger Idea&lt;br&gt;
What Karpathy identified isn't just a technical pattern. It's a shift in how we think about AI and knowledge.&lt;br&gt;
Most AI tools treat your documents as static inputs things to be searched. The LLM Wiki treats your knowledge as something alive something that grows, connects, and compounds every time you add to it.&lt;br&gt;
RAG answers questions. LLM Wiki builds understanding.&lt;br&gt;
And honestly? That's the kind of AI tool I actually want to use.&lt;/p&gt;

&lt;p&gt;Have you tried building a personal knowledge base with LLMs? Drop a comment below I'd love to hear what's working for you.&lt;/p&gt;

&lt;p&gt;Want a deeper dive?&lt;br&gt;
I wrote a more detailed version of this on Medium covering the full history behind the idea (including Vannevar Bush's 1945 Memex concept) and a step by step walkthrough for three different implementation paths.&lt;/p&gt;

&lt;p&gt;Read the full article on &lt;a href="https://medium.com/@shuklaanushka2024/stop-using-rag-for-everything-try-llm-wiki-instead-20db723f5548" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you find it useful, a follow there helps me write more content like this. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>productivity</category>
      <category>rag</category>
    </item>
  </channel>
</rss>
