RAG-এর মান বাড়ানো: chunking strategy, metadata filtering, reranking, hallucination কমানো

production-aware RAG (Series 08, Episode 05)

🔴 ADVANCED Series 08 — Generative AI Engineering Episode 05 / 09

📑 এই পর্বে যা যা আছে

🧩 ১. গল্প: RAG চলছে, কিন্তু উত্তর গুলো "কাছাকাছি ঠিক"

Rahim-এর RAG assistant চালু হলো। প্রথম দিকে সবাই খুশি। কিন্তু কিছুদিন পর অভিযোগ আসতে লাগল — "উত্তরটা মোটামুটি ঠিক, কিন্তু আসল পয়েন্টটা মিস করেছে", "একটা পুরনো policy-র কথা বলেছে, নতুনটা নয়"। model তো একই, prompt-ও ঠিক — তবে সমস্যা কোথায়?

Maya: "তোমার generation ঠিক আছে, তোমার retrieval দুর্বল। LLM যা context পায়, তার চেয়ে ভালো উত্তর দিতে পারে না — garbage in, garbage out। একটা কাজ করা RAG থেকে একটা ভালো RAG-এর পার্থক্য প্রায় পুরোটাই retrieval quality-তে। চল, সেটা ঠিক করি।"

২. সমস্যা: retrieval-ই RAG-এর দুর্বলতম কড়ি

RAG-এর একটা কঠিন সত্য: যে chunk retrieve হয়নি, LLM তার কথা জানেই না। তাই যদি সঠিক chunk top-K-তে না আসে, উত্তর ভুল/অসম্পূর্ণ হবেই — LLM যত ভালোই হোক। উন্নতির জায়গা তিনটা:

১. Chunk কীভাবে বানানো → সঠিক তথ্য একসাথে থাকছে কি? ২. কী filter করা হচ্ছে → পুরনো/অপ্রাসঙ্গিক বাদ যাচ্ছে কি? ৩. কীভাবে rank করা হচ্ছে → সেরা chunk কি সত্যিই উপরে?

✂️ ৩. Chunking strategy — এক মাপ সবার জন্য নয়

Strategyকীভাবেকখন ভালো
Fixed-size + overlapনির্দিষ্ট token, অল্প overlapসাধারণ text; সহজ baseline
Sentence/paragraph-basedবাক্য/অনুচ্ছেদ সীমায় ভাগঅর্থ ভাঙা এড়াতে; structured লেখা
Semantic chunkingঅর্থ বদলের জায়গায় ভাগদীর্ঘ, বিষয়-পরিবর্তনশীল document
Structure-awareheading/section ধরে ভাগPDF/manual/policy (heading আছে এমন)
নিয়ম নেই যে "৫০০ token-ই সঠিক"। খুব ছোট chunk = context হারায়; খুব বড় = noise ঢোকে ও similarity গড় হয়। কাজ অনুযায়ী পরীক্ষা করে ঠিক করতে হয়। heading থাকলে structure-aware chunking সাধারণত সেরা।

🎛️ ৪. Metadata filtering দিয়ে search সংকুচিত করা

প্রতিটা chunk-এর সাথে metadata রাখুন — source, তারিখ, বিভাগ, version। search-এ আগে filter করে তারপর similarity — এতে পুরনো/অপ্রাসঙ্গিক chunk শুরুতেই বাদ পড়ে।

-- শুধু সর্বশেষ version ও 2024-এর chunk-এর মধ্যে semantic search SELECT content FROM jd_chunks WHERE is_active = TRUE AND posted_at >= '2024-01-01' ORDER BY embedding <=> %s::vector LIMIT 8;
"পুরনো policy বলেছে, নতুনটা নয়" — Rahim-এর এই অভিযোগের সমাধান প্রায়ই একটা WHERE is_active filter। ভালো metadata অর্ধেক retrieval সমস্যা এমনিতেই মিটিয়ে দেয়।

🏅 ৫. Reranking: retrieve অনেক, রাখো সেরা কয়েকটা

embedding-based retrieval দ্রুত কিন্তু "মোটা দাগে" — কাছাকাছি অনেক chunk আনে, কিন্তু ঠিক সেরাটা হয়তো ৩ নম্বরে। সমাধান: দুই ধাপ

Query ↓ (ধাপ ১: দ্রুত, wide) Vector search → top-২০ candidate (recall বাড়াই) ↓ (ধাপ ২: ধীর, নিখুঁত) Reranker (cross-encoder) → প্রতিটা (query, chunk) জোড়া স্কোর ↓ সেরা top-৪ → LLM

Reranker একটা cross-encoder — query আর chunk একসাথে দেখে সরাসরি relevance স্কোর দেয় (embedding-এর মতো আলাদা vector নয়)। তাই এটা বেশি নিখুঁত, কিন্তু ধীর — তাই শুধু কয়েকটা candidate-এ চালানো হয়।

