<?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: Manju</title>
    <description>The latest articles on DEV Community by Manju (@manjuk-dev).</description>
    <link>https://dev.to/manjuk-dev</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%2F4000091%2Ff32445b4-d866-4517-abb4-5b689ef2e218.png</url>
      <title>DEV Community: Manju</title>
      <link>https://dev.to/manjuk-dev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/manjuk-dev"/>
    <language>en</language>
    <item>
      <title>Why Your AI App Is Failing in Production (And It’s Not an ML Problem)</title>
      <dc:creator>Manju</dc:creator>
      <pubDate>Fri, 07 Aug 2026 14:03:23 +0000</pubDate>
      <link>https://dev.to/manjuk-dev/why-your-ai-app-is-failing-in-production-and-its-not-an-ml-problem-3g7b</link>
      <guid>https://dev.to/manjuk-dev/why-your-ai-app-is-failing-in-production-and-its-not-an-ml-problem-3g7b</guid>
      <description>&lt;p&gt;Nobody tells you this until you’re on-call at 2 AM: &lt;strong&gt;testing AI pipelines is significantly harder than testing standard backend code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And skipping rigorous testing is exactly how "it works on my machine" transforms into "it confidently hallucinated garbage to a paid customer." &lt;/p&gt;

&lt;p&gt;Most developers test the happy path: feed clean input --&amp;gt; get a neat JSON response --&amp;gt; ship it.&lt;/p&gt;

&lt;p&gt;Except AI pipelines don't fail like normal software. They &lt;strong&gt;fail quietly.&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No NullPointerException.&lt;/li&gt;
&lt;li&gt;No 500 Internal Server Error.&lt;/li&gt;
&lt;li&gt;No red lines in your log aggregator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just a completely wrong answer served with 100% statistical confidence.&lt;br&gt;
Here is what is actually going wrong inside your orchestration layer and the silent bugs hiding in plain sight.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. The Silent Pipeline Crash: Unchecked Input Edge Cases
&lt;/h3&gt;

&lt;p&gt;When a standard REST endpoint receives unexpected null or empty fields, your DTO validations (@NotNull, &lt;a class="mentioned-user" href="https://dev.to/notblank"&gt;@notblank&lt;/a&gt;) usually catch it at the door.&lt;/p&gt;

&lt;p&gt;In an AI orchestration pipeline (e.g., using Spring AI or LangChain4j), a missing null check on an incoming user prompt or document metadata rarely throws a clean HTTP 400. Instead, it propagates deep into your prompt template.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;// ❌ Dangerous: Assuming user metadata is always present&lt;br&gt;
String systemPrompt = String.format(&lt;br&gt;
    "Context: %s\nUser Preference: %s\nUser Question: %s",&lt;br&gt;
    retrievedContext,&lt;br&gt;
    user.getPreferences().getLanguage(), // Silent NPE or inserts "null" into the prompt!&lt;br&gt;
    userInput&lt;br&gt;
);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If &lt;em&gt;getLanguage()&lt;/em&gt; returns null, String formatting will literally inject "&lt;em&gt;null&lt;/em&gt;" as a string into your LLM prompt. The model then tries to interpret "&lt;em&gt;User Preference: null&lt;/em&gt;" as an instruction or context, degrading response quality without ever throwing an exception.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Treat every input to a prompt builder with strict guard clauses and unit tests specifically designed to pass null, empty strings, and massive payloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Regex &amp;amp; Token Chunking: The Invisible Data Corrupters
&lt;/h3&gt;

&lt;p&gt;Before your data hits an embedding model or vector store, it gets cleaned, split, and chunked. Most devs rely on basic Regex or character splitters to handle this.&lt;/p&gt;

