<?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: harshi606</title>
    <description>The latest articles on DEV Community by harshi606 (@harshi606).</description>
    <link>https://dev.to/harshi606</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%2F670550%2Fa6ea080b-d635-4618-9cd8-f4d1dad41727.png</url>
      <title>DEV Community: harshi606</title>
      <link>https://dev.to/harshi606</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshi606"/>
    <language>en</language>
    <item>
      <title>I built an ML retraining pipeline that's allowed to say no</title>
      <dc:creator>harshi606</dc:creator>
      <pubDate>Mon, 03 Aug 2026 19:59:44 +0000</pubDate>
      <link>https://dev.to/harshi606/i-built-an-ml-retraining-pipeline-thats-allowed-to-say-no-10b7</link>
      <guid>https://dev.to/harshi606/i-built-an-ml-retraining-pipeline-thats-allowed-to-say-no-10b7</guid>
      <description>&lt;p&gt;Here's a thing that bugged me while I was learning MLOps: almost every tutorial ends the same way. Train a model, print the accuracy, done. Cool, but... then what? What happens in three weeks when new data shows up? Does the model just get retrained and shoved into production because a cron job said so? What if the new one is actually worse?&lt;/p&gt;

&lt;p&gt;Nobody seemed to want to answer that part. So I built something that does.&lt;/p&gt;

&lt;p&gt;I come from a backend/software engineering background, not classical ML, so honestly the model itself was the least interesting part of this to me. I used a plain Random Forest. I'm not trying to win a Kaggle competition. What I actually wanted to figure out was: how do you build a system that can look at a freshly trained model and say "no, not good enough" — and mean it?&lt;/p&gt;

&lt;p&gt;The actual problem&lt;/p&gt;

&lt;p&gt;Say you've got a churn prediction model in production. A month goes by, you've got new customer data, and you retrain. Now you have a new model. Is it better? Maybe! Maybe not. Maybe it just overfit to some weird pocket of last month's data. If you don't have a real answer to "is it better," you shouldn't be letting it anywhere near production.&lt;/p&gt;

&lt;p&gt;So I built a pipeline with an actual gate in it. A promotion gate. The new model has to prove itself before it's allowed to replace what's currently live.&lt;/p&gt;

&lt;p&gt;How the gate works&lt;/p&gt;

&lt;p&gt;Two conditions, both have to pass:&lt;/p&gt;

&lt;p&gt;The new model has to clear a minimum bar on its own (I used F1 ≥ 0.70). Doesn't matter what's in production — if it's bad, it's rejected, full stop.&lt;br&gt;
It has to beat whatever's currently in production, by a real margin. Not tie. Not "basically the same." I set the bar at 0.5% absolute F1 improvement.&lt;/p&gt;

&lt;p&gt;That second one matters more than it sounds like it should. If you promote on literally any improvement, even 0.0001, you get this annoying situation where production flips back and forth based on random noise instead of anything meaningful. Requiring an actual margin stops that.&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
def promote_if_better(candidate_version, candidate_metrics, model_name):&lt;br&gt;
    candidate_score = candidate_metrics["f1"]&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if candidate_score &amp;lt; MIN_ACCEPTABLE_F1:
    return {"promoted": False, "reason": "below the floor, not even close"}

prod_version, prod_metrics = get_current_production_metrics(model_name)

if prod_version is None:
    # nothing to compare against, this is the first one
    set_alias(model_name, "production", candidate_version)
    return {"promoted": True}

improvement = candidate_score - prod_metrics["f1"]

if improvement &amp;gt;= PROMOTION_MIN_IMPROVEMENT:
    set_alias(model_name, "previous-production", prod_version)  # keep it, just in case
    set_alias(model_name, "production", candidate_version)
    return {"promoted": True, "improvement": improvement}

return {"promoted": False, "improvement": improvement}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That previous-production alias is doing quiet but important work. Before I let a new model take over, I tag the old one so I can find it again. That's what makes rollback a single function call instead of me digging through run history at 2am trying to remember which version was good.&lt;/p&gt;

&lt;p&gt;I didn't just trust it, I tried to break it&lt;/p&gt;

&lt;p&gt;Writing the logic is one thing. Believing it actually works is another. So before I let myself trust it, I ran it through a few scenarios by hand:&lt;/p&gt;

&lt;p&gt;First model ever, nothing to compare to → should just promote. It did.&lt;br&gt;
A model that ties with production → should get rejected. It did.&lt;br&gt;
A model that's genuinely 3% better → should promote, and the old one should stick around for rollback → it did, and rollback actually worked.&lt;/p&gt;

