<?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: Pradeep K M</title>
    <description>The latest articles on DEV Community by Pradeep K M (@pradeepkm).</description>
    <link>https://dev.to/pradeepkm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4144365%2F71d47363-cb1a-4de6-9c0c-e8e5efe883ee.jpg</url>
      <title>DEV Community: Pradeep K M</title>
      <link>https://dev.to/pradeepkm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pradeepkm"/>
    <language>en</language>
    <item>
      <title>Stop Deleting "Useless" Features: Why Univariate AUC is Lying to You</title>
      <dc:creator>Pradeep K M</dc:creator>
      <pubDate>Tue, 13 Oct 2026 11:52:49 +0000</pubDate>
      <link>https://dev.to/pradeepkm/stop-deleting-useless-features-why-univariate-auc-is-lying-to-you-657</link>
      <guid>https://dev.to/pradeepkm/stop-deleting-useless-features-why-univariate-auc-is-lying-to-you-657</guid>
      <description>&lt;p&gt;In high-stakes domains like BFSI (Banking, Financial Services, and Insurance) and Healthcare, the most valuable predictive signals are often hiding in plain sight.&lt;/p&gt;

&lt;p&gt;Many data teams follow a standard pruning pipeline: calculate the univariate AUC for every feature, and if a feature scores near 0.5 (random noise), it gets tossed.&lt;/p&gt;

&lt;p&gt;This decision is quietly killing your model's performance.&lt;/p&gt;

&lt;p&gt;The Linear Trap vs. The Tree Power&lt;br&gt;
The problem is a confusion between marginal and conditional effects.&lt;/p&gt;

&lt;p&gt;The Linear Trap: In a Logistic Regression model, every feature gets a fixed coefficient (&lt;br&gt;
β&lt;br&gt;
β). It measures the effect of that feature in a vacuum. If "Age" has no individual linear relationship with the target across the whole dataset, it gets a high p-value and is zeroed out.&lt;/p&gt;

&lt;p&gt;The Tree Power: Gradient Boosting Decision Trees (GBDTs) like XGBoost or CatBoost operate on conditional logic. They don't ask, "Does Age matter?" They ask, "Does Age matter &lt;em&gt;given&lt;/em&gt; that Income is low and Education is X?"&lt;/p&gt;

&lt;p&gt;In sparse datasets, a feature might be globally irrelevant but locally critical.&lt;/p&gt;

&lt;p&gt;Proving it with Code&lt;br&gt;
Here is a simplified demonstration of how a feature can be "useless" on its own but essential when paired with another variable.&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;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sklearn.metrics&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;roc_auc_score&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;xgboost&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;XGBClassifier&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shap&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;

&lt;span class="c1"&gt;# 1. Create a synthetic dataset
&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;n_samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="c1"&gt;# Feature A: Pure noise
&lt;/span&gt;&lt;span class="n"&gt;feat_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_samples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Feature B: Also looks like noise globally
&lt;/span&gt;&lt;span class="n"&gt;feat_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_samples&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Target: Only depends on the INTERACTION of A and B
# Target is 1 ONLY if both A and B are positive (a non-linear pocket)
&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;feat_a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;feat_b&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Feature_A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;feat_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Feature_B&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;feat_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Target&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# 2. The "Univariate Check" (The mistake)
&lt;/span&gt;&lt;span class="n"&gt;auc_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;roc_auc_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Target&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Feature_A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;auc_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;roc_auc_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Target&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Feature_B&lt;/span&gt;&lt;span class="sh"&gt;'&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Univariate AUC Feature A: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;auc_a&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# ~0.50
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Univariate AUC Feature B: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;auc_b&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# ~0.50
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Result: A data scientist might delete both features here! ❌&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 3. The Boosting Approach
&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Feature_A&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;Feature_B&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Target&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="nc"&gt;XGBClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# 4. Explain with SHAP
&lt;/span&gt;&lt;span class="n"&gt;explainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;shap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;TreeExplainer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;shap_values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;explainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shap_values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;X&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="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;SHAP analysis reveals that both features are critical for the interaction.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;shap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;summary_plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shap_values&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What is SHAP actually telling us?&lt;br&gt;
When you see a feature with a weak univariate score but a high SHAP value, the model is telling you:&lt;/p&gt;