&lt;p&gt;Regex bugs in text processing rarely throw runtime exceptions, they just quietly slice words in half or drop crucial context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What actually happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Off-by-one boundary splits:&lt;/strong&gt; A regex split cuts a sentence right before a negation (e.g., separating "do not" from "transfer funds"), completely reversing the semantic meaning of the chunk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regex catastrophic backtracking:&lt;/strong&gt; Complex regex patterns parsing raw user HTML/Markdown can lock up CPU threads on specific inputs, causing silent timeouts in your worker threads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Special character encoding:&lt;/strong&gt; Unescaped unicode or emoji characters breaking byte-length assumptions during token calculation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Java// ❌ Smoke test passes on "clean text", fails on edge-case formatting&lt;br&gt;
public List&amp;lt;String&amp;gt; chunkText(String rawText) {&lt;br&gt;
    // Regex splits fine on normal sentences, but destroys code blocks, &lt;br&gt;
    // JSON payloads, or non-English punctuation silently.&lt;br&gt;
    return List.of(rawText.split("(?&amp;lt;=[.!?])\\s+")); &lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Write property-based tests (using tools like jqwik in Java) that feed randomized, unformatted text, raw HTML, code blocks, and foreign characters into your chunkers to ensure boundaries hold up.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Deduplication Gaps &amp;amp; Prompt Window Poisoning
&lt;/h3&gt;

&lt;p&gt;You pull &lt;strong&gt;top-K&lt;/strong&gt; vectors from Pinecone, pgvector, or Qdrant, normalize the text, and pass them to the LLM. You assume your ingest pipeline removed duplicates.&lt;/p&gt;

&lt;p&gt;It didn't.&lt;/p&gt;

&lt;p&gt;If slightly different versions of the same document survive ingestion (e.g., differing only by trailing whitespace or minor metadata tags), your vector search will return 3 or 4 almost-identical chunks.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;[Retrieved Chunk 1]: "Refund policy: 30 days with receipt."&lt;br&gt;
[Retrieved Chunk 2]: "Refund policy: 30 days with receipt. " &amp;lt;-- Trailing space created different hash&lt;br&gt;
[Retrieved Chunk 3]: "Refund policy: 30 days with receipt."&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why this breaks your app:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Context Window Waste:&lt;/strong&gt; You’re paying for output tokens and wasting limited context space on repeated info.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attention Degradation:&lt;/strong&gt; LLMs suffer from the "Lost in the Middle" phenomenon. Duplicate text distorts the model's self-attention weights, causing it to ignore unique context buried elsewhere in the prompt.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Fix:&lt;/strong&gt; Test your deduplication step with semantic and hash-level boundary tests before storing vectors. Never rely on the database to handle hygiene for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Architectural Reality: It's Just Backend Engineering
&lt;/h3&gt;

&lt;p&gt;Notice a trend?&lt;/p&gt;

&lt;p&gt;None of these issues are exotic machine learning or mathematical model failures. They are &lt;strong&gt;boring, classic software bugs&lt;/strong&gt; hiding in an architecture that is now too complex to debug by eyeballing code.&lt;/p&gt;

&lt;p&gt;If you’re building AI-adjacent features, stop treating the LLM as a magical black box that will sort out messy data. Treat your pipeline with the same rigor, unit testing, and edge-case coverage you’d give a financial transaction pipeline.&lt;/p&gt;

&lt;h3&gt;
  
  
  Over to You
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;What’s a silent bug or overlooked edge case in your pipeline that would have quietly broken production if you hadn’t caught it with a test first? Let’s discuss in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>testing</category>
      <category>java</category>
    </item>
    <item>
      <title>How I Boosted RAG Code Search Accuracy From 55% to 95%</title>
      <dc:creator>Manju</dc:creator>
      <pubDate>Fri, 03 Jul 2026 05:38:07 +0000</pubDate>
      <link>https://dev.to/manjuk-dev/how-i-boosted-rag-code-search-accuracy-from-55-to-95-3c1b</link>
      <guid>https://dev.to/manjuk-dev/how-i-boosted-rag-code-search-accuracy-from-55-to-95-3c1b</guid>
      <description>&lt;h4&gt;
  
  
  How I built GitGrok, a Java codebase search tool using Spring Boot 3.4 and Spring AI, and got to 95% retrieval accuracy by throwing out standard RAG for something closer to a search engine that understands intent.
&lt;/h4&gt;

&lt;p&gt;&lt;em&gt;A practical breakdown of how "just embed and retrieve" falls apart on real code, and what I built instead.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever built a basic Retrieval Augmented Generation (RAG) application, you know the general flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Chunk&lt;/strong&gt; the text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate&lt;/strong&gt; vector embeddings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Store&lt;/strong&gt; those embeddings in a vector database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run&lt;/strong&gt; a similarity search.&lt;/li&gt;
&lt;/ol&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%2Fyis0y1iyv22tmc9h3frn.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%2Fyis0y1iyv22tmc9h3frn.png" alt="Standard RAG flow" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This works incredibly well for text based documents like PDFs, articles, or wikis. However, it completely failed when I tried applying it to source code.&lt;/p&gt;

&lt;p&gt;When I was building GitGrok, a tool that lets developers chat with their repositories in plain English, I wanted the user experience to be simple: ask a question about your codebase and get an instant answer. Sounds straightforward, right?&lt;/p&gt;

&lt;p&gt;It wasn’t.&lt;/p&gt;

&lt;p&gt;Initially, I pushed my Java source code into a Pinecone vector database and built a basic search endpoint. This default semantic search yielded poor, noisy, inconsistent, and often outright wrong retrieval quality. Here is how I diagnosed the problems and how I fixed them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Pure Semantic Search Fails on Codebases
&lt;/h3&gt;

&lt;p&gt;Semantic search implies context-aware searching (focusing on meaning) instead of exact keyword matching. While this sounds powerful, codebases require deterministic precision.&lt;br&gt;
When I first implemented GitGrok using default, file-level embeddings, two fatal flaws emerged:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Test File Pollution Trap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The vector database consistently ranked test classes much higher than actual production code. This happened because test files are naturally more verbose and repetitive, whereas production source code files are compact and abstract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Semantic Drift and Confusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider a user querying: “&lt;em&gt;Show me the controller responsible for handling owner registration&lt;/em&gt;.”&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;The Drift:&lt;/strong&gt; Instead of returning OwnerController.java (the actual business logic), semantic search retrieved Owner.java (the domain entity) or OwnerControllerTests.java (the test suite).&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;The Cause:&lt;/strong&gt; Both the entity and the test file shared a high cosine similarity with the query because they contained the terms "Owner" and "Controller" repeatedly. Pure semantic search proved far too fuzzy for this use case.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Fix: Two Separate Phases
&lt;/h3&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%2F38u22s525xvxn9fv3bhr.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%2F38u22s525xvxn9fv3bhr.png" alt="GitGrok pipeline overview" width="800" height="676"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We cannot fix everything on the retrieval side alone; how we store code in a vector database is just as critical. You can't simply dump raw files into a database and expect them to yield high-quality embeddings.&lt;/p&gt;

&lt;p&gt;To solve this, I split the architecture into two clean phases:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Phase 1: Smart Ingestion&lt;/strong&gt; – Shaping and filtering the data before feeding it into Pinecone.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Phase 2: Smart Retrieval&lt;/strong&gt; – Processing user queries intelligently before they touch the database.&lt;/p&gt;
&lt;h3&gt;
  
  
  Phase 1: Smarter Ingestion
&lt;/h3&gt;

&lt;p&gt;I started my optimizations at the ingestion level. Initially, I had ingested entire files as single documents. This caused severe concept dilution because a 500-line Java class contains imports, annotations, comments, and various helper functions that muddy the waters. The first major pivot was changing how code is chunked before indexing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Drop Test Classes Entirely&lt;/strong&gt;&lt;br&gt;
I excluded test directories and documentation entirely during the ingestion phase, focusing the index strictly on production files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Chunk by Method&lt;/strong&gt;&lt;br&gt;
I broke classes down into distinct functional blocks (methods) to preserve tight, localized semantic context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Code-Aware Term Weighting&lt;/strong&gt;&lt;br&gt;
Because pure semantic search wasn’t enough, I needed to merge semantic meaning with exact syntax. I realized GitGrok couldn't rely on embeddings alone, so I pivoted to &lt;strong&gt;Hybrid Search&lt;/strong&gt;, combining dense vectors for context with sparse vectors for precise terminology.&lt;br&gt;
In simple terms, our hybrid search combines two retrieval methods:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Dense Vectors (Semantic Search):&lt;/strong&gt; An embedding model converts code into high-dimensional vectors. This is great at understanding underlying concepts and intent.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Sparse Vectors (Keyword Search):&lt;/strong&gt; A mechanism that scores documents based on token frequency, acting like a traditional search engine. This is great for exact matches and precise variable/method names.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solving the Scoring Problem&lt;/strong&gt;&lt;br&gt;
When you combine dense and sparse search methods in a hybrid pipeline, you run into a core mathematical hurdle: &lt;strong&gt;they score on completely different scales.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dense search returns scores between 0.0 and 1.0, while sparse keyword search returns scores from 1 to 100+. You cannot simply add them together (e.g., 0.85 + 45.0). If you do, raw keyword counts will completely drown out semantic intelligence.&lt;/p&gt;

&lt;p&gt;To fix this apples-to-oranges problem, I normalized the scales during ingestion by applying &lt;strong&gt;code-aware token multipliers&lt;/strong&gt; to the sparse vectors before storing them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Token Type                       Weight
Method signatures                 3.0x
Class names                       2.5x
Property names                    2.0x
Generic keywords                  0.3x
Stop words (if, for, return)      0.1x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This adjustment made the database inherently structure-aware before any queries were even executed against it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2: Smarter Retrieval
&lt;/h3&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%2Fni9nj8s1f49ow090e3jf.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%2Fni9nj8s1f49ow090e3jf.png" alt="GitGrok pipeline retrieval" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next came query handling. Instead of passing a user's raw query directly to the database, I routed it through layers of intelligent filtering first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Intent Detection&lt;/strong&gt;&lt;br&gt;
First, the system analyzes the query to understand exactly what the type of resource the user wants. Pre-compiled regex matching patterns are utilized in a helper method, detectQueryType(), to isolate the specific structural intent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Filename Extraction and Metadata Filtering&lt;/strong&gt;&lt;br&gt;
Once the intent is identified, the system extracts target filenames from the query (if mentioned) and builds a metadata filter map. If the intent is a method lookup, the system restricts the database search space exclusively to chunks tagged with symbolType: method/class, completely bypassing validators, repositories, and factories. This prunes irrelevant chunks and slashes latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Alpha-Scaled Hybrid Search&lt;/strong&gt;&lt;br&gt;
While hybrid search combines sparse and dense retrieval, a blind combination usually results in one side overpowering the other. To fix this, I optimized the pipeline by tuning the α (alpha) parameter to control the exact balance.&lt;/p&gt;

&lt;p&gt;After extensive experimentation, I landed on α = 0.6 as the sweet spot:&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Dense gets 60% weight:&lt;/strong&gt; Raw embedding coordinates are multiplied by α (0.6), capturing what the developer means.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;Sparse gets 40% weight:&lt;/strong&gt; Query token frequency scores are scaled by (1 - α) (0.4), keeping results rigidly tied to exact code syntax.&lt;/p&gt;

&lt;p&gt;The scaling happens inside the application layer before the payload leaves the app. Pinecone receives both the dense and sparse vectors together in a single payload with the balance pre-calibrated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; α scales the query vectors dynamically on every request, not the stored document vectors. The stored vectors remain fixed by our ingestion-time weights.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Result: 95% Accuracy, Zero Hallucinations
&lt;/h3&gt;

&lt;p&gt;Two shifts made all the difference: breaking code into clean, method-sized chunks, and pairing that with a tightly tuned hybrid search funnel. Together, they pushed retrieval accuracy to 95%.&lt;br&gt;
With such clean context finally reaching the LLM, I felt confident enough to enforce one hard rule in the prompt engineering layer:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"If the snippet isn't explicitly in the provided context, say 'Not Found'. Do not guess."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It worked flawlessly. Hallucinations plummeted - not because the LLM magically got smarter, but because the retrieval engine became reliable enough to back up that strict constraint. I learned that a system that honestly confesses "Not Found" is infinitely more valuable than one that confidently invents code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance Metrics&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Metric                     Before       After     Change
Retrieval Accuracy          55%          95%       +73%
Hallucinations              40%          &amp;lt;5%       −87%
Query Latency               45s          12s       3.7x faster
Wrong File Types Returned   60%          &amp;lt;10%      −83%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Full Architecture
&lt;/h3&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%2F7egzwn5tyl2ucapwtz20.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%2F7egzwn5tyl2ucapwtz20.png" alt="GitGrok high level design" width="800" height="656"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Takeaways
&lt;/h3&gt;

&lt;p&gt;• &lt;strong&gt;Meaning isn’t structure:&lt;/strong&gt; Building GitGrok taught me that standard semantic search only looks for the "vibe" of text. Code doesn't work that way. To cut through repository noise, you must lock things down with metadata filters and strict hybrid (vector + keyword) constraints.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;From fragments to graphs:&lt;/strong&gt; Right now, GitGrok fetches isolated code snippets, but it doesn't fully map how they connect. The next step is building AST-driven (Abstract Syntax Tree) graphs to trace deep dependencies, like tracking an API request all the way from a controller down to the database layer.&lt;/p&gt;

&lt;p&gt;• &lt;strong&gt;The "Why" matters:&lt;/strong&gt; If you ask GitGrok why a configuration value is set to 0.6, it can't tell you, because that context lives outside the source code. Future iterations will pull in Git commit histories and PR comments to surface the human decisions behind the lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Over to You
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Have you run into similar retrieval traps when building RAG systems for highly technical or structured datasets? Let's talk about your chunking and hybrid optimization strategies in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>java</category>
      <category>vectordatabase</category>
    </item>
  </channel>
</rss>
