Build Retrieval-Augmented Generation (RAG) systems for LLM applications using vector databases and semantic search. Useful for knowledge-grounded AI, building document Q&A systems, or integrating LLMs with external knowledge bases.
English | 日本語
外部知識ソースを使用して正確で根拠のある応答を提供するLLMアプリケーションを構築するために、Retrieval-Augmented Generation(RAG)をマスターします。
目的: ドキュメント埋め込みを効率的に保存および検索
オプション:
目的: テキストを類似性検索のための数値ベクトルに変換
モデル:
アプローチ:
目的: 結果を並べ替えて検索品質を向上
方法:
from langchain.document_loaders import DirectoryLoader
from langchain.text_splitters import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
from langchain.llms import OpenAI
# 1. ドキュメントを読み込み
loader = DirectoryLoader('./docs', glob="**/*.txt")
documents = loader.load()
# 2. チャンクに分割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len
)
chunks = text_splitter.split_documents(documents)
# 3. 埋め込みとベクトルストアを作成
embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(chunks, embeddings)
# 4. 検索チェーンを作成
qa_chain = RetrievalQA.from_chain_type(
llm=OpenAI(),
chain_type="stuff",
retriever=vectorstore.as_retriever(search_kwargs={"k": 4}),
return_source_documents=True
)
# 5. クエリ
result = qa_chain({"query": "What are the main features?"})
print(result['result'])
print(result['source_documents'])
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# スパースリトリーバー(BM25)
bm25_retriever = BM25Retriever.from_documents(chunks)
bm25_retriever.k = 5
# デンスリトリーバー(埋め込み)
embedding_retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
# 重みで結合
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, embedding_retriever],
weights=[0.3, 0.7]
)
from langchain.retrievers.multi_query import MultiQueryRetriever
# 複数のクエリ視点を生成
retriever = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(),
llm=OpenAI()
)
# 単一クエリ → 複数のバリエーション → 結合された結果
results = retriever.get_relevant_documents("What is the main topic?")
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor
compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vectorstore.as_retriever()
)
# ドキュメントの関連部分のみを返す
compressed_docs = compression_retriever.get_relevant_documents("query")
from langchain.retrievers import ParentDocumentRetriever
from langchain.storage import InMemoryStore
# 親ドキュメント用ストア
store = InMemoryStore()
# 検索用小チャンク、コンテキスト用大チャンク
child_splitter = RecursiveCharacterTextSplitter(chunk_size=400)
parent_splitter = RecursiveCharacterTextSplitter(chunk_size=2000)
retriever = ParentDocumentRetriever(
vectorstore=vectorstore,
docstore=store,
child_splitter=child_splitter,
parent_splitter=parent_splitter
)
from langchain.text_splitters import RecursiveCharacterTextSplitter
splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
separators=["\n\n", "\n", " ", ""] # これらを順番に試す
)
from langchain.text_splitters import TokenTextSplitter
splitter = TokenTextSplitter(
chunk_size=512,
chunk_overlap=50
)
from langchain.text_splitters import SemanticChunker
splitter = SemanticChunker(
embeddings=OpenAIEmbeddings(),
breakpoint_threshold_type="percentile"
)
from langchain.text_splitters import MarkdownHeaderTextSplitter
headers_to_split_on = [
("#", "Header 1"),
("##", "Header 2"),
("###", "Header 3"),
]
splitter = MarkdownHeaderTextSplitter(headers_to_split_on=headers_to_split_on)
import pinecone
from langchain.vectorstores import Pinecone
pinecone.init(api_key="your-api-key", environment="us-west1-gcp")
index = pinecone.Index("your-index-name")
vectorstore = Pinecone(index, embeddings.embed_query, "text")
import weaviate
from langchain.vectorstores import Weaviate
client = weaviate.Client("http://localhost:8080")
vectorstore = Weaviate(client, "Document", "content", embeddings)
from langchain.vectorstores import Chroma
vectorstore = Chroma(
collection_name="my_collection",
embedding_function=embeddings,
persist_directory="./chroma_db"
)
# インデックス作成時にメタデータを追加
chunks_with_metadata = []
for i, chunk in enumerate(chunks):
chunk.metadata = {
"source": chunk.metadata.get("source"),
"page": i,
"category": determine_category(chunk.page_content)
}
chunks_with_metadata.append(chunk)
# 検索時にフィルタリング
results = vectorstore.similarity_search(
"query",
filter={"category": "technical"},
k=5
)
# 関連性と多様性のバランスを取る
results = vectorstore.max_marginal_relevance_search(
"query",
k=5,
fetch_k=20, # 20を取得し、トップ5の多様なものを返す
lambda_mult=0.5 # 0=最大多様性、1=最大関連性
)
from sentence_transformers import CrossEncoder
reranker = CrossEncoder('cross-encoder/ms-marco-MiniLM-L-6-v2')
# 初期結果を取得
candidates = vectorstore.similarity_search("query", k=20)
# 再ランキング
pairs = [[query, doc.page_content] for doc in candidates]
scores = reranker.predict(pairs)
# スコアでソートし、トップkを取る
reranked = sorted(zip(candidates, scores), key=lambda x: x[1], reverse=True)[:5]
prompt_template = """Use the following context to answer the question. If you cannot answer based on the context, say "I don't have enough information."
Context:
{context}
Question: {question}
Answer:"""
prompt_template = """Answer the question based on the context below. Include citations using [1], [2], etc.
Context:
{context}
Question: {question}
Answer (with citations):"""
prompt_template = """Answer the question using the context. Provide a confidence score (0-100%) for your answer.
Context:
{context}
Question: {question}
Answer:
Confidence:"""
def evaluate_rag_system(qa_chain, test_cases):
metrics = {
'accuracy': [],
'retrieval_quality': [],
'groundedness': []
}
for test in test_cases:
result = qa_chain({"query": test['question']})
# 回答が期待値と一致するかチェック
accuracy = calculate_accuracy(result['result'], test['expected'])
metrics['accuracy'].append(accuracy)
# 関連ドキュメントが検索されたかチェック
retrieval_quality = evaluate_retrieved_docs(
result['source_documents'],
test['relevant_docs']
)
metrics['retrieval_quality'].append(retrieval_quality)
# 回答がコンテキストに基づいているかチェック
groundedness = check_groundedness(
result['result'],
result['source_documents']
)
metrics['groundedness'].append(groundedness)
return {k: sum(v)/len(v) for k, v in metrics.items()}
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer