આજકાલ RAGને ક્યારેક ખરાબ પ્રતિષ્ઠા મળે છે. કેટલાક લોકો હવે તેને સાવ સરળ માને છે (શરૂ કરવું સરળ છે, પણ મોટા પાયે લાગુ કરવું એટલું સરળ નથી), તો કેટલાક માને છે કે ‘એજન્ટિક સિસ્ટમ્સ’ તેનાથી આગળ નીકળી ગઈ છે (જોકે ઘણા કિસ્સામાં ઉપરછલ્લું આવરણ હટાવતાં જ તે બહુ ઝડપથી RAG જેવી દેખાવા લાગે છે…).
આ બ્લૉગ એકાદ વિગતવાર ઉદાહરણ દ્વારા બતાવે છે કે અમે કેટલીક સામાન્ય મુશ્કેલીઓનો સામનો કેવી રીતે કરીએ છીએ. ખાસ કરીને:
મિશ્ર ટેક્સ્ટ અને આંકડાકીય ડેટાનું સંચાલન અને તે સાદા RAGને કેમ નિષ્ફળ બનાવે છે: કીવર્ડ એકબીજા સાથે અથડાય છે અને સંખ્યાઓનો કોઈ અર્થગત સંદર્ભ હોતો નથી.
પહેલાં સારાંશ બનાવતા એમ્બેડિંગ્સની રચના કેમ મદદરૂપ થાય છે: દરેક ચંક માટે ટૂંકો વર્ણનાત્મક સારાંશ બનાવો અને પછી તે સારાંશને એમ્બેડ કરીને તેના પર ક્વેરી ચલાવો.
સંદર્ભયુક્ત સારાંશ કેવી રીતે બનાવવા: મૂળ દસ્તાવેજનો સંદર્ભ ઉમેરો, જેથી સમાન બંધારણ ધરાવતા આંકડા અલગ ઓળખી શકાય.
કોડ અને Pydantic મોડલ પર ક્યારે આધાર રાખવો: જ્યાં સામગ્રી શબ્દશઃ જાળવવી જરૂરી હોય ત્યાં વિશ્વસનીયતા માટે કસ્ટમ કોડ અને/અથવા Pydantic મોડલને LLM કૉલ્સ સાથે જોડો.
મૂળભૂત બાબતો
RAG સિસ્ટમ્સ ગ્રાહક સહાય બૉટથી લઈને આંતરિક જ્ઞાન સહાયકો સુધીની અનેક સેવાઓ ચલાવે છે.
આંતરિક રીતે તમે સામાન્ય રીતે આ કરો છો:
તમારા સ્રોત દસ્તાવેજોના ચંક બનાવો.
દરેક ચંકને વેક્ટર સ્પેસમાં એમ્બેડ કરો.
ક્વેરી વખતે ટોચના K ચંક મેળવો.
એ ચંકના આધારે જવાબ બનાવો.
LangChain, LlamaIndex અને OpenAIનું Filestore જેવાં લોકપ્રિય ટૂલકિટ આ પગલાંને લગભગ સાવ સરળ બનાવી દે છે. પરંતુ વાસ્તવિક પાઇપલાઇનમાં માત્ર ગીચ ટેક્સ્ટ ન હોય એવો ડેટા પણ મળે છે અને મૂળભૂત RAGને તેની સાથે મુશ્કેલી પડી શકે છે. આગળના વિભાગોમાં અમે ડેટાની મુશ્કેલીઓનાં નક્કર ઉદાહરણો બતાવીશું અને જટિલતા વધતી જાય તેમ ધીમે ધીમે ઉકેલ તૈયાર કરીશું.
જ્યારે તમારો ડેટા માત્ર ટેક્સ્ટ ન હોય (જે ખરેખર સામાન્ય બાબત છે)
ગેમિંગના સંદર્ભમાં નીચેના ડેટા ચંકનો વિચાર કરો:
JSON
એમ્બેડિંગ્સ કામ કરે છે, કારણ કે અર્થ અને વ્યાકરણ દ્વારા શબ્દો વચ્ચેના સંબંધો શીખવામાં આવ્યા હોય છે. ઉપરના ડેટામાં ટેક્સ્ટ અને સંખ્યાઓનું મિશ્રણ છે. આ ચોક્કસ સંદર્ભની બહાર એ સંખ્યાઓનો શબ્દો સાથે કોઈ સંબંધ નથી. એટલે કહી શકાય કે આ ડેટા ચંક અમુક અંશે વર્ણનાત્મક શબ્દો અને ત્યાર પછી આવતી કેટલીક રેન્ડમ સંખ્યાઓનું સંયોજન છે.
જો અમારી પાસે માત્ર આ જ પ્રકારનો ડેટા હોત તો સમસ્યા ન થાત, કારણ કે ઉપલબ્ધ થોડા વર્ણનાત્મક શબ્દોના એમ્બેડિંગ્સથી પણ અમે તેને મેળવી શકત (અથવા સીધું ટેક્સ્ટ-ટુ-SQL વાપરી શકત). પરંતુ આ ચંક એવા અનેક ગીચ ટેક્સ્ટવાળા ચંકની વચ્ચે દટાયેલો હોય, જેમાં એ જ શબ્દો આવતા હોય, તો શું થાય? ઉદાહરણ તરીકે:
JSON
હવે ધારો કે આપણે પૂછીએ, “ડ્રેકોનિક એસેન્શન સાથે હુમલાની રેન્જ કેટલી છે?” સંભવ છે કે આપણને જોઈતો સંબંધિત ચંક નહીં મળે, કારણ કે સમાન કીવર્ડ ધરાવતા અન્ય ચંકના ઘોંઘાટમાં તે ઊંડે દટાયેલો છે.
મૂળ સમસ્યા એ છે કે આ ડેટા ચંકમાં એક જ વિષય વિશે અલગ પ્રકારની માહિતી હોવા છતાં આપણે તેમની વચ્ચે સારી રીતે ભેદ કરી શકતા નથી. શું આપણે કોઈ રીતે તેને વધુ સમૃદ્ધ કે બહેતર બનાવી શકીએ? અલબત્ત બનાવી શકીએ:smile:
તમારા ડેટાનો સારાંશ બનાવીને તેને સમૃદ્ધ કરો. હા, તમે બરાબર વાંચ્યું.
ચંકને સીધો એમ્બેડ કરવાને બદલે પહેલાં ડેટા શેના વિશે છે તે સમજાવતો સારાંશ બનાવી શકીએ અને પછી એ સારાંશને એમ્બેડ કરીને તેના આધારે માહિતી મેળવી શકીએ. જવાબ બનાવવાના તબક્કે અમે હજી પણ સારાંશ સાથે જોડાયેલો મૂળ ડેટા જ વાપરીશું.
એટલે ઉપર બતાવેલા બે ચંક માટે અમે આવા સારાંશ બનાવીશું:
રેન્જ, ઝડપ અને નુકસાનના હુમલાના આંકડા (મૂળભૂત અને ડ્રેકોનિક એસેન્શન સાથે).
ડ્રેકોનિક એસેન્શનનું વર્ણન અને વિગતો, જેમાં સક્રિય થવાની શરતો, દૃશ્ય અસરો અને કથાજગતની માહિતીનો સમાવેશ થાય છે.
પછી અમે ક્વેરીને પણ સારાંશ સાથે “સુસંગત” બનાવવા વિસ્તૃત કરીએ છીએ. દાખલા તરીકે, “ડ્રેકોનિક એસેન્શન સાથે હુમલાની રેન્જ કેટલી છે?”ને બદલીને “ડ્રેકોનિક એસેન્શન સાથે હુમલાની રેન્જના આંકડા શું છે?” કરીશું. જ્યારે માહિતી મેળવવાની ક્વેરી ટેકનિકલ ક્ષેત્રની બહારના વપરાશકર્તાઓ સામાન્ય માનવીય ભાષામાં ~~“મનફાવે તેમ”~~ પૂછે ત્યારે આ ખાસ મહત્ત્વનું છે. છેવટે, ચોકસાઈ અને પુનઃપ્રાપ્તિ વધારવા RAG કેવી રીતે કામ કરે છે એ જાણવું તેમની સમજ કે ચિંતાનો વિષય નથી.


બાબતોને સંદર્ભથી અલગ ન કરો (જીવનમાં પણ સામાન્ય રીતે લાગુ પડે છે).
હવે પછીની પરિસ્થિતિમાં નીચે બતાવ્યા જેવા એકસરખા દેખાતા અસંખ્ય ડેટા ચંક સંભાળવાના છે:
Plain Text
જો આપણે એ જ અભિગમ જાળવીએ, તો કલ્પના કરો કે કોઈ પૂછે, “પાત્ર Xની હુમલાની રેન્જ કેટલી છે?” આપણે હમણાં બનાવેલા આ સારાંશ પણ એકસરખા દેખાતા હોવાથી જવાબ મેળવવો નસીબ આધારિત અનુમાનની રમત બની જશે. તો આપણે તેમને અલગ કેવી રીતે ઓળખી શકીએ?
સરળ જવાબ છે: સંદર્ભ આપો. આપણે ડેટા ચંકમાં તેના મૂળ દસ્તાવેજનો સંદર્ભ ઉમેરી શકીએ. દાખલા તરીકે, આ કિસ્સામાં {”પાત્ર”: “X”}. હવે પાત્ર Y અને Z માટે પણ સમાન ડેટા હોય ત્યારે આપણે પાત્ર X માટેનો સાચો ડેટા ચોકસાઈથી મેળવી શકીશું.
જોકે વધુ સારો અને વ્યાપક રીતે લાગુ કરી શકાય એવો અભિગમ ચંકનો સંદર્ભયુક્ત સારાંશ બનાવવાનો છે. એટલે કે, ફક્ત ડેટા ચંકનો સારાંશ બનાવવાને બદલે આપણે તેના મૂળ દસ્તાવેજ અને ચંક બંને આપીને સામાન્ય સંદર્ભયુક્ત સારાંશ બનાવી શકીએ. એ સારાંશમાં આ ચંક તેના મૂળ દસ્તાવેજ સાથે કેવી રીતે બંધબેસે છે તે પણ જણાવી શકાય. દાખલા તરીકે:
આ ચંક પાત્ર X માટે …ના વિગતવાર આંકડા આપે છે. આ ચંક હુમલાની ઝડપમાં Xની શક્તિ દર્શાવીને સંપૂર્ણ દસ્તાવેજ સાથે બંધબેસે છે…
આ ચંક પાત્ર Y માટે …ના વિગતવાર આંકડા આપે છે. આ ચંક Yની વિશેષ ક્ષમતાથી વધેલા તેના આંકડા દર્શાવીને સંપૂર્ણ દસ્તાવેજ સાથે બંધબેસે છે…
આ ચંક પાત્ર Z માટે …ના વિગતવાર આંકડા આપે છે. આ ચંક ટીમ મુકાબલામાં રક્ષણાત્મક ભૂમિકા માટે યોગ્ય Zના આંકડા દર્શાવીને સંપૂર્ણ દસ્તાવેજ સાથે બંધબેસે છે…
આ પદ્ધતિ (જે અંશતઃ Anthropicથી પ્રેરિત છે) ઉપરના ઉદાહરણ માટે જરૂર કરતાં વધારે લાગી શકે છે. જોકે “સંદર્ભની બહાર” ખોટી રીતે સમજી શકાય એવા ચંક માટે તે ખૂબ અસરકારક છે. ઉપરાંત, તે બધા ચંક માટે કામ કરતો એકરૂપ અભિગમ આપે છે અને એન્જિનિયરિંગ પાઇપલાઇન સુવ્યવસ્થિત રાખે છે.


જ્યારે તમારે ~~બધું નિયંત્રિત કરનારા~~ ચુસ્ત બનવું પડે.
સામાન્ય રીતે અમને સંપૂર્ણ સ્વરૂપે ડેટા મળે છે અને RAG સિસ્ટમ માટે અમે તેના ચંક બનાવીએ છીએ. આ ઉદાહરણમાં અમે કંઈક જુદું બતાવીએ છીએ: ડેટાના ચંક બનેલા છે, પણ એ ખરાબ ચંક છે. વાસ્તવમાં ફરી એકસાથે જૂથબદ્ધ કરવાની જરૂર હોય એવા તાર્કિક ચંકમાંથી લેવાયેલા આ રેન્ડમ વિભાગો છે. તાર્કિક ચંક એટલે સામગ્રીનો એવો ભાગ જે સ્વાભાવિક રીતે એકસાથે રહેવો જોઈએ, જેમ કે દસ્તાવેજનો પેટાવિભાગ અથવા સુસંગત ફકરો.


આ ડેટા સાથેના પ્રથમ પ્રયાસમાં અમે બધું એક LLM કૉલને આપ્યું અને તેને યોગ્ય લાગે તે રીતે જૂથબદ્ધ કરીને જૂથવાળી સામગ્રી પરત કરવા કહ્યું. LLM આમાં ઘણું સારું હોવું જોઈએ, ખરું ને? હા પણ અને ના પણ.
બીજા ઘણા પ્રસંગોએ પણ અમે જોયું છે કે સંપૂર્ણ અને ચોક્કસ સામગ્રી જોઈએ ત્યારે LLM આળસુ વલણ દાખવે છે અને વિશ્વસનીય રહેતા નથી, ખાસ કરીને જ્યારે સંદર્ભ લાંબો હોય. જે સંપૂર્ણપણે વાજબી છે. પરંતુ આ ચોક્કસ ઉપયોગ માટે એ મોટી અડચણ હતી, કારણ કે અમને શબ્દેશબ્દ ચોક્કસ સામગ્રી જ જોઈએ છે. કોઈ સારાંશ નહીં અને મૂળ સામગ્રીનો કોઈ ભાગ છોડવાનો નહીં. અમે કોઈ વિગત ચૂકી શકીએ નહીં.
અલબત્ત, “હા”વાળો ભાગ એ હતો કે તેણે તૂટેલા ચંકના અર્થ અને બંધારણને સમજવામાં ઉત્તમ કામ કર્યું. બસ, તે ચોક્કસ સામગ્રી ફરી રજૂ કરવાનો ઇનકાર ન કરે તો. અરે યાર:/
તો LLM જે કામ સારી રીતે કરે છે તેનો લાભ લઈને, જેમાં તે વિશ્વસનીય નથી તે કેવી રીતે ટાળી શકાય? અમે અમારા જૂના અને વિશ્વાસુ મિત્ર કોડની મદદ લીધી (અર્થાત્ કસ્ટમાઇઝ કરેલું Python ફંક્શન). અને એક અત્યંત સરળ Pydantic મોડલની. ઉકેલ આ રહ્યો:
વર્તમાન તાર્કિક ચંક જાળવી રાખીને બધા વિભાગોમાંથી ક્રમશઃ પસાર થાઓ.
દરેક વિભાગે LLMને પૂછો: શું આ વિભાગ વર્તમાન તાર્કિક ચંકનો ભાગ છે? Pydantic મોડલ મુજબ હા કે નામાં જવાબ આપો.
જો હા, તો વિભાગને ચંક સાથે જોડો. જો ના, તો પૂર્ણ થયેલો વર્તમાન તાર્કિક ચંક બહાર કાઢો અને આ વિભાગથી નવો ચંક શરૂ કરો.


અલબત્ત, અહીં સંપૂર્ણ સામગ્રીને એક જ વારમાં મોકલવા કરતાં થોડા વધુ ટોકન વપરાય છે. પરંતુ જ્યાં ચોક્કસ સામગ્રી જાળવવી સર્વોચ્ચ પ્રાથમિકતા હોય એવા આ ઉપયોગ માટે આ નાનો વધારાનો ખર્ચ સંપૂર્ણપણે યોગ્ય હતો.
આ બહુ સરળ ઉકેલ છે, પરંતુ તે એક મહત્ત્વના સિદ્ધાંતને અનુસરે છે: ચુસ્તતા જરૂરી હોય ત્યારે ફક્ત LLM પર આધાર રાખવો યોગ્ય નથી, કારણ કે છેવટે તે સંભાવના આધારિત છે.
કસ્ટમ કોડ અથવા ફંક્શન અને Pydantic મોડલ વડે અનુમાન કરી શકાય એવું વિશ્વસનીય પરિણામ મેળવી શકાય છે અને સાથે LLMની ક્ષમતાનો પણ પૂરો લાભ લઈ શકાય છે.
જનરેટિવ AI ઉકેલ બનાવવો એ AI જેટલો જ એન્જિનિયરિંગનો પણ પડકાર છે. અમને આશા છે કે આ ઉદાહરણોએ તમને તમારા અનોખા પડકારોનો સામનો કરવાની પ્રેરણા આપી હશે. એન્જિનિયરિંગને પ્રાથમિકતા આપતા જનરેટિવ AI ઉકેલો વિશે વધુ વાંચવા માટે રાઉટર-આધારિત એજન્ટિક સિસ્ટમની રચના વિશેની અમારી બ્લૉગ પોસ્ટ જુઓ.