<?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: mlops</title>
    <description>The latest articles tagged 'mlops' on DEV Community.</description>
    <link>https://dev.to/t/mlops</link>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tag/mlops"/>
    <language>en</language>
    <item>
      <title>Unlocking the Power of Gemini 3.7 Flash: A Developer's Perspective</title>
      <dc:creator>Naveen Malothu</dc:creator>
      <pubDate>Fri, 14 Aug 2026 05:16:23 +0000</pubDate>
      <link>https://dev.to/naveenmalothu/unlocking-the-power-of-gemini-37-flash-a-developers-perspective-40om</link>
      <guid>https://dev.to/naveenmalothu/unlocking-the-power-of-gemini-37-flash-a-developers-perspective-40om</guid>
      <description>&lt;h1&gt;
  
  
  Unlocking the Power of Gemini 3.7 Flash: A Developer's Perspective
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What was released / announced
&lt;/h2&gt;

&lt;p&gt;Google has recently announced the release of Gemini 3.7 Flash, a significant update to their Gemini models. This new release promises to bring improved performance, efficiency, and capabilities to the table, making it an exciting development for developers and engineers working with AI and machine learning. Gemini 3.7 Flash is designed to provide faster and more accurate results, making it a valuable tool for a wide range of applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;As someone who works with AI infrastructure and cloud systems, I believe that Gemini 3.7 Flash matters because it has the potential to revolutionize the way we approach AI and machine learning. With its improved performance and efficiency, developers can build more complex and powerful models, leading to breakthroughs in areas such as natural language processing, computer vision, and more. For example, in a real-world use case, Gemini 3.7 Flash could be used to improve the accuracy of chatbots, enabling them to better understand and respond to user queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;To get started with Gemini 3.7 Flash, developers can use the Google Cloud AI Platform, which provides a range of tools and services for building, deploying, and managing machine learning models. Here's an example of how to use the Gemini 3.7 Flash model with the Hugging Face Transformers library in Python:&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;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoModelForCausalLM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;

&lt;span class="n"&gt;gemini_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModelForCausalLM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;google/gemini-3.7-flash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;gemini_tokenizer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoTokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;google/gemini-3.7-flash&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Hello, how are you?&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;gemini_tokenizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;return_tensors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pt&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gemini_model&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="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gemini_tokenizer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;skip_special_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code snippet demonstrates how to use the Gemini 3.7 Flash model to generate text based on a given input.&lt;/p&gt;

&lt;h2&gt;
  
  
  My take
&lt;/h2&gt;

&lt;p&gt;As the founder of Griffin AI Tech, I'm excited to explore the possibilities of Gemini 3.7 Flash and its potential to drive innovation in the field of AI and machine learning. I believe that this technology has the potential to democratize access to AI and machine learning, enabling more developers to build powerful and complex models. However, I also recognize that there are challenges to be addressed, such as ensuring the responsible use of AI and mitigating potential biases. Overall, I'm eager to see how Gemini 3.7 Flash will be used in real-world applications and how it will shape the future of AI and machine learning.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>mlops</category>
    </item>
    <item>
      <title>Three Different RAG Bugs Produce the Same Wrong Answer. Without a Trace You Cannot Tell Them Apart</title>
      <dc:creator>Devanshu Biswas</dc:creator>
      <pubDate>Thu, 13 Aug 2026 22:47:22 +0000</pubDate>
      <link>https://dev.to/dev48v/three-different-rag-bugs-produce-the-same-wrong-answer-without-a-trace-you-cannot-tell-them-apart-1jn5</link>
      <guid>https://dev.to/dev48v/three-different-rag-bugs-produce-the-same-wrong-answer-without-a-trace-you-cannot-tell-them-apart-1jn5</guid>
      <description>&lt;p&gt;A user reports that your RAG system gave a wrong answer. You have exactly one string to work from. Here are three things that could have happened, and they are indistinguishable from the outside:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval never saw the right chunk.&lt;/strong&gt; The embedder put the query somewhere unhelpful, or the chunker split the passage down the middle, so the evidence was never a candidate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The right chunk was retrieved and then thrown away.&lt;/strong&gt; It made the shortlist, and the context budget truncated it out before the prompt was built. Retrieval did its job perfectly and the model never saw the result.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything arrived intact and the model ignored it.&lt;/strong&gt; The correct passage was sitting in the prompt, cited-and-all, and the answer went somewhere else.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Three different bugs. Three different fixes — re-ingest with a different embedder, raise &lt;code&gt;max_context_chars&lt;/code&gt;, rewrite the system prompt. And &lt;strong&gt;one identical symptom&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Guessing between them is how a team spends a fortnight tuning a prompt when the chunker was at fault. That is the entire reason evaluation and observability is level 1 of this stack rather than a nice-to-have you add later: &lt;strong&gt;you cannot debug levels 3 through 8 without it&lt;/strong&gt;, because every one of them fails into the same wrong string.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Live, everything computed in your browser:&lt;/strong&gt; &lt;a href="https://dev48.infy.uk/arcrector/level1-observability.html" rel="noopener noreferrer"&gt;https://dev48.infy.uk/arcrector/level1-observability.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built the instrument that ends the guessing as part of &lt;strong&gt;Arc Rector&lt;/strong&gt;, a nine-level agentic RAG stack where every layer is a swappable adapter and every default runs with &lt;strong&gt;zero vendor bills and no API keys&lt;/strong&gt;. The default here is &lt;strong&gt;Langfuse&lt;/strong&gt; (MIT, self-hosted) plus &lt;strong&gt;Ragas&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A span is a stopwatch with a name and a parent
&lt;/h2&gt;

&lt;p&gt;That is genuinely the whole primitive. Four fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name  ·  start  ·  end  ·  parent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything a tracing UI does is arithmetic on top of those four. The nesting is what makes it useful: &lt;code&gt;retrieve&lt;/code&gt; is the parent of &lt;code&gt;embed_query&lt;/code&gt;, &lt;code&gt;vector.search&lt;/code&gt; and &lt;code&gt;rerank&lt;/code&gt;, so when retrieval is slow you &lt;strong&gt;descend&lt;/strong&gt; rather than guess.&lt;/p&gt;

&lt;p&gt;Arc Rector expresses it as a context manager, which is the right shape for two reasons — a &lt;code&gt;with&lt;/code&gt; block cannot leak an unclosed span even when the body raises, and the nesting &lt;em&gt;is&lt;/em&gt; the Python call stack rather than a parallel structure you maintain by hand.&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;Tracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ABC&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;L1 -- observability. Records nested spans for every step of a run.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;name&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tracer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="nd"&gt;@abstractmethod&lt;/span&gt;
    &lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;span&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;name&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;**&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Iterator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SpanHandle&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;Open a span; yields a handle whose `.update(output=...)` records results.&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;flush&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trace_url&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="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;return&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;last_trace_id&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="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;return&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that it yields a &lt;code&gt;SpanHandle&lt;/code&gt; rather than the backend's own object. No caller ever touches a Langfuse or OpenTelemetry type, which is exactly what makes swapping the backend a one-word change instead of a refactor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Write the no-op tracer first
&lt;/h2&gt;

&lt;p&gt;Build the null implementation &lt;em&gt;before&lt;/em&gt; the real one and observability stops being a dependency. The pipeline keeps its &lt;code&gt;with tracer.span(...)&lt;/code&gt; structure whether or not a backend exists, the test suite runs with no containers, and "no tracing" is a supported low-RAM configuration rather than an outage.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;record=True&lt;/code&gt; flag is the part worth stealing:&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;NoopTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tracer&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;none&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;__init__&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="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;_&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;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;record&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;spans&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;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;span&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;name&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;**&lt;/span&gt;&lt;span class="n"&gt;attrs&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;record&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;spans&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;_NullSpan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# the test that keeps every framework adapter honest
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_langgraph_opens_every_span&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;tracer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;NoopTracer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;record&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nc"&gt;LangGraphAgent&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;what is the default vector store?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spans&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spans&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The null tracer became a &lt;strong&gt;test instrument&lt;/strong&gt;: it proves every agent-framework adapter really instruments every step, which is otherwise the sort of thing that silently rots.&lt;/p&gt;

&lt;h2&gt;
  
  
  Self-time is where the time actually went
&lt;/h2&gt;

&lt;p&gt;"Retrieval took 38 ms" is not a finding, because retrieval &lt;em&gt;contains&lt;/em&gt; three other things. What you want is a span's duration minus the sum of its &lt;strong&gt;direct&lt;/strong&gt; children's durations:&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;self_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;child&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;direct_children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the difference between "&lt;code&gt;retrieve&lt;/code&gt; took 38 ms" and "&lt;code&gt;retrieve&lt;/code&gt; itself took 0.4 ms and spent 37.6 of it inside &lt;code&gt;vector.search&lt;/code&gt;".&lt;/p&gt;

&lt;p&gt;Two properties are worth stating because they are also the invariants worth asserting in tests. &lt;strong&gt;Self-time is never negative&lt;/strong&gt; — children open and close inside their parent's &lt;code&gt;with&lt;/code&gt; block, so their durations cannot exceed it; a negative self-time in a real system means your clock is wrong or a span escaped its parent, and both are bugs. And &lt;strong&gt;a child's start and end must lie inside its parent's&lt;/strong&gt;, which is what lets a UI draw nested bars with real offsets instead of a flat list.&lt;/p&gt;

&lt;h2&gt;
  
  
  The attributes are the value, not the timings
&lt;/h2&gt;

&lt;p&gt;Duration tells you &lt;em&gt;where&lt;/em&gt;. Attributes tell you &lt;em&gt;what&lt;/em&gt;. This is the section that actually answers the three-identical-bugs problem:&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;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;arc-rector.turn&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;framework&lt;/span&gt;&lt;span class="o"&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;question&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;turn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;guardrails.input&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;question&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;sp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;guard_in&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;guardrails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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;allowed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;guard_in&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;guard_in&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory.recall&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&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;sp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;memories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rag_core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;memories&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;retrieve&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fetch_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fetch_k&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;sp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rag_core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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;chunk_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;score&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&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="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                           &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&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;h&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;hits&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;as_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generation&lt;/span&gt;&lt;span class="sh"&gt;"&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="nf"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inference&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;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="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;prompt&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;sp&lt;/span&gt;&lt;span class="p"&gt;:&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;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inference&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;complete&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;system&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rag_core&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;sp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;turn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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;answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;citations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;citations&lt;/span&gt;&lt;span class="p"&gt;)})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That turns a trace from a performance tool into a &lt;strong&gt;correctness&lt;/strong&gt; tool. With the chunk ids and scores on &lt;code&gt;retrieve&lt;/code&gt; and the full prompt on &lt;code&gt;generate&lt;/code&gt;, the three failure modes from the opening separate instantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the right chunk id is &lt;strong&gt;not in &lt;code&gt;retrieve&lt;/code&gt;'s output&lt;/strong&gt; → retrieval bug, go and look at chunk size, the embedder, &lt;code&gt;top_k&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the chunk id is in &lt;code&gt;retrieve&lt;/code&gt; but &lt;strong&gt;not in &lt;code&gt;generate&lt;/code&gt;'s input&lt;/strong&gt; → the budget truncated it, go and look at &lt;code&gt;max_context_chars&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;it is in &lt;code&gt;generate&lt;/code&gt;'s input and the answer contradicts it → &lt;strong&gt;generation bug&lt;/strong&gt;, go and look at the system prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the difference between "retrieve was slow" and "retrieve returned chunk 7 at 0.61 when chunk 12 was the right one".&lt;/p&gt;

&lt;p&gt;Two cautions. Marking the generation span &lt;code&gt;as_type="generation"&lt;/code&gt; is not decoration — both Langfuse and Phoenix render generations differently from plain spans, prompt and completion side by side, with token accounting where the backend can compute it. And &lt;strong&gt;whatever you attach is stored&lt;/strong&gt;: putting a full prompt on every span is how a trace backend's disk fills up, which is what retention policy and sampling exist for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug that cost an evening, and it looks completely reasonable
&lt;/h2&gt;

&lt;p&gt;Telemetry must not break the request it observes. Every &lt;code&gt;update()&lt;/code&gt; is wrapped in a bare &lt;code&gt;try/except: pass&lt;/code&gt;, and an unreachable backend degrades to a dead span whose methods do nothing, so a Langfuse outage costs you visibility and not availability. That part is obvious.&lt;/p&gt;

&lt;p&gt;This part is not, and it is the best thing in the whole level:&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="c1"&gt;# WRONG - looks equivalent to entering and exiting by hand. It is not.
&lt;/span&gt;&lt;span class="nd"&gt;@contextmanager&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;span&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;):&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;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;attrs&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;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;_LangfuseSpan&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="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;_DeadSpan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;          &lt;span class="c1"&gt;# second yield -&amp;gt; RuntimeError, traceback lost
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the &lt;strong&gt;caller's&lt;/strong&gt; block raises — an Ollama read timeout, say — &lt;code&gt;contextlib&lt;/code&gt; throws that exception in at the &lt;code&gt;yield&lt;/code&gt;. Your &lt;code&gt;except&lt;/code&gt; catches it, you yield a second time, and &lt;code&gt;contextlib&lt;/code&gt; raises &lt;code&gt;RuntimeError: generator didn't stop after throw()&lt;/code&gt; &lt;strong&gt;with the original traceback gone&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The user's real error message became a &lt;code&gt;contextlib&lt;/code&gt; internal. Losing the receipt is annoying; losing the &lt;em&gt;explanation&lt;/em&gt; is a day.&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="c1"&gt;# RIGHT - drive __enter__ and __exit__ yourself
&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;raw_span&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nf"&gt;_DeadSpan&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="k"&gt;return&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;yield&lt;/span&gt; &lt;span class="nf"&gt;_LangfuseSpan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_span&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exc_info&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;   &lt;span class="c1"&gt;# pass the real exception through
&lt;/span&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a regression test pinning it. &lt;strong&gt;Tracing must not break the request it observes, and it must not hide why the request broke.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;flush()&lt;/code&gt; — the spans you never see
&lt;/h2&gt;

&lt;p&gt;Every serious tracing SDK buffers spans and ships them on a background thread, because a synchronous HTTP call per span would make tracing more expensive than the thing it traces.&lt;/p&gt;

&lt;p&gt;The consequence is specific and bites exactly once per project: &lt;strong&gt;a CLI run that finishes and exits can terminate the exporter before it has sent anything.&lt;/strong&gt; Clean run, empty trace list. It feels like a configuration problem and it is a lifecycle problem — a web server hides it entirely, because the process lives long enough for the batch to go out on its own, which is why it reliably surfaces the first time you run the same code from a script.&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;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last_trace_id&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;   &lt;span class="c1"&gt;# hang it on the answer
&lt;/span&gt;&lt;span class="n"&gt;deps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tracer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flush&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;                        &lt;span class="c1"&gt;# a CLI exits; batched spans do not survive that
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is a nastier second-order version: &lt;strong&gt;a process that crashes loses its buffer too&lt;/strong&gt;, so the traces you most want — from the run that fell over — are the ones most likely to be missing.&lt;/p&gt;

&lt;p&gt;Capture the trace id off the raw span as it opens and hang it on the answer, and every answer in the UI carries a link straight to its own receipt. That single link is what turns "it gave a bad answer" into a bug report with evidence attached.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mean lies
&lt;/h2&gt;

&lt;p&gt;Latency distributions in a RAG system are not symmetric. They are a tight body plus a long right tail, produced by a cache miss, a cold model, a retry, a GC pause, or one question whose prompt is twice as long as the others.&lt;/p&gt;

&lt;p&gt;A mean averages the tail away &lt;strong&gt;by construction&lt;/strong&gt;. A p95 is an observation that actually happened to somebody.&lt;/p&gt;

&lt;p&gt;Percentiles are also the only honest way to talk about a change. "The mean went from 380 ms to 372 ms" is noise; "p95 went from 2.1 s to 900 ms" is a fix. Compute them by nearest rank — sort, take element &lt;code&gt;ceil(p/100 × n)&lt;/code&gt; — and know the rule that catches people out in aggregation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Percentiles do not average.&lt;/strong&gt; The p95 of two services is not the mean of their p95s. Aggregate raw samples or a histogram, never pre-computed percentiles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The live panel makes the asymmetry visible: turn the slow path on for 1 run in 20 and the mean drifts by a few per cent while p95 moves to a different part of the chart — because 5% of runs are now the slow path and p95 is looking exactly there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sampling is cheap storage paid for in accuracy
&lt;/h2&gt;

&lt;p&gt;Eventually somebody suggests keeping one trace in ten. That is fine, and it is not free.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Head-based sampling&lt;/strong&gt; hashes the trace id and keeps 1-in-N, deciding &lt;em&gt;before&lt;/em&gt; the work starts. It is cheap, stateless, and every service in a distributed trace reaches the same decision from the same id. It is also &lt;strong&gt;blind by construction&lt;/strong&gt;: it cannot preferentially keep the slow traces, because at decision time nothing knows the trace will be slow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tail-based sampling&lt;/strong&gt; buffers a whole trace and decides after it completes — keep everything with an error, everything over 2 s, and 1% of the rest. That is what you actually want, and it needs a collector holding spans in memory.&lt;/p&gt;

&lt;p&gt;The number nobody puts on a dashboard is the error that sampling puts on the percentile you are reading. At 1-in-2 it is usually small. At 1-in-64 over a few hundred runs, &lt;strong&gt;your p95 is being estimated from a handful of observations and can be wildly wrong in either direction — and it will still render as a confident number with two decimal places.&lt;/strong&gt; Langfuse exposes &lt;code&gt;LANGFUSE_SAMPLE_RATE&lt;/code&gt;; Phoenix inherits OpenTelemetry's &lt;code&gt;TraceIdRatioBased&lt;/code&gt; sampler. Neither shows you the error bar, which is why the page computes it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The other half: four metrics, two jobs
&lt;/h2&gt;

