മിക്ക എഞ്ചിനീയറിംഗ് ടീമുകളും Retrieval-Augmented Generation (RAG) ഉപയോഗിക്കുമ്പോൾ ഒരേ തടസ്സമാണ് നേരിടുന്നത്. അവർ ട്യൂട്ടോറിയലുകളിൽ കാണുന്ന രീതി തന്നെ പിന്തുടരുന്നു: ഡോക്യുമെന്റുകളെ 512 അല്ലെങ്കിൽ 1024 ടോക്കണുകൾ വീതമുള്ള നിശ്ചിത ഭാഗങ്ങളായി (fixed chunks) മുറിക്കുക, അവയെ ഒരു എംബെഡിംഗ് മോഡലിലൂടെ കടത്തിവിടുക, തുടർന്ന് ഒരു വെക്റ്റർ ഡാറ്റാബേസിൽ ലളിതമായ top-k ലുക്കപ്പ് നടത്തുക. ഒരു സ്ലൈഡ് ഡെക്കിൽ ഇത് മികച്ചതായി തോന്നാം, എന്നാൽ പ്രൊഡക്ഷനിൽ ഇത് പരാജയപ്പെടുന്നു.
നിശ്ചിത ചങ്കുകൾ (Fixed chunks) ഉള്ളടക്കത്തെ പരിഗണിക്കുന്നില്ല. അവ ഒരു നിയമപരമായ കരാറിനെ (legal contract) വാചകത്തിന്റെ പകുതിയിൽ വെച്ച് മുറിച്ചേക്കാം, ഇത് ഉത്തരവാദിത്ത ക്ലോസുകളെ (liability clauses) പരസ്പരബന്ധമില്ലാത്ത രണ്ട് ഭാഗങ്ങളായി മാറ്റുന്നു. ഒരു API എൻഡ്പോയിന്റ് വിവരണത്തെ മുഴുവനായി ഒരു വലിയ ചങ്കിലേക്ക് മാറ്റിയാൽ, ഉപയോക്താവ് ചോദിച്ച പ്രത്യേക പാരാമീറ്റർ ആ വലിയ വിവരങ്ങൾക്കിടയിൽ മുങ്ങിപ്പോകുന്നു. റിട്രീവൽ വേഗത കുറയുമ്പോൾ, ഓരോ മില്ലിസെക്കൻഡ് ലേറ്റൻസിയും ഉപയോക്താവിന്റെ അനുഭവത്തെ നേരിട്ട് ബാധിക്കുന്നു. ഞങ്ങൾ ഇത് കഠിനമായ അനുഭവത്തിലൂടെയാണ് പഠിച്ചത്. പിന്നീട് ഞങ്ങൾ ഞങ്ങളുടെ റിട്രീവൽ ലെയർ പൂർണ്ണമായും മാറ്റി നിർമ്മിച്ചു. ഞങ്ങളുടെ recall at ten 78 ശതമാനത്തിൽ നിന്ന് 95 ശതമാനമായി ഉയർന്നു. ലേറ്റൻസി വർദ്ധിച്ചില്ല, പകരം അത് ഗണ്യമായി കുറഞ്ഞു.
കോപ്പി-പേസ്റ്റ് RAG-ലെ പ്രശ്നങ്ങൾ
നിലവിലുള്ള RAG സ്റ്റാക്ക് ഒരു ഡിഫോൾട്ട് സെറ്റിംഗ് പോലെയായി മാറിയിരിക്കുന്നു. ചെറിയ ചങ്കുകൾ, ഒരു എംബെഡിംഗ് മോഡൽ, വെക്റ്റർ സെർച്ച് - ഇത്രയും മതി എന്ന് പലരും കരുതുന്നു. ഡെമോകളിൽ ഈ രീതി വിജയിച്ചേക്കാം, കാരണം ഡെമോകളിൽ വ്യക്തമായ ചോദ്യങ്ങളും വൃത്തിയുള്ള ഡോക്യുമെന്റുകളുമാണ് ഉപയോഗിക്കുന്നത്. എന്നാൽ പ്രൊഡക്ഷൻ ഡാറ്റ ഒരിക്കലും അത്ര വൃത്തിയുള്ളതാകില്ല.
നിയമപരമായ രേഖകൾക്ക് ഒരു ശ്രേണിപരമായ ഘടനയുണ്ട് (hierarchical structure). സെക്ഷനുകൾക്കുള്ളിൽ സബ്സെക്ഷനുകളും, സബ്സെക്ഷനുകൾക്കുള്ളിൽ ക്ലോസുകളും ഉണ്ടാകും. ഒരു ടോക്കൺ കൗണ്ടർ ഉപയോഗിച്ച് ഇവയെ മുറിക്കുമ്പോൾ, മോഡലിന് വിശകലനം ചെയ്യാൻ ആവശ്യമായ ആ ബന്ധങ്ങൾ തന്നെ നശിപ്പിക്കപ്പെടുന്നു. API ഡോക്യുമെന്റേഷനും ഒരു ഘടനയുണ്ട്, പക്ഷേ അത് വ്യത്യസ്തമാണ്. ഒരു ഫങ്ക്ഷൻ സിഗ്നേച്ചർ, അതിന്റെ പാരാമീറ്ററുകൾ, റിട്ടേൺ വാല്യൂ, ഒരു ഉദാഹരണം എന്നിവയെല്ലാം ചേർന്ന് ഒരു ലോജിക്കൽ യൂണിറ്റായി പ്രവർത്തിക്കുന്നു. ഇവയെ ഒരു നിശ്ചിത ടോക്കൺ വിൻഡോയിലേക്ക് നിർബന്ധിച്ചാൽ, ഒന്നുകിൽ ഉദാഹരണം അപൂർണ്ണമാകും അല്ലെങ്കിൽ അനാവശ്യമായ ഫങ്ക്ഷനുകൾ ചേർത്ത് ചങ്ക് വലുതാകും. സപ്പോർട്ട് ടിക്കറ്റുകൾ ആശയക്കുഴപ്പമുണ്ടാക്കുന്നതും, സംഭാഷണ രൂപത്തിലുള്ളതും, പെട്ടെന്ന് വിഷയം മാറുന്നവയുമാണ്. വികി (Wikis) വിപുലവും പരസ്പരം റഫറൻസ് ചെയ്യുന്നതുമാണ്. എല്ലാത്തിനും ഒരേ ചങ്കിംഗ് രീതി ഉപയോഗിക്കാൻ കഴിയില്ല, എന്നിട്ടും ടീമുകൾ അത് തന്നെയാണ് ചെയ്യുന്നത്. അത് സാധ്യമാണെന്ന് വിശ്വസിക്കുന്നത് ഞങ്ങൾ നിർത്തി.
സ്ട്രാറ്റജിക് ചങ്കിംഗ്: രീതികൾ ഉള്ളടക്കത്തിന് അനുസൃതമാക്കുക
ഞങ്ങൾ ഉള്ളടക്കത്തെ തിരിച്ചറിയുന്ന (content-aware) ചങ്കിംഗിലേക്ക് മാറി. നിയമപരമായ രേഖകൾക്കായി, ഡോക്യുമെന്റിന്റെ ഘടനയെ മാനിക്കുന്ന 'റിക്കേഴ്സീവ് ചങ്കിംഗ്' (recursive chunking) ഞങ്ങൾ ഉപയോഗിക്കുന്നു. ഇത് ക്ലോസുകളെ മാറ്റമില്ലാതെ നിലനിർത്തുകയും സെക്ഷനുകൾ തമ്മിലുള്ള ബന്ധം സംരക്ഷിക്കുകയും ചെയ്യുന്നു. API ഡോക്യുമെന്റേഷനായി, ഓരോ ഫങ്ക്ഷനെയോ എൻഡ്പോയിന്റോ ഒരു അതിർവരമ്പായി കാണുന്ന 'ഫങ്ക്ഷൻ-അവയർ ചങ്കിംഗ്' (function-aware chunking) ഞങ്ങൾ നിർമ്മിച്ചു. ഒരു പാരാമീറ്റർ വിവരണം നീണ്ടുപോയാൽ, അത് ടോക്കൺ പരിധിക്കനുസരിച്ചല്ല, മറിച്ച് ആ ഫങ്ക്ഷന് ചുറ്റും വികസിക്കുന്നു. സപ്പോർട്ട് ടിക്കറ്റുകൾക്കായി, സ്വാഭാവികമായ വിഷയാന്തരം തിരിച്ചറിയുന്ന 'സെമാന്റിക് ചങ്കിംഗ്' (semantic chunking) ഞങ്ങൾ ഉപയോഗിക്കുന്നു. ഒരു ഉപഭോക്താവ് ബില്ലിംഗ് പരാതിയിൽ നിന്ന് പെട്ടെന്ന് ഒരു സാങ്കേതിക പിഴവിലേക്ക് (technical bug) മാറുന്നအခിൽ, ആ മാറ്റത്തിന് അനുസരിച്ചാണ് സ്പ്ലിറ്റ് നടക്കുന്നത്. വികി (Wikis), അസംഘടിതമായ നോളജ് ബേസുകൾ എന്നിവയ്ക്കായി, ഒരു ലഘുവായ LLM ഉപയോഗിച്ച് എവിടെയാണ് അർത്ഥവത്തായ അതിർവരമ്പ് വയ്ക്കേണ്ടതെന്ന് തീരുമാനിക്കുന്ന 'ഏജന്റിക് ചങ്കിംഗ്' (agentic chunking) ഞങ്ങൾ ഉപയോഗിക്കുന്നു. ഇത് ഒരു ക്യാരക്ടർ സ്പ്ലിറ്റിനേക്കാൾ സജ്ജീകരിക്കാൻ സമയമെടുക്കുമെങ്കിലും, കൃത്യമായ റിട്രീവലും ഊഹിച്ചുകൊണ്ടുള്ള റിട്രീവലും തമ്മിലുള്ള വ്യത്യാസം ഇതാണ്.
ഹൈബ്രിഡ് റിട്രീവൽ: വെക്റ്റർ സെർച്ച് മാത്രം മതിയാകില്ലേ?
വെക്റ്റർ സെർച്ചന് അർത്ഥം മനസ്സിലാക്കാൻ കഴിയും, പക്ഷേ കൃത്യമായ പദങ്ങൾ (exact matches) കണ്ടെത്താൻ അതിന് കഴിഞ്ഞെന്നു വരില്ല. ഒരു ഉപയോക്താവ് ERR_CONNECTION_RESET_0x5F3 പോലുള്ള ഒരു എറർ കോഡ് നൽകിയാൽ, സെമാന്റിക് സമാനത (semantic similarity) കാരണം നെറ്റ്വർക്ക് എററുകളെക്കുറിച്ച് പൊതുവായി പറയുന്ന ഖണ്ഡികകൾക്ക് അത് ഉയർന്ന റാങ്ക് നൽകിയേക്കാം. മറുവശത്ത്, BM25 കൃത്യമായ സ്ട്രിംഗുകൾ കണ്ടെത്തുന്നുണ്ടെങ്കിലും ആശയപരമായ ബന്ധങ്ങൾ (conceptual relatedness) തിരിച്ചറിയുന്നില്ല. അതിനാൽ നിങ്ങൾക്ക് രണ്ടും ആവശ്യമാണ്.
ഞങ്ങൾ വെക്റ്റർ സെർച്ചും BM25-ഉം സമാന്തരമായി (parallel) പ്രവർത്തിപ്പിക്കുന്നു. തുടർന്ന്, രണ്ട് വ്യത്യസ്ത സെർച്ച് സ്പേസുകളിൽ നിന്നുള്ള സ്കോറുകളെ ഒരേ അളവുകോലിലേക്ക് മാറ്റാതെ തന്നെ സംയോജിപ്പിക്കുന്ന 'റെസിപ്രോക്കൽ റാങ്ക് ഫ്യൂഷൻ' (Reciprocal Rank Fusion - RRF) ഉപയോഗിച്ച് ഫലങ്ങൾ യോജിപ്പിക്കുന്നു. ഫ്യൂഷന് ശേഷം, മികച്ച ഫലങ്ങളെ ഒരു 'ക്രോസ്-എൻകോഡർ റീറങ്കർ' (cross-encoder reranker) വഴി കടത്തിവിടുന്നു. ഇത് ചെറിയ തോതിൽ ലേറ്റൻസി കൂട്ടുമെങ്കിലും, കൃത്യതയിൽ (precision) വലിയ വർദ്ധനവ് ഉണ്ടാക്കുന്നു. റീറങ്കർ ക്വറിയും ഓരോ ഫലവും ഒന്നിച്ച് വായിക്കുകയും, ആദ്യത്തെ എംബെഡിംഗിന്റെ കോസൈൻ സമാനതയേക്കാൾ (cosine similarity) വളരെ കൃത്യമായ ഒരു റിലവൻസ് സ്കോർ നൽകുകയും ചെയ്യുന്നു. പ്രായോഗികമായി പറഞ്ഞാൽ, വെക്റ്റർ സെർച്ച് കാണാതെ പോകുന്ന കൃത്യമായ എറർ കോഡുകൾ ഈ രീതിയിലൂടെ കണ്ടെത്താനും, കീവേഡ് സെർച്ച് അവഗണിക്കുന്ന ആശയപരമായ പ്രശ്നപരിഹാര മാർഗങ്ങൾ കണ്ടെത്താനും സാധിക്കുന്നു.
ക്വറി എക്സ്പാൻഷൻ: ഇൻഡക്സിലേക്ക് എത്തുന്നതിന് മുമ്പ് ഉപയോക്താവിന്റെ ഇൻപുട്ട് ശരിയാക്കുക
ഉപയോക്താക്കൾ എപ്പോഴും കൃത്യമായ സെർച്ച് ക്വറികൾ എഴുതാറില്ല. "എന്റെ അവസാനത്തെ ഡിപ്ലോയ്മെന്റ് (deploy) എന്തുകൊണ്ട് പരാജയപ്പെട്ടു, അത് എങ്ങനെ റോളബാക്ക് ചെയ്യാം?" എന്നിങ്ങനെയുള്ള 'മൾട്ടി-ഹോപ്പ്' (multi-hop) ചോദ്യങ്ങൾ അവർ ചോദിച്ചേക്കാം; ഇതിനായി രണ്ട് വ്യത്യസ്ത വിവരങ്ങൾ കണ്ടെത്തി അവ തമ്മിൽ ബന്ധിപ്പിക്കേണ്ടി വരും. അല്ലെങ്കിൽ ഇൻഡക്സുമായി പൊരുത്തപ്പെടാൻ പ്രയാസമുള്ള അവ്യക്തമായ ചോദ്യങ്ങൾ അവർ ചോദിച്ചേക്കാം.
We transform queries before searching. A multi-hop question gets broken into sub-questions. A vague intent gets expanded into multiple specific search queries. We found that expanding one user query into five distinct search queries can move recall from seventy-eight percent to ninety-six percent. This is not about prompting the LLM harder. It is about giving the retrieval system more shots at finding the right context. Each generated query captures a different angle or terminology, and the merged results paint a complete picture.
Bayesian Optimization: Stop Guessing
Once you have multiple chunking strategies, hybrid retrieval, and query expansion, you face a new problem. There are too many knobs. Chunk size, overlap percentage, vector weight versus BM25 weight, reranking thresholds, and top-k values all interact in nonlinear ways. Manual tuning becomes a guessing game.
We stopped guessing. We treat the
