زیادہ تر RAG پروٹو ٹائپس اندرونی طور پر ایک جیسے نظر آتے ہیں۔ کوئی ایک پائپ لائن میں PDF ڈالتا ہے، متن کو 512-ٹیکن (token) کے صاف ستھرے ٹکڑوں (chunks) میں تقسیم کرتا ہے، انہیں ایک ویکٹر ڈیٹا بیس میں ڈال دیتا ہے، اور کام مکمل سمجھ لیتا ہے۔ ایک عام ڈیمو کے لیے، یہ متاثر کن ہو سکتا ہے۔ لیکن پروڈکشن میں، یہ ناکام ہو جاتا ہے۔

ایک فکسڈ چنک (fixed chunk) اس بات کی پرواہ نہیں کرتا کہ وہ کہاں سے کٹ رہا ہے۔ یہ ایک قانونی معاہدے کو تلافی کی شرط (indemnity clause) کے بیچ میں سے تقسیم کر دے گا۔ یہ پانچ غیر متعلقہ API endpoints کو ایک ہی کانٹیکسٹ ونڈو (context window) میں بھر دے گا اور ماڈل کو شور (noise) میں غرق کر دے گا۔ یہ آپ کو ضرورت سے زیادہ ٹکڑے تلاش کرنے پر مجبور کرے گا، جس سے لیٹنسی (latency) بڑھے گی اور ٹوکنز ضائع ہوں گے۔ اس کا نتیجہ ادھورے جوابات، ہالوسینیشنز (hallucinations)، اور مایوس صارفین کی صورت میں نکلتا ہے۔

ہم نے اپنے ریٹریول لیئر (retrieval layer) کو مکمل طور پر تبدیل کر کے دوبارہ تعمیر کیا۔ اس کا نتیجہ ایک ایسا سسٹم تھا جس نے لیٹنسی میں 40 فیصد کمی کے ساتھ 95 فیصد ریکال (recall) حاصل کیا۔ یہاں تفصیل ہے کہ ہم نے یہ کیسے کیا۔

پروڈکشن میں فکسڈ چنکس (Fixed Chunks) کیوں ناکام ہو جاتے ہیں

512-ٹیکن کا ڈیفالٹ کوئی ڈیزائن کا انتخاب نہیں ہے۔ یہ ابتدائی ایمبیڈنگ ماڈل کے کانٹیکسٹ ونڈوز اور لائبریری کے ڈیفالٹ سیٹنگز کا ایک ضمنی نتیجہ ہے۔ اسے نافذ کرنا آسان ہے لیکن اس پر بھروسہ کرنا تباہ کن ہے۔

دستاویزات یکساں نہیں ہوتیں۔ ایک قانونی شق (legal clause) بغیر کسی واضح وقفے کے سات سو ٹیکن تک طویل ہو سکتی ہے۔ اگر آپ اسے پانچ سو بارہ پر تقسیم کرتے ہیں، تو آپ دو بکھرے ہوئے ٹکڑے بنا دیتے ہیں۔ جب کوئی وکیل یا تعمیل افسر (compliance officer) ذمہ داری کی حد (liability caps) کے بارے میں پوچھتا ہے، تو سسٹم آدھی ذمہ داری واپس کرتا ہے۔ لینگویج ماڈل گمشدہ حصے کے بارے میں ہالوسینیشن کرتا ہے، یا اس سے بھی بدتر، یہ انکار کر دیتا ہے کہ ایسی کوئی حد موجود ہے۔

API ڈاکومنٹیشن اس کے برعکس مسئلے کا شکار ہوتی ہے۔ پانچ سو ٹیکن کا ایک چنک پورے ماڈول کو نگل سکتا ہے: آتھنٹیکیشن ہیڈرز (authentication headers)، ایرر کوڈز، ریٹ لمٹس، اور ویب ہک اسکیمائیں۔ جب ایک ڈویلپر پوچھتا ہے کہ AUTH_4027 کو کیسے ہینڈل کیا جائے، تو ریٹریور غیر متعلقہ فنکشنز کا ایک مجموعہ سامنے لے آتا ہے۔ ماڈل کے پاس انہیں ایک عام سی چیز میں بدلنے کے سوا کوئی چارہ نہیں ہوتا۔

