बहुतेक RAG ट्युटोरियल्स नोटबुकवरच संपतात. ते काही पॉलिश केलेले PDFs लोड करतात, प्रत्येक हजार कॅरेक्टर्सवर मजकूर विभागतात, ते तुकडे (fragments) वेक्टर डेटाबेसमध्ये टाकतात आणि त्याला आर्किटेक्चर म्हणतात. शुक्रवारी दुपारी, ती डेमो अगदी व्यवस्थित चालते. पण प्रोडक्शनमध्ये, तीच पाइपलाइन शांतपणे एक ओझे (liability) बनते.

रिट्रिव्हल सिस्टममधील खरा अडथळा (bottleneck) क्वचितच मॉडेल किंवा प्रॉम्प्ट असतो. तो असतो 'इन्जेशन' (ingestion). RAG पाइपलाइन फक्त तेच रिट्रिव्ह करू शकते जे तिला पुरवले गेले आहे, आणि जर पुरवलेला डेटा गोंधळलेला (noisy), जुना (stale) किंवा अपूर्ण असेल, तर मॉडेल आत्मविश्वासाने चुकीची माहिती देईल. जेव्हा युजर्स तक्रार करतात की बॉटने 'हॅलुसिनेशन' (hallucination) केले, तेव्हा दोष अनेकदा डेटा पाइपलाइनमध्ये असतो, ज्यावर कोणीही बारकाईने लक्ष ठेवत नाही.

व्हाईटबोर्डचा सापळा (The Whiteboard Trap)

आर्किटेक्चर डायग्राम्समुळे इन्जेशन हे "Documents $\rightarrow$ Vector DB" असे लेबल असलेल्या एका साध्या बाणासारखे वाटते. वास्तव अधिक गुंतागुंतीचे आहे. सोर्स सिस्टम्स कोणतीही सूचना न देता बदलतात. HTML लेआउट्सची पुनर्रचना होते. URLs सामान्य लँडिंग पेजेसवर रिडायरेक्ट होतात. JavaScript फ्रेमवर्क्स सुरुवातीच्या HTTP रिस्पॉन्स नंतर मजकूर बदलून टाकतात. इन्जेशनला केवळ एकदाच करायचे काम समजणे ही पहिली चूक आहे. ही एक निरंतर चालणारी डेटा इंजिनिअरिंगची समस्या आहे ज्याला कोणत्याही ETL पाइपलाइनप्रमाणेच गांभीर्याने हाताळण्याची गरज आहे.

RAG मधील अपयश सहसा फीडमधील अपयश का असते?

अशी कल्पना करा: एक युजर तुमच्या अंतर्गत असिस्टंटला सध्याच्या रिफंड पॉलिसीबद्दल विचारतो. मॉडेल वेक्टर स्टोअरमधून वरचा तुकडा (chunk) काढते आणि ३० दिवसांचा कालावधी सांगते. प्रत्यक्षात, गेल्या तिमाहीत पॉलिसी बदलून ६० दिवस झाली आहे. LLM ने चुकीचे उत्तर शोधून काढले नाही. त्याने चुकीच्या इनपुटवर विश्वास ठेवला. रिट्रिव्हल लेयरने जुने पेज दाखवले आणि कारण एम्बेडिंग (embedding) अर्थपूर्णदृष्ट्या (semantically) जवळचे वाटले, मॉडेलने त्याला सत्य मानले.

ही पद्धत सतत पुन्हा पुन्हा घडते. जेव्हा तुमचा कॉर्पस (corpus) नेव्हिगेशन फूटर्स, डुप्लिकेट प्रेस रिलीज आणि टेबल अर्धवट तोडणाऱ्या तुकड्यांनी भरलेला असतो, तेव्हा टीम्स 'temperature' आणि 'top-k' मध्ये बदल करण्यात तासनतास वाया घालवतात. जनरेशन ऑप्टिमाइझ करण्यापूर्वी, तुमच्या सिस्टमला काय माहिती असण्याची परवानगी आहे, याचे ऑडिट करा.

इन्जेशन नष्ट करणारे सात सापळे

१. पहिली रन (First Run) ही एक खोटेपणा आहे

