বেশিরভাগ RAG টিউটোরিয়াল ডেমোতেই শেষ হয়ে যায়। আপনি টোকেন কাউন্ট অনুযায়ী চাঙ্ক (chunk) করেন, সবকিছু একটি ভেক্টর ডেটাবেসে ঢুকিয়ে দেন এবং কাজ শেষ বলে ধরে নেন। এটি তখনই কাজ করে যখন কোনো ব্যবহারকারী একটি পরিষ্কার FAQ-তে "রিটার্ন পলিসি কী?" জিজ্ঞেস করেন। কিন্তু যখন কেউ অর্ধেক চুক্তি পেস্ট করে তৃতীয় ধারা সম্পর্কে জানতে চায়, অথবা যখন একজন ডেভেলপার আপনার ডকুমেন্টেশন সার্চে কোনো অস্পষ্ট এরর কোড (error code) টাইপ করে, তখন এটি ব্যর্থ হয়।

নির্দিষ্ট টোকেন উইন্ডো আইনি চুক্তিগুলোকে বাক্যের মাঝপথে কেটে ফেলে। বড় চাঙ্কগুলো API রেফারেন্সগুলোকে অনেক প্যারাগ্রাফের শব্দের ভিড়ে হারিয়ে ফেলে। সবচেয়ে খারাপ বিষয় হলো, ধীরগতির রিট্রিভাল (retrieval) ব্যবহারকারীকে মডেলটি জেনারেট করা শুরু করার আগেই কুয়েরিটি ছেড়ে দিতে বাধ্য করে। আমরা এটি কঠিন অভিজ্ঞতার মাধ্যমে শিখেছি। যখন আমরা আমাদের রিট্রিভাল লেয়ারটিকে কেবল আশার ওপর ভিত্তি না করে পরিমাপযোগ্য করে তুললাম, তখন আমরা ল্যাটেন্সি (latency) ৪০ শতাংশ কমিয়েছিলাম এবং রিকল (recall) ৯৫ শতাংশে উন্নীত করেছিলাম। ঠিক কী কী পরিবর্তন করা হয়েছে তা নিচে দেওয়া হলো।

স্মার্ট চাঙ্কিং (Smart Chunking)

চাঙ্ক সাইজকে কোনো জাদুকরী সংখ্যা হিসেবে ভাবা বন্ধ করুন। একটি ৫১২-টোকেন উইন্ডো এমন আইনি নথির জন্য অর্থহীন যেখানে একটি মাত্র ধারা একাধিক প্যারাগ্রাফ জুড়ে বিস্তৃত, এবং এটি API ডকসের জন্যও সমানভাবে অকেজো যেখানে একটি ফাংশন সিগনেচার এবং তার দুই লাইনের বর্ণনা একসাথে থাকা উচিত। আমরা স্ট্রাকচার-অ্যাওয়ার স্প্লিটিং (structure-aware splitting)-এ চলে এসেছি।

আইনি টেক্সটের জন্য, রিকার্সিভ চাঙ্কিং (recursive chunking) ডকুমেন্টের হায়ারার্কি বা শ্রেণিবিন্যাসকে সম্মান করে। ফলে ধারাগুলো অক্ষত থাকে। API ডকুমেন্টেশনের জন্য, আমরা ফাংশন-অ্যাওয়ার স্প্লিটিং (function-aware splitting) ব্যবহার করি যা সিগনেচার, প্যারামিটার এবং উদাহরণগুলোকে একটি একক ইউনিট হিসেবে একসাথে রাখে। সাপোর্ট টিকিট এবং কথোপকথনমূলক ডেটার জন্য সিম্যান্টিক বা অর্থগত সীমানা প্রয়োজন, যেখানে কোনো নির্দিষ্ট ক্যারেক্টার কাউন্টের পরিবর্তে টপিক বা বিষয় পরিবর্তনের ভিত্তিতে ভাগ করা হয়। এর ফলে প্রতিটি চাঙ্ক যথেষ্ট প্রাসঙ্গিক তথ্য বহন করে, কিন্তু এত বেশিও নয় যা মূল তথ্যকে অস্পষ্ট করে ফেলে। আপনার এমবেডিং মডেলের (embedding model) মনোযোগ দেওয়ার ক্ষমতা বা অ্যাটেনশন বাজেট সীমিত। এটি বুদ্ধিমত্তার সাথে ব্যবহার করুন।

হাইব্রিড রিট্রিভাল (Hybrid Retrieval)