برا چنکنگ (chunking) لیٹنسی کو بھی بڑھاتا ہے۔ کمزور ٹکڑوں کا مطلب ہے کہ کسی موضوع کو مکمل طور پر کور کرنے کے لیے آپ کو بڑے top-k کی ضرورت ہوگی۔ زیادہ چنکس کا مطلب ہے طویل پرامپٹس (prompts)۔ طویل پرامپٹس کا مطلب ہے سست جنریشن اور زیادہ بلز۔ صارف کا تجربہ مسلسل چھوٹی چھوٹی خرابیوں کی وجہ سے تباہ ہو جاتا ہے۔

چنک (Chunk) کو دستاویز کے مطابق بنائیں

ہم نے ٹیکنز گننا بند کر دیا اور مواد کو پڑھنا شروع کیا۔ صحیح چنکنگ حکمت عملی کا انحصار اصل ذریعے (source) کی ساخت پر ہوتا ہے۔

قانونی دستاویزات (Legal documents) کے لیے شقوں کے لحاظ سے حدود (clause-aware boundaries) کے ساتھ ریکرسو کیریکٹر چنکنگ (recursive character chunking) کی ضرورت ہوتی ہے۔ اس اسپلٹر (splitter) میں درجہ بندی کا احترام کیا جاتا ہے: یہ پہلے سیکشن ہیڈرز، پھر نمبر والے پیراگراف، اور پھر قدرتی جملوں کے وقفوں کو دیکھتا ہے۔ یہ کبھی بھی کسی ذیلی شق (sub-clause) کو نہیں کاٹتا اور نہ ہی کسی ذمہ داری والے جملے کو چنکس کے درمیان تقسیم کرتا ہے۔ جب آپ تلافی (indemnification) کے بارے میں کوئی اقتباس تلاش کرتے ہیں، تو آپ کو مکمل شق، اس کی حد، اور استثنیٰ ملتے ہیں۔

API ڈاکومنٹیشن کے لیے اسٹرکچر کے لحاظ سے چنکنگ (structure-aware chunking) ضروری ہے۔ ہم ٹیکن بجٹ کے بجائے فنکشن کی تعریف کے مطابق ڈیٹا کو پارس کرتے ہیں۔ ہر چنک میں ایک مکمل فنکشن سگنیچر، اس کی پیرامیٹر تفصیلات، اور اس کے ساتھ منسلک ایرر ہینڈلنگ نوٹس شامل ہوتے ہیں۔ اگر کوئی ڈویلپر کسی مخصوص میتھڈ کو تلاش کرتا ہے، تو اسے پورا معاہدہ ملتا ہے، نہ کہ کسی بے ترتیب تقسیم میں پھنسا ہوا ٹکڑا۔

سپورٹ ٹکٹس (Support tickets) شور سے بھرپور اور غیر خطی (nonlinear) ہوتے ہیں۔ ایک تھریڈ ایک بگ رپورٹ سے شروع ہو سکتا ہے، ایک ورک ارائونڈ (workaround) متعارف کروا سکتا ہے، اور ایک اندرونی ایسکلیشن نوٹ پر ختم ہو سکتا ہے۔ سیمنٹک چنکنگ (Semantic chunking) جملوں کے درمیان ایمبیڈنگ کی مماثلت کو ناپ کر موضوع کی تبدیلیوں کا پتہ لگاتی ہے۔ ہم صرف قدرتی موضوعی حدود پر ہی وقفہ کرنے کی اجازت دیتے ہیں، تاکہ لاگ ان کی ناکامی کے بارے میں گفتگو بلنگ سائیکلز کے بارے میں فالو اپ سے الگ رہے۔

ویکی (Wikis) سب سے مشکل تھے۔ یہ پھیلی ہوئی، ایک دوسرے سے جڑی ہوئی اور غیر منظم ہوتی ہیں۔ ہم نے ایجنٹک چنکنگ (agentic chunking) کا استعمال کیا، جہاں ایک ہلکا پھلکا LLM صفحہ پڑھتا ہے اور موضوعی ہم آہنگی (thematic coherence) کی بنیاد پر وقفے کا فیصلہ کرتا ہے۔ یہ ڈیٹا داخل کرنے کے وقت تھوڑا زیادہ خرچ کرتا ہے، لیکن نتیجے کے طور پر ملنے والے چنکس خود مختار اور ریٹریول کے لیے تیار ہوتے ہیں۔ ڈیپلائمنٹ کے بہترین طریقوں کے بارے میں ایک صفحہ بے ترتیب ٹیکسٹ بلاکس کے بجائے منطقی اکائیوں میں تقسیم ہوتا ہے: پری فلائٹ چیک، رول بیک طریقہ کار، اور مانیٹرنگ سیٹ اپ۔