तुमच्या सुरुवातीच्या क्रॉलवर (crawl) दिसणारे हिरवे टिक मार्क जवळजवळ काहीच अर्थ ठेवत नाही. प्रोडक्शन डेटा जिवंत असतो. डॉक्युमेंटेशन पेजेसमध्ये बदल होतात, ब्लॉगचे परमलिंक्स तुटतात आणि साइटमॅप्समधील काही विभाग शांतपणे निघून जातात. जर तुम्ही फक्त पाइपलाइनने एरर न देता काम पूर्ण केले आहे हे तपासले, तर तुम्ही अंधारात काम करत आहात. तुम्हाला आउटपुटची पडताळणी (validate) करणे आवश्यक आहे. अपेक्षित डॉक्युमेंट्स उपलब्ध आहेत का, त्यांची रचना अजूनही योग्य आहे का आणि एखाद्या सोर्सने रिझल्ट्सचे पेजिंग (pagination) वेगळ्या पद्धतीने करायचे ठरवल्यामुळे मजकुराचे एकूण प्रमाण कमी झाले नाही ना, हे तपासा.

२. क्रॉलिंग म्हणजे इन्जेशन नाही

HTML मिळवणे हा सोपा भाग आहे. एक रॉ क्रॉल (raw crawl) सर्व काही कॅप्चर करते: कुकी बॅनर्स, "Related Articles" साइडबार्स, ॲड ब्लॉक्स आणि फूटर कॉपीराइट नोटिसेस. जर तुम्ही त्या रॉ HTML चे साध्या पद्धतीने तुकडे (chunking) केले, तर मजकुराच्या प्रत्येक तुकड्यात नेव्हिगेशन मेनूचे अंश असतील. जेव्हा एखादा युजर API रेट लिमिट्सबद्दल विचारतो, तेव्हा रिट्रिव्हर असा तुकडा समोर आणू शकतो ज्यामध्ये ४० टक्के साइडबार लिंक्स आहेत. स्वच्छ एक्स्ट्रॅक्शन (clean extraction) महत्त्वाचे आहे. तुम्हाला मुख्य मजकूर भाग ओळखणे, बॉयलरप्लेट (boilerplate) काढून टाकणे आणि प्रत्येक पेजवर वारंवार येणारे घटक काढून टाकणे आवश्यक आहे. अन्यथा तुम्ही नॉलेज बेस तयार करत नाही आहात, तर तुम्ही वेबसाइटच्या 'क्रोम'साठी (website chrome) सर्च इंजिन तयार करत आहात.

३. चंकिंगमुळे अर्थाचा भंग होतो

जवळपास प्रत्येक क्विकस्टार्ट गाईडमध्ये 'फिक्स्ड-साईज चंकिंग' (Fixed-size chunking) हे डिफॉल्ट असते आणि ते धोकादायक आहे. जर तुम्ही केवळ कॅरेक्टर काउंटनुसार डॉक्युमेंट विभागले, तर तुम्ही टेबल्स मधूनच कापून टाकाल, क्रमांकाच्या प्रक्रियेतील पायरी ४ आणि ५ वेगळी कराल आणि बुलेट पॉइंट्स त्यांच्या हेडिंगपासून वेगळे कराल. किंमत तक्त्याचा (pricing table) फक्त दुसरा अर्धा भाग असलेला तुकडा अर्थहीन असतो. 'स्ट्रक्चर-अवेअर चंकिंग' (Structure-aware chunking) मूळ फॉरमॅटचा आदर करते. हेडिंग हायरार्की (heading hierarchy) समजून घ्या. शक्य असेल तिथे टेबल्स अखंड ठेवा. एकाच H2 किंवा H3 अंतर्गत पॅराग्राफच्या सीमांवर विभागणी करा. जर बुलेट पॉइंट्स पुरेसे लहान असतील तर ते एकाच चंकमध्ये ठेवा. ध्येय समान आकाराचे ब्लॉक्स तयार करणे हे नाही, तर अर्थपूर्ण एकसंध युनिट्स तयार करणे हे आहे.

४. फ्रेशनेसची समस्या (The Freshness Problem)

अंतर्गत विकीचा (internal wiki) स्टॅटिक स्नॅपशॉट घेणे सोपे आहे. परंतु, थेट वेबवरून (live web) सतत डेटा घेणे कठीण आहे. एखादे पेज शेवटचे कधी गोळा केले होते, तेव्हापासून त्यात काही बदल झाले आहेत का आणि ती माहिती किती काळ वैध राहील, हे तुम्हाला माहित असणे आवश्यक आहे. जुना (stale) डेटा म्हणजे नेहमीच एखादी जुनी तारीख असा अर्थ होत नाही. कधीकधी एखादे पेज मजकूर अपडेट करते पण URL तीच ठेवते, त्यामुळे 'content hashing' शिवाय तुमच्या सिस्टमला ते कधीच लक्षात येत नाही. स्त्रोताच्या अस्थिरतेवर (source volatility) आधारित स्पष्ट रिफ्रेश नियम तयार करा. आर्थिक डेटा फीडसाठी तासाला तपासणीची गरज असू शकते, तर कंपनीच्या 'About' पेजसाठी त्रैमासिक तपासणीची गरज असू शकते. टाइमस्टॅम्प रेकॉर्ड करा आणि 'time-to-live' च्या मर्यादा निश्चित करा, विशेषतः जर तुमचे क्षेत्र नियमन केलेले (regulated) किंवा सुरक्षिततेशी संबंधित (safety-critical) मार्गदर्शन असेल, जिथे जुनी तथ्ये प्रत्यक्ष हानी पोहोचवू शकतात.