&lt;p&gt;Only after all three checked out did I go write proper integration tests for it — four of them, running against a real (but temporary) MLflow store so they're testing actual behavior, not just asserting that some constant is greater than zero.&lt;/p&gt;

&lt;p&gt;python&lt;br&gt;
def test_weak_candidate_is_rejected(mlflow_tracking):&lt;br&gt;
    v1 = register_and_promote(f1=0.80)&lt;br&gt;
    v2 = register_candidate(f1=0.801)  # barely ties&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;decision = promote_if_better(v2, {"f1": 0.801})

assert decision["promoted"] is False
# and production should still be v1, unchanged
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Genuinely satisfying watching that test suite go green after knowing I'd already proven the logic by hand first.&lt;/p&gt;

&lt;p&gt;Why the data has to drift&lt;/p&gt;

&lt;p&gt;If you're not simulating some kind of change over time, there's no real reason to have a retraining pipeline at all — you'd just train once and stop. So I generated a synthetic churn dataset (sklearn's make_classification, nothing fancy) and then made a second "new batch" of data with a slight shift applied to it, like customer behavior nudging over time. That's the whole justification for the pipeline existing in the first place.&lt;/p&gt;

&lt;p&gt;The part nobody puts in tutorials: it broke&lt;/p&gt;

&lt;p&gt;Midway through wiring up Prefect to orchestrate all this, I got a error that looked like this:&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz6miaoi6n2r06q2lm0db.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%2Fz6miaoi6n2r06q2lm0db.png" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool, cool, very helpful. Turns out the pipeline had actually finished — trained the model, registered it, made the promotion decision, all correctly — and then crashed while Prefect was cleaning up afterward. A version mismatch between Prefect and one of its dependencies, anyio. Prefect wanted anyio somewhere between 4.4.0 and 5.0.0, and whatever version pip grabbed inside that range had changed something internally that Prefect's code didn't expect.&lt;/p&gt;

&lt;p&gt;Pinned it down to anyio==4.4.0 and it went away.&lt;/p&gt;

&lt;p&gt;I'm including this because I think it's actually the most "real" part of the whole project. Nobody warns you that half of building these pipelines is just fighting with dependency versions that don't agree with each other. Reading a traceback carefully enough to realize "wait, this isn't my code, my code already finished" is its own skill, and it's one you only get by actually hitting the wall.&lt;/p&gt;

&lt;p&gt;What I think this actually proves&lt;/p&gt;

&lt;p&gt;Not "I can train a model." Anyone can train a model. What I think this shows instead:&lt;/p&gt;

&lt;p&gt;I can build a system that's allowed to say no, not just one that says yes to everything&lt;br&gt;
Every model version is traceable back to the exact run that produced it — no mystery models&lt;br&gt;
Rollback isn't theoretical, I actually tested it&lt;br&gt;
The whole thing runs as one command, not a pile of notebook cells I run in a specific order and hope I remember correctly&lt;br&gt;
I can debug real infrastructure problems, not just tune hyperparameters&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdwkigfrv8ho8lcm6u9pl.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%2Fdwkigfrv8ho8lcm6u9pl.png" alt=" " width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What's next&lt;/p&gt;

&lt;p&gt;This pipeline is good at deciding which model deserves to be in production. It doesn't actually serve anything yet. So next up: wrapping the promoted model in a real API, with some actual monitoring on it, so I can watch it in the wild instead of just trusting it blindly. That's the other half of this — one system decides what's good enough, the other one keeps an eye on it once it's out there.&lt;/p&gt;

&lt;p&gt;Code's here: &lt;a href="https://github.com/harshi606/churn-retraining-pipeline" rel="noopener noreferrer"&gt;https://github.com/harshi606/churn-retraining-pipeline&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've built something similar, especially around the "how do I actually trust an automated promotion" problem, I'd genuinely like to hear how you approached it.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deploying streamlit apps for free !</title>
      <dc:creator>harshi606</dc:creator>
      <pubDate>Fri, 23 Jul 2021 04:37:17 +0000</pubDate>
      <link>https://dev.to/harshi606/deploying-streamlit-apps-for-free-11f1</link>
      <guid>https://dev.to/harshi606/deploying-streamlit-apps-for-free-11f1</guid>
      <description>&lt;h1&gt;
  
  
  Most of the machine learning enthusiasts would be familiar with this framework.
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Streamlit&lt;/strong&gt; is an open-source,free framework using which you can build data webapps in a less amount of time.And you ask me whats so special about it !? Well, it is the fact that you can develop the webapps without any frontend knowledge !!! &lt;em&gt;Sounds cool ! right ?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It has a very user-friendly interface using which you can turn your data scripts into cool apps within minutes . It is all written in python and you just have type these magical words to install streamlit .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pip install streamlit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;or if pip isn't working then you can try this &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;conda install -c conda-forge streamlit&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Thats it ! You have installed streamlit. Since this post is dedicated to streamlit deploy, I am gonna restrict myself here and soon, I will make a post on streamlit for beginners.&lt;/p&gt;

&lt;p&gt;Now that you have built an app, You can run it only on your local host. Imagine, you are sitting for interviews and you have mentioned about your project in the resume. It will be really cool to attach a working link of your project which can be run anywhere and at anytime without depending on your local host ! Wondering how you can do that !?&lt;/p&gt;

&lt;p&gt;We have many free and paid deployment platforms like heroku, where deployment is very easy. You also have github IO where you can deploy your static webpages. &lt;/p&gt;

&lt;p&gt;Streamlit sharing is one such platform where you can make your webapps sharable. It is a perfect choice if your project is hosted public in github.&lt;/p&gt;

&lt;p&gt;I will list out the steps you need to follow in order to deploy your app.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First, you have to request an invite from the streamlit sharing &lt;a href="https://streamlit.io/sharing"&gt;over here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I got my invite acceptance after 5 days and hopefully it will be the case for everyone.Check your mail(spam folder too) and once you are accepted, You are ready to deploy.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, push your projects into your github repository(You need to be familiar with github !) and dont forget to add requirements.txt file same as you do for heroku.Make sure your repository is public.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;4.Visit the streamlit share link here:&lt;a href="https://share.streamlit.io/"&gt;click&lt;/a&gt;&lt;br&gt;
Now you can see the sigin page.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PFzwepeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hgqeelwlktgmyeaptzyk.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PFzwepeG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hgqeelwlktgmyeaptzyk.JPG" alt="Sig-in page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5.Sigin either using your email id or using your github account.I prefer github. &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vTDHUbpe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kopmxadmluanu3jrokfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vTDHUbpe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kopmxadmluanu3jrokfu.png" alt="Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;After you sign-in, You can see like this
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Ne0O7hN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yenwpd92ycnsg1ploq5q.png" alt="dashboard"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;7.click on new app -&amp;gt; From existing repo.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5neNCeY5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0pkcpnofx18mv3vahh8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5neNCeY5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b0pkcpnofx18mv3vahh8.png" alt="new app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Now you will be directed to this page.&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JrKHRRZL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snlv0u5r007jqk2a8opo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JrKHRRZL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/snlv0u5r007jqk2a8opo.png" alt="page"&gt;&lt;/a&gt;. Here my github is pasted by default. You can even paste the desired url here.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After you click deploy, then you can see a screen like this.It will take some time to deploy.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LVU0kB0v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6ykb06om7202kadtps9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LVU0kB0v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6ykb06om7202kadtps9.png" alt="deploy"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the app compiled without errors, It will be shown like this.&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q-pfCj-R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/do6zpltkpx5quiwwyvls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q-pfCj-R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/do6zpltkpx5quiwwyvls.png" alt="web app"&gt;&lt;/a&gt;. I showed the demo with a sample app available.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Try this out with  the sample app to get the taste of streamlit by following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click new app -&amp;gt; from sample app template.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R8nhWKFY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o16oxozf7k3daxqv18jq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R8nhWKFY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o16oxozf7k3daxqv18jq.png" alt="sample"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You will see a message window like this.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ogftH-jS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1g26ce5gsk6vxt42p5w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ogftH-jS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b1g26ce5gsk6vxt42p5w.png" alt="msg"&gt;&lt;/a&gt;&lt;br&gt;
Click on Get Authorization and fork sample app.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;3.You need to authorize to your github account. After that you can see a window similar to this.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YYsjFGHE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i19dmjctdkeequv166bo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YYsjFGHE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i19dmjctdkeequv166bo.png" alt="github"&gt;&lt;/a&gt;&lt;br&gt;
Click deploy and you can see the app compiling and finally running.&lt;/p&gt;

&lt;p&gt;Note: You can look and monitor your deployed apps from the dashboard.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--c1aNYk89--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q21n9jgqrpnsg5tpcyvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--c1aNYk89--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q21n9jgqrpnsg5tpcyvg.png" alt="Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have come to the end.I guess this article went too long and it is really a big one for my first article here !&lt;/p&gt;

&lt;p&gt;If you find any mistake or discrepancies do comment it and I'll rectify it straightaway. I am a learner and newbie for both technical articles as well as software world. So drop in a heart if you found this useful . Happy Reading !&lt;/p&gt;

</description>
      <category>streamlit</category>
      <category>deployment</category>
      <category>project</category>
    </item>
  </channel>
</rss>
