<?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: Anubhav Verma</title>
    <description>The latest articles on DEV Community by Anubhav Verma (@anubhav_verma_c15696e7d7b).</description>
    <link>https://dev.to/anubhav_verma_c15696e7d7b</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%2F3994991%2F32a657ad-e808-41f7-a2b8-0402fc76a736.png</url>
      <title>DEV Community: Anubhav Verma</title>
      <link>https://dev.to/anubhav_verma_c15696e7d7b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anubhav_verma_c15696e7d7b"/>
    <language>en</language>
    <item>
      <title>The day i witnessed timeless beauty</title>
      <dc:creator>Anubhav Verma</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:53:29 +0000</pubDate>
      <link>https://dev.to/anubhav_verma_c15696e7d7b/the-day-i-witnessed-timeless-beauty-2fk5</link>
      <guid>https://dev.to/anubhav_verma_c15696e7d7b/the-day-i-witnessed-timeless-beauty-2fk5</guid>
      <description>&lt;p&gt;Time seemed to stand still when I saw &lt;em&gt;her&lt;/em&gt; in that elegant traditional attire, especially the way she adorned that delicate cotton kurti with intricate red white prints. She don't need any jewellery she &lt;em&gt;herself&lt;/em&gt; is nothing less than real gold.  Oh, the way she carries herself, there's a charm that is impossible to resist. The moment she stepped into the sunlight, with a gentle breeze playing with her hair, she looked nothing less than a vision sent from the heavens above.&lt;/p&gt;

</description>
      <category>life</category>
      <category>love</category>
      <category>she</category>
      <category>beauty</category>
    </item>
    <item>
      <title>Building RAG that doesn't hallucinate</title>
      <dc:creator>Anubhav Verma</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:41:25 +0000</pubDate>
      <link>https://dev.to/anubhav_verma_c15696e7d7b/building-rag-that-doesnt-hallucinate-1did</link>
      <guid>https://dev.to/anubhav_verma_c15696e7d7b/building-rag-that-doesnt-hallucinate-1did</guid>
      <description>&lt;p&gt;Every RAG tutorial promises the same thing: hook a vector database up to an LLM, and suddenly your model is "grounded" and "won't hallucinate anymore." Then you actually build one, point it at real research papers, and watch it confidently cite a claim that isn't anywhere in the source document. RAG doesn't eliminate hallucination by default — it just gives the model more rope to hang itself with, dressed up as "context." Fixing that, for PaperMind, came down to two unglamorous things: chunking well, and refusing to hide the model's uncertainty from the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The retrieval pipeline&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;PaperMind's job is to let someone ask questions against a corpus of research papers and get answers grounded in the actual text — not in whatever LLaMA 3.1 happens to remember from pretraining. The pipeline behind that is a fairly standard RAG shape on the surface: documents get chunked, embedded, and stored in Pinecone; a query gets embedded the same way; the most relevant chunks get retrieved and stuffed into the prompt; LLaMA 3.1, served through Groq, generates the answer from that context.&lt;br&gt;
