RAG Retrieval Pain Point: Strong Semantic Understanding but Weak Code Identification — How to Fix It

Why RAG systems fail at exact identifiers and how to approach fixing the retrieval-evaluation gap.
Enterprise RAG systems often excel at semantic queries but collapse when users input exact part codes or internal abbreviations. This article analyzes why both dense retrieval and BM25 fail in these scenarios, why common optimizations like chunk overlap, acronym expansion, and RRF merely shift problems around, and argues that building robust evaluation frameworks with dual scoring for identifier recall and clause-level support is the essential first step toward real solutions.
A Real-World RAG Dilemma
In the practical deployment of enterprise-grade Retrieval-Augmented Generation (RAG) systems, there's one failure mode that's particularly frustrating: the system handles ordinary natural language questions with ease, but the moment a user inputs an internal abbreviation or a precise part code, retrieval quality collapses instantly.
Recently, a Reddit developer shared their hard-won lessons from the field, pointing directly at the deep-seated conflict between "semantic understanding" and "exact matching" in RAG systems. Their words paint a vivid picture: "Our RAG assistant handles general questions just fine, but the moment someone types in an internal abbreviation or an exact part code, it completely falls apart."
This problem may seem niche, but it actually touches on the most fundamental technical weakness of current RAG architectures — dense retrieval and lexical retrieval each have fatal shortcomings, and any single optimization approach is just robbing Peter to pay Paul.
The Dual Failure of Dense Retrieval and BM25
This developer precisely described how both types of retrievers fail — lessons every RAG practitioner should take to heart.
Dense Retrieval: Returns "Semantically Pleasant Junk"
Dense retrieval is based on vector similarity and excels at capturing semantic relationships. Its core idea is to encode both queries and documents into high-dimensional vectors — typically generated by pre-trained language models like BERT, E5, or BGE — then calculate semantic proximity using metrics like cosine similarity or inner product. Unlike traditional keyword matching, dense retrieval can understand synonyms, semantic paraphrasing, and even cross-lingual semantic equivalence. For example, when a user searches for "how to fix engine overheating," dense retrieval can establish a connection even if the document uses "solutions for abnormal engine temperature."
However, when faced with a precise part code or internal abbreviation, dense retrieval often returns "semantically pleasant junk from the right general area."
In other words, vector search knows roughly which domain your question belongs to, but it can't grasp the exact identifier that determines whether the answer is right or wrong. For queries that are low in semantics but demand high precision — like part codes — vector embeddings inherently perform poorly. This is because embedding models are primarily trained on natural language text, and for semantically meaningless code strings (like "XJ-4420-B"), the model tends to map them to fuzzy regions in the embedding space, resulting in severely insufficient discriminability.
BM25: Finds the Code but Loses the Exception Clause
Term-frequency-based BM25 can precisely hit identifiers, but it often "drops the nearby exception clause that changes the answer."
BM25 (Best Matching 25) is a classic probabilistic ranking algorithm in information retrieval, proposed by Stephen Robertson et al. in the 1990s, and it remains the default ranking function in mainstream search engines like Elasticsearch and Solr. Its core mechanism is based on three factors: term frequency (TF), inverse document frequency (IDF), and document length normalization. The more frequently a term appears in a document and the rarer it is across the entire corpus, the higher that document scores. BM25's strength lies in its extreme sensitivity to exact term matching, which makes it well-suited for queries involving part codes, product numbers, and similar precise identifiers. But its fundamental limitation is a complete lack of semantic understanding — it matches word by word and cannot handle synonym substitution, let alone contextual dependencies.
This is an extremely subtle trap. In enterprise documents, the rules for a part code are often accompanied by a critical "unless..." or "but in case X..." exception statement. BM25 precisely locates the chunk containing the code, but because the chunking strategy has sliced the decisive exception clause into another chunk, the final answer formally cites what appears to be a relevant page while actually hallucinating an incorrect applicable rule.
Chunking is a critical preprocessing step in RAG systems that divides long documents into retrievable segments. Common strategies include fixed-length chunking (e.g., cutting every 512 tokens), sliding window chunking (maintaining some overlap between adjacent chunks), semantic-based chunking (splitting at sentence boundaries or paragraph structures), and recursive chunking (first splitting by major structure then refining layer by layer). The choice of chunk granularity is fundamentally a trade-off between precision and contextual completeness: chunks too small make precise codes easy to locate but lose context; chunks too large preserve context but degrade retrieval precision and vector representation quality. The "exception clause cut into another chunk" described here is a classic boundary effect in sliding window chunking — when a business rule spans a chunk boundary, no single chunk can fully express the complete semantics of that rule.
The result: the support team has stopped trusting those "pretty citations." The author admitted he couldn't blame them.
Every Optimization Is Robbing Peter to Pay Paul
This developer tried multiple commonly used RAG retrieval optimization techniques, but each one fell into the trap of "helping one thing while hurting another." This list of failures is itself highly instructive.
Pre-Retrieval Acronym Expansion
Expanding acronyms before retrieval (acronym expansion) is a common practice. But the problem is that the same code may mean completely different things across different departments. Blindly expanding acronyms creates new confusion, causing the system to conflate cross-departmental homonyms.
Larger Chunk Overlap
Increasing chunk overlap can preserve exception clauses, but larger chunks also "bury" precise identifiers in lengthy text, diluting BM25's hit weight for the code.
Increasing top-k and Reciprocal Rank Fusion
Increasing top-k can recover recall, but it floods the reranker with "near matches." Rerankers are typically implemented using Cross-Encoders — unlike the bi-encoder architecture of dense retrieval, Cross-Encoders concatenate the query and document and jointly feed them into a Transformer model, capturing finer-grained interaction information with significantly higher ranking precision than the initial retrieval stage. Typical rerankers include Cohere Rerank, bge-reranker, and the cross-encoder/ms-marco series. However, a reranker's effectiveness depends critically on recall quality in the initial retrieval stage — if the correct document doesn't exist in the initial top-k, no amount of reranker precision can help. When the top-k is filled with semantically similar but imprecise results, the reranker lacks sufficient signal to distinguish "roughly relevant" from "exact match."
Reciprocal Rank Fusion (RRF) across dense and lexical results also only mitigates the problem without curing it. RRF is a classic multi-list result merging algorithm proposed by Cormack et al. in 2009. Its formula works as follows: for each document d, the final score = Σ 1/(k + rank_i(d)), where rank_i(d) is document d's rank in the i-th retriever's result list, and k is a smoothing constant (typically set to 60). The elegance of RRF lies in not requiring normalization of raw scores from different retrievers (since dense retrieval's cosine similarity and BM25's probability scores have completely different scales) — it relies solely on ranking information. However, RRF is fundamentally a heuristic method. It assumes that documents ranking highly across multiple lists are more likely to be relevant, but it cannot address systematic biases in both retrievers — when dense retrieval and BM25 both make errors on the same type of query, RRF only amplifies the mistakes.
The author's summary is particularly sharp: "The metric that looks best in aggregate is rarely the one that fixes the failed cases."
This statement exposes a common misconception in RAG evaluation: improvements in average metrics may actually mask damage to critical long-tail cases.
Evaluation First: Preserve the Failed Cases
Facing this back-and-forth dilemma, the author shifted to a more fundamental direction — building a solid evaluation framework rather than blindly tuning parameters.
They are considering adopting evaluation tools like Braintrust, with three core requirements:
- Preserve failed code query cases to form a regression test set;
- Compare different retrieval strategies against the same batch of cases;
- When a case fails, be able to inspect the specific chunks retrieved to pinpoint the root cause.
RAG system evaluation has been a persistent pain point in the industry. Mainstream evaluation frameworks include RAGAS (Retrieval Augmented Generation Assessment), TruLens, DeepEval, and others, which typically score along two dimensions: retrieval quality (e.g., context precision, context recall) and generation quality (e.g., faithfulness, answer relevance). Braintrust is a more engineering-oriented evaluation and observability platform that supports organizing evaluation cases into datasets, comparing different pipeline configurations, and tracking regressions. However, a common challenge these frameworks face is that their evaluation metrics are designed for general Q&A scenarios and lack built-in support for specialized enterprise needs like "identifier exact matching" and "rule clause completeness" — practitioners must define their own evaluation dimensions and annotation standards.
This approach is worth emulating for all RAG practitioners. The worst thing in RAG optimization is "feeling like it got better" without reproducible, comparable evaluation baselines. Only by solidifying failed cases into fixed test sets can you determine whether a particular fusion configuration remains robust after the corpus frequently changes.
The Real Missing Puzzle Piece: Dual Scoring
The author ultimately distilled the problem down to one unresolved core challenge:
There's no clean way to simultaneously score identifier recall and clause-level support without hand-labeling every document family.
This actually points to two orthogonal dimensions of RAG evaluation:
- Identifier Recall: Did the system find that exact code or abbreviation?
- Clause Support: After finding the code, did it also preserve the exception clause that determines the answer's correctness?
Traditional retrieval evaluation typically only looks at overall relevance and struggles to decompose these two independent dimensions. Meanwhile, manually annotating every document family is prohibitively expensive and difficult to scale. This is a real and widespread technical gap in enterprise RAG deployment today.
Key Takeaways for RAG Practitioners
Drawing from this case, several universally applicable lessons for RAG engineering can be distilled:
First, hybrid retrieval is not a silver bullet. The fusion of dense retrieval and sparse retrieval may seem like the best of both worlds, but the complex interactions between fusion weights, top-k, and chunk strategies require iterative tuning against specific corpora, with optimization objectives that are specific to concrete failure types.
Second, chunking strategies must account for the coupling between identifiers and clauses. For scenarios involving part codes, dedicated metadata extraction or structured indexing may be needed to explicitly link codes with their applicable rules and exception clauses, rather than relying on generic sliding window chunking. Specific approaches include: using regular expressions or NER models during document preprocessing to identify entities like part codes and model numbers, attaching them as structured metadata to corresponding chunks, and supporting hybrid queries at retrieval time (first narrowing scope through metadata filtering, then performing semantic retrieval on the filtered subset). More advanced approaches include building knowledge graphs — explicitly modeling the relationships between codes, rules, and exception clauses as graph structures, and traversing relationship edges during retrieval to ensure completeness. Some vector databases (like Weaviate and Milvus) already natively support joint queries combining scalar filtering with vector search, and Elasticsearch 8.x has implemented native hybrid BM25 and vector retrieval through kNN search. These infrastructure evolutions are providing the foundational support for more refined hybrid retrieval strategies.
Third, evaluation matters more than parameter tuning. First establish evaluation dimensions that can distinguish between identifier recall and clause support, and solidify failed cases into regression test sets — only then can you avoid the trap of "falsely prosperous aggregate metrics."
Fourth, beware of "pretty citations." When citations look relevant but reference the wrong rules, the damage to user trust is devastating. It's better for the system to explicitly state "no clear evidence found" when uncertain than to produce a confident hallucinated answer.
This real-world dilemma from the front lines reminds us: RAG is far from as simple as "hooking up a vector database to an LLM." In enterprise scenarios demanding high precision and strong rule constraints, the engineering details of the retrieval layer are often what determine whether the system can truly be trusted.
Related articles

AI Beginner's Guide: Three Stages to Building Your Own Personal AI Assistant from Scratch
No tech background? No problem. This beginner's guide maps out a 3-stage path to building a personal AI assistant — from prompt engineering to no-code automation to API calls.

Zero to Vibe Coding in Seven Days: A Complete Beginner's Guide to AI Programming
A beginner's guide to Vibe Coding: learn the 6-step path covering Claude Code, Cursor, Codex, prompt engineering, and project practice to build products with AI.

Tailcat: Tailscale's Official Decentralized Minimalist Networking Solution
Tailcat is Tailscale's official decentralized networking project that strips control plane dependencies, offering self-hosting users a more autonomous, privacy-focused WireGuard mesh experience.