&lt;p&gt;"This variable cannot carry the model alone, but across the forest's decision paths, knowing this variable helped me carve out a high-precision pocket of truth."&lt;/p&gt;

&lt;p&gt;The Takeaway for Data Leaders&lt;br&gt;
If you are working with complex, multi-dimensional data in Healthcare or Finance, remember: Global irrelevance &lt;br&gt;
≠&lt;br&gt;
&lt;br&gt;
= Local uselessness.&lt;/p&gt;

&lt;p&gt;Respect Interactions: Healthcare and BFSI data thrive on combinations, not solo acts.&lt;br&gt;
Audit your Pruning: Before deleting a feature based on a p-value or univariate AUC, check its interaction strength via a tree-based model.&lt;br&gt;
Trust Non-Linear Architectures: Let your boosting models exploit the conditional depth they were designed for.&lt;/p&gt;

&lt;p&gt;About the Author:&lt;br&gt;
I specialize in building high-precision predictive models for BFSI and Healthcare, focusing on extracting signal from sparse, non-linear datasets through advanced feature engineering and XAI. I'm currently open to new opportunities where I can help teams turn "noise" into actionable insights.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>NSE-MCP: A Step Toward AI-Ready Data, or Just Playing Catch-up? 📈🤖</title>
      <dc:creator>Pradeep K M</dc:creator>
      <pubDate>Sat, 03 Oct 2026 17:05:44 +0000</pubDate>
      <link>https://dev.to/pradeepkm/nse-mcp-a-step-toward-ai-ready-data-or-just-playing-catch-up-2m64</link>
      <guid>https://dev.to/pradeepkm/nse-mcp-a-step-toward-ai-ready-data-or-just-playing-catch-up-2m64</guid>
      <description>&lt;p&gt;As someone who has spent a significant amount of time working with &lt;strong&gt;NSE (National Stock Exchange of India)&lt;/strong&gt; data, I was intrigued to see the launch of the &lt;strong&gt;NSE-MCP (Model Context Protocol)&lt;/strong&gt; initiative.&lt;/p&gt;

&lt;p&gt;For those who aren't aware, MCP is designed to standardize how LLMs and AI agents connect to data sources. Instead of writing a custom integration for every single API endpoint, MCP provides a "plug-and-play" interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Good Part ✅
&lt;/h3&gt;

&lt;p&gt;The initiative opens up two critical paths:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Historical Analysis:&lt;/strong&gt; Access to Bhavcopy data from the last 5 years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Near Real-Time Monitoring:&lt;/strong&gt; A 1–3 minute delayed live feed (CM Market Live).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From a DX (Developer Experience) perspective, moving toward a standardized protocol is a huge win. It reduces the boilerplate code required to feed financial context into an LLM and makes the data more "discoverable" for AI agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Real Talk" 🚩
&lt;/h3&gt;

&lt;p&gt;However, looking at this from an SME perspective... &lt;strong&gt;the NSE is late to the party.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you've ever tried to build a production-grade fintech app in India, you know the struggle. For years, the community has been forced to build complex middleware, custom scrapers, and fragile wrappers just to get institutional data into a usable format for modern AI workflows.&lt;/p&gt;

&lt;p&gt;While the architecture of MCP is the right choice, the timing feels reactive. The LLM explosion happened years ago; providing a standardized context protocol now is like installing a high-speed rail line after everyone has already bought electric scooters to get around the traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Verdict ⚖️
&lt;/h3&gt;

