অধিকাংশ RAG টিউটোরিয়াল নোটবুকেই শেষ হয়ে যায়। তারা কয়েকটি পরিমার্জিত PDF লোড করে, প্রতি এক হাজার ক্যারেক্টার অন্তর টেক্সট স্প্লিট করে, সেই ফ্র্যাগমেন্টগুলোকে একটি ভেক্টর ডেটাবেসে ঢুকিয়ে দেয় এবং একেই আর্কিটেকচার বলে দাবি করে। শুক্রবার বিকেলে সেই ডেমোটি নিখুঁতভাবে চলে। কিন্তু প্রোডাকশনে, একই পাইপলাইন নিঃশব্দে একটি বোঝা বা ঝুঁকির কারণ হয়ে দাঁড়ায়।
একটি রিট্রিভাল সিস্টেমের আসল বাধা খুব কমই মডেল বা প্রম্পট হয়। আসল বাধা হলো ইনজেশন (ingestion)। একটি RAG পাইপলাইন কেবল সেটুকুই রিট্রিভ করতে পারে যা তাকে খাওয়ানো হয়েছে, আর যদি সেই ফিডটি কোলাহলপূর্ণ (noisy), পুরনো (stale) বা অসম্পূর্ণ হয়, তবে মডেলটি আত্মবিশ্বাসের সাথে ভুল বা অর্থহীন তথ্য প্রদান করবে। যখন ব্যবহারকারীরা অভিযোগ করেন যে বটটি হ্যালুসিনেশন (hallucination) করেছে, তখন সেই দোষটি প্রায়শই ডেটা পাইপলাইনের অনেক আগে বা আপস্ট্রিম-এ থাকে, যা কেউ নিবিড়ভাবে পর্যবেক্ষণ করে না।
হোয়াইটবোর্ড ট্র্যাপ
আর্কিটেকচার ডায়াগ্রামগুলো ইনজেশনকে "Documents → Vector DB" লেবেলযুক্ত একটি একক তীর চিহ্ন হিসেবে দেখায়। বাস্তবতা অনেক বেশি জটিল। সোর্স সিস্টেমগুলো কোনো নোটিশ ছাড়াই পরিবর্তিত হয়। HTML লেআউট নতুন করে ডিজাইন করা হয়। URL গুলো সাধারণ ল্যান্ডিং পেজে রিডাইরেক্ট হয়। প্রাথমিক HTTP রেসপন্সের পরে JavaScript ফ্রেমওয়ার্কগুলো কন্টেন্ট পরিবর্তন করে ফেলে। ইনজেশনকে একটি ওয়ান-টাইম সেটআপ টাস্ক হিসেবে বিবেচনা করা প্রথম ভুল। এটি একটি চলমান ডেটা ইঞ্জিনিয়ারিং সমস্যা যা যেকোনো ETL পাইপলাইনের মতোই কঠোরতা দাবি করে।
কেন RAG ব্যর্থতা মূলত ফিড ব্যর্থতা
কল্পনা করুন: একজন ব্যবহারকারী আপনার ইন্টারনাল অ্যাসিস্ট্যান্টকে বর্তমান রিফান্ড পলিসি সম্পর্কে জিজ্ঞাসা করলেন। মডেলটি ভেক্টর স্টোর থেকে টপ চাঙ্কটি (top chunk) তুলে নিল এবং ৩০ দিনের উইন্ডোর কথা বলল। কিন্তু গত কোয়ার্টারে প্রকৃত পলিসি পরিবর্তন করে ৬০ দিন করা হয়েছে। LLM ভুল উত্তরটি নিজে থেকে তৈরি করেনি। এটি কেবল ভুল ইনপুটকে বিশ্বাস করেছিল। রিট্রিভাল লেয়ার একটি পুরনো পেজ সরবরাহ করেছিল, এবং যেহেতু এমবেডিংটি (embedding) সেমান্টিক্যালি যথেষ্ট কাছাকাছি ছিল, তাই মডেলটি এটিকে গ্রাউন্ড ট্রুথ হিসেবে গণ্য করেছিল।
এই প্যাটার্নটি ক্রমাগত চলতে থাকে। যখন তাদের কর্পাস (corpus) নেভিগেশন ফুটার, ডুপ্লিকেট প্রেস রিলিজ এবং টেবিলকে অর্ধেক করে ফেলা চাঙ্ক দিয়ে পূর্ণ থাকে, তখন টিমগুলো টেম্পারেচার (temperature) এবং top-k টিউন করার পেছনে ঘণ্টার পর ঘণ্টা ব্যয় করে। জেনারেশন অপ্টিমাইজ করার আগে, আপনার সিস্টেম কী কী জানার অনুমতি পাচ্ছে তা অডিট করুন।
ইনজেশন নষ্ট করে দেয় এমন সাতটি ফাঁদ
১. প্রথম রান একটি মিথ্যা
আপনার প্রাথমিক ক্রল-এ একটি সবুজ টিক চিহ্ন থাকা মানে প্রায় কিছুই না। প্রোডাকশন ডেটা জীবন্ত। ডকুমেন্টেশন পেজগুলো রিফ্যাক্টর করা হয়, ব্লগের পারমালিঙ্ক ভেঙে যায় এবং সাইটম্যাপগুলো নিঃশব্দে কিছু সেকশন বাদ দিয়ে দেয়। আপনি যদি কেবল এটি যাচাই করেন যে পাইপলাইনটি কোনো এরর ছাড়াই সম্পন্ন হয়েছে, তবে আপনি অন্ধভাবে কাজ করছেন। আপনার আউটপুট যাচাই করা প্রয়োজন। প্রত্যাশিত ডকুমেন্টগুলো উপস্থিত আছে কিনা, তাদের স্ট্রাকচার এখনও পার্স (parse) করা যাচ্ছে কিনা এবং কোনো সোর্স যদি ফলাফলগুলো ভিন্নভাবে পেজিনেট (paginate) করার সিদ্ধান্ত নেয় তবে মোট টেক্সটের পরিমাণ কমে গেছে কিনা তা পরীক্ষা করুন।
২. ক্রলিং মানেই ইনজেশন নয়
HTML ফেচ করা সহজ অংশ। একটি র (raw) ক্রল সবকিছু ক্যাপচার করে: কুকি ব্যানার, "Related Articles" সাইডবার, অ্যাড ব্লক এবং ফুটার কপিরাইট নোটিশ। আপনি যদি সেই র HTML-কে নির্বিচারে চাঙ্ক করেন, তবে প্রতিটি টেক্সট ফ্র্যাগমেন্টের সাথে নেভিগেশন মেনুর অংশও চলে আসবে। যখন একজন ব্যবহারকারী API রেট লিমিট সম্পর্কে জিজ্ঞাসা করবেন, তখন রিট্রিভার এমন একটি চাঙ্ক সামনে আনতে পারে যার ৪০ শতাংশই সাইডবার লিঙ্ক। ক্লিন এক্সট্রাকশন অত্যন্ত গুরুত্বপূর্ণ। আপনাকে মূল কন্টেন্ট এরিয়া শনাক্ত করতে হবে, বয়লারপ্লেট (boilerplate) বাদ দিতে হবে এবং এমন উপাদানগুলো সরিয়ে ফেলতে হবে যা প্রতিটি পেজে বারবার আসে। অন্যথায় আপনি কোনো নলেজ বেস তৈরি করছেন না; আপনি ওয়েবসাইটের ক্রোম (chrome)-এর জন্য একটি সার্চ ইঞ্জিন তৈরি করছেন।
৩. চাঙ্কিং অর্থ নষ্ট করে দেয়
প্রায় প্রতিটি কুইকস্টার্ট গাইডে ফিক্সড-সাইজ চাঙ্কিং ডিফল্ট হিসেবে থাকে এবং এটি বিপজ্জনক। আপনি যদি শুধুমাত্র ক্যারেক্টার কাউন্ট দিয়ে একটি ডকুমেন্ট স্প্লিট করেন, তবে আপনি টেবিলগুলোকে মাঝখান থেকে কেটে ফেলবেন, একটি নম্বরযুক্ত পদ্ধতির ধাপ ৪ এবং
একটি ইন্টারনাল উইকির স্ট্যাটিক স্ন্যাপশট নেওয়া সহজ। কিন্তু লাইভ ওয়েব থেকে ক্রমাগত ডেটা ইনজেস্ট করা কঠিন। আপনাকে জানতে হবে একটি পেজ শেষ কবে সংগ্রহ করা হয়েছিল, তারপর থেকে এতে কোনো পরিবর্তন হয়েছে কি না এবং তথ্যটি কতক্ষণ বৈধ থাকবে। 'স্টেল' (stale) বা পুরনো ডেটার মানে সবসময় দৃশ্যমান কোনো পুরনো তারিখ নয়। মাঝে মাঝে একটি পেজ তার টেক্সট আপডেট করে কিন্তু একই URL বজায় রাখে, তাই কন্টেন্ট হ্যাশিং (content hashing) ছাড়া আপনার সিস্টেম তা কখনোই বুঝতে পারবে না। সোর্সের অস্থিরতার (volatility) ওপর ভিত্তি করে স্পষ্ট রিফ্রেশ রুল তৈরি করুন। একটি ফিন্যান্সিয়াল ডেটা ফিড প্রতি ঘণ্টায় চেক করার প্রয়োজন হতে পারে। একটি কোম্পানির 'About' পেজ ত্রৈমাসিক ভিত্তিতে চেক করার প্রয়োজন হতে পারে। টাইমস্ট্যাম্প রেকর্ড করুন এবং time-to-live সীমানা নির্ধারণ করুন, বিশেষ করে যদি আপনার ডোমেইনটি নিয়ন্ত্রিত বা নিরাপত্তা-সংবেদনশীল নির্দেশনার সাথে যুক্ত হয় যেখানে পুরনো তথ্য প্রকৃত ক্ষতি করতে পারে।
৫. ডুপ্লিকেট দূষণ (Duplicate Pollution)
ওয়েবসাইটগুলো পুনরাবৃত্তি দিয়ে পূর্ণ। একই পণ্যের বিবরণ ক্যাটাগরি পেজ, প্রোডাক্ট পেজ এবং একটি প্রমোশনাল ল্যান্ডিং পেজে দেখা যায়। একই প্রেস রিলিজ /news/, /press/, এবং /blog/ এর অধীনে থাকতে পারে। ভেক্টর সার্চ স্বয়ংক্রিয়ভাবে ডুপ্লিকেট বা পুনরাবৃত্তি দূর করতে পারে না। যদি আপনার ডেটাবেসে দশটি প্রায় একই রকম চাঙ্ক (chunk) থাকে, তবে সেগুলো আপনার top-k রিট্রিভ্যালে বৈচিত্র্যময় এবং প্রাসঙ্গিক ফলাফলগুলোকে সরিয়ে দিতে পারে। এমবেডিং করার আগে আপনার ক্যানোনিকাল ট্র্যাকিং (canonical tracking) বা কন্টেন্ট ডিডুপ্লিকেশন প্রয়োজন। যদি দুটি চাঙ্ক একই কথা বলে, তবে অথরিটেটিভ সোর্সটি রাখুন এবং কপিগুলো বাদ দিন। আপনার রিট্রিভারের স্লট সীমিত। সেগুলো অপচয় হতে দেবেন না।
৬. মিসিং মেটাডেটা (Missing Metadata)
মেটাডেটা ছাড়া একটি ভেক্টর ডেটাবেস হলো কেবল একটি ডেন্স টেক্সট সার্চ ইঞ্জিন যার কোনো কনটেক্সট বা প্রেক্ষাপটের স্মৃতি নেই। স্মার্ট রিট্রিভাল ফিল্টারিং এবং র্যাঙ্কিং সিগন্যালের ওপর নির্ভর করে যা র (raw) এমবেডিং প্রদান করতে পারে না। সোর্স URL, ক্যাপচার ডেট, ডকুমেন্টের ক্যাটাগরি এবং ভার্সন নম্বর সংরক্ষণ করুন। আপনি যদি API ডকুমেন্টেশন ইনজেস্ট করেন, তবে ভার্সনিং অপরিহার্য। এটি ছাড়া, একটি কুয়েরি v1 এবং v2 স্পেকগুলোকে একই উত্তরের সাথে মিশিয়ে দিতে পারে। আপনি যদি HR পলিসি ইনজেস্ট করেন, তবে অঞ্চল বা বিভাগ অনুযায়ী ট্যাগিং করলে মডেলের কাছে পৌঁছানোর আগেই ফলাফল ফিল্টার করা সম্ভব হবে। মেটাডেটা একটি টেক্সট ডাম্পকে একটি কিউরেটেড নলেজ সিস্টেমে রূপান্তরিত করে।
৭. জাভাস্ক্রিপ্ট গ্যাপস (JavaScript Gaps)
আধুনিক সাইটগুলো তাদের প্রথম HTML পেলোডেই কন্টেন্ট পাঠায় না। তারা একটি স্কেলিটন পাঠায় এবং জাভাস্ক্রিপ্ট কলের মাধ্যমে সেটিকে হাইড্রেট (hydrate) করে। একটি সাধারণ HTTP রিকোয়েস্ট হয়তো একটি লোডিং স্পিনার এবং লেআউট শেল ছাড়া আর কিছুই দেখতে পাবে না। যদি আপনার পাইপলাইন জাভাস্ক্রিপ্ট এক্সিকিউট করতে না পারে, তবে আপনি খালি পেজ বা আংশিক ফ্র্যাগমেন্ট ইনজেস্ট করবেন এবং কোনো সমস্যা হচ্ছে তা কখনোই বুঝতে পারবেন না। একটি হেডলেস ব্রাউজার ব্যবহার করলে রেন্ডারিং সমস্যার সমাধান হয় কিন্তু নতুন কিছু সমস্যা তৈরি হয়: অধিক মেমরি ব্যবহার, ধীর থ্রুপুট এবং বট ডিটেকশন ওয়াল। আপনার ট্রেড-অফগুলো সতর্কতার সাথে বেছে নিন, তবে প্রতিটি সোর্সের জন্য একটি সাধারণ curl সমতুল্য কমান্ড যথেষ্ট বলে ধরে নেবেন না।
একটি ব্যবহারিক ইনজেশন চেকলিস্ট
আপনি যদি একটি RAG ফিড তৈরি বা রিভিউ করেন, তবে এখান থেকে শুরু করুন:
- সোর্স কভারেজ এবং পেজিনেশন যাচাই করুন। একটি সাইটম্যাপ হয়তো একটি ক্যাটাগরির প্রথম দশটি আর্টিকেলই তালিকাভুক্ত করতে পারে। গভীরভাবে ক্রল করুন এবং নিশ্চিত করুন যে পেজিনেশন করা বা ডাইনামিকভাবে লোড করা কন্টেন্টগুলো আসলে ক্যাপচার করা হয়েছে।
- চাঙ্কিং করার আগে বয়েলারপ্লেট (boilerplate) সরিয়ে ফেলুন। নেভিগেশন, বিজ্ঞাপন, ফুটার এবং বারবার আসা আইনি ডিসক্লেইমারগুলো বাদ দিন। যদি কোনো শব্দ বা বাক্য প্রতিটি পেজে থাকে, তবে সেটি নয়েজ বা অপ্রয়োজনীয়।
- স্ট্রাকচার-অ্যাওয়ার চাঙ্কিং ব্যবহার করুন। হেডিং, বুলেট লিস্ট এবং টেবিলকে গুরুত্ব দিন। ক্যারেক্টার কাউন্টের বদলে সিম্যান্টিক বা অর্থগত সীমানার ভিত্তিতে ভাগ করুন।
- সমৃদ্ধ মেটাডেটা যুক্ত করুন। URL, ক্যাপচার ডেট, কন্টেন্ট ক্যাটাগরি এবং ভার্সন অন্তর্ভুক্ত করুন। আপনার রিট্রিভাল কুয়েরিতে এই ফিল্ডগুলোকে ফিল্টারযোগ্য করে তুলুন।
- ডেটার অস্থিরতার ওপর ভিত্তি করে রিফ্রেশ ফ্রিকোয়েন্সি নির্ধারণ করুন। যেসব সোর্স দ্রুত পরিবর্তিত হয় সেগুলোর ঘন ঘন রি-ক্রল প্রয়োজন। স্ট্যাটিক আর্কাইভের প্রয়োজন নেই।
- শুধুমাত্র জব স্ট্যাটাস নয়, বরং কর্পাস (corpus) মনিটর করুন। একটি পাইপলাইন জিরো কোড (code zero) দিয়ে শেষ হতে পারে কিন্তু সেটি আবর্জনা বা গারবেজ ডেটা তৈরি করতে পারে। ডেটার পরিবর্তন (drift) এবং গুণমান যাচাই করতে নিয়মিত স্টোর করা চাঙ্কগুলোর নমুনা অডিট করুন।
- ভার্সনিং এবং ডিলিট করার জন্য নিয়ম নির্ধারণ করুন। যখন কোনো সোর্স পেজ সরিয়ে ফেলা হয়, তখন তার চাঙ্কগুলোও মুছে ফেলুন। যখন এটি আপডেট হয়, তখন সেগুলো ওভাররাইট করুন বা ভার্সন করুন। অরফানিং ডেটা (orphaned data) একটি নীরব ঘাতক।
এমবেডিং সম্পর্কে কঠিন সত্য
কোনো এমবেডিং মডেলই, তা যতই উন্নত হোক না কেন, একটি হারিয়ে যাওয়া ডকুমেন্ট মেরামত করতে পারে না। আপনার ফিডে যদি গত বছরের কপি থাকে, তবে এটি অনুমান করতে পারবে না যে একটি পেজ গত সপ্তাহে আপডেট করা হয়েছে। একটি খারাপ চাঙ্ক বাউন্ডারির কারণে যদি একটি টেবিল রো তার হেডার থেকে আলাদা হয়ে যায়, তবে এটি সেই রো-এর প্রেক্ষাপট বা কনটেক্সট অনুধাবন করতে পারে না। এমবেডিং অর্থকে সংকুচিত করে, কিন্তু ইনজেশন লেয়ার যদি অর্থ বা কনটেক্সট সংরক্ষণ করতে ব্যর্থ হয়, তবে এমবেডিং তা তৈরি করতে পারে না।
রিট্রিভালের গুণমান ইনজেশন লেয়ার থেকেই শুরু হয়। সেই লেয়ারটিই ঠিক করে যে আপনার RAG সিস্টেমটি একটি দরকারী টুল নাকি কেবল একটি ভেক্টর ডেটাবেসের আড়ালে থাকা একজন আত্মবিশ্বাসী মিথ্যাবাদী।
আসল শিক্ষা (The Real Takeaway)
শুধুমাত্র পাইপলাইন ড্যাশবোর্ডের মাধ্যমে ইনজেশন হেলথ পরিমাপ করা বন্ধ করুন। সফল জব এবং ত্রুটিহীন লগ মানেই যে একটি পরিচ্ছন্ন কর্পাস পাওয়া যাবে, তার কোনো নিশ্চয়তা নেই। ডাটাবেসটি খুলুন এবং ব্যবহারকারীরা প্রকৃতপক্ষে যে চঙ্কগুলো রিট্রিভ করবে, সেগুলো পড়ে দেখুন। যদি টেক্সট কপিরাইট নোটিশ, ভেঙে যাওয়া টেবিল এবং পুরনো পলিসি পেজে ঠাসা থাকে, তবে আপনার সমস্যাটি LLM নয়। আগে ফিডটি ঠিক করুন। বাকি সবকিছু হলো আবর্জনার ওপর টিউনিং করা মাত্র।
