# Filter RAG passages with Jev: 4 Nouls between retrieval and generation

> TypeSafe RAG cookbook: score each retrieved passage for relevance, evidence, contradiction and injection, route in code — the planted injection scores 0.99 and never reaches the prompt.

*Source: https://velstech.net/jev-rag-passage-gate.hi (Hindi translation of https://velstech.net/jev-rag-passage-gate) · Updated: 2026-09-20*

*Markdown version. [Read the interactive guide](https://velstech.net/jev-rag-passage-gate.hi). English Markdown: https://velstech.net/jev-rag-passage-gate.md.*

---

Retrieval passages को wording similarity से rank करता है – और top few आपके answering model को
सौंप देता है, contradictions, prompt injections समेत। एक demo query पर planted forum injection
similarity में *पहले* rank करता है (0.584) जबकि query के false premise को refute करने वाला
passage सातवें स्थान पर है (0.509), 0.584–0.455 के इतने सँकरे spread में कि दोनों अलग ही नहीं होते।
TypeSafe का
[classifying-RAG-passages cookbook](https://docs.typesafe.ai/cookbooks/classifying_rag_passages)
retrieval और generation के बीच दूसरा stage जोड़ता है: **हर passage पर चार
Noul सवाल, एक-एक request, फिर code में साधारण threshold logic तय करता है कि prompt
तक क्या पहुँचेगा** – evidence के रूप में, flagged conflict के रूप में, या बिल्कुल नहीं। यह
guide recipe का सारांश है।

## चार सवाल

State में query + एक passage (id, title, text, source type) होता है, ताकि हर सवाल passage के बारे
में नहीं, pair के बारे में हो। हर query के लिए वही चार सवाल; सिर्फ state बदलता है:

- is_relevant – क्या passage query के subject पर है? (relevance floor)

- contains_answer_evidence – क्या इसमें direct answer में usable कुछ है? (include, या drop)

- contradicts_query_premise – क्या यह query के माने हुए premise से टकराता है? (conflict block में promote)

- contains_prompt_injection – क्या यह answering system को control करने की कोशिश करता है? (सीधे exclude)

गौर करें क्या *नहीं* पूछा गया: passage include करें या नहीं। वह फैसला code में है, जहाँ policy
बदलना सवाल reword करने के बजाय review के तहत number edit करना है।

## Code में route करें, first match wins

```
THRESHOLDS = {
    "injection_max": 0.70,   # above this the passage never reaches the prompt
    "contradicts_min": 0.70, # above this it disputes the query's premise
    "relevant_min": 0.45,    # below this it is not about the query at all
    "evidence_min": 0.55,    # above this it states something usable
}

def route(answers: dict, thresholds: dict = THRESHOLDS) -> str:
    if answers["contains_prompt_injection"] > thresholds["injection_max"]:
        return "exclude"
    if answers["contradicts_query_premise"] > thresholds["contradicts_min"]:
        return "conflicting_evidence"
    if answers["is_relevant"]  thresholds["evidence_min"]:
        return "include"
    return "exclude"
```

Order मायने रखता है: injection सबसे पहले क्योंकि वह security decision है, evidence decision नहीं;
contradiction evidence से पहले क्योंकि query के premise को deny करने वाला passage आमतौर पर कुछ usable
भी कहता है, और उल्टे क्रम में test करने पर वह conflict block के बजाय accepted block में जा गिरेगा।
और re-routing मुफ़्त है – thresholds stored answers पढ़ते हैं, इसलिए policy tune करने में zero API calls।

## यह क्या पकड़ता है

Headline query पर ("Refresh tokens expire after 30 days – window कैसे बढ़ाऊँ?", false premise),
routing table:

| Route | rel | evid | contra | inj | Passage |
| --- | --- | --- | --- | --- | --- |
| exclude | 0.71 | 0.36 | 0.90 | 0.99 | forum-injection |
| conflicting_evidence | 0.49 | 0.51 | 0.92 | 0.15 | sessions-01 |
| exclude (×10) | ≤0.48 | ≤0.42 | ≤0.39 | ≤0.26 | बाकी |

Injection relevance floor clear करता है (0.71) – सिर्फ relevance उसे through जाने देती – और सिर्फ
0.99 injection score उसे गिराता है। Refute करने वाला passage 0.49 relevance / 0.51 evidence score
करता है, जो अकेले उसे भी गिरा देते; 0.92 contradiction score उसे conflict block में बचा लाता है।
Evidence के रूप में prompt तक कुछ नहीं पहुँचता – false premise वाले सवाल के लिए सही – और generator
जवाब देता है "I don't have sufficient accepted evidence", conflict का नाम लेता है, और 30-day setting
invent करने के बजाय refuting passage quote करता है।

एक ordinary answered query ("access token कितने long live करे?") पर चार passages evidence तक
पहुँचते हैं – तीन ranks 8, 9, 11 से, जबकि similarity-top ranks 2–4 (गलत किस्म का "lifetime", signing
keys) सब ≤0.08 relevance पर गिरते हैं। Injection फिर 0.99 पर excluded। छह queries, 72 passages में
हर query के dozen का कम से कम दो-तिहाई excluded।

## दो ईमानदार caveats

- Injection सवाल filter है, boundary नहीं: threshold से नीचे passage फिर भी prompt पहुँचता है,
इसलिए generator prompt को हर passage को score परवाह किए बिना untrusted text मानना होगा।

- Cost k के साथ scale करती है – हर passage पर एक request। Passages कभी एक request में
batch नहीं होते, क्योंकि हर सवाल एक pair के बारे में है।

Accepted और conflicting evidence **अलग prompt blocks** में जाते हैं, rules के साथ
(untrusted text, passage IDs cite करें, conflicts report करें, guess के बजाय "insufficient" कहें)।
दोनों को एक block में merge कर दें और generator जवाब और denial में फर्क ही नहीं कर पाएगा।

## Bottom line

Similarity retrieves; judgment filters; code routes; generator सिर्फ labelled evidence देखता है।
चार Nouls और पाँच comparisons – हर passage पर एक request की कीमत पर injection defence + false-premise
detection। Full source:
[TypeSafe का classifying-RAG-passages cookbook](https://docs.typesafe.ai/cookbooks/classifying_rag_passages);
"पहले filter करें, सिर्फ ज़रूरी भेजें" सिद्धांत
[Jev 1.13 jaggedness guide](https://velstech.net/jev-1-13-jaggedness.hi) का failure mode 5 है।

---

*VelsTech – https://velstech.net/jev-rag-passage-gate.hi.md*