&lt;p&gt;A trace tells you what happened on one turn. It cannot tell you whether the change you just made helped. For that you need a marked exam — and the design decision that matters is &lt;strong&gt;scoring retrieval and generation separately&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ragas' four metrics split cleanly:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;metric&lt;/th&gt;
&lt;th&gt;scores&lt;/th&gt;
&lt;th&gt;question it answers&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;context precision&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;retrieval&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;was what you fetched on-topic and well-ranked?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;context recall&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;retrieval&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;did it contain what the reference answer needed?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;faithfulness&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;generation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;is every claim supported by the retrieved context?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;answer relevancy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;generation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;does the answer address the question asked?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And the diagnostic rule falls straight out of the split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;recall low, faithfulness high&lt;/strong&gt; → the model faithfully used context that did not contain the answer. A &lt;strong&gt;retrieval&lt;/strong&gt; bug. Go and look at chunk size, the embedder, the prefixes, &lt;code&gt;top_k&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;recall high, faithfulness low&lt;/strong&gt; → the evidence was right there and the answer went elsewhere. A &lt;strong&gt;generation&lt;/strong&gt; bug. Go and look at the system prompt, the model, the context ordering.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Merge the four into one headline score and you have thrown that diagnosis away. That is the whole argument for keeping the halves apart, and the live panel makes it provable rather than assertable: force &lt;code&gt;top_k&lt;/code&gt; to 1 and the retrieval metrics drop while faithfulness holds; generate the answer from a &lt;em&gt;different&lt;/em&gt; question and the retrieval metrics are untouched while faithfulness and relevancy collapse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Eight pairs is a regression check, not a benchmark
&lt;/h2&gt;

&lt;p&gt;The gold set here is eight hand-written question/reference pairs, with &lt;strong&gt;every reference written from the demo corpus&lt;/strong&gt; so the harness measures the system and not the corpus.&lt;/p&gt;

&lt;p&gt;Eight pairs will not tell you your RAG is good, and the repo says so plainly. It will tell you whether the &lt;code&gt;chunk_size&lt;/code&gt; you just changed made things better or worse — a question no amount of eyeballing one answer can settle, because a single answer varies with the question you happened to pick.&lt;/p&gt;

&lt;p&gt;Two disciplines make it work. &lt;strong&gt;Change one knob at a time&lt;/strong&gt;, or you learn nothing about which knob did it. And &lt;strong&gt;treat absolute numbers as directional&lt;/strong&gt;: a small local judge grades differently from a frontier one, and a proxy metric grades differently again, so the delta between runs on the same setup is the signal and the absolute value is decoration.&lt;/p&gt;

&lt;p&gt;When you outgrow eight pairs, the next step is not a public benchmark. It is fifty pairs drawn from questions your users actually asked and got wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The judge is the slowest thing you own
&lt;/h2&gt;

