సున్నా నుండి ఒక RAG ని నిర్మించడం
నా మొదటి AI వెర్షన్ నేను ఒక హైడ్రాలిక్ ఎక్స్కవేటర్ను విక్రయిస్తున్నానని చెప్పింది. నేను ఎక్స్కవేటర్లను అమ్మను. అది పూర్తి నమ్మకంతో ఒక తప్పుడు ధరను మరియు తప్పుడు వివరణను ఇచ్చింది.
ప్రాంప్ట్లను మాత్రమే నమ్మడం నేను ఆపివేసిన క్షణం అది. నేను ఒకే ఒక నియమంతో సిస్టమ్ను మళ్లీ నిర్మించాను: అది కేటలాగ్ నుండి సమాధానం చెప్పాలి, లేదంటే అసలు సమాధానం చెప్పకూడదు.
Postgres మరియు Python ఉపయోగించి నేను ఒక నమ్మదగిన RAG (Retrieval-Augmented Generation) సిస్టమ్ను ఎలా నిర్మించానో ఇక్కడ ఉంది.
డేటా తయారీ చాలా ట్యుటోరియల్స్ కష్టమైన భాగాన్ని వదిలేస్తాయి: డేటాను క్లీన్ చేయడం. నేను నా ప్రక్రియను రెండు దశలుగా విభజించాను:
- దశ 1: HTML ఫైళ్లను డిస్క్లోకి డౌన్లోడ్ చేయడం. నేను ప్రతి ఫైల్ పైన కామెంట్గా మెటాడేటాను సేవ్ చేస్తాను. ఇది ప్రక్రియను idempotent చేస్తుంది. ఒకవేళ ఫైల్ ఇప్పటికే ఉంటే, నేను దానిని వదిలేస్తాను.
- దశ 2: ఆ ఫైళ్లను ఆఫ్లైన్లో పార్స్ చేయడం. ఇది HTMLని క్లీన్ JSON కేటలాగ్గా మారుస్తుంది.
పార్సింగ్ తర్వాత నేను ఫీల్డ్ కవరేజీని తనిఖీ చేస్తాను. బరువు లేదా ధర వంటి ఫీల్డ్ ఖాళీగా ఉంటే, నేను వెంటనే తెలుసుకుంటాను. నిజమైన పని క్లీన్ డేటాలోనే జరుగుతుంది.
AI భాగం నేను ప్రతి ఉత్పత్తిని ఒక టెక్స్ట్ బ్లాక్గా మార్చి, bge-m3 మోడల్ని ఉపయోగించి దానిని వెక్టర్గా మారుస్తాను. నేను ఈ వెక్టర్లను pgvector ఎక్స్టెన్షన్ని ఉపయోగించి Postgresలో నిల్వ చేస్తాను.
ఉత్పత్తులను కనుగొనడానికి నేను హైబ్రిడ్ సెర్చ్ విధానాన్ని ఉపయోగిస్తాను:
- Semantic Search: మీ ప్రశ్న యొక్క అర్థానికి సరిపోయే ఉత్పత్తులను కనుగొనడానికి వెక్టర్లను ఉపయోగిస్తుంది.
- Structured Filters: "Siemens motors under €2000" వంటి క్వెరీని JSONగా మార్చడానికి నేను LLMని ఉపయోగిస్తాను. ఇది బ్రాండ్ మరియు ధర కోసం ఖచ్చితమైన ఫిల్టర్లతో SQL క్వెరీని రన్ చేయడానికి నాకు అనుమతిస్తుంది.
ఒకే SQL స్టేట్మెంట్ ఫజీ సెర్చ్ మరియు హార్డ్ ఫిల్టర్లు రెండింటినీ నిర్వహిస్తుంది. ఇది అన్నింటినీ సింక్లో ఉంచుతుంది.
గార్డ్రైల్స్ మంచి RAG ఎప్పుడు మౌనంగా ఉండాలో తెలిసి ఉండాలి. హాలూసినేషన్స్ (hallucinations) నివారించడానికి నేను రెండు పొరలను ఉపయోగిస్తాను:
- Similarity Threshold: ప్రతి మ్యాచ్కు ఒక స్కోరు ఉంటుంది. స్కోరు నిర్ణీత పరిమితి కంటే తక్కువగా ఉంటే, నేను ఫలితాలను తొలగిస్తాను. ఏ ఫలితాలు కూడా సరిపోకపోతే, సిస్టమ్ LLMని పిలవకుండానే "not found" అని చెబుతుంది. మోడల్ డేటాను చూడనప్పుడు అది హాలూసినేట్ చేయడం సాధ్యం కాదు.
- Strict System Prompt: అందించిన ఉత్పత్తుల నుండి మాత్రమే సమాధానం ఇవ్వమని నేను మోడల్కు చెబుతాను. ఉత్పత్తులు సంబంధం లేనివి అయితే, అది నిరాకరించాలి.
థ్రెషోల్డ్ తప్పుడు ప్రవర్తనను అసాధ్యం చేస్తుంది. ప్రాంప్ట్ కేవలం మంచి ప్రవర్తన కోసం అడుగుతుంది. రెండింటినీ ఉపయోగించండి
మొదటి నుండి RAGని నిర్మించడం: సేకరించడం, శుభ్రపరచడం, ఎంబెడ్ చేయడం, తిరిగి పొందడం
RAG (Retrieval-Augmented Generation) అనేది LLMల (Large Language Models) యొక్క ఖచ్చితత్వాన్ని మరియు విశ్వసనీయతను పెంచడానికి ఉపయోగించే ఒక శక్తివంతమైన పద్ధతి. ఇది మోడల్కు తెలియని బాహ్య సమాచారాన్ని (external information) అందించడం ద్వారా, మోడల్ తనంతట తానుగా సృష్టించే తప్పుడు సమాచారాన్ని (hallucinations) తగ్గించి, మరింత ఖచ్చితమైన సమాధానాలను ఇవ్వడానికి సహాయపడుతుంది.
ఈ వ్యాసంలో, మనం ఒక RAG సిస్టమ్ను మొదటి నుండి ఎలా నిర్మించాలో నాలుగు ముఖ్యమైన దశల ద్వారా తెలుసుకుందాం:
- సేకరించడం (Collect)
- శుభ్రపరచడం (Clean)
- ఎంబెడ్ చేయడం (Embed)
- తిరిగి పొందడం (Retrieve)
1. డేటాను సేకరించడం (Collect Data)
మొదటి దశ ఏమిటంటే, మీ RAG సిస్టమ్ దేని గురించి సమాధానం చెప్పాలో దానికి సంబంధించిన డేటాను సేకరించడం. ఈ డేటా వివిధ రూపాల్లో ఉండవచ్చు:
- వెబ్ పేజీలు (Web pages)
- PDF డాక్యుమెంట్లు
- టెక్స్ట్ ఫైళ్లు (.txt, .md)
- డేటాబేస్ రికార్డులు
ఉదాహరణకు, మీరు BeautifulSoup వంటి లైబ్రరీలను ఉపయోగించి వెబ్ స్క్రాపింగ్ (Web scraping) చేయవచ్చు లేదా ఇప్పటికే ఉన్న ఫైళ్లను లోడ్ చేయవచ్చు.
2. డేటాను శుభ్రపరచడం (Clean Data)
సేకరించిన డేటా ఎప్పుడూ ఉపయోగించడానికి సిద్ధంగా ఉండదు. అందులో అనవసరమైన HTML ట్యాగ్లు, స్పెషల్ క్యారెక్టర్లు, డూప్లికేట్ సమాచారం లేదా అసంబద్ధమైన వైట్స్పేస్ ఉండవచ్చు. డేటా నాణ్యత ఎంత బాగుంటే, RAG సిస్టమ్ అంత బాగా పనిచేస్తుంది.
శుభ్రపరచడంలో మనం చేసే పనులు:
- HTML ట్యాగ్లను మరియు అనవసరమైన స్క్రిప్ట్లను తొలగించడం.
- అదనపు ఖాళీలు (whitespace) మరియు కొత్త లైన్లను సరిచేయడం.
- టెక్స్ట్ను ఒకే ఫార్మాట్లోకి మార్చడం.
import re
def clean_text(text):
# HTML ట్యాగ్లను తొలగించడం
text = re.sub(r'<.*?>', '', text)
# అదనపు వైట్స్పేస్ను తొలగించడం
text = re.sub(r'\s+', ' ', text).strip()
return text
3. డేటాను ఎంబెడ్ చేయడం (Embed Data)
శుభ్రపరిచిన టెక్స్ట్ను కంప్యూటర్ అర్థం చేసుకునే విధంగా సంఖ్యా రూపంలోకి మార్చాలి. దీనినే 'ఎంబెడ్ చేయడం' అంటారు. ఈ దశలో రెండు కీలక ప్రక్రియలు ఉంటాయి:
చంకింగ్ (Chunking)
పెద్ద టెక్స్ట్ డాక్యుమెంట్లను చిన్న చిన్న ముక్కలుగా (chunks) విభజించాలి. ఒకేసారి పెద్ద సమాచారాన్ని ప్రాసెస్ చేయడం కష్టం కాబట్టి, చిన్న ముక్కలుగా విభజించడం వల్ల సెర్చ్ చేయడం సులభమవుతుంది.
వెక్టరైజేషన్ (Vectorization)
ఈ చంక్స్ను 'Embeddings' (సంఖ్యా వెక్టర్లు) గా మార్చాలి. దీని కోసం OpenAI లేదా Hugging Face వంటి మోడళ్లను ఉపయోగించవచ్చు. ఈ ఎంబెడ్డింగ్స్ను ఒక Vector Database (ఉదాహరణకు ChromaDB, Pinecone లేదా FAISS) లో భద్రపరుస్తాము.
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
# 1. చంకింగ్
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)
chunks = text_splitter.split_text(cleaned_text)
# 2. ఎంబెడ్డింగ్ మరియు స్టోరేజ్
embeddings = OpenAIEmbeddings()
vector_db = Chroma.from_texts(chunks, embeddings, persist_directory="./chroma_db")
4. డేటాను తిరిగి పొందడం (Retrieve Data)
చివరి దశలో, వినియోగదారు ఒక ప్రశ్న అడిగినప్పుడు, ఆ ప్రశ్నను కూడా ఎంబెడ్డింగ్గా మార్చి, మన Vector Databaseలో ఉన్న సమాచారంతో పోల్చి చూడాలి.
దీనిని Similarity Search అంటారు. ప్రశ్నకి అత్యంత దగ్గరగా ఉన్న సమాచారాన్ని (relevant chunks) వెలికితీసి, దానిని LLMకి పంపిస్తారు. LLM ఆ సమాచారాన్ని ఆధారంగా చేసుకుని ఖచ్చితమైన సమాధానాన్ని రూపొందిస్తుంది.
query = "RAG అంటే ఏమిటి?"
docs = vector_db.similarity_search(query)
# అత్యంత సంబంధిత సమాచారాన్ని పొందడం
context = "\n".join([doc.page_content for doc in docs])
print(context)
ముగింపు
మొదటి నుండి RAGని నిర్మించడం అనేది ఒక క్రమబద్ధమైన ప్రక్రియ. డేటా సేకరణ నుండి రిట్రీవల్ వరకు ప్రతి దశ కూడా సిస్టమ్ యొక్క పనితీరుపై ప్రభావం చూపుతుంది. ఈ ప్రాథమిక అంశాలను అర్థం చేసుకోవడం ద్వారా, మీరు మీ స్వంత తెలివైన AI అప్లికేషన్లను నిర్మించవచ్చు.