বেশিরভাগ টিমই তাদের প্রথম রিট্রিভাল পাইপলাইন (retrieval pipeline) একইভাবে তৈরি করে। তারা একটি নির্দিষ্ট টোকেন লিমিট বেছে নেয়, সম্ভবত ৫১২, ডকুমেন্টগুলোকে সমান ব্লকে বিভক্ত করে এবং সেই ব্লকগুলোকে একটি ভেক্টর ডেটাবেসে (vector database) ইনপুট হিসেবে দেয়। ছোট ডেটাসেট এবং সহজ প্রশ্নের ক্ষেত্রে এটি জাদুকরী মনে হতে পারে। কিন্তু প্রোডাকশনে এটি পুরোপুরি ব্যর্থ হয়।

আইনি চুক্তিগুলো অর্থহীন খণ্ডে খণ্ডে বিভক্ত হয়ে যায় যখন কোনো ধারা (clause) বাক্যের মাঝপথে কেটে ফেলা হয়। এপিআই (API) ডকুমেন্টেশন একটি বিশৃঙ্খল মিশ্রণে পরিণত হয় যদি একটি মাত্র চাঙ্ক (chunk) তিনটি সম্পর্কহীন ফাংশনকে একসাথে অন্তর্ভুক্ত করে ফেলে। ওভারল্যাপ (overlap) না থাকলে কাস্টমার সাপোর্ট টিকিটগুলোর বর্ণনামূলক ধারাবাহিকতা হারিয়ে যায়। এর ফলাফলটি অনুমান করা সহজ: অত্যধিক ল্যাটেন্সি (latency), দুর্বল রিকল (recall) এবং এমন উত্তর যা জেনারেটরকে হ্যালুসিনেশন (hallucinate) করতে বাধ্য করে।

আমরা আমাদের রিট্রিভাল লেয়ারটি ভেঙে নতুন করে তৈরি করেছি। এর ফলে রিকল ৭৮ শতাংশ থেকে বেড়ে ৯৫ শতাংশে পৌঁছেছে, ল্যাটেন্সি ৬২ শতাংশ কমেছে এবং পাইপলাইনটি অবশেষে একটি সাধারণ 'উইকেন্ড হ্যাক'-এর পরিবর্তে প্রকৃত ইনফ্রাস্ট্রাকচারের মতো কাজ করছে। নিচে দেওয়া হলো আসলে কী কাজ করেছে।

স্মার্ট চাঙ্কিং: টোকেনের চেয়ে স্ট্রাকচার বেশি গুরুত্বপূর্ণ

প্রথম ভুলটি হলো ধরে নেওয়া যে প্রতিটি ডকুমেন্ট একই ভাষায় কথা বলে। একটি ৫১২-টোকেন চাঙ্ক বর্ণনামূলক গদ্যের (narrative prose) জন্য উপযুক্ত হতে পারে, কিন্তু অন্য ক্ষেত্রে নয়। আমরা এমন একটি কৌশলে চলে এসেছি যা সোর্সের গঠন বা অ্যানাটমিকে (anatomy) সম্মান করে।

আইনি দলিলের জন্য আমরা রিকার্সিভ চাঙ্কিং (recursive chunking) ব্যবহার করি। অ্যালগরিদমটি প্রথমে সেকশন এবং আর্টিকেলগুলোর মতো উচ্চ-স্তরের সীমানা অনুযায়ী বিভক্ত করার চেষ্টা করে। যদি কোনো সেকশন তখনও অনেক বড় হয়, তবে এটি সাব-সেকশন, তারপর প্যারাগ্রাফ এবং শেষে বাক্য খোঁজে। এটি ধারার (clause) যৌক্তিক বিন্যাস বজায় রাখে। একটি নন-কম্পিট এগ্রিমেন্ট (non-compete agreement) অক্ষত থাকে। সংজ্ঞাসমূহ (definitions) ক্ষতিপূরণ সংক্রান্ত শর্তাবলীর (indemnity terms) সাথে মিশে যায় না।

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

সাপোর্ট টিকিটগুলোর জন্য সিম্যান্টিক চাঙ্কিং (semantic chunking) স্বাভাবিকভাবেই বেশি উপযোগী। টোকেন বা সীমানার ভিত্তিতে না কেটে, আমরা শনাক্ত করি কোথায় বিষয়বস্তু পরিবর্তিত হচ্ছে। একটি টিকিট যা লগইন সংক্রান্ত অভিযোগ দিয়ে শুরু হয়ে বিলিং সংক্রান্ত প্রশ্নে মোড় নেয়, তা দুটি সুসংগত অংশে বিভক্ত হয়। প্রতিটি অংশ তার প্রয়োজনীয় মেটাডেটা বহন করে এবং মডেলকে আর অনুমান করতে হয় না যে ব্যবহারকারী আসলে কোন সমস্যাটি নিয়ে চিন্তিত।

ইন্টারনাল উইকিগুলো (Internal wikis) আরও বেশি অগোছালো। এতে গদ্য, টেবিল, ডায়াগ্রাম এবং এমবেডেড থ্রেড মিশ্রিত থাকে। এগুলোর জন্য আমরা এজেন্টিক চাঙ্কিং (agentic chunking) ব্যবহার করি। একটি ছোট ল্যাঙ্গুয়েজ মডেল আগে থেকে পড়ে দেখে এবং সিদ্ধান্ত নেয় একটি থিম্যাটিক্যালি সম্পূর্ণ ইউনিট কোথায় শেষ হচ্ছে। ইনজেশন (ingestion) সময়ে এতে কিছুটা বেশি খরচ হয়, তবে এটি প্রতিটি নতুন পেজ ফরম্যাটের জন্য নিয়ম হাতে কলমে ঠিক করার ঝামেলা দূর করে দেয়।

হাইব্রিড রিট্রিভাল: সব দিক বিবেচনা করুন

ভেক্টর সার্চ (Vector search) অস্পষ্ট অর্থ (fuzzy meaning) ধরার ক্ষেত্রে চমৎকার। স্লো আপলোড সম্পর্কে জিজ্ঞাসা করলে এটি ল্যাটেন্সি এবং ব্যান্ডউইথ সংক্রান্ত অনুচ্ছেদগুলো সহজেই খুঁজে দেবে। কিন্তু এটি সঠিক বা হুবহু মিল (exact matches) খুঁজে পেতে ব্যর্থ হওয়ার জন্য পরিচিত। যদি একজন ডেভেলপার ERR_CONNECTION_REFUSED এরর কোডটি দিয়ে সার্চ করেন, তবে ডেন্স এমবেডিং (dense embeddings) প্রায়ই এটিকে সাধারণ নয়েজ হিসেবে গণ্য করবে।

BM25, যা একটি ক্লাসিক কিওয়ার্ড অ্যালগরিদম, ঠিক তার উল্টো কাজ করে। এটি সুনির্দিষ্ট স্ট্রিং এবং বিরল শব্দগুলো নিখুঁতভাবে খুঁজে পায়, কিন্তু সিম্যান্টিক সূক্ষ্মতা (semantic nuance) মিস করে। চুক্তি স্বাক্ষর (signing the agreement) সংক্রান্ত একটি কুয়েরি হয়তো 'executing the contract' ট্যাগ করা কন্টেন্ট খুঁজে পাবে না।