&lt;p&gt;Ragas' metrics are LLM-judged, and that is the point of them: a judge can tell that a correct paraphrase is correct, and token overlap never will. It is also the cost, in two ways people hit in order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, it bills you by default.&lt;/strong&gt; Ragas reaches for OpenAI for &lt;em&gt;both&lt;/em&gt; its judge model and its embeddings, so an out-of-the-box run is a vendor bill you did not ask for. Pointing both at the same local Ollama the rest of the stack uses makes it genuinely zero-key:&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;chat&lt;/span&gt;     &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ChatOllama&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;llama3.2:3b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OLLAMA&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&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="n"&gt;embedder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OllamaEmbeddings&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;nomic-embed-text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;base_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OLLAMA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LangchainLLMWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;LangchainEmbeddingsWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embedder&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;metric&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;            &lt;span class="c1"&gt;# metrics carry their OWN handles --
&lt;/span&gt;    &lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;llm&lt;/span&gt;              &lt;span class="c1"&gt;# setting these is what keeps the judge
&lt;/span&gt;    &lt;span class="n"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;  &lt;span class="c1"&gt;# local instead of reaching for OpenAI
&lt;/span&gt;
&lt;span class="n"&gt;run_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RunConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# default 180s: fine hosted, fatal local
&lt;/span&gt;                       &lt;span class="n"&gt;max_workers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;# Ollama serialises; parallel just queues
&lt;/span&gt;                       &lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Then the arithmetic bites.&lt;/strong&gt; A 3B model on a CPU-only box needs 45–60 s per generation, each metric makes several calls per sample, and Ragas' default per-job timeout is &lt;strong&gt;180 seconds&lt;/strong&gt; — designed for a hosted judge and far too short for a local one. Every metric times out and every score comes back &lt;code&gt;n/a&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Honest outcome on my development machine, and I would rather print it than round it off: &lt;strong&gt;the path runs, the judge really receives calls, one metric took 12 minutes 22 seconds&lt;/strong&gt;, and the numbers actually reported came from the deterministic fallback. On a GPU box the defaults are fine. Say which one you are on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Always ship an evaluator that cannot fail
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;fallback_to_builtin: true&lt;/code&gt; is one line of config and it is the difference between an eval harness and an eval &lt;em&gt;aspiration&lt;/em&gt;.&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;evaluate&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;samples&lt;/span&gt;&lt;span class="p"&gt;):&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_evaluate_with_ragas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&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="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&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;fallback_to_builtin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;raise&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BuiltinEvaluator&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# deterministic proxies
&lt;/span&gt;        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;backend&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;builtin (ragas unavailable)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ragas_error&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)[:&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;            &lt;span class="c1"&gt;# say WHY, in the output
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The builtin computes four things from token overlap and citation structure — &lt;code&gt;context_recall&lt;/code&gt;, &lt;code&gt;answer_correctness&lt;/code&gt; as token F1, &lt;code&gt;faithfulness_proxy&lt;/code&gt; and &lt;code&gt;citation_rate&lt;/code&gt; — with no model, no network and no judge. So &lt;code&gt;make eval&lt;/code&gt; always produces numbers, and the harness itself is unit-testable.&lt;/p&gt;

&lt;p&gt;The repo calls them &lt;strong&gt;proxies&lt;/strong&gt; in the module docstring and never upgrades that word. &lt;code&gt;faithfulness_proxy&lt;/code&gt; cannot tell a correct paraphrase from an invented claim that happens to reuse context vocabulary, and pretending otherwise would be worse than having no metric at all.&lt;/p&gt;

&lt;p&gt;Note what the fallback &lt;em&gt;also&lt;/em&gt; does: it writes &lt;code&gt;backend: "builtin (ragas unavailable)"&lt;/code&gt; and a truncated &lt;code&gt;ragas_error&lt;/code&gt; into the result, so the output says which evaluator produced it and why. &lt;strong&gt;A fallback that hides the fact that it fired is a lie with a nice interface.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two boot bugs neither of which is findable by reading
&lt;/h2&gt;

&lt;p&gt;Self-hosting Langfuse is five containers, not one — the Next.js web app, Postgres for metadata, ClickHouse for span data, Redis for queueing, MinIO for large payloads — with &lt;code&gt;LANGFUSE_INIT_*&lt;/code&gt; seeding an organisation, a project and an API key pair so first boot needs no account and no clicking.&lt;/p&gt;

&lt;p&gt;Both of these cost an evening of actually running it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# MUST be quoted. This particular 64-char hex key happens to be all digits,&lt;/span&gt;
&lt;span class="c1"&gt;# and unquoted, YAML parses it as the integer 0 -- which Langfuse rejects&lt;/span&gt;
&lt;span class="c1"&gt;# with a Zod error about the key not being 256 bits.&lt;/span&gt;
&lt;span class="na"&gt;ENCRYPTION_KEY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then ClickHouse restart-looped because the tuning file mounted into it had a &lt;code&gt;--&lt;/code&gt; inside an XML comment. That is illegal in XML, so the config never parsed, so ClickHouse never started, so Langfuse's whole dependency chain sat waiting on a healthcheck that would never go green.&lt;/p&gt;

&lt;p&gt;Neither is in any documentation. Both are the reason I keep saying "found by running it".&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification
&lt;/h2&gt;

&lt;p&gt;The trace really came back. Reading it out of the self-hosted Langfuse through its own API returned trace &lt;code&gt;5fd2af30…&lt;/code&gt; with &lt;strong&gt;7 nested spans&lt;/strong&gt; — &lt;code&gt;arc-rector.turn&lt;/code&gt; wrapping &lt;code&gt;guardrails.input&lt;/code&gt;, &lt;code&gt;memory.recall&lt;/code&gt;, &lt;code&gt;retrieve&lt;/code&gt;, &lt;code&gt;generate&lt;/code&gt;, &lt;code&gt;guardrails.output&lt;/code&gt; and &lt;code&gt;memory.write&lt;/code&gt; — as part of a &lt;strong&gt;5-of-5&lt;/strong&gt; verified local run against &lt;strong&gt;21 real 768-dimensional vectors&lt;/strong&gt; in Qdrant. The repo carries &lt;strong&gt;216 pytest cases&lt;/strong&gt; that need no Docker, no Ollama, no network and no model.&lt;/p&gt;

&lt;p&gt;The level page ships four panels that genuinely compute in your browser: a real nested span recorder with real &lt;code&gt;performance.now()&lt;/code&gt; timings and real self-time arithmetic, a real pipeline scored on six gold pairs, real nearest-rank percentiles over really-run samples, and a real hash-based sampler whose estimation error is &lt;em&gt;measured&lt;/em&gt; rather than asserted.&lt;/p&gt;

&lt;p&gt;What that page is not: there is no OTLP exporter, no collector and no server, so &lt;code&gt;flush()&lt;/code&gt; has nothing to flush there. One process means parent/child is a stack, where a real trace crosses process boundaries by carrying a trace id and a span id in a header. There is no LLM judge on the page — the four metrics are clearly-labelled overlap and cosine proxies, and the milliseconds are JavaScript arithmetic, so the &lt;em&gt;shape&lt;/em&gt; is real and the absolute numbers mean nothing outside the tab.&lt;/p&gt;

&lt;p&gt;And the framing for the project, stated rather than left to be inferred: this is &lt;strong&gt;a complete, correct, zero-cost starting point — not a production system.&lt;/strong&gt; No auth, no multi-tenancy, no rate limiting, no retention policy on trace storage. &lt;code&gt;PRODUCTION.md&lt;/code&gt; lists the gap rather than hiding it.&lt;/p&gt;

&lt;p&gt;If you take one thing from this: &lt;strong&gt;score retrieval and generation separately.&lt;/strong&gt; One blended number tells you something broke. Two numbers tell you which half to go and fix, and that is the entire difference between having an instrument and having an opinion.&lt;/p&gt;

&lt;p&gt;Live page: &lt;a href="https://dev48.infy.uk/arcrector/level1-observability.html" rel="noopener noreferrer"&gt;https://dev48.infy.uk/arcrector/level1-observability.html&lt;/a&gt;&lt;br&gt;
Repo: &lt;a href="https://github.com/dev48v/arc-rector" rel="noopener noreferrer"&gt;https://github.com/dev48v/arc-rector&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>observability</category>
      <category>mlops</category>
    </item>
    <item>
      <title>Production ML Pipelines: From Notebook to Serving</title>
      <dc:creator>Aarush Karak</dc:creator>
      <pubDate>Thu, 13 Aug 2026 18:17:55 +0000</pubDate>
      <link>https://dev.to/3ni8ma/production-ml-pipelines-from-notebook-to-serving-39j</link>
      <guid>https://dev.to/3ni8ma/production-ml-pipelines-from-notebook-to-serving-39j</guid>
      <description>&lt;h2&gt;
  
  
  The Notebook Problem
&lt;/h2&gt;

&lt;p&gt;Jupyter notebooks don't scale. This post covers feature stores, model versioning, A/B testing infrastructure, monitoring drift, and the engineering practices that separate research ML from production ML systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Notebook Problem
&lt;/h2&gt;

&lt;p&gt;Jupyter notebooks mix code, results, and narrative — great for exploration, terrible for production. Cells executed out of order produce unreproducible states. No versioning of data or parameters. No testing. The solution: refactor notebooks into modular Python packages with entry points, type hints, and unit tests before deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Stores: Curated Data
&lt;/h2&gt;

&lt;p&gt;Features are computed once and served for both training and inference. A feature store (Feast, Tecton) handles: point-in-time correct joins (avoiding data leakage), feature serving with low latency, and feature versioning when source data changes. Without a feature store, training/serving skew is inevitable — the training code computes features differently than the serving code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Model Versioning and Registry
&lt;/h2&gt;

&lt;p&gt;Models are artifacts with metadata: training hyperparameters, validation metrics, dataset hash, framework version, and training code commit. An MLflow or Weights &amp;amp; Biases registry tags each model version as staging, production, or archived. Models are deployed by tag, not by file path — enabling instant rollbacks.&lt;/p&gt;

&lt;h2&gt;
  
  
  A/B Testing Infrastructure
&lt;/h2&gt;

&lt;p&gt;Production ML systems need controlled experiments: 10% of traffic gets model v2, 90% gets model v1. The serving layer routes requests based on a shadow flag, and comparison metrics (accuracy, latency, cost) are logged to a separate analytics pipeline. Automated rollback triggers if metrics degrade beyond thresholds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring for Drift
&lt;/h2&gt;

&lt;p&gt;Data drift (input distribution changes), concept drift (relationship between input and target changes), and model degradation (accuracy decay over time) must be detected automatically. Monitoring computes statistical tests (KS test, population stability index) on prediction distributions per time window and alerts when drift exceeds thresholds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Prophet Forecasting Pipeline
&lt;/h2&gt;

&lt;p&gt;AuraFinance uses Prophet for 30-day stock price forecasts. The pipeline: fetch 2 years of daily close prices, log-transform for variance stabilization, fit Prophet with yearly/weekly seasonality and holiday effects, cache the forecast for 12 hours. The 80% confidence interval provides a realistic uncertainty range.&lt;/p&gt;




&lt;p&gt;Production ML is an engineering discipline, not a data science exercise. Feature stores, model registries, A/B testing, and drift monitoring transform ML from a notebook experiment into a reliable, auditable system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/3ni8ma/aura-finance" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>pipelines</category>
      <category>featurestores</category>
    </item>
    <item>
      <title>Your ML accuracy might be quietly cheating</title>
      <dc:creator>Divyakush Punjabi</dc:creator>
      <pubDate>Thu, 13 Aug 2026 15:11:21 +0000</pubDate>
      <link>https://dev.to/dev-into-space/your-ml-accuracy-might-be-quietly-cheating-1jf3</link>
      <guid>https://dev.to/dev-into-space/your-ml-accuracy-might-be-quietly-cheating-1jf3</guid>
      <description>&lt;p&gt;&lt;strong&gt;If your model predicts sequences and you evaluated it on a random split, your accuracy number is probably lying to you.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's the leak. You shuffle your data and carve out a random test set. But if behavior unfolds over time, a random split drops &lt;em&gt;future&lt;/em&gt; events into the training set and &lt;em&gt;past&lt;/em&gt; events into the test set. Your model gets to peek at what comes later, then gets graded on what came before. The score looks fantastic and means very little.&lt;/p&gt;

&lt;p&gt;If instead you split on &lt;em&gt;time&lt;/em&gt; — train on the past, test strictly on the future, the way the model will actually be used — the number drops. And that lower number is the honest one. It's the only one that tells you whether the thing will work in production.&lt;/p&gt;

&lt;p&gt;I held that line building a &lt;a href="https://www.divyakush.com" rel="noopener noreferrer"&gt;sequential recommender&lt;/a&gt;: evaluated on a temporal, leave-last-out split so nothing from the future ever leaked backward, with a simpler baseline kept alongside so every claim was measured against something real.&lt;/p&gt;

&lt;p&gt;An unflattering metric you trust beats a beautiful one you can't. When a result looks too good, suspect your split before you celebrate.&lt;/p&gt;




&lt;p&gt;More ML notes and projects → &lt;a href="https://www.divyakush.com" rel="noopener noreferrer"&gt;www.divyakush.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>datascience</category>
      <category>mlops</category>
      <category>python</category>
    </item>
    <item>
      <title>Master MLOps &amp; AIOps Training | MLOps &amp; AIOps Course</title>
      <dc:creator>vamsi visualpath</dc:creator>
      <pubDate>Thu, 13 Aug 2026 11:22:15 +0000</pubDate>
      <link>https://dev.to/vamsi_visualpath_826a9ad2/master-mlops-aiops-training-mlops-aiops-course-2g8j</link>
      <guid>https://dev.to/vamsi_visualpath_826a9ad2/master-mlops-aiops-training-mlops-aiops-course-2g8j</guid>
      <description>&lt;p&gt;🚀 𝗕𝘂𝗶𝗹𝗱 𝗙𝘂𝘁𝘂𝗿𝗲-𝗥𝗲𝗮𝗱𝘆 𝗔𝗜 𝗦𝗸𝗶𝗹𝗹𝘀 𝘄𝗶𝘁𝗵 𝗠𝗟𝗢𝗽𝘀 &amp;amp; 𝗔𝗜𝗢𝗽𝘀 𝗧𝗿𝗮𝗶𝗻𝗶𝗻𝗴!&lt;br&gt;
🎯 Gain practical skills to develop, automate, deploy, monitor, and scale production-ready AI systems through hands-on learning with Visualpath.&lt;/p&gt;

&lt;p&gt;✨ 𝗪𝗵𝗮𝘁 𝗬𝗼𝘂’𝗹𝗹 𝗟𝗲𝗮𝗿𝗻:&lt;br&gt;
✅ Machine Learning with Python&lt;br&gt;
✅ MLflow &amp;amp; Kubeflow for Model Management&lt;br&gt;
✅ Docker, Kubernetes &amp;amp; Git&lt;br&gt;
✅ CI/CD &amp;amp; Automated ML Workflows&lt;br&gt;
✅ AWS EKS &amp;amp; Cloud AI Deployment&lt;br&gt;
✅ AI Automation &amp;amp; AIOps&lt;br&gt;
✅ Prometheus, Grafana &amp;amp; AI Monitoring&lt;br&gt;
✅ End-to-End AI Model Deployment&lt;/p&gt;

&lt;p&gt;🎁 𝗙𝗥𝗘𝗘 𝗟𝗶𝘃𝗲 𝗗𝗲𝗺𝗼 𝗔𝘃𝗮𝗶𝗹𝗮𝗯𝗹𝗲! &lt;br&gt;
📞 𝗖𝗮𝗹𝗹: +91 7032290546&lt;br&gt;
🌐 𝗖𝗼𝘂𝗿𝘀𝗲 𝗗𝗲𝘁𝗮𝗶𝗹𝘀: &lt;a href="https://www.visualpath.in/mlops-aiops-online-training.html" rel="noopener noreferrer"&gt;https://www.visualpath.in/mlops-aiops-online-training.html&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;💡 𝗗𝗲𝘃𝗲𝗹𝗼𝗽. 𝗔𝘂𝘁𝗼𝗺𝗮𝘁𝗲. 𝗗𝗲𝗽𝗹𝗼𝘆. 𝗠𝗼𝗻𝗶𝘁𝗼𝗿. 𝗕𝘂𝗶𝗹𝗱 𝗬𝗼𝘂𝗿 𝗙𝘂𝘁𝘂𝗿𝗲 𝘄𝗶𝘁𝗵 𝗠𝗟𝗢𝗽𝘀 &amp;amp; 𝗔𝗜𝗢𝗽𝘀!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mlops</category>
      <category>machinelearning</category>
      <category>python</category>
    </item>
    <item>
      <title>qModel OSS v1.4.0: One-Click API Publishing &amp; Full-Link Computing Tasks Bring Models to Life</title>
      <dc:creator>TongWu</dc:creator>
      <pubDate>Thu, 13 Aug 2026 06:57:52 +0000</pubDate>
      <link>https://dev.to/tongwu/qmodel-oss-v140-one-click-api-publishing-full-link-computing-tasks-bring-models-to-life-l1c</link>
      <guid>https://dev.to/tongwu/qmodel-oss-v140-one-click-api-publishing-full-link-computing-tasks-bring-models-to-life-l1c</guid>
      <description>&lt;p&gt;In traditional algorithm development workflows, models often get stuck in the internal debugging phase. They are "runnable," but not quite ready for production. &lt;/p&gt;

&lt;p&gt;Common bottlenecks include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployed models can only be called within the platform, making external business integration difficult.&lt;/li&gt;
&lt;li&gt;Computing task management is fragmented, lacking centralized control over execution and results.&lt;/li&gt;
&lt;li&gt;Missing execution records make troubleshooting and task tracking costly.&lt;/li&gt;
&lt;li&gt;Model outputs are displayed as raw data, lacking intuitive visualization for complex results.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To bridge the gap from development to practical application, &lt;strong&gt;qModel Algorithm Model Platform Open Source v1.4.0&lt;/strong&gt; is officially released! &lt;/p&gt;

&lt;p&gt;This update focuses on model service invocation, computing task management, execution tracking, and result visualization, completing the workflow from model configuration to result analysis.&lt;/p&gt;

&lt;p&gt;Here is a technical breakdown of the core capability upgrades in v1.4.0.&lt;/p&gt;




&lt;h2&gt;
  
  
  One-Click API Service Publishing
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;qmodelv1.4.0 introduces the ability to publish model API services. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For already deployed models, users can quickly expose capabilities to third-party systems via remote API calls. &lt;/p&gt;

&lt;p&gt;The platform provides comprehensive API invocation information, including Base URL configuration, interface path definitions, authentication method descriptions, and parameter details. &lt;/p&gt;

&lt;p&gt;Users can combine the Base URL with specific interface paths to generate complete call addresses. &lt;/p&gt;

&lt;p&gt;Additionally, API keys can be centrally viewed and managed through the key management module, enhancing security and maintainability during invocation.&lt;/p&gt;




&lt;h3&gt;
  
  
  Brand-New Model Computing Task Management
&lt;/h3&gt;

&lt;p&gt;To improve the manageability of the model running process, qModel v1.4.0 adds a dedicated model computing task list. The platform uniformly displays all computing task information, including running status, execution duration, basic task details, and search/management capabilities. Through centralized task management, users can gain a more intuitive understanding of current model computing operations, significantly reducing management complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Task Creation with Flexible Strategy Configuration
&lt;/h3&gt;

&lt;p&gt;During the computing task creation process, v1.4.0 supports visual task configuration. Users can associate existing models, configure task execution strategies, and set computing parameters for different business scenarios. This ensures that the model invocation process is no longer dependent on fixed workflows but can be flexibly adjusted according to actual computing needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Unified Input Parameter Management
&lt;/h3&gt;

&lt;p&gt;On the computing task details page, the platform now displays input parameters (Tags). Input information configured during task creation is presented uniformly, helping users quickly confirm the data parameters used, the model invocation context, and the task execution configuration. This further enhances task comprehensibility and troubleshooting efficiency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Complete Execution Records for Traceability
&lt;/h3&gt;

&lt;p&gt;qModel v1.4.0 fully records the model invocation process. The platform saves every execution history, displaying call time, execution status, and task running information in the execution record list. This allows users to quickly trace historical tasks, forming a complete model computing tracking chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Execution Details Combined with Resource Monitoring
&lt;/h3&gt;

&lt;p&gt;After a computing task is completed, the platform displays the model's output results in a structured format, such as JSON. Simultaneously, qModel's built-in resource monitoring probes collect hardware resource usage during execution. Currently, it supports displaying average CPU usage, peak memory consumption, and execution duration. These resource metrics help developers further analyze model running status, providing references for performance optimization and resource scheduling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Display for Model Computing Results
&lt;/h3&gt;

&lt;p&gt;Addressing the issue of monotonous output display, v1.4.0 enhances result visualization. On the result display page, the left side shows the JSON data structure returned by the model, while the right side visually renders the parsed JSON data. &lt;/p&gt;

&lt;p&gt;Currently supported visualization components include Base64 image parsing and line charts. Users can add corresponding display components based on the output data structure and configure the component name, type, and bound field keys for intuitive result presentation. Configured components also support subsequent adjustments, including modification, deletion, and downloading.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Bottom Line
&lt;/h3&gt;

&lt;p&gt;qModel OSS v1.4.0 focuses on perfecting the application chain from "runnable" to "callable, manageable, and analyzable." This upgrade reduces external integration costs through API publishing, refines the running process via computing task management, enhances traceability with execution records and resource monitoring, and improves output comprehension through result visualization. Moving forward, qModel will continue to iterate around algorithm model engineering management and intelligent computing process optimization, helping developers manage and apply algorithm model capabilities more efficiently.&lt;/p&gt;

&lt;h1&gt;
  
  
  MLOps #MachineLearning #DataScience #OpenSource #qModel #API #Algorithm
&lt;/h1&gt;

</description>
      <category>opensource</category>
      <category>api</category>
      <category>mlops</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>AI Infrastructure Engineering for Production AI Systems</title>
      <dc:creator>Scott McMahan</dc:creator>
      <pubDate>Wed, 12 Aug 2026 14:27:56 +0000</pubDate>
      <link>https://dev.to/scott_mcmahan_d085ae6e508/ai-infrastructure-engineering-for-production-ai-systems-28h3</link>
      <guid>https://dev.to/scott_mcmahan_d085ae6e508/ai-infrastructure-engineering-for-production-ai-systems-28h3</guid>
      <description>&lt;p&gt;Building an AI model is only the beginning. Production AI also requires infrastructure that can handle intensive workloads, manage data, maintain security, control costs, and scale reliably.&lt;/p&gt;

&lt;h3&gt;
  
  
  What AI Infrastructure Engineering Includes
&lt;/h3&gt;

&lt;p&gt;AI infrastructure engineering combines cloud platforms, GPUs, storage, networking, containers, orchestration, monitoring, and automation. These technologies create the foundation for training, deploying, and operating AI models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Production Infrastructure Matters
&lt;/h3&gt;

&lt;p&gt;Models that perform well during development can experience latency, reliability, scalability, and cost problems after deployment. Strong infrastructure helps teams identify these problems and maintain consistent performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Growing Engineering Discipline
&lt;/h3&gt;

&lt;p&gt;As organizations move from AI experiments to operational systems, they need engineers who understand both infrastructure and machine learning workloads. This makes AI infrastructure engineering an increasingly important part of successful AI adoption.&lt;/p&gt;

&lt;p&gt;Read the full article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aitransformer.online/ai-infrastructure-engineering/" rel="noopener noreferrer"&gt;https://aitransformer.online/ai-infrastructure-engineering/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>FastAPI vs Flask ML Serving: Beginner Speed Test in 50 Lines</title>
      <dc:creator>TildAlice</dc:creator>
      <pubDate>Tue, 11 Aug 2026 15:04:47 +0000</pubDate>
      <link>https://dev.to/tildalice/fastapi-vs-flask-ml-serving-beginner-speed-test-in-50-lines-3n8n</link>
      <guid>https://dev.to/tildalice/fastapi-vs-flask-ml-serving-beginner-speed-test-in-50-lines-3n8n</guid>
      <description>&lt;h2&gt;
  
  
  Most Speed Comparisons Skip the Setup Cost
&lt;/h2&gt;

&lt;p&gt;Every FastAPI vs Flask benchmark focuses on request throughput under load. But if you're deploying your first ML model, that's not what kills you. It's the 40 seconds your Flask app spends loading a 500MB model on every cold start, or the mystery "Address already in use" error that costs you 20 minutes of Googling.&lt;/p&gt;

&lt;p&gt;Here's what actually matters for beginners: how fast can you go from &lt;code&gt;pip install&lt;/code&gt; to a working prediction endpoint? I built the same sklearn model server in both frameworks, keeping each under 50 lines. The results surprised me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftildalice.io%2Fwp-content%2Fuploads%2F2026%2F08%2Fstock-fastapi-vs-flask-ml-serving-beginner-speed-test-1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Ftildalice.io%2Fwp-content%2Fuploads%2F2026%2F08%2Fstock-fastapi-vs-flask-ml-serving-beginner-speed-test-1.jpg" alt="A set of three clear glass laboratory flasks on a clean white and green background, ideal for science themes." width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;
Photo by &lt;a href="https://www.pexels.com/@tara-winstead" rel="nofollow noopener noreferrer"&gt;Tara Winstead&lt;/a&gt; on &lt;a href="https://www.pexels.com" rel="nofollow noopener noreferrer"&gt;Pexels&lt;/a&gt;



&lt;h2&gt;
  
  
  The Test: Identical Model, Minimal Code
&lt;/h2&gt;

&lt;p&gt;I trained a simple RandomForestClassifier on the iris dataset (yes, iris — the point is framework overhead, not model complexity). Both servers expose a &lt;code&gt;/predict&lt;/code&gt; POST endpoint that accepts JSON features and returns a class prediction.&lt;/p&gt;

&lt;p&gt;Here's the FastAPI version:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
# fastapi_serve.py
from fastapi import FastAPI
from pydantic import BaseModel
import joblib
import numpy as np

---

*Continue reading the full article on [TildAlice](https://tildalice.io/fastapi-vs-flask-ml-serving-beginner-speed-test/)*
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>fastapi</category>
      <category>flask</category>
      <category>mlops</category>
      <category>modelserving</category>
    </item>
    <item>
      <title>Master MLOps Online Training | MLOps Course Online</title>
      <dc:creator>vamsi visualpath</dc:creator>
      <pubDate>Tue, 11 Aug 2026 07:56:12 +0000</pubDate>
      <link>https://dev.to/vamsi_visualpath_826a9ad2/master-mlops-online-training-mlops-course-online-1p41</link>
      <guid>https://dev.to/vamsi_visualpath_826a9ad2/master-mlops-online-training-mlops-course-online-1p41</guid>
      <description>&lt;p&gt;How to Choose the Right MLOps Tools for Your Organization&lt;br&gt;
Introduction&lt;br&gt;
Machine learning projects often begin with simple experiments. But production ML systems need much more. Teams must train models, test them, deploy them, and monitor them. This is where MLOps Tools can help. They reduce manual work and make ML workflows easier to manage.&lt;br&gt;
However, every organization has different needs. A small team may need simple tools. A large company may need stronger security and automation. Your team may also use AWS, Azure, Google Cloud, or Kubernetes. So, choosing the right tools requires careful planning. A good MLOps Online Training can also help teams understand these tools better.&lt;br&gt;
Featured Snippet&lt;br&gt;
How do you choose the right MLOps tools?&lt;br&gt;
Choose tools based on your ML workflow, team skills, cloud setup, security, cost, and future growth. Test the tool with a real project before choosing it. Visualpath can also help learners build practical MLOps skills.&lt;br&gt;
What Are MLOps Tools?&lt;br&gt;
MLOps tools help teams manage machine learning work. They support tasks from model development to production. These tools can reduce repeated manual work.&lt;br&gt;
Common uses include:&lt;br&gt;
• Tracking machine learning experiments.&lt;br&gt;
• Managing model versions.&lt;br&gt;
• Building ML pipelines.&lt;br&gt;
• Testing machine learning models.&lt;br&gt;
• Deploying models.&lt;br&gt;
• Monitoring model performance.&lt;br&gt;
• Managing user access.&lt;br&gt;
• Connecting different systems.&lt;br&gt;
For example, a data scientist may test five models. An experiment tracking tool can save the results. The team can then compare the models easily. This saves time and reduces confusion.&lt;br&gt;
Why Choosing the Right MLOps Tools Matters&lt;br&gt;
Your tool choice affects how easily your team runs ML systems. The right tools can make daily work simpler. They can also reduce errors and repeated tasks.&lt;br&gt;
Key benefits include:&lt;br&gt;
• Faster model delivery.&lt;br&gt;
• Easier model tracking.&lt;br&gt;
• Better workflow automation.&lt;br&gt;
• Simpler team collaboration.&lt;br&gt;
• Easier model monitoring.&lt;br&gt;
• Better control over deployments.&lt;br&gt;
• More consistent ML processes.&lt;br&gt;
However, more tools do not always mean better results. Too many tools can create extra work. Teams may also spend more time connecting and managing them. Therefore, focus on tools that solve clear problems.&lt;br&gt;
How to Assess Your Organization’s MLOps Requirements&lt;br&gt;
Start by looking at your current ML process. Write down each step from data to production. Then, find the areas that need improvement.&lt;br&gt;
Ask these questions:&lt;br&gt;
• How many ML projects do we run?&lt;br&gt;
• How many people work on them?&lt;br&gt;
• Where do we train our models?&lt;br&gt;
• How do we store model versions?&lt;br&gt;
• How do we deploy models?&lt;br&gt;
• How do we monitor models?&lt;br&gt;
• Which cloud platform do we use?&lt;br&gt;
• What security rules must we follow?&lt;br&gt;
• How much automation do we need?&lt;br&gt;
For example, a small team may need basic tracking and deployment. A large team may need advanced access control and monitoring. Your needs should guide your tool choice.&lt;br&gt;
Essential Features of MLOps Tools&lt;br&gt;
Good MLOps tools can support many parts of the ML lifecycle. However, the required features depend on your project.&lt;br&gt;
Experiment Tracking&lt;br&gt;
Teams often run many experiments. Tracking tools record model settings, results, and metrics.&lt;br&gt;
This makes experiments easier to compare.&lt;br&gt;
Model Versioning&lt;br&gt;
Model versioning shows which model is being used. It also helps teams return to an older version.&lt;br&gt;
This can be useful when a new model has problems.&lt;br&gt;
Pipeline Automation&lt;br&gt;
Pipelines connect different ML tasks. For example, a pipeline can run data checks before training.&lt;br&gt;
It can then test and deploy the model.&lt;br&gt;
Model Monitoring&lt;br&gt;
Models can change after deployment. New data may also change model results.&lt;br&gt;
Monitoring helps teams find these changes early.&lt;br&gt;
Access Control&lt;br&gt;
Different users may need different permissions. Access controls help protect models, data, and systems.&lt;br&gt;
How to Compare and Evaluate MLOps Tools&lt;br&gt;
Do not choose a tool after reading only its feature list.&lt;br&gt;
Create a simple comparison plan. First, list your most important requirements. Then, give each requirement a priority.&lt;br&gt;
For example:&lt;br&gt;
• High: Security and deployment.&lt;br&gt;
• High: Pipeline automation.&lt;br&gt;
• Medium: Monitoring.&lt;br&gt;
• Medium: Team collaboration.&lt;br&gt;
• Low: Extra features.&lt;br&gt;
Next, select two or three tools. Test them with a real ML project. Check how much time each tool needs. Also check how easy it is to maintain. Look at the full workflow, not just one feature.&lt;br&gt;
Practical learning through MLOps Online Course can also help professionals understand real ML workflows before tool selection.&lt;br&gt;
Popular MLOps Tools and Their Use Cases&lt;br&gt;
Different tools solve different ML problems. There is no single tool that fits every organization.&lt;br&gt;
MLflow&lt;br&gt;
MLflow helps teams track experiments and manage models. It is useful for teams that want flexible ML lifecycle support.&lt;br&gt;
Kubeflow&lt;br&gt;
Kubeflow supports ML workflows on Kubernetes. It can fit teams that already use Kubernetes.&lt;br&gt;
Amazon SageMaker&lt;br&gt;
SageMaker provides managed tools for machine learning. It supports model development, training, deployment, and monitoring.&lt;br&gt;
It can suit teams using AWS services.&lt;br&gt;
Google Vertex AI&lt;br&gt;
Vertex AI provides managed ML services on Google Cloud. It supports many stages of the ML workflow.&lt;br&gt;
It can fit teams already using Google Cloud.&lt;br&gt;
Azure Machine Learning&lt;br&gt;
Azure Machine Learning supports model training and deployment. It also provides tools for model management and monitoring. It can work well with Microsoft-based environments.&lt;br&gt;
The right choice depends on your systems, skills, and project needs.&lt;br&gt;
How to Choose MLOps Tools Based on Team and Project Needs&lt;br&gt;
Different teams need different capabilities. A small research team may focus on experiment tracking. A production team may need strong deployment tools. An enterprise team may need security and governance.&lt;br&gt;
Consider these common needs:&lt;br&gt;
• Small teams: Choose simple and easy-to-manage tools.&lt;br&gt;
• Research teams: Focus on experiment tracking and model management.&lt;br&gt;
• Production teams: Focus on deployment and monitoring.&lt;br&gt;
• Enterprise teams: Focus on security, access, and governance.&lt;br&gt;
• Cloud teams: Consider tools that fit the current cloud platform.&lt;br&gt;
• Platform teams: Look for automation and infrastructure support.&lt;br&gt;
Avoid building a toolchain that is harder than the problem.&lt;br&gt;
Common Mistakes to Avoid When Choosing MLOps Tools&lt;br&gt;
Tool selection can become difficult when teams focus on the wrong things. Avoid these common mistakes.&lt;br&gt;
Choosing a Tool Because It Is Popular&lt;br&gt;
A popular tool may not fit your needs. Always compare it with your own requirements.&lt;br&gt;
Using Too Many Tools&lt;br&gt;
Every extra tool can add setup and maintenance work. Keep your toolchain as simple as possible.&lt;br&gt;
Ignoring Team Skills&lt;br&gt;
Your team must be able to use and maintain the tools. Consider training needs before making a final choice.&lt;br&gt;
Skipping a Test Project&lt;br&gt;
A small pilot can reveal hidden problems. Test the tool before using it across the organization.&lt;br&gt;
Looking Only at Price&lt;br&gt;
A low price does not always mean lower total cost. Include maintenance and training costs in your comparison.&lt;br&gt;
Ignoring Future Growth&lt;br&gt;
Think about future models, users, data, and workloads. Choose tools that can grow with your organization.&lt;br&gt;
For practical exposure, MLOps Training in Ameerpet helps learners understand tools, workflows, and deployment.&lt;/p&gt;

&lt;p&gt;Frequently Asked Questions (FAQs)&lt;br&gt;
Q. What factors should you consider when choosing MLOps tools?&lt;br&gt;
A. Consider team skills, cloud setup, security, automation, scalability, and integration, ease of use, support, and total cost.&lt;br&gt;
Q. How do you choose the right MLOps tools for your organization?&lt;br&gt;
A. Start with your ML workflow. Then compare tools for features, cost, security, integration, scalability, and ease of use.&lt;br&gt;
Q. Which MLOps tools are best for machine learning model deployment?&lt;br&gt;
A. MLflow, Kubeflow, SageMaker, Vertex AI, and Azure Machine Learning can support deployment in different environments.&lt;br&gt;
Q. What features should an organization look for in an MLOps platform?&lt;br&gt;
A. Look for experiment tracking, model versioning, pipelines, testing, deployment, monitoring, security, access control, and integration.&lt;br&gt;
Q. How can you compare MLOps tools for scalability, automation, and cost?&lt;br&gt;
A. Test each tool with a real project. Compare setup time, automation, resource use, scaling, support needs, and total cost.&lt;/p&gt;

&lt;p&gt;Final Thoughts&lt;br&gt;
Choosing the right MLOps Tools starts with understanding your real project needs. Consider your team skills, ML workflow, cloud setup, security, budget, and future growth.&lt;br&gt;
Do not choose a tool only because it is popular. Compare tools based on features, ease of use, integration, scalability, and maintenance needs. A small pilot can help you test a tool before making a larger decision. The best choice is a tool that supports your team, reduces manual work, and keeps ML workflows simple and reliable.&lt;/p&gt;

&lt;p&gt;Visualpath is the leading and best software and online training institute in Hyderabad&lt;br&gt;
For More Information about MLOps Online Training&lt;br&gt;
Contact Call/WhatsApp: +91-7032290546&lt;br&gt;
Visit: &lt;a href="https://www.visualpath.in/mlops-course.html" rel="noopener noreferrer"&gt;https://www.visualpath.in/mlops-course.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>mlops</category>
      <category>devops</category>
    </item>
    <item>
      <title>Agentic Incident Response for GPU Clusters: A Safe Playbook</title>
      <dc:creator>Tran Tien Van</dc:creator>
      <pubDate>Tue, 11 Aug 2026 07:30:56 +0000</pubDate>
      <link>https://dev.to/tran_tienvan_e45fc26d655/agentic-incident-response-for-gpu-clusters-a-safe-playbook-1310</link>
      <guid>https://dev.to/tran_tienvan_e45fc26d655/agentic-incident-response-for-gpu-clusters-a-safe-playbook-1310</guid>
      <description>&lt;p&gt;HyperPod's Health Monitoring Agent (HMA) detects unhealthy nodes and performs supported mechanical recovery. AWS DevOps Agent is documented separately for incident triage and root-cause analysis (RCA).&lt;/p&gt;

&lt;p&gt;That split is the practical starting point for agentic incident response—not an assumption that AWS ships a native bridge between the two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the documented boundary
&lt;/h2&gt;

&lt;p&gt;Amazon SageMaker HyperPod documents a cluster health loop: health monitoring plus automatic node recovery. AWS DevOps Agent documents an investigation loop that works through supported inputs.&lt;/p&gt;

&lt;p&gt;The cited material does not say that HyperPod events or HMA telemetry flow directly into DevOps Agent. It also does not establish a native HyperPod-to-DevOps Agent integration or a launch date for one.&lt;/p&gt;

&lt;p&gt;That distinction changes the implementation plan. Treat any handoff between health detection and incident investigation as an interface you must verify. Document what starts an investigation, which evidence is available, what an agent may recommend, and what a person must approve.&lt;/p&gt;

&lt;p&gt;Without that boundary, two individually useful capabilities can look like one end-to-end system when the sources only support two separate loops.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimize the whole MTTR path
&lt;/h2&gt;

&lt;p&gt;Mean time to recovery covers six stages here: detection, triage, diagnosis, decision, remediation, and workload resume.&lt;/p&gt;

&lt;p&gt;A faster health alert improves only part of that chain. HMA may identify an unhealthy node and carry out supported mechanical recovery, but the wider incident can still require diagnosis, a remediation decision, and confirmation that the workload has resumed safely.&lt;/p&gt;

&lt;p&gt;Measure the complete path instead of stopping the clock at detection or node recovery. This makes bottlenecks visible. A team may discover that approval, evidence gathering, or workload resumption takes longer than finding the failed node.&lt;/p&gt;

&lt;p&gt;The goal is not maximum agent activity. It is a shorter, explainable path to safe recovery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adopt autonomy in stages
&lt;/h2&gt;

&lt;p&gt;A conservative rollout gives the team useful assistance without granting broad action rights on day one:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the loops explicit. Use HMA for its documented node-health role, and use DevOps Agent for wider investigation through supported inputs. Do not represent a direct connection unless you can verify it.&lt;/li&gt;
&lt;li&gt;Make the first RCA advisory. Let the agent propose a root cause and supporting evidence, then require a human to approve remediation.&lt;/li&gt;
&lt;li&gt;Test the control surface. Check evidence quality, false positives, permissions, rollback, and auditability against thresholds your team defines.&lt;/li&gt;
&lt;li&gt;Expand one permission at a time. Grant more autonomy only when the previous stage produces reliable evidence and a recoverable action path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This sequence preserves a review point between diagnosis and action. It also creates a clear place to inspect whether the proposed remediation follows from the available evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make each gate observable
&lt;/h2&gt;

&lt;p&gt;Evidence quality should answer a basic question: can an operator trace the RCA back to the incident inputs that support it? False-positive thresholds should reflect the failure cost your team is willing to accept.&lt;/p&gt;

&lt;p&gt;Permissions need the same precision. An investigation capability does not automatically justify remediation authority. Keep the agent's allowed actions narrower than its ability to analyze until the team has validated the workflow.&lt;/p&gt;

&lt;p&gt;Rollback must be more than a reassuring word. The team should know which automated actions are reversible and how recovery is initiated. Auditability should preserve who or what proposed, approved, and executed each action.&lt;/p&gt;

&lt;p&gt;These are team-defined gates, not universal numbers. The right threshold depends on the operational risk and the reversibility of the action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Accept the honest tradeoff
&lt;/h2&gt;

&lt;p&gt;Human approval adds time between diagnosis and remediation. Early in adoption, that delay buys a deliberate checkpoint for weak evidence, false positives, and overly broad permissions.&lt;/p&gt;

&lt;p&gt;Greater autonomy can remove some waiting, but it can also accelerate the wrong action if those controls are immature. Mechanical node recovery is narrower than resolving every operational incident, so success criteria should distinguish the two.&lt;/p&gt;

&lt;p&gt;Agentic incident response works best as a governed operating model: supported automation where the mechanism is documented, explicit interfaces where it is not, and authority that grows only after the evidence earns it.&lt;/p&gt;

&lt;p&gt;Where does your GPU incident process lose the most time today—triage, diagnosis, approval, remediation, or workload resume—and what proof would you require before an agent owned that step?&lt;/p&gt;




&lt;p&gt;📖 &lt;strong&gt;Read the full guide → &lt;a href="https://vandatateam.com/blog/agentic-incident-response" rel="noopener noreferrer"&gt;Agentic Incident Response for GPU Clusters&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>mlops</category>
      <category>aws</category>
    </item>
    <item>
      <title>Build Production-Ready AI Skills with MLOps Certification</title>
      <dc:creator>Jeevan Kumbhar</dc:creator>
      <pubDate>Tue, 11 Aug 2026 06:29:13 +0000</pubDate>
      <link>https://dev.to/jeevan_kumbhar_0dddb49b1a/build-production-ready-ai-skills-with-mlops-certification-4ble</link>
      <guid>https://dev.to/jeevan_kumbhar_0dddb49b1a/build-production-ready-ai-skills-with-mlops-certification-4ble</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe8chzbu6tr5dp6bnwjzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe8chzbu6tr5dp6bnwjzv.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Machine learning is moving beyond model development as organizations increasingly focus on deploying, monitoring, and managing AI systems in real-world environments. This has created a growing need for professionals who understand how machine learning and operational practices work together.&lt;br&gt;
The GSDC certified MLOps professional program provides structured learning for professionals seeking an &lt;strong&gt;&lt;a href="https://www.gsdcouncil.org/mlops-certification" rel="noopener noreferrer"&gt;mlops certificate&lt;/a&gt;&lt;/strong&gt; and practical knowledge of the machine learning operations lifecycle. The program focuses on helping learners understand how models can be deployed, automated, monitored, and managed effectively in production environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strengthening the Machine Learning Lifecycle&lt;/strong&gt;&lt;br&gt;
MLOps connects machine learning development with DevOps practices to create reliable and repeatable workflows. The certification introduces important concepts that help professionals understand the transition from developing models to operating them at scale.&lt;br&gt;
Key Learning Areas&lt;br&gt;
The program covers several practical areas relevant to modern AI environments, including:&lt;br&gt;
Machine learning lifecycle management&lt;br&gt;
CI/CD practices for ML workflows&lt;br&gt;
Model deployment and monitoring&lt;br&gt;
Experiment tracking and model versioning&lt;br&gt;
Automated ML pipelines&lt;br&gt;
Containerization and scalable infrastructure&lt;br&gt;
Learners also gain exposure to technologies such as Docker, Kubernetes, MLflow, TensorFlow Extended (TFX), FastAPI, and GitHub Actions. The program also introduces emerging areas including LLMOps and RAG deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developing Practical MLOps Capabilities&lt;/strong&gt;&lt;br&gt;
Professionals pursuing certified ml ops credentials can strengthen their understanding of automation, deployment, monitoring, and collaboration across technical teams. These capabilities can support organizations working to make machine learning workflows more efficient, reproducible, and scalable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Professionals Who Can Benefit&lt;/strong&gt;&lt;br&gt;
The program can be valuable for machine learning engineers, data scientists, DevOps engineers, software developers, cloud professionals, AI consultants, technical leads, and project managers involved in AI initiatives. It can also benefit professionals looking to expand their technical knowledge into production-focused machine learning operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building Career-Ready AI Expertise&lt;/strong&gt;&lt;br&gt;
An ml ops certification can help professionals develop structured knowledge around modern machine learning operations and better understand the technologies used to support production AI systems. The GSDC program combines relevant concepts with practical learning to support professionals building skills for evolving AI environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start Your MLOps Journey&lt;/strong&gt;&lt;br&gt;
Explore the GSDC Certified MLOps Professional program and develop practical skills for modern machine learning operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explore the MLOps Certification Program&lt;/strong&gt;: &lt;a href="https://www.gsdcouncil.org/mlops-certification" rel="noopener noreferrer"&gt;https://www.gsdcouncil.org/mlops-certification&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mlops</category>
      <category>mlopscertificaton</category>
    </item>
    <item>
      <title>What It Takes to Run a Feature Store in Production</title>
      <dc:creator>Scott McMahan</dc:creator>
      <pubDate>Mon, 10 Aug 2026 15:00:20 +0000</pubDate>
      <link>https://dev.to/scott_mcmahan_d085ae6e508/what-it-takes-to-run-a-feature-store-in-production-3ke0</link>
      <guid>https://dev.to/scott_mcmahan_d085ae6e508/what-it-takes-to-run-a-feature-store-in-production-3ke0</guid>
      <description>&lt;p&gt;Feature stores are becoming a common part of machine learning infrastructure. They give teams a central system for defining, storing, and serving the features used during model training and inference.&lt;/p&gt;

&lt;p&gt;That sounds straightforward, but running a feature store in production involves much more than installing a platform and connecting it to a model. Data engineers must account for consistency, latency, versioning, monitoring, governance, and long-term maintenance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Preventing Training-Serving Skew
&lt;/h3&gt;

&lt;p&gt;A model may use features generated by batch pipelines during training and features produced by real-time services after deployment.&lt;/p&gt;

&lt;p&gt;If those systems implement a transformation differently, the model receives data that does not match its training environment. This problem is known as training-serving skew.&lt;/p&gt;

&lt;p&gt;Consider a feature that calculates a customer’s average transaction amount over 30 days. The batch pipeline might include the current day while the streaming implementation excludes it. The difference may appear small, but it can change model predictions and reduce production performance.&lt;/p&gt;

&lt;p&gt;A feature store addresses this problem by giving both environments access to a shared feature definition. Teams no longer have to reproduce transformation logic in multiple systems and hope that every implementation remains identical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Combining Offline and Online Storage
&lt;/h3&gt;

&lt;p&gt;Model training and live inference have different storage requirements.&lt;/p&gt;

&lt;p&gt;Training jobs usually need large historical datasets and can tolerate slower retrieval. Production predictions may require only a small group of current features, but those values must be returned within milliseconds.&lt;/p&gt;

&lt;p&gt;A typical architecture uses an offline store for historical training data and an online store for low-latency retrieval. The challenge is keeping the two systems synchronized. If they contain different versions of a feature, the architecture can still produce training-serving skew.&lt;/p&gt;

&lt;p&gt;Data engineers need dependable pipelines that move calculated features into both stores while preserving timestamps, definitions, and data quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Designing for Real Traffic
&lt;/h3&gt;

&lt;p&gt;Feature retrieval becomes part of the request path when a model supports fraud detection, recommendations, personalization, or dynamic pricing.&lt;/p&gt;

&lt;p&gt;Slow lookups increase the latency of every prediction. Caching frequently requested features and locating the online store close to the serving layer can help, but performance must be tested under realistic conditions.&lt;/p&gt;

&lt;p&gt;Average traffic is not enough. A system that works during normal activity may fail during a product launch, sales event, or sudden traffic spike. Load testing should reflect the peak conditions the application is likely to encounter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versioning Feature Definitions
&lt;/h3&gt;

&lt;p&gt;Features evolve as source systems, transformation logic, and business requirements change. A team might revise a calculation to fix an error or incorporate a new data source.&lt;/p&gt;

&lt;p&gt;Changing the existing definition without versioning can silently alter every model using that feature. A production feature store should allow multiple versions to exist while teams test and migrate dependent models.&lt;/p&gt;

&lt;p&gt;Version history also makes debugging easier. When a model’s output changes, engineers can determine whether a feature definition changed at the same time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monitoring More Than Pipeline Status
&lt;/h3&gt;

&lt;p&gt;A successful pipeline run does not guarantee that its features are usable.&lt;/p&gt;

&lt;p&gt;A feature may contain unexpected null values, stop refreshing, drift outside its normal range, or become inconsistent after an upstream schema change. These failures may not produce obvious application errors.&lt;/p&gt;

&lt;p&gt;Monitoring should track freshness, missing values, distributions, retrieval latency, and pipeline failures. Alerts should reach the feature owner early enough to correct the problem before it affects customers or business decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Governance Into the Platform
&lt;/h3&gt;

&lt;p&gt;As feature stores expand, teams need a reliable way to understand what each feature means and where it comes from.&lt;/p&gt;

&lt;p&gt;Every feature should have an owner, definition, source, refresh schedule, and documented purpose. Lineage should show how raw data becomes a feature and identify which models depend on it.&lt;/p&gt;

&lt;p&gt;Access controls also matter. Some features may contain personal, financial, or other sensitive information. The platform needs clear permissions for discovering, retrieving, and modifying those features.&lt;/p&gt;

&lt;p&gt;Governance is easier to establish while the feature catalog is small. Waiting until hundreds of features exist creates a documentation and ownership problem that becomes difficult to reverse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evaluating Managed and Self-Hosted Options
&lt;/h3&gt;

&lt;p&gt;Managed feature stores reduce the operational work associated with scaling, updates, monitoring, and availability. They may help smaller teams reach production without creating a dedicated platform engineering group.&lt;/p&gt;

&lt;p&gt;Self-hosted platforms offer greater control over infrastructure, security, architecture, and cost. They can be a strong option for organizations with experienced engineers and specialized requirements.&lt;/p&gt;

&lt;p&gt;The best choice depends on the team that will operate the platform. A technically powerful feature store will not provide much value if it requires more maintenance than the organization can support.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treating Features as Production Assets
&lt;/h3&gt;

&lt;p&gt;A feature store is not merely a convenient repository for model inputs. It is shared infrastructure that influences the reliability of every model connected to it.&lt;/p&gt;

&lt;p&gt;Teams should operate feature stores with the same discipline they apply to production databases and APIs. Consistent definitions, low-latency retrieval, version control, monitoring, ownership, and governance all contribute to reliable machine learning systems.&lt;/p&gt;

&lt;p&gt;Read the original article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aitransformer.online/ai-powered-feature-stores-in-production/" rel="noopener noreferrer"&gt;https://aitransformer.online/ai-powered-feature-stores-in-production/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>dataengineering</category>
      <category>mlops</category>
    </item>
  </channel>
</rss>