🪜 ৬. তিন স্তরে বোঝা (reranking)

Level 1 — সহজ intuition

চাকরির shortlisting ভাবুন। প্রথমে HR দ্রুত ৫০০ CV থেকে ২০টা বাছে (দ্রুত, মোটা দাগে = retrieval)। তারপর panel প্রতিটা মন দিয়ে দেখে সেরা ৪ জন বাছে (ধীর, নিখুঁত = reranking)।

Level 2 — technical ভাবে কী হচ্ছে

Bi-encoder (embedding) query ও document আলাদা encode করে — দ্রুত, scalable, কিন্তু interaction কম। Cross-encoder (reranker) দুটোকে একসাথে model-এ দেয় — token-level interaction ধরে, তাই relevance স্কোর অনেক নির্ভুল।

Level 3 — engineer perspective

Engineer latency budget দেখে ঠিক করে — কত candidate rerank করবে (২০? ৫০?), কোন reranker (local vs API)। wide retrieval দিয়ে recall, তারপর rerank দিয়ে precision — এই combo production RAG-এ মান নাটকীয়ভাবে বাড়ায়।

💻 ৭. Code: reranker যোগ করা

কেন cross-encoder reranker? — vector search recall দেয়, কিন্তু precision কম। একটা ছোট cross-encoder (locally চলে, free) দিয়ে top candidate গুলো পুনরায় sort করলে LLM-এর হাতে সেরা context যায়।

from sentence_transformers import CrossEncoder # cross-encoder: (query, passage) → relevance score reranker = CrossEncoder( "cross-encoder/ms-marco-MiniLM-L-6-v2" ) def retrieve_and_rerank(question, first_k=20, final_k=4): # ধাপ ১: vector search থেকে wide candidate (recall) candidates = vector_search(question, k=first_k) # list[str] # ধাপ ২: প্রতিটা (query, chunk) জোড়ার score pairs = [(question, c) for c in candidates] scores = reranker.predict(pairs) # score অনুযায়ী sort করে সেরা final_k রাখি (precision) ranked = sorted( zip(candidates, scores), key=lambda x: x[1], reverse=True, ) return [c for c, _ in ranked[:final_k]] context_chunks = retrieve_and_rerank("Python remote job আছে?")
এখানে first_k=20 দিয়ে recall বাড়ালাম (সঠিক chunk ২০-এর মধ্যে আসার সম্ভাবনা বেশি), তারপর reranker দিয়ে final_k=4 সেরা রাখলাম (precision) — এই ৪টাই LLM-কে দেব।

🔀 ৮. Hybrid search — keyword + semantic

Semantic search অর্থ ধরে, কিন্তু নির্দিষ্ট নাম/কোড/আইডি (যেমন "FastAPI", "SKU-2291") keyword search ভালো ধরে। দুটো মিলিয়ে hybrid search প্রায়ই সেরা — বিশেষত technical বা কোড-ভরা text-এ।

সহজ hybrid: keyword (BM25/full-text) স্কোর + vector similarity স্কোর মিলিয়ে (weighted) একটা combined ranking। junior হিসেবে জানা যথেষ্ট যে এটা আছেকেন ভালো; পরে দরকারে গভীরে যাবেন।

👻 ৯. Hallucination কমানোর ব্যবহারিক কৌশল

মনে রাখুন — এগুলো hallucination কমায়, শূন্য করে না। তাই sensitive domain-এ (health, legal, finance) সবসময় source দেখান আর "AI-generated, যাচাই করুন" disclaimer রাখুন।

🇧🇩 ১০. বাস্তব উদাহরণ: বাংলাদেশের context

💼 ১১. Boss Question

Boss: "RAG তো আগেই বানিয়েছ। এখন reranking-এ আবার সময়-খরচ কেন?"

উত্তর: একটা কাজ-করা RAG আর একটা বিশ্বাসযোগ্য RAG-এর পার্থক্য এখানেই। ভুল উত্তর দিলে user আস্থা হারায়, আর একবার আস্থা গেলে assistant কেউ ব্যবহার করে না — পুরো বিনিয়োগ নষ্ট। reranking + metadata filter অল্প খরচে উত্তরের নির্ভুলতা বড় মাত্রায় বাড়ায়। মানে — বেশি adoption, কম ভুল, বেশি ROI।

🔎 ১২. Job Requirement Decoder

JD: "Improve retrieval quality / experience with reranking, hybrid search"

