RAG(Retrieval-Augmented Generation)は、LLMに外部知識を与えて回答精度を向上させる手法です。社内ドキュメントやFAQをベクトルデータベースに格納し、質問に関連する情報を検索してからLLMに回答させます。
RAGの仕組み
RAGは大きく2つのフェーズで動作します。
- インデックス作成: ドキュメントをチャンクに分割→ベクトル化→ベクトルDBに格納
- 検索+生成: ユーザーの質問をベクトル化→類似チャンクを検索→検索結果+質問をLLMに渡して回答生成
環境準備
pip install langchain langchain-openai faiss-cpu tiktoken
ドキュメントの読み込みとチャンク分割
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.document_loaders import TextLoader
# ドキュメント読み込み
loader = TextLoader("company_faq.txt", encoding="utf-8")
documents = loader.load()
# チャンク分割(500文字ごと、100文字オーバーラップ)
splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=100,
separators=["nn", "n", "。", "、", " "]
)
chunks = splitter.split_documents(documents)
print(f"チャンク数: {len(chunks)}")
ベクトルDBの構築
from langchain_openai import OpenAIEmbeddings
from langchain_community.vectorstores import FAISS
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
# FAISSインデックスを作成
vectorstore = FAISS.from_documents(chunks, embeddings)
# ローカルに保存(永続化)
vectorstore.save_local("faiss_index")
# 読み込み
vectorstore = FAISS.load_local("faiss_index", embeddings, allow_dangerous_deserialization=True)
RAGチェーンの構築
from langchain_openai import ChatOpenAI
from langchain.chains import RetrievalQA
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
return_source_documents=True,
)
result = qa_chain.invoke({"query": "有給休暇の申請方法を教えてください"})
print(result["result"])
print("---参照ドキュメント---")
for doc in result["source_documents"]:
print(f" - {doc.page_content[:100]}...")
精度向上のコツ
- チャンクサイズ: 小さすぎると文脈が失われ、大きすぎるとノイズが増える。300-500文字が目安
- オーバーラップ: チャンク境界での情報欠落を防ぐ。チャンクサイズの20%程度
- 検索件数(k): 多すぎるとコンテキストウィンドウを圧迫。3-5件が推奨
- リランキング: 検索結果をLLMで再評価してから使うと精度が上がる
まとめ
RAGを使えば、LLMが学習していない最新情報や社内固有の知識に基づいた回答が可能になります。FAISSは無料で使えるベクトルDBとして優秀で、小〜中規模のドキュメントであれば十分な性能を発揮します。
コメントを残す