ভেক্টর সার্চ ধারণাগতভাবে সদৃশ কন্টেন্ট খুঁজে পেতে পারদর্শী। স্লো ডেটাবেস কুয়েরি সম্পর্কে জিজ্ঞাসা করলে এটি পারফরম্যান্স টিউনিং গাইডগুলো সামনে নিয়ে আসে। কিন্তু "Error 0x80070057" এর কথা বললে সিম্যান্টিক সার্চ অপ্রাসঙ্গিক দিকে চলে যায়, কারণ ডেন্স এমবেডিং (dense embeddings) নিখুঁত মিল (exact match) ভালোভাবে হ্যান্ডেল করতে পারে না। অন্যদিকে, BM25 নিখুঁত স্ট্রিং এবং বিরল শব্দগুলো খুঁজে পেতে দক্ষ, কিন্তু এটি জানে না যে "latency" এবং "slow response time" একই জিনিস।

আমরা উভয় পদ্ধতি সমান্তরালভাবে চালাই এবং Reciprocal Rank Fusion (RRF) দিয়ে সেগুলোকে মার্জ করি। RRF সহজ এবং কার্যকর। এটি প্রতিটি পদ্ধতি থেকে র‍্যাঙ্ক করা তালিকা গ্রহণ করে এবং তাদের অবস্থানের ভিত্তিতে ডকুমেন্টগুলোকে স্কোর দেয়, যা উভয় সিস্টেমের শক্তিশালী প্রার্থীদের সমান সুযোগ দেয়। ফিউশনের পরে, আমরা সম্মিলিত ফলাফলগুলোর ওপর একটি ক্রস-এনকোডার রির্যাঙ্কার (cross-encoder reranker) চালাই এবং শুধুমাত্র সেরা পাঁচটি ফলাফল প্রদান করি। রির্যাঙ্কারটি প্রায় ৫০ মিলিসেকেন্ড ল্যাটেন্সি বাড়ায় কিন্তু আমাদের রিকল ১৫ শতাংশ উন্নত করেছে। জেনারেশন কোয়ালিটির ক্ষেত্রে এই ট্রেড-অফটি অনেক বেশি লাভজনক।

কুয়েরি এক্সপ্যানশন (Query Expansion)

ব্যবহারকারীরা কুয়েরি করার ক্ষেত্রে খুব একটা দক্ষ নন। তারা শব্দ সংক্ষেপ করে, বানান ভুল করে অথবা একটি দীর্ঘ অগোছালো বাক্যে তিনটি প্রশ্ন ঢুকিয়ে দেয়। আপনি যদি ঠিক তারা যা টাইপ করেছে তাই সার্চ করেন, তবে আপনি সেই ডকুমেন্টগুলো মিস করবেন যা তাদের আসলে প্রয়োজন।

আমরা এখন ইনডেক্সে পৌঁছানোর আগে প্রতিটি কুয়েরিকে রূপান্তরিত করি। প্রথমত, সমার্থক শব্দ এবং বিকল্প প্রকাশভঙ্গি কভার করার জন্য আমরা মূল প্রশ্নের একাধিক রিফ্রেজড (rephrased) সংস্করণ তৈরি করি। দ্বিতীয়ত, আমরা জটিল প্রশ্নগুলোকে ছোট ছোট উপ-প্রশ্নে (sub-questions) বিভক্ত করি। যেমন, "Why is the refund failing for international customers and how do I fix it?"—এই কুয়েরিটি দুটি আলাদা সার্চে পরিণত হয়: একটি আন্তর্জাতিক রিফান্ড ব্যর্থতা সম্পর্কে এবং অন্যটি সমাধানের পদক্ষেপ সম্পর্কে। শুধুমাত্র কুয়েরি এক্সপ্যানশনের মাধ্যমেই আমাদের রিকল ৭৮ শতাংশ থেকে ৯৪ শতাংশে পৌঁছেছে। শিক্ষাটি সহজ: ব্যবহারকারীর প্রথম খসড়ার ওপর নির্ভর করবেন না। তাদের সাহায্য করুন।

অনুমান করা বন্ধ করুন, সার্চ করা শুরু করুন

চাঙ্ক সাইজ, ওভারল্যাপ পার্সেন্টেজ, top-k কাটঅফ এবং রির্যাঙ্কার ডেপথ এমনভাবে একে অপরের সাথে কাজ করে যা হাতে টিউন করা অসম্ভব। আমরা ২৫৬ টোকেন কি ৫১২ টোকেনের চেয়ে ভালো হবে তা নিয়ে তর্কে অনেক সময় নষ্ট করেছি, অথচ ওভারল্যাপ সেটিংসটি উপেক্ষা করেছি যা আসলে তথ্যের ধারাবাহিকতা (coherence) নষ্ট করছিল।