&lt;p&gt;The most disappointing part? The current limitation to &lt;strong&gt;"educational and informational purposes only."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a developer, "educational" is code for &lt;em&gt;"don't try to build a real business on this yet."&lt;/em&gt; To truly lead the fintech space, the NSE needs to move beyond the sandbox and provide a production-ready, high-throughput infrastructure that doesn't shy away from commercial utility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it a step forward?&lt;/strong&gt; Yes.&lt;br&gt;
&lt;strong&gt;Is it a lead?&lt;/strong&gt; No. It's a recovery.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;I’m curious to hear from other devs and data engineers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Are you already using MCP in your stack?&lt;/li&gt;
&lt;li&gt;  Do you think this will actually reduce the friction of working with Indian market data?&lt;/li&gt;
&lt;li&gt;  Or are you sticking with your custom pipelines?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's discuss in the comments! 👇&lt;/p&gt;

&lt;h1&gt;
  
  
  fintech #ai #mcp #nse #dataengineering #llm #india #tradingbot
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"nse-bhavcopy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.nseindia.in/bhavcopy/cm/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"transport"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"streamable-http"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cm-market"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://mcp.nseindia.in/cmmkt/mcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"transport"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"streamable-http"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;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;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;polars&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pl&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ClientSession&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;mcp.client.streamable_http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;streamablehttp_client&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_reliance_quote_clean&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://mcp.nseindia.in/cmmkt/mcp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Connecting to NSE MCP server at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;streamablehttp_client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;as &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ClientSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;write&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;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

            &lt;span class="n"&gt;target_tool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cm_get_stock_quote&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="n"&gt;arguments&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;symbol&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;RELIANCE&lt;/span&gt;&lt;span class="sh"&gt;"&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Calling tool &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;target_tool&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; with arguments: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call_tool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;target_tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Extract raw text content
&lt;/span&gt;            &lt;span class="n"&gt;raw_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&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;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;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;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;raw_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;content&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;break&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;raw_text&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error: No text data returned from the MCP tool.&lt;/span&gt;&lt;span class="sh"&gt;"&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="n"&gt;parsed_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c1"&gt;# If the response wraps data in a dictionary, structure it for Polars
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parsed_json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="c1"&gt;# Extract fields if they are nested inside 'stock' or similar keys
&lt;/span&gt;                    &lt;span class="n"&gt;data_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;parsed_json&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
                &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;data_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parsed_json&lt;/span&gt;

                &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data_list&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c1"&gt;# Check if 'stock' column exists as a struct and unpack it safely
&lt;/span&gt;                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stock&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;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unnest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stock&lt;/span&gt;&lt;span class="sh"&gt;"&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="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;--- Unpacked Polars DataFrame ---&lt;/span&gt;&lt;span class="sh"&gt;"&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;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="c1"&gt;# Export to CSV (now flattened successfully)
&lt;/span&gt;                &lt;span class="n"&gt;output_filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reliance_live_quote_flat.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_filename&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;Successfully exported flattened data to &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output_filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&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;df&lt;/span&gt;

            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Failed to parse response text as JSON. Raw output:&lt;/span&gt;&lt;span class="sh"&gt;"&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;raw_text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Run directly in your interactive cell
&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch_reliance_quote_clean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Bridging the Knowledge Gap: Why General LLMs Fail at HEOR and How to Fix it with RAG 🏥🤖</title>
      <dc:creator>Pradeep K M</dc:creator>
      <pubDate>Mon, 28 Sep 2026 10:18:07 +0000</pubDate>
      <link>https://dev.to/pradeepkm/bridging-the-knowledge-gap-why-general-llms-fail-at-heor-and-how-to-fix-it-with-rag-47mn</link>
      <guid>https://dev.to/pradeepkm/bridging-the-knowledge-gap-why-general-llms-fail-at-heor-and-how-to-fix-it-with-rag-47mn</guid>
      <description>&lt;p&gt;The ambition for AI in European healthcare is sky-high. Policymakers see AI as the key to optimizing health budgets and patient outcomes. However, there is a critical bottleneck: General-purpose LLMs are fundamentally mismatched with the reality of Health Economics and Outcomes Research (HEOR).&lt;br&gt;