5. Duplicate Pollution

वेबसाइट्स पुनरावृत्तीने भरलेल्या असतात. तेच उत्पादन वर्णन कॅटेगरी पेज, प्रॉडक्ट पेज आणि प्रमोशनल लँडिंग पेजवर दिसते. तीच प्रेस रिलीज /news/, /press/, आणि /blog/ अंतर्गत असू शकते. वेक्टर सर्च आपोआप 'deduplicate' करत नाही. जर तुमच्या डेटाबेसमध्ये दहा जवळजवळ सारखेच 'chunks' असतील, तर ते तुमच्या 'top-k retrieval' मधील विविध आणि संबंधित निकालांना मागे टाकू शकतात. एम्बेडिंग (embedding) करण्यापूर्वी तुम्हाला 'canonical tracking' किंवा 'content deduplication' ची आवश्यकता आहे. जर दोन 'chunks' एकच गोष्ट सांगत असतील, तर अधिकृत स्त्रोत ठेवा आणि इतर प्रती काढून टाका. तुमच्या 'retriever' कडे मर्यादित स्लॉट्स आहेत. त्यांचा अपव्यय करू नका.

6. Missing Metadata

मेटाडेटाशिवाय वेक्टर डेटाबेस म्हणजे संदर्भाची (context) कोणतीही स्मृती नसलेले केवळ एक 'dense text search engine' आहे. स्मार्ट रिट्रिव्हल हे फिल्टरिंग आणि रँकिंग सिग्नल्सवर अवलंबून असते, जे रॉ एम्बेडिंग्स (raw embeddings) देऊ शकत नाहीत. सोर्स URL, कॅप्चर तारीख, डॉक्युमेंट कॅटेगरी आणि व्हर्जन नंबर साठवून ठेवा. जर तुम्ही API डॉक्युमेंटेशन घेणार असाल, तर व्हर्जनिंग (versioning) आवश्यक आहे. त्याशिवाय, एखादी क्वेरी v1 आणि v2 च्या स्पेसिफिकेशन्सना एकाच उत्तरात मिसळू शकते. जर तुम्ही HR पॉलिसीज घेत असाल, तर रिजन किंवा डिपार्टमेंटनुसार टॅगिंग केल्यामुळे मॉडेलपर्यंत पोहोचण्यापूर्वीच तुम्ही निकाल फिल्टर करू शकता. मेटाडेटा मजकुराच्या ढिगाऱ्याचे (text dump) एका सुव्यवस्थित ज्ञान प्रणालीमध्ये (curated knowledge system) रूपांतर करतो.

7. JavaScript Gaps

आधुनिक साइट्स त्यांचा मजकूर पहिल्या HTML पेलोडमध्ये पाठवत नाहीत. त्या एक सांगाडा (skeleton) पाठवतात आणि JavaScript कॉल्सद्वारे तो पूर्ण करतात. एका साध्या HTTP रिक्वेस्टमध्ये तुम्हाला फक्त 'loading spinner' आणि 'layout shell' दिसेल. जर तुमच्या पाइपलाइनमध्ये JavaScript एक्झिक्युट करण्याची क्षमता नसेल, तर तुम्ही रिकामे पेजेस किंवा अर्धवट तुकडे (fragments) गोळा कराल आणि काहीतरी चुकीचे आहे हे तुम्हाला कधीच समजणार नाही. 'Headless browser' वापरल्याने रेंडरिंगची समस्या सुटते पण नवीन समस्या निर्माण होतात: जास्त मेमरी वापर, कमी थ्रूपुट (throughput) आणि बॉट डिटेक्शन (bot detection) अडथळे. तुमचे तडजोड (trade-offs) विचारपूर्वक निवडा, पण प्रत्येक स्त्रोतासाठी साधा curl पुरेसा आहे असा समज करू नका.

A Practical Ingestion Checklist