ہائبرڈ ریٹریول (Hybrid Retrieval): کی ورڈز اور ویکٹرز ایک ساتھ

ڈینس ویکٹر سرچ (Dense vector search) معنی کو سمجھتا ہے۔ لیکن یہ درست اسٹرنگز (exact strings) کے معاملے میں بہت برا ہے۔ اگر کوئی صارف کسی درست ایرر کوڈ جیسے AUTH_4027 یا کسی کسٹمر کے نام جیسے "Stark Industries" کو تلاش کرتا ہے، تو ویکٹر ایمبیڈنگز ہدف سے چوک سکتی ہیں کیونکہ وہ تصوراتی قربت (conceptual proximity) کے لیے بہتر ہوتی ہیں، نہ کہ حروف کی درستگی کے لیے۔

BM25 کے ذریعے خالص کی ورڈ سرچ میں اس کا الٹ نقص ہے۔ یہ AUTH_4027 کو بالکل درست طریقے سے تلاش کر لے گا، لیکن یہ "authorization failure" اور "login denied" کے درمیان تصوراتی تعلق کو نہیں سمجھ پائے گا۔

ہم دونوں کو متوازی طور پر چلاتے ہیں۔ BM25 اور vector search ایک ہی corpus پر آزادانہ طور پر کام کرتے ہیں۔ ان کی رزلٹ لسٹوں کو Reciprocal Rank Fusion کے ذریعے ضم کیا جاتا ہے، جو ان کے پوزیشنل رینک (positional ranks) کو متوازن کر کے امیدواروں کی دوبارہ ترتیب کرتا ہے۔ آپ کو کیلیبریٹڈ ویٹس (calibrated weights) کی ضرورت نہیں ہوتی۔ آپ کو ایک ہی رینکڈ لسٹ میں exact match کی درستگی اور semantic search کی بصیرت مل جاتی ہے۔

پھر ہم ایک cross-encoder reranker شامل کرتے ہیں۔ یہ ایک الگ ماڈل ہے جو اصل کوئری کے مقابلے میں ہر پیراگراف (passage) کو اسکور کرتا ہے، جس سے ایک ایسا relevance signal حاصل ہوتا ہے جو کسی بھی ایک retriever کے مقابلے میں کہیں زیادہ باریک بینی والا ہوتا ہے۔ یہ تقریباً 50 ملی سیکنڈ کی لیٹنسی (latency) کا اضافہ کرتا ہے۔ یہ recall کو 15 فیصد بڑھا دیتا ہے۔ اگر آپ جواب کے معیار کی فکر کرتے ہیں، تو یہ سمجھوتہ ناگزیر ہے۔

Query Expansion: تلاش شروع ہونے سے پہلے اسے درست کریں

خراب کوئریز ہر retrieval system کا ایک چھپا ہوا راز ہیں۔ صارفین آپ کے embedding space کی طرح نہیں لکھتے۔ وہ "it broke" ٹائپ کرتے ہیں۔ وہ ادھورے stack traces پیسٹ کرتے ہیں۔ وہ ایسی اندرونی اصطلاحات (jargon) استعمال کرتے ہیں جو آپ کے انڈیکس نے کبھی نہیں دیکھی ہوتیں۔

ہم کوئری کو انڈیکس تک پہنچنے سے پہلے ہی تبدیل کر دیتے ہیں۔ سب سے پہلے، ہم ایک واحد کوئری کو تین سے پانچ متنوع سرچ ٹرمز (search terms) میں پھیلاتے ہیں۔ اگر اصل کوئری "payment failed" ہے، تو ہم "transaction error"، "billing declined" اور "charge unsuccessful" کے لیے بھی تلاش کرتے ہیں۔