RAG architektura od nuly
RAG (Retrieval-Augmented Generation) architektura revolucionizuje způsob, jak velké jazykové modely pracují s externími daty. Tento průvodce vás provede od základních konceptů až po praktickou implementaci vlastního RAG systému.
Základy RAG architektury
RAG (Retrieval-Augmented Generation) představuje revoluční přístup k práci s velkými jazykovými modely, který kombinuje sílu generování textu s přesností informačního vyhledávání. Místo spoléhání pouze na parametrickou znalost modelu RAG dynamicky obohacuje kontext o relevantní informace z externí databáze.
Architektura RAG řeší zásadní problém současných LLM - omezenou a často zastaralou znalostní bázi. Zatímco standardní model může poskytnout pouze obecné odpovědi založené na trénovacích datech, RAG dokáže pracovat s aktuálními a specifickými informacemi z firemních dokumentů, databází nebo webového obsahu.
Komponenty RAG systému
Vector Database
Srdcem každého RAG systému je vector database, která ukládá dokumenty ve formě vektorových reprezentací (embeddings). Tyto vektory zachycují sémantický význam textu v multidimenzionálním prostoru, což umožňuje rychlé vyhledávání podobného obsahu.
import chromadb
from sentence_transformers import SentenceTransformer
# Inicializace vector databáze
client = chromadb.Client()
collection = client.create_collection("documents")
# Model pro vytváření embeddings
encoder = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
def add_document(text, doc_id):
embedding = encoder.encode([text])
collection.add(
embeddings=embedding.tolist(),
documents=[text],
ids=[doc_id]
)
Embedding Model
Embedding model transformuje textové dokumenty i uživatelské dotazy do vektorové podoby. Pro český obsah doporučuji modely jako paraphrase-multilingual-MiniLM-L12-v2 nebo sentence-transformers/LaBSE, které dobře zvládají vícejazyčný obsah.
Implementace základního RAG workflow
Ingestion pipeline
První krok spočívá v načtení a zpracování dokumentů. Důležité je rozdělit dlouhé texty na menší chunky, které zachovají sémantickou souvislost.
from langchain.text_splitter import RecursiveCharacterTextSplitter
def process_documents(documents):
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", " ", ""]
)
chunks = []
for doc in documents:
text_chunks = splitter.split_text(doc.content)
for i, chunk in enumerate(text_chunks):
chunks.append({
'text': chunk,
'doc_id': f"{doc.id}_{i}",
'metadata': doc.metadata
})
return chunks
def ingest_documents(chunks):
for chunk in chunks:
add_document(chunk['text'], chunk['doc_id'])
Retrieval mechanismus
Retrieval fáze vyhledává nejrelevantnější dokumenty na základě sémantické podobnosti s uživatelským dotazem. Klíčové je správné nastavení parametrů jako počet výsledků a threshold podobnosti.
def retrieve_documents(query, k=5):
# Vytvoření embedding pro dotaz
query_embedding = encoder.encode([query])
# Vyhledání podobných dokumentů
results = collection.query(
query_embeddings=query_embedding.tolist(),
n_results=k
)
return [
{'text': doc, 'score': score}
for doc, score in zip(results['documents'][0], results['distances'][0])
if score < 0.8 # threshold pro relevanci
]
Generation s kontextem
Finální krok kombinuje vyhledané dokumenty s původním dotazem do promptu pro LLM. Správně strukturovaný prompt je klíčový pro kvalitu odpovědi.
import openai
def generate_answer(query, retrieved_docs):
context = "\n\n".join([doc['text'] for doc in retrieved_docs])
prompt = f"""
Odpověz na následující otázku na základě poskytnutého kontextu.
Pokud odpověď v kontextu nenajdeš, řekni to přímo.
Kontext:
{context}
Otázka: {query}
Odpověď:
"""
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.1
)
return response.choices[0].message.content
Pokročilé techniky a optimalizace
Hybrid search
Kombinace dense (vector) a sparse (keyword) vyhledávání často přináší lepší výsledky než každá metoda samostatně. Sparse vyhledávání excelize při přesných termínech, dense při sémantické podobnosti.
from rank_bm25 import BM25Okapi
class HybridRetriever:
def __init__(self):
self.bm25 = None
self.documents = []
def index_documents(self, docs):
self.documents = docs
tokenized_docs = [doc.split() for doc in docs]
self.bm25 = BM25Okapi(tokenized_docs)
def hybrid_search(self, query, k=5, alpha=0.7):
# Vector search
vector_results = retrieve_documents(query, k)
# BM25 search
bm25_scores = self.bm25.get_scores(query.split())
# Kombinace skórů
final_scores = {}
for i, doc in enumerate(self.documents):
vector_score = next((r['score'] for r in vector_results
if r['text'] == doc), 1.0)
bm25_score = bm25_scores[i]
final_scores[doc] = alpha * (1 - vector_score) + (1 - alpha) * bm25_score
return sorted(final_scores.items(), key=lambda x: x[1], reverse=True)[:k]
Reranking
Po initial retrieval můžete použít specializovaný reranking model pro lepší seřazení výsledků podle relevance k dotazu.
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
def rerank_documents(query, documents, top_k=3):
pairs = [(query, doc['text']) for doc in documents]
scores = reranker.predict(pairs)
# Seřazení podle skóre
ranked_docs = sorted(
zip(documents, scores),
key=lambda x: x[1],
reverse=True
)
return [doc for doc, score in ranked_docs[:top_k]]
Monitoring a evaluace
RAG systémy vyžadují kontinuální monitoring kvality. Klíčové metriky zahrnují retrieval precision, context relevance a answer faithfulness.
def evaluate_rag_performance(test_queries):
metrics = {
'retrieval_precision': 0,
'answer_relevance': 0,
'response_time': 0
}
for query_data in test_queries:
start_time = time.time()
# Retrieval
retrieved = retrieve_documents(query_data['query'])
# Generation
answer = generate_answer(query_data['query'], retrieved)
end_time = time.time()
# Výpočet metrik
metrics['response_time'] += end_time - start_time
# Další evaluační logika...
return metrics
Shrnutí
RAG architektura představuje praktický způsob, jak rozšířit možnosti LLM o aktuální a specifické znalosti. Úspěšná implementace vyžaduje pečlivou volbu embedding modelu, správnou segmentaci dokumentů a optimalizaci retrieval mechanismů. S pokročilými technikami jako hybrid search a reranking můžete dosáhnout produkční kvality systému, který spolehlivě odpovídá na dotazy z vaší znalostní báze. Klíčem k úspěchu je iterativní přístup s kontinuálním monitoringem a vylepšováním na základě reálného použití.