はじめに
こんにちは。ITフィールドセールスをしている長井洸太です。
最近、企業向けのAI導入案件で「RAG」という言葉をよく耳にします。
ChatGPTは知っているけどRAGは知らない、という方も多いと思うので、仕組みの解説から実際の構築方法、精度改善の手法まで まとめました。
RAGとは何か
RAG(Retrieval-Augmented Generation) とは、AIが回答を生成するときに「外部のドキュメントやデータベース」を検索して参照する仕組みです。
通常のChatGPTとの違いはこうです。
| 通常のLLM | RAG | |
|---|---|---|
| 参照するデータ | 学習データのみ | 学習データ + 外部ドキュメント |
| 最新情報 | 使えない | 使える |
| 社内文書 | 使えない | 使える |
| ハルシネーション | 多い | 少ない |
社内マニュアル・契約書・議事録などを読ませてQ&Aができるので、企業の情報活用に非常に相性が良いです。
RAGの処理フロー
RAGは大きく「事前準備フェーズ」と「質問応答フェーズ」に分かれます。
事前準備(インデックス作成)
① ドキュメント投入
PDF / テキスト / Webページ
↓
② チャンク分割
文章を小さなブロックに切り分ける
↓
③ ベクトル化(Embedding)
テキストを数値ベクトルに変換
↓
④ ベクトルDBに保存
Chroma / FAISS / Pinecone など
質問応答(推論)
ユーザーの質問
↓
① 質問をベクトル化
↓
② ベクトルDBで類似検索(上位N件取得)
↓
③ Re-rank(関連度を再スコアリング)
↓
④ LLMに「文書 + 質問」を渡す
↓
回答生成
Difyで手軽にRAGを構築する
Dify はRAGアプリをGUIとAPIの両方で構築できるOSSプラットフォームです。コードを書かなくてもチャットボットUIが作れるため、検証フェーズに最適です。
ローカル起動(Docker)
git clone https://github.com/langgenius/dify.git
cd dify/docker
docker compose up -d
http://localhost にアクセスするとセットアップ画面が表示されます。
基本的な使い方
- ナレッジ からPDF/テキストをアップロード
- スタジオ でチャットボットを作成し、ナレッジを紐付ける
- APIキーを発行してPythonから呼び出す
import requests
url = "http://localhost/v1/chat-messages"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
payload = {
"inputs": {},
"query": "社内の有給申請の手順を教えてください",
"response_mode": "blocking",
"conversation_id": "",
"user": "user-001"
}
response = requests.post(url, headers=headers, json=payload)
print(response.json()["answer"])
RAG精度改善の3つのポイント
RAGを動かすだけなら簡単ですが、実用レベルの精度を出すには工夫が必要です。
1. チャンク戦略
ドキュメントをどう分割するかで精度が大きく変わります。
| 戦略 | 概要 | 向いているケース |
|---|---|---|
| Fixed Size | 固定文字数で分割 | シンプルな構造のドキュメント |
| Semantic | 意味の区切りで分割 | 自然文が多い文書 |
| Hierarchical | 大→小の階層構造で保持 | 章立てのある長文書 |
チャンクサイズの目安:512〜1024トークン。小さすぎると文脈が失われ、大きすぎるとノイズが増えます。
2. Retrieval改善
検索精度を上げるテクニックです。
- Hybrid Search:ベクトル検索 + キーワード検索(BM25)を組み合わせる
- HyDE(Hypothetical Document Embedding):質問から仮の回答を生成してから検索
- Multi-query:質問を複数のバリエーションに変換して検索
# LangChainでのMulti-query例
from langchain.retrievers.multi_query import MultiQueryRetriever
retriever = MultiQueryRetriever.from_llm(
retriever=vectorstore.as_retriever(),
llm=llm
)
3. Re-rank
ベクトル検索で取得した候補(例:上位20件)を、より精密なモデルで再スコアリングして上位5件に絞ります。
# Cohereのre-rankを使う例
import cohere
co = cohere.Client("YOUR_COHERE_API_KEY")
results = co.rerank(
query="有給申請の手順",
documents=retrieved_chunks, # ベクトル検索で取得したチャンク
top_n=5,
model="rerank-multilingual-v3.0"
)
LLMOps:品質をモニタリングする(Langfuse)
本番運用では「どの質問で精度が落ちているか」を可視化することが重要です。
Langfuse を使うと、以下が可視化できます。
- 各クエリのレイテンシ
- 使用トークン数・コスト
- 取得されたチャンクの内容
- LLMの入出力ログ
from langfuse import Langfuse
langfuse = Langfuse(
public_key="YOUR_PUBLIC_KEY",
secret_key="YOUR_SECRET_KEY"
)
trace = langfuse.trace(name="rag-query")
span = trace.span(name="retrieval", input={"query": user_query})
# ... 検索処理 ...
span.end(output={"chunks": retrieved_chunks})
まとめ
RAGの精度改善は「取得(Retrieval)」と「生成(Generation)」の両方に手を入れる必要があります。
| フェーズ | 手法 |
|---|---|
| 取得 | チャンク戦略、Hybrid Search、Re-rank |
| 生成 | プロンプト改善、Few-shot例示 |
| 運用 | Langfuseでモニタリング |
まずは Difyをローカルで立ち上げてPDFを投入する ところから始めると、全体の流れがつかみやすいです。
参考リンク
ITフィールドセールスの視点から、AI・自動化について発信しています。フォローや「いいね」していただけると励みになります。