जर तुम्ही RAG फीड तयार करत असाल किंवा त्याचे पुनरावलोकन करत असाल, तर इथून सुरुवात करा:

  • सोर्स कव्हरेज आणि पेजिनेशन (pagination) तपासा. साइटमॅपमध्ये एखाद्या कॅटेगरीमधील फक्त पहिले दहा लेख असू शकतात. सखोल क्रॉल (crawl) करा आणि पेजिनेटेड किंवा डायनॅमिकली लोड केलेले कंटेंट खरोखर कॅप्चर झाले आहे की नाही याची खात्री करा.
  • चंकिंग (chunking) करण्यापूर्वी boilerplate मजकूर काढून टाका. नेव्हिगेशन, जाहिराती, फुटर आणि वारंवार येणारे कायदेशीर डिस्क्लेमर काढून टाका. जर एखादा शब्दसमूह प्रत्येक पेजवर येत असेल, तर तो केवळ 'noise' आहे.
  • स्ट्रक्चर-अवेअर चंकिंग वापरा. हेडिंग्स, बुलेट लिस्ट आणि टेबल्सचा आदर करा. कॅरेक्टर काउंटऐवजी सिमेंटिक बाउंड्रीजवर (semantic boundaries) विभागणी करा.
  • समृद्ध मेटाडेटा जोडा. URL, कॅप्चर तारीख, कंटेंट कॅटेगरी आणि व्हर्जन समाविष्ट करा. तुमच्या रिट्रिव्हल क्वेरीजमध्ये हे फील्ड्स फिल्टर करण्यायोग्य बनवा.
  • डेटाच्या अस्थिरतेनुसार रिफ्रेश फ्रिक्वेन्सी सेट करा. वारंवार बदलणाऱ्या स्त्रोतांसाठी वारंवार री-क्रॉलची गरज असते. स्टॅटिक आर्काइव्हसाठी तशी गरज नसते.
  • केवळ जॉब स्टेटसवर लक्ष न ठेवता कॉर्पसवर (corpus) लक्ष ठेवा. एखादी पाइपलाइन 'code zero' सह यशस्वीरित्या संपू शकते पण तरीही कचरा (garbage) डेटा तयार करू शकते. डेटा ड्रिफ्ट आणि गुणवत्तेसाठी साठवलेल्या चंक्सच्या नमुन्यांचे (samples) नियमितपणे ऑडिट करा.
  • व्हर्जनिंग आणि डिलीशनसाठी नियम ठरवा. जेव्हा एखादे सोर्स पेज काढून टाकले जाते, तेव्हा त्याचे चंक्स देखील डिलीट करा. जेव्हा ते अपडेट होते, तेव्हा ते ओव्हरराईट करा किंवा त्यांचे व्हर्जन तयार करा. 'Orphaned data' (अनावश्यक उरलेला डेटा) हा एक शांत मारेकरी आहे.

The Hard Truth About Embeddings

कोणतेही एम्बेडिंग मॉडेल, ते कितीही प्रगत असले तरी, गहाळ झालेला दस्तऐवज दुरुस्त करू शकत नाही. जर तुमच्या फीडमध्ये गेल्या वर्षीची प्रत असेल, तर एखादे पेज गेल्या आठवड्यात अपडेट झाले आहे याचा अंदाज ते मॉडेल लावू शकत नाही. चुकीच्या चंक बाउंड्रीमुळे हेडरपासून वेगळी झालेली टेबल रो (table row) मधील संदर्भ ते मॉडेल काढू शकत नाही. एम्बेडिंग्स अर्थ संकुचित (compress) करतात, परंतु जिथे इन्जेशन लेयर (ingestion layer) तो अर्थ जतन करण्यात अपयशी ठरला आहे, तिथे ते नवीन अर्थ निर्माण करू शकत नाहीत.

रिट्रिव्हलची गुणवत्ता इन्जेशन लेयरपासून सुरू होते. तुमचा RAG सिस्टम एक उपयुक्त साधन आहे की केवळ वेक्टर डेटाबेसच्या आधारे आत्मविश्वासाने खोटे बोलणारा एक यंत्र आहे, हे तो लेयरच ठरवतो.

The Real Takeaway

केवळ पाइपलाइन डॅशबोर्ड्सच्या आधारे डेटा इनजेशनची (ingestion) स्थिती मोजणे थांबवा. यशस्वीरित्या पूर्ण झालेले जॉब्स आणि स्वच्छ लॉग्स म्हणजे तुमचा कॉर्पस (corpus) स्वच्छ आहेच याची खात्री नाही. डेटाबेस उघडा आणि तुमचे युजर्स प्रत्यक्षात जे चंक्स (chunks) मिळवतील ते वाचा. जर मजकूर कॉपीराइट सूचना, विस्कळीत झालेली तक्ते आणि कालबाह्य पॉलिसी पेजेसनी भरलेला असेल, तर तुमची समस्या LLM ची नाहीये. आधी फीड (feed) सुधारा. बाकी सर्व गोष्टी म्हणजे केवळ कचऱ्यावर आधारित ट्यूनिंग आहे.