Hard Negative Mining: Teaching an LLM What "Almost Right" Looks Like Shrijith Venkatramana, an engineer building the AI code review tool LiveReview, explains hard negative mining — training retrieval and embedding models on examples that are almost right rather than obviously wrong. He traces the technique from FaceNet's online triplet mining in 2015 through Dense Passage Retrieval and Microsoft's ANCE work, arguing that production retrieval systems fail from semantic confusion rather than semantic ignorance. Hello, I'm Shrijith Venkatramana, and I'm building LiveReview — a blast-radius aware AI code review built for your business-critical systems. Star us https://github.com/HexmosTech/LiveReview/ to help devs discover the project, give it a try, and share your feedback to help improve the product. A model learns surprisingly little from examples that are obviously wrong. Suppose you are training a retrieval model with: Query: "How do I rotate an AWS IAM access key?" And your negative example is: "How do I resize a Kubernetes pod?" The model can separate these easily. One is about IAM credentials; the other is about Kubernetes. Now give it: "How do I create an AWS IAM access key?" That is a much more interesting negative. It uses the same vocabulary. It concerns the same object. It may even appear in the right neighborhood of the embedding space. But it answers a different question. This is the basic idea behind hard negative mining : instead of teaching a model merely what is wrong, deliberately show it things that are almost right and force it to learn the distinction. The technique became important in computer vision with work such as FaceNet, and later became a major component of dense text retrieval. The interesting part for LLM developers is that the same idea now appears in RAG, semantic search, reranking, embedding training, preference data, and other systems where the model must distinguish between closely related alternatives. CV Foundation https://www.cv-foundation.org/openaccess/content cvpr 2015/html/Schroff FaceNet A Unified 2015 CVPR paper.html Imagine you have a query q , a relevant document d+ , and an irrelevant document d- . A contrastive training objective wants: similarity q, d+ similarity q, d- An easy negative might already be far away: similarity q, d+ = 0.82 similarity q, d- = 0.12 There is little ambiguity. The model already knows that the two things are different. A hard negative could look like: similarity q, d+ = 0.82 similarity q, d- = 0.76 Now the model has a real problem. Why does this matter? Because retrieval systems rarely fail by retrieving something completely unrelated. They fail by retrieving: In production, the enemy is usually semantic confusion , not semantic ignorance. Hard negative mining turns that confusion into training data. The underlying idea is older than language models. In 2015, Florian Schroff, Dmitry Kalenichenko and James Philbin published FaceNet. They trained a neural network to map faces into an embedding space where images of the same person were close together and different people were far apart. The important engineering problem was choosing which examples to train on. Suppose you have: anchor = Alice's face positive = another image of Alice negative = Bob's face A completely different-looking Bob is not particularly useful. The interesting negative is a Bob who looks sufficiently similar to Alice to make the distinction difficult. FaceNet therefore used online triplet mining, progressively selecting difficult examples during training. The paper describes this as a way of increasing the difficulty of the triplets as the network improves. CV Foundation https://www.cv-foundation.org/openaccess/content cvpr 2015/html/Schroff FaceNet A Unified 2015 CVPR paper.html A few years later, the same logic became important in text retrieval. Karpukhin and colleagues' 2020 Dense Passage Retrieval work showed that a relatively simple dual-encoder could produce effective dense retrieval for open-domain question answering. But there was a problem: what you use as a negative during training determines what distinctions the retriever learns. ACL Anthology https://aclanthology.org/2020.emnlp-main.550/ Then came ANCE from Microsoft researchers including Lee Xiong and Chenyan Xiong. Their observation was particularly important: The negatives used during training often did not resemble the documents the model would actually confuse during inference. Their solution was to use an approximate-nearest-neighbor index to retrieve difficult negatives using the model itself, and periodically refresh that index as the model changed. In other words, the model was used to discover the mistakes that the next version of the model needed to learn from. arXiv https://arxiv.org/abs/2007.00808 That creates an interesting feedback loop: train model | v model retrieves difficult documents | v use those as negatives | v train model again | v model discovers new difficult documents Hard negative mining is therefore partly a data-generation strategy and partly an optimization strategy . You do not usually "hard-negative mine an LLM" in the same sense that you mine negatives for a classifier. The technique is most useful when an LLM system has to rank, retrieve, compare, or distinguish things. Consider a typical RAG pipeline: user query | v embedding model | v vector database | v top 20 passages | v reranker | v top 5 passages | v LLM There are several places where hard negatives matter. You train: php query - relevant passage and contrast it against: php query - similar but irrelevant passage This teaches the embedding space to preserve the distinctions your application actually cares about. Suppose the retriever returns: 1. PostgreSQL deadlock troubleshooting 2. PostgreSQL transaction rollback 3. PostgreSQL isolation levels 4. PostgreSQL connection pooling A reranker needs to understand why 1 answers the query while 3 is merely related. That makes 2 and 3 substantially more useful negatives than an article about Kubernetes. The same pattern appears in: php query - document user - product question - answer bug report - solution code change - relevant documentation Whenever the challenge is distinguishing nearby alternatives, hard negatives are valuable. This is also why systems such as RocketQA explicitly incorporated denoised hard negatives alongside cross-batch negatives and data augmentation when training dense passage retrievers. ACL Anthology https://aclanthology.org/2021.naacl-main.466/ The simplest method is almost embarrassingly straightforward. Take your current model and ask: "What documents does this model think are relevant?" Suppose your training example is: q = "How do I configure PostgreSQL connection pooling?" d+ = "PgBouncer configuration guide" Run the query through your retriever. It produces: 1. PgBouncer configuration guide 0.91 2. PostgreSQL connection pooling 0.89 3. PostgreSQL connection management 0.87 4. PostgreSQL authentication 0.71 5. PostgreSQL installation 0.62 After removing the known positive, candidates 2 and 3 are excellent places to look for hard negatives. A basic mining procedure is: for each q, d+ : candidates = retrieve q, corpus, top k=100 candidates = remove candidates, d+ hard negatives = top candidates But there is a major trap. A document can be highly similar because it is actually relevant. That gives you a false negative . For example: Query: "How do I rotate an AWS access key?" Positive: "Rotating IAM access keys" Candidate: "IAM access key security best practices" You might classify the candidate as irrelevant simply because it does not contain the exact answer. But it may still be legitimately useful. Training the model to push it away could damage the retrieval space. This is one of the reasons RocketQA introduced denoising for hard negatives rather than simply taking the nearest documents blindly. Later work on dense retrieval has continued to treat false-negative removal as an important part of hard-negative construction. ACL Anthology https://aclanthology.org/2021.naacl-main.466/ A practical production pipeline therefore looks more like: BM25 / embedding retrieval | v 100 candidates | v remove known positives | v cross-encoder / LLM judge | v remove probable false negatives | v hard negatives This is considerably more useful than simply selecting the nearest vectors. Consider a simple contrastive objective. For query q , positive d+ , and negatives d1 ... dn : L = -log exp sim q,d+ / T -------------------------------- exp sim q,d+ / T + sum i exp sim q,di / T where: sim q,d = similarity between query and document T = temperature You do not need to memorize the equation. Think of it as a competition. The model gets rewarded when the positive takes most of the probability mass. Suppose: positive = 0.90 negative A = 0.20 negative B = 0.10 negative C = 0.05 The positive is already winning comfortably. Now consider: positive = 0.90 negative A = 0.87 negative B = 0.25 negative C = 0.10 Negative A is creating a much larger training signal. The model must figure out: "What feature distinguishes these two things?" That is exactly the behavior we want. There is a useful geometric interpretation. Imagine the embedding space as a map: unrelated positive \ hard negative Easy negatives teach the model about broad regions. Hard negatives teach it about the decision boundary . That distinction becomes especially important as the model gets better. Early in training: php easy negatives - useful Later: php easy negatives - mostly redundant hard negatives - increasingly valuable This is the same basic intuition behind ANCE's dynamic mining: use the evolving model to find examples near its current retrieval boundary. arXiv https://arxiv.org/abs/2007.00808 Hard negative mining costs compute. 1,000,000 training queries and you want: 20 hard negatives / query You now have roughly: 20,000,000 candidate relationships The expensive part is often not training itself. It is finding and validating those negatives . There are several ways to control the cost. Use BM25 or an existing embedding model to retrieve: top 100 Then only send a small candidate set to a more expensive judge. You do not need an LLM to examine one million documents per query. You also rarely need to regenerate the negatives after every optimization step. php train - mine - train - mine - train rather than: php train - mine - train - mine - train - mine ANCE is an interesting example of this engineering compromise: it uses an asynchronously refreshed approximate-nearest-neighbor index instead of rebuilding everything synchronously after every parameter update. arXiv https://arxiv.org/abs/2007.00808 Suppose an expensive cross-encoder can score a candidate at: 0.97 relevant 0.84 relevant 0.31 relevant 0.02 relevant The useful region may be around: 0.4 - 0.8 The 0.02 example teaches almost nothing. The 0.97 example may actually be another positive. The middle examples are where the information density is. So the goal is not: "Find the hardest possible negative." It is: Find negatives that are difficult enough to produce useful learning without becoming mislabeled positives. That is a much better engineering objective. Suppose you are building a retrieval system for a company's internal engineering documentation. You have: 10,000 queries 50,000 documents Start with ordinary positive examples: query, relevant document Then: Step 1: Retrieve candidates For every query: top 50 using BM25 top 50 using embeddings Union them. Step 2: Remove obvious positives Remove the labeled document and documents known to answer the same question. Step 3: Score candidates Use a cross-encoder or sufficiently capable LLM judge. Ask something like: Given the query and document, does this document directly answer the query? Return: RELEVANT IRRELEVANT Step 4: Keep the confusing ones Construct something like: positive: "How to rotate PostgreSQL credentials" hard negative: "How to rotate PostgreSQL TLS certificates" hard negative: "How to reset PostgreSQL passwords" easy negative: "How to install PostgreSQL" Step 5: Train Use the positive and selected negatives in your contrastive objective. Step 6: Re-mine After the model improves, ask it again what it gets confused by. The old hard negatives may become easy. New hard negatives will emerge. That gives you a virtuous cycle: php better model - better mistakes - better training data - better model And that is the deeper lesson of hard negative mining. You are not merely collecting more examples. You are collecting the examples that expose the current limits of the model . For LLM systems, that can be more valuable than adding another 10 million random training examples. The interesting question is therefore: When building your next RAG or retrieval system, would you rather collect more data—or deliberately collect the mistakes your current model is already making? Your team's attention is limited, and the deluge of AI-generated code is making it harder to keep production reliable and secure without slowing you down. I'm building LiveReview , a blast-radius aware AI code review built for your business-critical systems. Instead of presenting every diff with equal emphasis, LiveReview scores each change by blast radius — how far its impact reaches through your call graph — so you can focus attention where it actually matters. Spend code review effort where business risk is highest — not spread evenly across every diff. ⭐ Star it on GitHub: LiveReview is an AI code reviewer that scores every hunk of a diff by blast radius : how far a change reaches through your call graph, how much persistent state it touches, and how well-tested it is. A 3-line change to a shared auth check can outrank a 300-line UI tweak. Your team's attention goes to the highest-risk code first, not spread evenly across every diff. LiveReview's Blast Radius & Review Priority scoring, live in the diff viewer. | The exact math, not a black box | Visualize blast radius at a glance | Every factor that feeds the score | |---|---|---| Here's the goal: Click below to try LiveReview with your codebase: