Loading
Loading
RAG (Retrieval-Augmented Generation) solves the hallucination problem in LLMs by connecting the model to real, up-to-date knowledge sources.
Without RAG: LLMs have a knowledge cutoff, don't know your documents, and can hallucinate confidently.
With RAG:
Question + [Retrieved relevant chunks] โ LLM โ Fact-grounded answer
Indexing (once): Documents โ Chunking โ Embedding โ Vector DB
Retrieval + Generation (per query): Question โ Embedding โ Vector Search โ Top Chunks โ LLM โ Answer
| Metric | Meaning | |--------|---------| | Faithfulness | Is the answer grounded in the retrieved context? | | Answer Relevance | Does the answer address the question? | | Context Recall | Did retrieval fetch the right information? |
Answer the question based ONLY on the provided context.
If the context doesn't contain the answer, say "I don't know."
Context: {context}
Question: {question}
import anthropic
import chromadb
from sentence_transformers import SentenceTransformer
from pathlib import Path
print("=" * 60)
print("RAG System: ูุธุงู
Q&A ุนูู ุงูู
ุณุชูุฏุงุช")
print("=" * 60)
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# ุงูุฅุนุฏุงุฏ
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
claude_client = anthropic.Anthropic()
embed_model = SentenceTransformer("all-MiniLM-L6-v2")
chroma_client = chromadb.Client()
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# 1. Indexing โ ุจูุงุก ูุงุนุฏุฉ ุงูู
ุนุฑูุฉ
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def chunk_text(text: str, chunk_size: int = 300, overlap: int = 50) -> list[str]:
"""ุชูุณูู
ุงููุต ุฅูู chunks ู
ุชุฏุงุฎูุฉ"""
chunks, start = [], 0
while start < len(text):
end = min(start + chunk_size, len(text))
chunk = text[start:end].strip()
if len(chunk) > 50:
chunks.append(chunk)
start += chunk_size - overlap
return chunks
# ู
ุณุชูุฏุงุช ุชุฌุฑูุจูุฉ (ูู ุงููุงูุน: PDF, Word, Web pages)
documents = {
"ai_basics.txt": """
ุงูุฐูุงุก ุงูุงุตุทูุงุนู ูู ู
ุฌุงู ูู ุนููู
ุงูุญุงุณูุจ ููุฏู ุฅูู ู
ุญุงูุงุฉ ุงูุฐูุงุก ุงูุจุดุฑู.
ูุดู
ู ุชุนูู
ุงูุขูุฉ ูุงูุชุนูู
ุงูุนู
ูู ูู
ุนุงูุฌุฉ ุงููุบุฉ ุงูุทุจูุนูุฉ.
Claude ูู ูู
ูุฐุฌ ูุบูู ู
ู Anthropic ูุชู
ูุฒ ุจุงูุฃู
ุงู ูุงูุฏูุฉ.
GPT-4 ู
ู OpenAI ูู ุฃุญุฏ ุฃููู ุงููู
ุงุฐุฌ ูู ุงูุณูู ุญุงููุงู.
ูู
ูู ููุฐูุงุก ุงูุงุตุทูุงุนู ุงูุญุฏูุซ ูุชุงุจุฉ ุงูููุฏ ูุชุญููู ุงูุจูุงูุงุช ูุชุฑุฌู
ุฉ ุงููุตูุต.
""",
"programming.txt": """
Python ูู ูุบุฉ ุจุฑู
ุฌุฉ ุนุงููุฉ ุงูู
ุณุชูู ุชุชู
ูุฒ ุจุณูููุฉ ุงููุฑุงุกุฉ.
ุชูุณุชุฎุฏู
Python ุนูู ูุทุงู ูุงุณุน ูู ุชุนูู
ุงูุขูุฉ ูุงูุฐูุงุก ุงูุงุตุทูุงุนู.
ู
ูุชุจุฉ NumPy ุชุชูุญ ุงูุนู
ููุงุช ุงูุฑูุงุถูุฉ ุนูู ุงูู
ุตูููุงุช ุจููุงุกุฉ ุนุงููุฉ.
Pandas ุชููุฑ ุฃุฏูุงุช ูููุฉ ูุชุญููู ุงูุจูุงูุงุช ุงูุฌุฏูููุฉ.
Scikit-learn ูู ุงูู
ูุชุจุฉ ุงูุฃูุซุฑ ุงุณุชุฎุฏุงู
ุงู ูุชุนูู
ุงูุขูุฉ ุงูููุงุณููู.
""",
"rag_info.txt": """
RAG ุงุฎุชุตุงุฑ Retrieval-Augmented Generation ุฃู ุงูุชูููุฏ ุงูู
ูุนุฒููุฒ ุจุงูุงุณุชุฑุฏุงุฏ.
ุชูููุฉ RAG ุชุญูู ู
ุดููุฉ Hallucination ูู ูู
ุงุฐุฌ ุงููุบุฉ ุงููุจูุฑุฉ.
ุชุนู
ู RAG ุจู
ุฑุญูุชูู: ุงูุฃููู Indexing ูุงูุซุงููุฉ Retrieval ู
ุน Generation.
ูู ู
ุฑุญูุฉ Indexing ูุชู
ุชุญููู ุงูู
ุณุชูุฏุงุช ุฅูู embeddings ูุชุฎุฒูููุง ูู vector database.
ูู ู
ุฑุญูุฉ ุงูุงุณุชุฎุฏุงู
ูุชู
ุชุญููู ุงูุณุคุงู ูู embedding ูุงูุจุญุซ ุนู ุฃูุฑุจ ุงูู
ุณุชูุฏุงุช.
"""
}
# ุจูุงุก ุงูู collection
collection = chroma_client.create_collection("knowledge_base")
all_chunks, all_ids, all_metas = [], [], []
for doc_name, doc_text in documents.items():
chunks = chunk_text(doc_text)
for i, chunk in enumerate(chunks):
all_chunks.append(chunk)
all_ids.append(f"{doc_name}_{i}")
all_metas.append({"source": doc_name, "chunk_idx": i})
# ุชูููุฏ embeddings ูุฅุถุงูุฉ ููู collection
embeddings = embed_model.encode(all_chunks).tolist()
collection.add(
ids=all_ids,
documents=all_chunks,
embeddings=embeddings,
metadatas=all_metas
)
print(f"โ
ุชู
ุฅูุดุงุก ูุงุนุฏุฉ ุงูู
ุนุฑูุฉ: {len(all_chunks)} chunk ู
ู {len(documents)} ู
ุณุชูุฏ")
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# 2. RAG Pipeline โ ุงูุงุณุชุนูุงู
ูุงูุฅุฌุงุจุฉ
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
def rag_query(question: str, top_k: int = 3, verbose: bool = True) -> str:
"""ูุธุงู
RAG ูุงู
ู: ุจุญุซ + ุชูููุฏ"""
# ุงูุจุญุซ ุนู ุฃูุฑุจ chunks
q_emb = embed_model.encode([question]).tolist()
results = collection.query(
query_embeddings=q_emb,
n_results=top_k
)
# ุชุฌู
ูุน ุงูุณูุงู
chunks = results["documents"][0]
sources = [m["source"] for m in results["metadatas"][0]]
context = "\n\n---\n\n".join(chunks)
if verbose:
print(f"\n{'='*50}")
print(f"ุงูุณุคุงู: {question}")
print(f"\nุงูู Chunks ุงูู
ูุณุชุฑุฌูุนุฉ ({top_k}):")
for chunk, src in zip(chunks, sources):
print(f" [{src}] {chunk[:80].strip()}...")
# ุจูุงุก ุงูู Prompt
prompt = f"""ุฃุฌุจ ุนูู ุงูุณุคุงู ุงูุชุงูู ุจูุงุกู ุนูู ุงูุณูุงู ุงูู
ูุฏููู
ููุท.
ุฅุฐุง ูู
ููู ุงูุณูุงู ูุญุชูู ุนูู ุงูู
ุนููู
ุงุช ุงููุงููุฉุ ูู ุฐูู ุจูุถูุญ.
ุงูุณูุงู:
{context}
ุงูุณุคุงู: {question}
ุฃุฌุจ ุจุฅูุฌุงุฒ ูุฏูุฉ ุจุงููุบุฉ ุงูุนุฑุจูุฉ."""
# ุงุณุชุฏุนุงุก Claude
message = claude_client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=400,
messages=[{"role": "user", "content": prompt}]
)
answer = message.content[0].text
if verbose:
print(f"\nุงูุฅุฌุงุจุฉ:")
print(answer)
return answer
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
# 3. ุชุฌุฑุจุฉ ุงูู RAG
# โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
questions = [
"ู
ุง ูู Claude ูู
ุง ู
ู
ูุฒุงุชูุ",
"ู
ุง ุงููุฑู ุจูู NumPy ูPandasุ",
"ููู ุชุนู
ู ุชูููุฉ RAGุ",
"ู
ุง ูู ุนุงุตู
ุฉ ูุฑูุณุงุ", # ุณุคุงู ุฎุงุฑุฌ ูุทุงู ุงูู
ุนุฑูุฉ
]
for q in questions:
rag_query(q, top_k=3, verbose=True)