১. কী বোঝায়? RAG-এর retrieval অংশকে chunking, filtering, reranking, hybrid দিয়ে নির্ভুল করা।
২. কেন চায়? baseline RAG সহজ, কিন্তু production-এ মান বাড়ানোই আসল দক্ষতা।
৩. কোন সমস্যা সমাধান করে? "মোটামুটি ঠিক" উত্তর, পুরনো/অপ্রাসঙ্গিক context, মিস হওয়া তথ্য।
৪. junior-এর কী জানা লাগে? bi-encoder vs cross-encoder, wide-retrieve-then-rerank, metadata filter, hybrid-এর ধারণা।
৫. এখনই কী master লাগে না? custom reranker train, learned sparse retrieval, বড় স্কেলের latency tuning।
৬. GitHub-এ কীভাবে দেখাবে? RAG repo-তে "with vs without reranking" তুলনা, metadata filter ও একটা eval নোট।
৭. interview প্রশ্ন? "RAG accuracy কীভাবে বাড়াবে?", "bi-encoder vs cross-encoder?", "hybrid search কী?"

⚠️ ১৩. সাধারণ ভুল

ভুল ১: retrieval খারাপ রেখে বড় LLM দিয়ে সমাধানের চেষ্টা। → আগে retrieval ঠিক করুন।

ভুল ২: সব candidate rerank করা (ধীর)। → wide retrieve, তারপর কয়েকটা rerank।

ভুল ৩: metadata না রাখা। → পুরনো/ভুল version filter করা অসম্ভব হয়ে যায়।

ভুল ৪: এক chunk-size সব কাজে চাপানো। → data অনুযায়ী strategy পরীক্ষা করুন।

ভুল ৫: reranker-কে embedding model ভাবা। → cross-encoder আলাদা; জোড়া নিয়ে score দেয়।

🎤 ১৪. Interview Prep

প্র: RAG-এর accuracy কীভাবে বাড়াবে?
উ: ভালো chunking, metadata filtering, wide-retrieve + rerank, hybrid search, grounding নিয়ম।

প্র: Bi-encoder আর cross-encoder-এর পার্থক্য?
উ: Bi-encoder আলাদা embed করে (দ্রুত, scalable); cross-encoder জোড়া একসাথে দেখে (নিখুঁত, ধীর) — তাই rerank-এ ব্যবহৃত।

প্র: কেন retrieve বেশি, LLM-কে দাও কম?
উ: wide retrieve recall বাড়ায়; rerank দিয়ে precision নিয়ে সেরা কয়েকটা LLM-কে দিই।

প্র: Hybrid search কেন?
উ: keyword নির্দিষ্ট term/আইডি ধরে, semantic অর্থ ধরে — মিলিয়ে দুটোর শক্তি।

✍️ ১৫. হাতে-কলমে

আগের RAG-এ ১০টা প্রশ্নের উত্তর নোট করুন (baseline)। এবার retrieve_and_rerank() যোগ করে একই ১০ প্রশ্ন চালান। প্রতিটা উত্তর "আগের চেয়ে ভালো / একই / খারাপ" — এই ৩ ভাগে চিহ্নিত করুন। কত শতাংশে উন্নতি হলো, লিখে রাখুন — এটাই আপনার প্রথম RAG evaluation-এর হাতেখড়ি।

🚀 ১৬. Project Connection

flagship assistant এখন শুধু "কাজ করা" নয়, "ভালো" হচ্ছে — metadata filter (শুধু active JD), reranking (সেরা match উপরে), grounding নিয়ম (জানি না বললে বলবে)। এই উন্নতিগুলো P8 (RAG system)-কে একটা portfolio-worthy project বানায়। পরের episode-এ প্রশ্ন — এই "ভালো" আমরা সংখ্যায় মাপব কীভাবে?

📌 ১৭. সারসংক্ষেপ ও পরবর্তী পর্ব

✓ RAG-এর মান প্রায় পুরোটাই retrieval quality-তে
✓ chunking strategy data-নির্ভর; heading থাকলে structure-aware সেরা
✓ metadata filtering পুরনো/অপ্রাসঙ্গিক chunk বাদ দেয়
✓ wide retrieve → cross-encoder rerank → সেরা কয়েকটা LLM-কে
✓ hybrid search = keyword + semantic শক্তি
✓ grounding, citation, threshold দিয়ে hallucination কমানো (দূর নয়)
পরবর্তী Episode: "RAG Evaluation" — "ভালো হয়েছে" বলা সহজ, কিন্তু faithfulness ও relevance সংখ্যায় মাপব কীভাবে? এটাই interview-তে আপনাকে আলাদা করে দেবে।
© 2025 Sheikh Thanbir Alam. All Rights Reserved. thanbirtamim.github.io
এই লেখা মূল লেখকের সম্পত্তি — লিখিত অনুমতি ছাড়া কপি করে অন্য কোনো ওয়েবসাইট, ব্লগ, বই বা প্ল্যাটফর্মে প্রকাশ/বিতরণ করা কঠোরভাবে নিষিদ্ধ। Content may not be copied or republished without permission.