RAG(Retrieval-Augmented Generation)
RAGは、次の2つの構成要素を組み合わせる手法です。
- Retrieval: データストア(vector database、search engineなど)から関連情報を取得します。
- Generation: 取得した情報に基づき、大規模言語モデル(LLM)で回答を生成します。
手順:
- ユーザーが質問します。
- システムがデータストア内の関連テキスト箇所を検索します(retriever)。
- これらの箇所をLLMのpromptへ入れ、最終回答を生成します(generator)。
一般的なRAG手法
古典的RAG(Classic RAG)
- 説明: データストアから関連テキスト箇所を取得し、LLMのpromptへ入れて回答を生成します。
- 適用:
- 社内文書の質疑応答(FAQ、利用ガイド、技術文書)。
- 企業向けバーチャルアシスタント。
- カスタマーサポート向けチャットボット。
- 手法:
- 文書を小さな箇所(chunk)に分割します。
- 各箇所のembeddingを作成し、vector databaseへ保存します。
- 質問が来たら、質問をembeddingへ変換し、最も関連する箇所(top-k)を探します。
- これらの箇所をLLMのpromptへ入れて回答を生成します。
- ツール: Chroma、FAISS、Pinecone、LangChain、HuggingFace。
複数文書RAG(Multi-Document RAG)
- 説明: 複数の異なる文書から情報を取得し、統合します。
- 適用:
- 法務検索、診療記録の取りまとめ。
- 複数データソースからのレポート統合。
- 手法:
- 複数の異なる文書のembeddingを保存します(ソースラベルを付けてもよいです)。
- 複数文書から同時に関連箇所を取得します。
- 文書ソースごとに結果を統合またはグループ化できます。
- ツール: メタデータをサポートするVector DB(Chroma、Weaviate、Qdrant)、LangChain。
マルチモーダルRAG(Multi-modal RAG)
- 説明: テキスト、画像、音声など、複数種類のデータから情報を取得して組み合わせます。
- 適用:
- 医療アシスタント(X線画像と診療記録の組み合わせ)。
- 画像と説明による製品検索。
- 手法:
- 異なるモデルで複数種類のデータ(テキスト、画像、音声)のembeddingを作成します。
- マルチモーダルembeddingをvector DBへ保存します。
- クエリ時に、質問または入力データを適切なembeddingへ変換し、異なるデータ種別を取得します。
- 複数データ種別からの結果を組み合わせてLLMへ渡します。
- ツール: CLIP、BLIP、Weaviate、Milvus、LangChain。
Conversational RAG
- 説明: 会話履歴を保持し、会話全体の文脈に基づいて情報を取得します。
- 適用:
- スマートチャットボット、パーソナルアシスタント。
- 複数ターンのカスタマーサポート。
- 手法:
- 会話履歴(context window)を保持します。
- クエリ時に、新しい質問と会話履歴を組み合わせて適切な情報を取得します。
- contextと会話履歴をLLMのpromptへ入れます。
- ツール: LangChain Memory、ConversationBuffer、vector DB。
Hybrid RAG(複数retrieverの組み合わせ)
- 説明: 複数の取得手法(semantic search、keyword search、rule-basedなど)を組み合わせて精度を高めます。
- 適用:
- 大企業におけるデジタル検索。
- 専門的な質疑応答システム(医療、法務)。
- 手法:
- 複数の取得手法を並列に使います: semantic search(embedding)、keyword search(BM25)、rule-basedなど。
- 異なるretrieverからの結果を統合または選別します。
- 最も関連する箇所をLLMへ渡します。
- ツール: LangChain MultiRetriever、ElasticSearch、FAISS、BM25。
動的チャンキングRAG(Dynamic Chunking RAG)
- 説明: 意味または動的な構造に従って文書を分割し、LLMへ渡すcontextを最適化します。
- 適用:
- 長文、技術レポート、書籍の処理。
- 専門分野の質疑応答システム。
- 手法:
- 意味、構造、または動的な長さ(固定ではない)に基づいて文書を分割します。
- semantic chunking、sliding window、またはadaptive chunkingを使えます。
- LLMのcontext windowに合うよう、chunkの数と長さを最適化します。
- ツール: LangChain SemanticChunker、custom splitter、HuggingFace tokenizer。
RAG手法と他のチャットボット手法の比較
Rule-basedチャットボット(固定ルール)
- 原理: IF-THENルールの集合、あらかじめ定義されたシナリオ、または決定木に基づきます。
- 利点:
- 制御しやすく、応答を予測できます。
- 大規模データは不要で、単純なタスクへ導入しやすいです。
- 欠点:
- 柔軟性が低く、複雑な文脈を理解しません。
- 多くのトピックへうまく拡張できません。
- 応用:
- 単純なFAQ、選択メニュー、自動コールセンター。
Retrievalベースのチャットボット(純粋な検索)
- 原理: キーワードまたはsemantic searchにより、既存データストア(FAQ、文書)から最良の回答を探します。
- 利点:
- データストアに情報があれば正確に答えられます。
- 内容を制御しやすく、誤情報を生成しません。
- 欠点:
- 情報を統合したり言い換えたりしません。
- 新規で複雑な質問には答えられません。
- 応用:
- 社内検索システム、文書アシスタント。
Generativeチャットボット(純粋なテキスト生成)
- 原理: LLM(GPT、Llamaなど)を使い、promptに基づいて回答を生成します。外部データは取得しません。
- 利点:
- 柔軟で創造的な回答ができ、文脈理解が優れています。
- データにないトピックも含め、多くのテーマに答えられます。
- 欠点:
- 情報を「捏造」しやすいです(hallucination)。
- 内容を制御しにくく、誤情報を生成することがあります。
- 応用:
- 自然会話チャットボット、パーソナルアシスタント。
RAG(Retrieval-Augmented Generation)
- 原理: データストアから関連情報を取得する(retriever)ことと、その情報に基づいてLLM(generator)で回答を生成することを組み合わせます。
- 利点:
- 柔軟で創造的な回答でありながら、実データに基づきます。
- 情報の「捏造」リスクを下げ、信頼性を高めます。
- 拡張しやすく、LLMを再学習せずに新しいデータを更新できます。
- 欠点:
- 技術的に複雑です(vector DB、embedding、pipelineが必要です)。
- 性能は取得品質とchunkingに依存します。
- 応用:
- 文書Q&Aチャットボット、企業アシスタント、知識検索、レポート統合。
比較まとめ表
| 手法 | 柔軟性 | 信頼性 | 文脈理解 | 制御しやすさ | 拡張しやすさ | 主な応用 |
|---|---|---|---|---|---|---|
| Rule-based | 低い | 高い | 低い | 高い | 低い | FAQ、メニュー、コールセンター |
| Retrieval | 中程度 | 非常に高い | 低い | 高い | 中程度 | 検索、文書アシスタント |
| Generative | 非常に高い | 低い | 非常に高い | 低い | 高い | 自然会話、創造的利用 |
| RAG | 高い | 高い | 高い | 中程度 | 高い | 文書QA、企業アシスタント |
ベースコードの技術分析とプログラミングフロー
Pipeline
-
ステップ1. PDF文書のアップロード: file_uploaderを使用します
-
ステップ2: PDF文書の分割:
PyPDFLoaderを使ってPDF内容を読みます。 -
ステップ3: Semantic Chunking:
SemanticChunkerを使い、文書を意味のある箇所(chunk)へ分割し、取得効果を高めます。Semantic Chunking
これは、文字数、文数、語数だけに基づくのではなく、意味または語義に基づいてテキストを箇所(chunk)へ分割する手法です。目標は、各箇所(chunk)が完結した考えを含むことであり、RAGなどのタスク実行時にモデルが取得と文脈理解をより良く行えるようにすることです。
一般的なchunkingの種類:
-
Fixed-size Chunking
- テキストを固定長の箇所へ分割します(語数、文字数、文数による)。
- 単純で速いですが、意味が途中で切れやすいです。
-
Sliding Window Chunking
- 重なり合う箇所(overlap)へ分割し、箇所間の文脈を保ちやすくします。
- fixed-sizeより効果的ですが、意味の面ではまだ最適ではありません。
-
Semantic Chunking
- 意味、文法構造、または自然な区切り(例: 段落、見出し、主題文)に基づいて分割します。
- 言語モデル、文法解析、またはembeddingを使って区切り点を決められます。
- 各箇所の完結した意味を保てるため、RAGや高度なNLP応用に適しています。
-
-
ステップ4: Embeddings:
embeddingモデルを使い、テキスト箇所を数値ベクトル(embedding)へ変換します。 -
ステップ5: Vector Databaseへ保存: **Chroma(Vector database)**でembeddingを保存し、関連箇所を高速に取得します。
-
ステップ6: Retriever: 質問に最も関連するテキスト箇所を取得します。
-
ステップ7: Prompt Template: LangChain Hubのサンプルpromptを使い、contextと質問を組み合わせます。
-
ステップ8: LLMを使って回答を生成: 取得したcontextに基づき、
LLMモデルで回答を生成します。 -
ステップ9: StreamlitでUIを構築し、LLMの回答を表示: ユーザーがファイルをアップロードし、質問し、回答を受け取れる簡単なWebインターフェースを構築します。
一般的なvector databaseの種類
- Chroma
- オープンソースで、Pythonとの統合が容易、localとcloudをサポートします。
- 小規模プロジェクト、デモ、研究に適しています。
- Pinecone
- クラウドサービスで、高性能、拡張性が高く、管理しやすいです。
- 実プロダクト、大規模データ、多数ユーザーに適しています。
- Weaviate
- オープンソースで、cloud対応、多くのデータ種別(テキスト、画像、グラフ)を統合できます。
- 拡張可能で、多くのAI機能をサポートします。
- Qdrant
- オープンソースで、高性能、cloud対応、強力なREST APIを持ちます。
- 意味検索とAI応用に最適化されています。
- FAISS
- FacebookのC++/Pythonライブラリで、非常に高性能、主にlocal利用です。
- 他のvector DBのようなデータ管理機能はありません。
- Milvus
- オープンソースで、高性能、cloud対応、大規模データを管理できます。
- 大規模AIシステムに適しています。
| VDB名 | オープンソース | Cloud | 性能 | データ管理 | 使いやすさ | 適する用途 |
|---|---|---|---|---|---|---|
| Chroma | あり | あり | 中程度 | 基本 | 非常に容易 | デモ、小規模 |
| Pinecone | なし | あり | 高い | 充実 | 容易 | プロダクト |
| Weaviate | あり | あり | 高い | 充実 | 容易 | プロダクト |
| Qdrant | あり | あり | 高い | 充実 | 容易 | プロダクト |
| FAISS | あり | なし | 非常に高い | なし | 中程度 | 研究、local |
| Milvus | あり | あり | 非常に高い | 充実 | 中程度 | 大規模 |
サンプルprompt
サンプルprompt(prompt template)は、動的な内容(例: context、質問、データなど)を挿入するための変数(placeholder)を含む、あらかじめ構造化されたテキストです。サンプルpromptにより、大規模言語モデル(LLM)への入力指示を一貫して作りやすくなり、生成結果の品質と安定性が高まります。
サンプルpromptの例:
以下の情報に基づいて質問に答えてください:
{context}
質問: {question}
回答:
LangChainからのprompt
LangChain Hubは、コミュニティが共有するサンプルprompt、chain、agent templateのリポジトリであり、多くの目的(QA、要約、分類など)向けに最適化されています。LangChainのコードから直接ダウンロードして使えます。
LangChain Hubは多くの種類のサンプルpromptを提供しており、一般的なものには次があります。
- Question Answering(QA)Prompt: contextまたは文書に基づいて質問に答えます。
- Summarization Prompt: テキストを要約します。
- Classification Prompt: テキスト、意図、感情などを分類します。
- Translation Prompt: 言語を翻訳します。
- Chat/Conversation Prompt: 対話、チャットボットを作成します。
- Extraction Prompt: 情報を抽出します(entity、key-valueなど)。
- Rewriting/Paraphrasing Prompt: テキストを書き直し、言い換えます。
- Custom Prompt: 特別な目的のためにコミュニティが作成したpromptです。
注意: LangChain Hub上のpromptの数と種類は、コミュニティにより継続的に更新・拡張されています。
サンプルpromptでよく使う形式
1. 変数(placeholder)付きテンプレート形式のprompt
以下の情報に基づいて質問に答えてください:
{context}
質問: {question}
回答:
• {context}と{question}は、実行時に実際のデータへ置き換えられる変数です。
2. JSONまたはYAML形式のprompt(より複雑なシステム向け)
system: |
あなたは賢いAIアシスタントです。
user: |
次の情報に基づいて、質問に答えてください:
{context}
質問: {question}
assistant: |
回答:
3. Python f-string形式のprompt
prompt = f"""
次の情報に基づいて答えてください:
{context}
質問: {question}
回答:
"""
4. LangChain PromptTemplate形式のprompt
from langchain.prompts import PromptTemplate
template = """
次の情報に基づいて、質問に答えてください:
{context}
質問: {question}
回答:
"""
prompt = PromptTemplate(template=template, input_variables=["context", "question"])
5. チャット形式のprompt(multi-turn)
messages = [
{"role": "system", "content": "あなたはAIアシスタントです。"},
{"role": "user", "content": "次の情報に基づいて答えてください: {context}"},
{"role": "user", "content": "質問: {question}"}
]
よく使われ、ベトナム語をよくサポートするLLMモデル
- BKAI-ViLM
- 作者: BKAI(BKAV人工知能研究所)
- 特徴:
- ベトナム語向けに深く学習されています。
- encoder版(bi-encoder、cross-encoder)とdecoderがあります。
- ベトナム語の質疑応答、分類、semantic searchで高い効果があります。
- PhoGPT
- 作者: VinAIResearch
- 特徴:
- 大規模なベトナム語データで学習された汎用LLMです。
- 対話、要約、翻訳、質疑応答をよくサポートします。
- VietAI/vietnamese-llama
- 作者: VietAI
- 特徴:
- Llamaからベトナム語向けにfine-tuneされています。
- 一般タスク、対話、質疑応答をよくサポートします。
- VinAI PhoBERT / ViT5
- 作者: VinAIResearch
- 特徴:
- PhoBERT: ベトナム語向けの強力なencoderモデル(embedding、分類に適しています)。
- ViT5: テキスト生成、要約、翻訳向けのencoder-decoderモデルです。
- Mistral、Llama-2、GPT-3.5/4(多言語で、一定程度ベトナム語をサポート)
- 特徴:
- これらのモデルはベトナム語を含む多くの言語をサポートしますが、品質はベトナム語特化モデルには及びません。
- 多言語が必要、または迅速な統合が必要な場合に適しています。
ベースコードの長所/短所
長所
- 拡張しやすい: embeddingモデル、LLM、またはvector DBを容易に変更できます。
- ベトナム語サポート: ベトナム語embeddingと強力なLLMを使います。
- 賢い分割: Semantic chunkingにより取得品質が上がります。
- 親しみやすいUI: Streamlitによりデモが速いです。
短所
- 性能: 個人のCPU/GPU上で動くため、大きな文書や多数ユーザーの処理は遅くなります。
- バージョン管理: パッケージ間の依存関係エラーが起きやすいです(すでに遭遇されたとおりです)。
- セキュリティ: アクセス制御がなく、誰でも文書をアップロードできます。
- スケーラビリティ: productionや大規模データ量には適していません。
- エラー処理: エラー制御や詳細なloggingがまだ多くありません。
ベースコードのアップグレード提案
- クラウドサービスの利用: vector DB(Pinecone、Weaviate、Qdrant)とLLM(OpenAI、Azureなど)をcloudへデプロイし、性能と拡張性を高めます。
- 動的chunking: adaptive chunkingまたはsliding windowを適用してcontextを最適化します。
- Caching & batching: embedding、取得、回答生成の結果をcacheし、latencyを下げます。
- パッケージバージョン管理:
requirements.txtファイルまたはconda envでversionを固定し、dependencyエラーを避けます。 - セキュリティ: ユーザー認証を追加し、upload/downloadを制御します。
- 複数文書の処理: 複数ファイルのupload、分類、複数文書検索をサポートします。
- promptの最適化: 質問や文書の種類ごとにpromptをカスタマイズします。
- Logging & monitoring: loggingを追加し、性能とエラーを監視します。
まとめ
現在のベースコードは、デモ、研究、または小規模応用に適しています。実運用へ展開するには、microserviceアーキテクチャへ移行し、cloudを使い、chunkingを最適化し、セキュリティとバージョン管理をより厳密にすべきです。

執筆 Huỳnh Phước Nguyên
AIエンジニア、BK Hightech