আমরা আমাদের অনুমানের পরিবর্তে Bayesian optimization ব্যবহার করেছি। গ্রিড সার্চের পরিবর্তে—যা স্পষ্টতই খারাপ অঞ্চলে কম্পিউটেশন নষ্ট করে—Bayesian পদ্ধতিগুলো কী কাজ করে তার একটি প্রোবাবিলিস্টিক মডেল তৈরি করে এবং ল্যাটেন্সি কমানোর পাশাপাশি রিকল সর্বোচ্চ করার জন্য একটি Pareto frontier সক্রিয়ভাবে খুঁজে বের করে। আমাদের স্ট্যাকের জন্য, এর অর্থ ছিল চাঙ্ক সাইজ, ওভারল্যাপ এবং top-k-এর সেই নির্দিষ্ট কম্বিনেশন খুঁজে বের করা যা আমাদের ল্যাটেন্সি বাজেট নষ্ট না করেই ৯৫ শতাংশ রিকল প্রদান করে। বিভিন্ন ব্যবহারের ক্ষেত্রে সেই ফ্রন্টিয়ারের ভিন্ন ভিন্ন পয়েন্টে ফলাফল পাওয়া গেছে। কাস্টমার-ফেসিং চ্যাটবটগুলো গতিকে প্রাধান্য দিয়েছে, আর অভ্যন্তরীণ আইনি গবেষণায় রিকলকে প্রাধান্য দেওয়া হয়েছে। স্বয়ংক্রিয় অপ্টিমাইজেশন আমাদের কনফিগ ফাইল ম্যানুয়ালি কপি-পেস্ট না করেই উভয় ক্ষেত্রেই সেবা দিতে সাহায্য করেছে।

ফলাফল

সংখ্যাগুলো সব পরিষ্কার করে দিচ্ছে। আমাদের Recall@10 78% থেকে বেড়ে 95% হয়েছে। p95 latency 850 মিলিসেকেন্ড থেকে কমে 320 মিলিসেকেন্ডে নেমে এসেছে। এবং মডেলটি অবশেষে নয়েজের (noise) পরিবর্তে প্রাসঙ্গিক কনটেক্সট (context) পাওয়ায়, hallucination rate 12% থেকে কমে 3% এ নেমে এসেছে। উন্নত রিট্রিভাল (retrieval) শুধু উত্তর দ্রুততর করে না, বরং সেগুলোকে সঠিক করে তোলে।

এরপর কী করবেন

আপনি যদি আপনার রিট্রিভাল লেয়ার (retrieval layer) নতুন করে তৈরি করেন, তবে এখান থেকে শুরু করুন:

  • টোকেন সংখ্যা নয়, বরং ডকুমেন্টের গঠন অনুযায়ী চাঙ্ক (chunk) করুন। আপনার স্প্লিটিং স্ট্র্যাটেজিকে (splitting strategy) ডেটার আকৃতির সাথে সামঞ্জস্যপূর্ণ করুন।
  • হাইব্রিড রিট্রিভাল (hybrid retrieval) ব্যবহার করুন। ভেক্টর সার্চ (vector search) এবং BM25-কে একত্রিত করুন, Reciprocal Rank Fusion-এর মাধ্যমে মার্জ করুন এবং জেনারেট করার আগে র র‍্যাঙ্ক (rerank) করুন।
  • আরও ভালো কভারেজের জন্য কুয়েরি (query) সম্প্রসারিত করুন। সার্চ শুরু করার আগেই সেটিকে পুনরায় সাজান (rephrase) এবং বিশ্লেষণ (decompose) করুন।
  • টেস্টিংয়ের জন্য একটি গোল্ডেন ডেটাসেট (golden dataset) তৈরি করুন। আপনি যা পরিমাপ করতে পারেন না, তা অপ্টিমাইজ করতে পারবেন না।
  • অটোমেটেড টুলস দিয়ে প্যারামিটার অপ্টিমাইজ করুন। আপনার অনুমানের চেয়ে Bayesian search আরও উন্নত সেটিংস খুঁজে দেবে।

রিট্রিভাল কোনো কনফিগারেশন ফাইল নয় যা একবার সেট করে ভুলে যাওয়া যায়। এটি একটি ইনফ্রাস্ট্রাকচার (infrastructure), আর ইনফ্রাস্ট্রাকচারের ক্ষেত্রে প্রোডাকশন কোডের মতোই কঠোরতা প্রয়োজন: টেস্ট, পরিমাপ এবং ক্রমাগত অপ্টিমাইজেশন। এটিকে সেভাবেই বিবেচনা করুন, তাহলেই আপনার RAG সিস্টেমটি কেবল একটি ডেমো হিসেবে না থেকে একটি পূর্ণাঙ্গ প্রোডাক্টে পরিণত হবে।

ঐচ্ছিক লার্নিং কমিউনিটি: GyaanSetu AI