The standard shape is also where most RAG systems quietly fail, and it's worth being specific about where.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why naive chunking breaks things&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The default move in most RAG walkthroughs is fixed-size chunking — split every document into, say, 500-token blocks and move on. For research papers, this is close to actively hostile to retrieval quality. A 500-token window will frequently cut a sentence in half, separate a claim from the citation that supports it, or split a table from the caption that explains what it means. When that broken chunk gets retrieved and handed to the LLM as "context," the model is now trying to answer a question using a fragment that's missing exactly the information that would have made the answer correct — and it'll often fill the gap with something plausible-sounding instead of saying "I don't have enough information."&lt;br&gt;
That's the actual mechanism behind a lot of RAG hallucination. It's not that the model is "ignoring" the context — it's that the context it was handed was already broken before it ever reached the prompt.&lt;br&gt;
The fix in PaperMind is semantic chunking: instead of splitting on a fixed token count, chunks are formed around semantically coherent units — keeping a claim together with its supporting sentences, keeping a section's argument intact rather than slicing it at an arbitrary boundary. This is more expensive to compute than fixed-size splitting and it's not a solved problem — there's no chunking strategy that's perfect for every paper structure — but it consistently produces retrieved context that actually contains complete thoughts, which matters more for answer quality than almost any other knob in the pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pinecone, and the boring part that actually matters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The vector store itself — Pinecone, in this case — is the least interesting part of the system to talk about and one of the most important to get right operationally. The embeddings need to be generated with a model whose notion of "similarity" actually matches what counts as relevant for research-paper Q&amp;amp;A — abstract semantic similarity isn't quite the same thing as "this chunk would help answer this specific question." Tuning the retrieval — how many chunks to pull back, how to handle the score threshold below which a chunk probably isn't actually relevant — turned out to matter more for final answer quality than swapping the LLM ever did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The part most RAG demos skip: chunk-score transparency&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the piece I think actually made PaperMind trustworthy rather than just functional: surfacing the retrieval scores to the user instead of hiding them behind the final generated answer.&lt;br&gt;
Every RAG system already computes a similarity score for each retrieved chunk — that's how it decides what to retrieve in the first place. Almost no RAG demo shows that number to the user. The answer just appears, fully formed, with the same tone of confidence whether the underlying retrieval was a strong match or a desperate scrape of the least-bad chunk available.&lt;br&gt;
PaperMind surfaces the chunk scores alongside the answer, so a user can see not just "here's the answer" but "here's the answer, and here's how confident the retrieval step actually was in the material it found." When the top retrieved chunk has a low similarity score, that's a signal worth seeing — it usually means the answer is more synthesis-from-weak-evidence than direct citation, and a user who can see that score knows to double check before treating the answer as settled. This is a small UI decision with an outsized effect on trust: it turns the system from "is this thing lying to me" into "I can see exactly how grounded this particular answer is."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I'd tell someone building their first RAG system&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If I had to compress this into the two things that actually matter, beyond getting embeddings and an LLM call working: chunk like the structure of your documents actually matters, because it does, and never let the final answer hide how confident the retrieval step was. The LLM generating fluent, confident-sounding text is the easy part — it's good at that regardless of whether the underlying evidence supports it. The hard part, and the part that actually determines whether your RAG system is trustworthy in production, is making sure the retrieval step is honest about what it found, and making sure that honesty doesn't get lost between the vector store and the chat bubble the user reads.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>genai</category>
      <category>llama</category>
    </item>
    <item>
      <title>Shipping a BERT model as a browser extension</title>
      <dc:creator>Anubhav Verma</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:26:14 +0000</pubDate>
      <link>https://dev.to/anubhav_verma_c15696e7d7b/shipping-a-bert-model-as-a-browser-extension-4kch</link>
      <guid>https://dev.to/anubhav_verma_c15696e7d7b/shipping-a-bert-model-as-a-browser-extension-4kch</guid>
      <description>&lt;p&gt;Most fine-tuned BERT tutorials end at the same place: a confusion matrix, a nice accuracy number, and a notebook that never leaves your laptop. The part that's actually hard — and the part almost nobody writes about — is what happens after that, when you decide the model should live where the problem lives. For a fake news detector, that means inside the browser, next to the article someone is actually reading, not in a notebook three tabs away.&lt;br&gt;
&lt;em&gt;That gap between "the model works" and "the model is useful" is what this post is about.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Starting point: a fine-tuned BERT that actually performed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core model is a BERT classifier fine-tuned for fake news detection, landing at 96% accuracy on the evaluation set. Getting there involved the usual fine-tuning work — tokenization choices, learning rate schedules, deciding how much of BERT to freeze versus fine-tune end-to-end — but I want to skip past that part, because the more interesting engineering started once the model was good enough to actually use.&lt;br&gt;
A model sitting in a .pt file isn't a product. It's a liability waiting for someone to ask "okay, but how do I use this?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step one: wrapping it in a Flask API&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The first move was the obvious one — wrap the model behind a Flask REST API. A single /predict endpoint, taking in article text and returning a label and confidence score. This sounds trivial and mostly is, but there are a few decisions here that matter more than they look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tokenization has to happen inside the API, not on the client.&lt;/strong&gt; The browser extension shouldn't need to know anything about how BERT was trained — it just sends raw text and gets back a verdict. This keeps the extension dumb and the model's internals swappable later without touching the frontend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batching versus single-request inference.&lt;/strong&gt; A browser extension calling the API is almost always going to send one article at a time, not a batch, so optimizing for batch throughput (the thing most ML tutorials optimize for) was the wrong target. The real target was single-request latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model loading time.&lt;/strong&gt; Loading a fine-tuned BERT model from disk on every request is a rookie mistake that'll tank your response times. The model gets loaded once, at server startup, and kept in memory for the life of the process.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is exotic. It's just the difference between a model that works in a Jupyter cell and a model that responds in time for someone to actually read the verdict before they've already finished the article.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step two: getting to sub-second inference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the API was up, the next problem was speed. A 96%-accurate model that takes four seconds to respond is not a usable product — by the time the verdict shows up, the reader has already formed an opinion about the article. The target was sub-second response time, end to end: text leaves the browser, hits the Flask endpoint, gets tokenized, runs through BERT, and comes back as a label.&lt;br&gt;
Getting there meant treating inference latency as a first-class metric, not an afterthought measured once at the end. A few things mattered more than I expected going in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Truncating input length sensibly. Full articles can run long, and BERT's quadratic attention cost means trimming to a reasonable max token length (rather than feeding in the entire article) cut inference time noticeably without meaningfully hurting accuracy — most of the signal for "is this fake" tends to be front-loaded in an article anyway.&lt;/li&gt;
&lt;li&gt;Keeping the API stateless and lightweight, so there's no overhead beyond the model call itself.&lt;/li&gt;
&lt;li&gt;Testing latency under realistic conditions actual articles pulled from real pages, not clean benchmark text — because real-world text is messier and longer than curated eval sets, and that messiness is exactly where latency surprises hide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step three: the browser extension itself&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the part that turns an API into something a person actually touches. The extension's job is narrow on purpose: grab the visible article text from the page, send it to the Flask endpoint, and render the verdict somewhere the reader will actually see it — not buried in a popup they have to click to open.&lt;/p&gt;

