पाठ 13 / 28

Metadata Filtering

Similarity को tenant, तिथि और अनुमतियों जैसी कठोर बाधाओं के साथ मिलाएँ।

Similarity क्रम देती है; filters पात्रता तय करते हैं

अकेली similarity कौन-सा दस्तावेज़ कौन देख सकता है, वह किस देश या उत्पाद को कवर करता है और कितना नया है जैसे तथ्य अनदेखे करती है। ऐसे fields हर vector के पास metadata में रखें और कठोर filters के रूप में लगाएँ: "सिर्फ़ user के tenant के, भारत के, 2025 से प्रभावी दस्तावेज़"। दो डिज़ाइन हैं: pre-filtering (पहले उम्मीदवार सीमित करें, फिर खोजें) और post-filtering (खोजें, फिर बेमेल परिणाम हटाएँ)। Post-filtering सरल है पर यदि अधिकांश निकटतम पड़ोसी छन जाएँ तो k से कम परिणाम लौट सकते हैं, इसलिए ज़्यादा लाएँ (k से अधिक retrieve करें) या filter-जागरूक खोज वाला engine उपयोग करें। अनुमति filters सुरक्षा नियंत्रण हैं: उन्हें query में ही लागू करें, सिर्फ़ prompt या UI में कभी नहीं।

Filter, मिलाएँ, rerank, समूह बनाएँ

असली खोज metadata filters, keyword scores और reranking मिलाती है, और embeddings clustering व de-duplication भी चलाते हैं।

चार पैटर्न: filter, hybrid, rerank, समूह।
चित्र 4.1 — Filter, hybrid, rerank और समूह।

Filter फिर rank, चलाकर

मैंने यह Python virtual environment में numpy 2.5.3, scikit-learn 1.9.1 और faiss-cpu 1.15.1 के साथ चलाया, निश्चित random seeds के साथ ताकि संख्याएँ दोहराई जाएँ। Filter के बिना पुरानी 2022 की भारत नीति और UK नीति कच्चे similarity score पर जीतती हैं। पहले भारत और 2025 पर filter करने से chunks 1 और 4 बचते हैं, score से क्रमित।

chunks = [
    {"id": 1, "text": "Leave policy for India", "country": "IN", "year": 2025, "score": 0.91},
    {"id": 2, "text": "Leave policy for UK",    "country": "UK", "year": 2025, "score": 0.93},
    {"id": 3, "text": "Old leave policy India", "country": "IN", "year": 2022, "score": 0.95},
    {"id": 4, "text": "Travel policy India",    "country": "IN", "year": 2025, "score": 0.70},
]
def top_k(items, k, **where):
    ok = [c for c in items if all(c[f] == v for f, v in where.items())]     # hard filter, then rank by similarity
    return [c["id"] for c in sorted(ok, key=lambda c: -c["score"])[:k]]

print("no filter     :", top_k(chunks, 2))
print("IN + 2025 only:", top_k(chunks, 2, country="IN", year=2025))

Output:

no filter     : [3, 2]
IN + 2025 only: [1, 4]

Post-filtering से पहले ज़्यादा लाएँ

k का 5 से 10 गुना माँगें, filter करें, फिर k तक काटें, या pre-filtering उपयोग करें ताकि कम परिणाम कभी न लौटें।

त्वरित जाँच: "यह user सिर्फ़ अपने दस्तावेज़ देखे" कहाँ लागू होना चाहिए?

  • सिर्फ़ prompt में
  • Retrieval query में filter के रूप में
  • सिर्फ़ UI में
  • कहीं नहीं
Answer

Retrieval query में filter के रूप में — जो दस्तावेज़ user नहीं देख सकता वे कभी retrieve नहीं होने चाहिए।