The Problem: The "Knowledge Gap"&lt;/p&gt;

&lt;p&gt;General AI is trained on the public web. But Real-World Evidence (RWE) is:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Siloed &amp;amp; Protected: GDPR prevents "scraping" sensitive patient trajectories.
Noisy: EHRs are fragmented and inconsistently coded.
Logic-Heavy: Calculating a QALY (Quality-Adjusted Life Year) requires longitudinal reasoning, not just probabilistic word prediction.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In short: General AI simulates the language of health economics without possessing the underlying data-driven logic.&lt;br&gt;
The Solution: Moving from General AI to RAG&lt;/p&gt;

&lt;p&gt;To bridge this gap, we must stop relying on the model's internal weights and start using Retrieval-Augmented Generation (RAG). Instead of asking the AI to "remember" a medical fact, we provide it with a secure, retrieved slice of actual RWE data to analyze in real-time.&lt;/p&gt;

&lt;p&gt;Below is a conceptual Python implementation using LangChain and ChromaDB to show how we can ground an LLM in specific, secure medical documentation.&lt;/p&gt;

&lt;p&gt;import os&lt;br&gt;
from langchain_community.document_loaders import PyPDFLoader&lt;br&gt;
from langchain_community.vectorstores import Chroma&lt;br&gt;
from langchain_openai import OpenAIEmbeddings, ChatOpenAI&lt;br&gt;
from langchain.chains import RetrievalQA&lt;br&gt;
from langchain.prompts import PromptTemplate&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Setup: Use a secure, local vector store to avoid data leakage
&lt;/h1&gt;

&lt;h1&gt;
  
  
  In a real HEOR scenario, this would be connected to a
&lt;/h1&gt;

&lt;h1&gt;
  
  
  Federated Learning node or a secure hospital vault.
&lt;/h1&gt;

&lt;p&gt;os.environ["OPENAI_API_KEY"] = "your-api-key"&lt;/p&gt;

&lt;p&gt;def setup_heor_rag_pipeline(document_path):&lt;br&gt;
    # Load secure RWE/HEOR documentation&lt;br&gt;
    loader = PyPDFLoader(document_path)&lt;br&gt;
    documents = loader.load()&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Create embeddings - converting medical text into vectors
embeddings = OpenAIEmbeddings()

# Store in a local vector database (ChromaDB)
# This ensures the data stays under our control, not in the model's training set
vectorstore = Chroma.from_documents(
    documents=documents, 
    embedding=embeddings, 
    persist_directory="./heor_secure_vault"
)

return vectorstore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  2. The "Reasoning" Layer
&lt;/h1&gt;
&lt;h1&gt;
  
  
  We use a custom prompt to force the AI to act as a Health Economist
&lt;/h1&gt;

&lt;p&gt;template = """&lt;br&gt;
You are a specialized HEOR Expert. Use the following pieces of retrieved &lt;br&gt;
Real-World Evidence (RWE) to answer the user's question. &lt;br&gt;
If the evidence does not contain the answer, state that the data is insufficient.&lt;br&gt;
Do not simulate or hallucinate figures.&lt;/p&gt;

&lt;p&gt;Context: {context}&lt;br&gt;
Question: {question}&lt;/p&gt;

&lt;p&gt;Expert Analysis:"""&lt;/p&gt;

&lt;p&gt;QA_CHAIN_PROMPT = PromptTemplate(&lt;br&gt;
    input_variables=["context", "question"],&lt;br&gt;
    template=template,&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;def analyze_health_economics(vectorstore, query):&lt;br&gt;
    llm = ChatOpenAI(model_name="gpt-4", temperature=0) # Low temp for precision&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;qa_chain = RetrievalQA.from_chain_type(
    llm,
    retriever=vectorstore.as_retriever(),
    chain_type_kwargs={"prompt": QA_CHAIN_PROMPT}
)