&lt;p&gt;A few practical lessons from building this part:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extracting "the article" from a webpage is messier than it sounds.&lt;/strong&gt; Pages are full of navigation menus, ads, related-article widgets, and comment sections. Sending all of that text to the model means feeding it noise the fine-tuning data never looked like. Getting a reasonably clean extraction of just the article body — without writing a full bespoke parser for every site — took more iteration than the model training did.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Permissions matter more than code.&lt;/strong&gt; Browser extensions live or die on what permissions they request. Asking for broad host permissions to "read and change all your data on all websites" is the kind of thing that gets an extension flagged or just makes people uninstall it. Scoping permissions down to only what's needed for content extraction was as much a part of "shipping" as the ML pipeline was.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Showing confidence, not just a verdict.&lt;/strong&gt; A flat "FAKE" or "REAL" label is both less honest and less useful than a confidence score. A 96%-accurate model is still wrong roughly one time in twenty-five, and an interface that hides that uncertainty behind a binary label is setting the user up to over-trust it. Surfacing the confidence score directly in the extension UI was a small change that made the whole tool feel more honest.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the gap between notebook and product actually looks like&lt;/strong&gt;&lt;br&gt;
If I had to compress the lesson from this project into one sentence: the model is maybe a third of the work, and it's the third that's well-documented everywhere else. The other two-thirds — a clean API contract, a latency budget you actually hit, and an extension that extracts the right text and is honest about its own confidence — is where a fake news detector goes from "an accuracy number in a paper" to something that changes what a person believes while they're actually reading.&lt;br&gt;
That's also, not coincidentally, the part that's the most fun to build.&lt;/p&gt;

</description>
      <category>news</category>
      <category>nlp</category>
      <category>bertmodel</category>
      <category>flask</category>
    </item>
    <item>
      <title>Why I put a 4-qubit circuit inside a brain tumor classifier</title>
      <dc:creator>Anubhav Verma</dc:creator>
      <pubDate>Sun, 21 Jun 2026 07:03:08 +0000</pubDate>
      <link>https://dev.to/anubhav_verma_c15696e7d7b/why-i-put-a-4-qubit-circuit-inside-a-brain-tumor-classifier-2pg2</link>
      <guid>https://dev.to/anubhav_verma_c15696e7d7b/why-i-put-a-4-qubit-circuit-inside-a-brain-tumor-classifier-2pg2</guid>
      <description>&lt;p&gt;A few months ago I would have told you quantum machine learning was mostly hype dressed up in cool-sounding words — "superposition," "entanglement," "quantum advantage" — thrown around papers that never quite show you the number that matters. Then I built one of these systems myself, for something that actually has stakes: classifying brain tumors from MRI scans. And I came out the other side with a more interesting opinion than "hype" or "revolution." It's somewhere in between, and the in-between is where the actual engineering lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The setup: a classifier that already worked fine&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I didn't start from scratch. The backbone of the system is DenseNet121, a convolutional architecture that's been doing solid work on medical imaging for years. Trained on MRI slices, a plain DenseNet121 classifier already gets you a respectable accuracy on tumor classification. If your only goal is "ship something that works," you could stop there and nobody would blame you.&lt;br&gt;
So why didn't I stop there?&lt;br&gt;
Because "works" and "trustworthy enough to sit next to a radiologist" are different bars. Medical imaging is one of the few domains where a model being slightly better isn't really the point — the point is whether you can explain why it made a call, and whether that explanation would survive a doctor asking "wait, why?" That question is what pulled me toward two very different ideas at once: quantum circuits and explainability, bolted onto the same model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where the qubits come in&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The quantum part isn't replacing the neural network — that's a common misconception about hybrid quantum-classical models, and it's worth being blunt about. DenseNet121 still does the heavy lifting: extracting features from the MRI images, learning what textures and shapes correlate with tumor types. What I added on top is a 4-qubit variational quantum circuit, built with PennyLane, sitting at the tail end of the pipeline where the classical network would normally just feed straight into a final classification layer.&lt;br&gt;
A variational quantum circuit is, at a practical level, a small set of parameterized quantum gates whose parameters get trained the same way a classical layer's weights get trained — through gradient descent, just computed via a different mechanism (parameter-shift rules instead of standard backprop). The promise is that the quantum circuit can represent certain non-linear feature interactions more efficiently than a classical layer of comparable size, because superposition lets it explore a larger effective feature space with fewer parameters.&lt;br&gt;
In this project, that promise showed up as a real, measurable gain over the classical-only baseline. Swapping the final classical layer for the 4-qubit circuit pushed accuracy up by around six percentage points. That's not a "we ran it once and got lucky" number — it held up across the held-out test set. But I want to be honest about what that gain actually represents, because "quantum gives you free accuracy" is the wrong takeaway.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gain is real, but it's not magic&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What the quantum layer is really doing here is acting as a different kind of non-linear transformation on the features DenseNet121 has already extracted — one that's harder to replicate exactly with a classical layer of the same parameter count. Whether that's because of genuine quantum effects or just a different inductive bias that happens to fit this dataset well is an open and genuinely debated question in the QML literature, and I don't think it's fully settled even by people far more qualified than me. What I can say with confidence is: on this dataset, with this architecture, the hybrid model classified more tumors correctly than the classical-only one did, consistently.&lt;br&gt;
The honest framing I'd give anyone asking "should I add a quantum layer to my model" is: it's a tool worth testing when your classical model has plateaued and you have a small number of features feeding into a final decision layer — 4 to 8 qubits is the realistic, simulable range right now. It is not a tool for squeezing performance out of a model that's already well-fit, and it is absolutely not free — every quantum circuit you simulate classically costs you exponentially more compute as qubit count grows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trusting the model: Grad-CAM and SHAP, together&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The accuracy gain was the smaller part of why I built this. The bigger part was explainability, because a 6% lift means nothing in a clinical context if you can't show why the model is making its decisions.&lt;br&gt;
I used two explainability techniques side by side, deliberately, because they answer different questions:&lt;br&gt;
Grad-CAM answers "where in the image was the model looking?" It produces a heatmap over the MRI slice, highlighting the regions that most influenced the classification. For a tumor classifier, this is the sanity check a radiologist would actually want — does the hot region in the heatmap correspond to the tumor, or is the model fixating on some artifact in the corner of the scan?&lt;br&gt;
SHAP answers a different question: "of the features the model extracted, which ones mattered most for this specific prediction, and in which direction?" Where Grad-CAM is spatial, SHAP is attributional — it decomposes the prediction into per-feature contributions, which is useful for catching cases where the model's spatial attention looks fine but its actual decision logic is leaning on something subtle and wrong.&lt;br&gt;
Running both gave me a much more complete picture than either alone would have. There were a handful of cases where Grad-CAM's heatmap looked perfectly reasonable — centered right on the tumor — but SHAP revealed the model was still weighting some unrelated texture feature more heavily than it should have. Without the second lens, I'd have shipped that case as "explained" when it wasn't really.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Noise, and why NISQ matters more than people think&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The last piece — and the part that gets skipped in a lot of QML write-ups — is noise evaluation under NISQ (Noisy Intermediate-Scale Quantum) conditions. Right now, every real quantum computer is noisy. Gates have error rates, qubits decohere, and a circuit that works beautifully in a noiseless simulation can degrade meaningfully once you account for realistic hardware noise.&lt;br&gt;
I didn't just train the model on a clean simulator and call it done — I evaluated how the 4-qubit circuit's performance held up under simulated NISQ noise conditions, because that's the actual environment any near-term quantum hardware will run in. This matters for one practical reason: if you're going to claim a quantum-enhanced model is viable, you have to show it's still better than the classical baseline after accounting for the noise you'd see on real hardware, not just in the idealized simulator where every gate is perfect.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where I landed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're considering a hybrid quantum-classical approach for your own project, here's the honest summary: it's a legitimate technique, not a buzzword, but it's a narrow tool. It earns its place when you have a small, well-defined final decision layer, when you've already squeezed what you can out of the classical architecture, and when you're willing to do the unglamorous work of explainability and noise evaluation rather than just reporting one accuracy number and calling it a day.&lt;br&gt;
The six points of accuracy were nice. The two explainability methods agreeing with each other — most of the time — was the part that actually made me trust the system.&lt;/p&gt;

</description>
      <category>quantumml</category>
      <category>deeplearning</category>
      <category>pennylane</category>
      <category>explainableai</category>
    </item>
  </channel>
</rss>