return qa_chain.invoke(query)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  --- Execution ---
&lt;/h1&gt;

&lt;p&gt;if &lt;strong&gt;name&lt;/strong&gt; == "&lt;strong&gt;main&lt;/strong&gt;":&lt;br&gt;
    # Assume 'clinical_trial_rwe.pdf' contains granular patient trajectory data&lt;br&gt;
    vault = setup_heor_rag_pipeline("clinical_trial_rwe.pdf")&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;question = "Based on the provided RWE, what is the incremental cost-effectiveness ratio (ICER) for Therapy X compared to the standard of care?"
result = analyze_health_economics(vault, question)

print(f"Analysis: {result['result']}")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Why the "Newest" Healthcare Data is Often the Worst for ML</title>
      <dc:creator>Pradeep K M</dc:creator>
      <pubDate>Sat, 26 Sep 2026 13:29:21 +0000</pubDate>
      <link>https://dev.to/pradeepkm/why-the-newest-healthcare-data-is-often-the-worst-for-ml-3nlf</link>
      <guid>https://dev.to/pradeepkm/why-the-newest-healthcare-data-is-often-the-worst-for-ml-3nlf</guid>
      <description>&lt;p&gt;If you are building machine learning models using healthcare claims data, your biggest enemy isn't usually the algorithm—it's the &lt;strong&gt;claims lag&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When working with real-world data (RWD), there is a common temptation to use the most recent data available to keep models "current." In reality, using the most recent 60 days of claims data is often a recipe for model failure and skewed results.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: The "Incomplete Picture"
&lt;/h2&gt;

&lt;p&gt;Healthcare claims aren't instantaneous. Between provider submissions, insurance adjudication, corrections, and deduplication, there is a significant time gap between a clinical event and a finalized claim.&lt;/p&gt;

&lt;p&gt;If you train a model on data from "yesterday," you aren't seeing the full truth. You are seeing a filtered version of the truth where only the fastest-reporting providers are represented. This creates a massive &lt;strong&gt;late-claim bias&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: The X–60 Day Analytical Cut-off
&lt;/h2&gt;

&lt;p&gt;To solve this, I implement an analytical cut-off. Instead of using the data extraction date (&lt;strong&gt;X&lt;/strong&gt;), I use:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;T = X − 60 days&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By ignoring the most recent 60 days, we allow the data to "mature." This approach provides several critical advantages for ML stability:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reducing Undercounting:&lt;/strong&gt; Ensures that a patient isn't flagged as "inactive" simply because their claim is still being processed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Preventing Data Leakage:&lt;/strong&gt; Prevents the model from picking up on temporal artifacts that wouldn't exist in a real-world deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency:&lt;/strong&gt; Creates a stable baseline for train/test splits, ensuring that the "completeness" of the data is uniform across both sets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Warning: 60 Days is Not a Magic Number
&lt;/h2&gt;

&lt;p&gt;A 60-day lag is a starting point, not a universal law. The required "maturity window" varies wildly depending on the data source:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;Typical Maturity Lag&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pharmacy Claims&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Short (30–60 days)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Hospitalizations&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Medium (60–120 days)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mortality/Outcomes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Long (180+ days)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How to Determine Your Own Cut-off
&lt;/h2&gt;

&lt;p&gt;If you're unsure what lag to use, don't guess. Run a &lt;strong&gt;Completeness Test&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Compare the volume and characteristics of your data at 30, 60, 90, and 180-day intervals. Plot the "capture rate" over time. Once the curve flattens (reaches an asymptote), you've found your optimal analytical cut-off.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Golden Rule of Healthcare ML:&lt;/strong&gt; Use the newest &lt;em&gt;sufficiently mature&lt;/em&gt; data—not simply the newest data available.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>healthcareai</category>
      <category>rwe</category>
    </item>
  </channel>
</rss>
