LlamaIndex の使い方:ゼロから本番環境までの実践ガイド
もしあなたが検索拡張生成 (RAG) アプリを構築しようとして、「なぜ埋め込み、ベクターストア、プロンプトの配線はこんなに面倒なんだ?」と思ったことがあるなら、あなたは決して一人ではありません。LlamaIndex は、そのパイプラインを高速、健全、そして本番環境に対応できるようにするために存在します。この実践的でソリューション指向のガイドでは、LlamaIndex のエンドツーエンドの使い方(データ取り込み、インデックス作成、クエリ、評価、デプロイ)を説明します。これにより、グルーコードに迷うことなく、信頼性の高いものを出荷できます。
質問主導の構成で、段階的なステップ、実行可能なスニペット、そして実際のヒントを紹介します。社内ドキュメント用のチャットボットをプロトタイプ作成する場合でも、顧客向けのナレッジアシスタントをデプロイする場合でも、LlamaIndex の効果的な使い方を学ぶことで、何日も節約できます。
:LlamaIndex は、インデックス作成、検索、オーケストレーションツールを使用して、データを大規模言語モデルに接続するのに役立つフレームワークです。RAG、エージェント、構造化された出力に最適です。
LlamaIndex とは?そして、なぜそれを使うのか?
- LlamaIndex は、LLM アプリケーションのためのデータフレームワークです。以下のための構成要素を提供します。
- 取り込み (Ingestion):ファイル、ウェブページ、データベース、API をロードします。
- チャンク分割とインデックス作成 (Chunking & Indexing):生のコンテンツをクエリ可能な構造(ベクトル、キーワード、グラフインデックス)に変換します。
- 検索 (Retrieval):柔軟な戦略(BM25、ハイブリッド、リランキング)でコンテキストを検索します。
- クエリエンジンとエージェント (Query Engines & Agents):検索、ツール、プロンプトを組み合わせて、一貫した QA 体験を実現します。
- 評価とモニタリング (Evaluation & Monitoring):検索品質と回答の関連性を評価します。
- チャンク分割、埋め込み、検索を再発明することなく、堅牢な RAG スタックが必要な場合。
- 複数のデータソース(PDF + Notion + SQL)を組み合わせる必要がある場合。
- ハイブリッド検索、リランキング、または構造化された出力を試したい場合。
- LlamaIndex の使い方を学ぶ際の 中心となるメンタルモデル:
- データ → ノード → インデックス → リトリーバー → クエリエンジン → アプリ
クイックスタート:最小限の RAG ループ
これは、動作するプロトタイプへの最速の道です。ドキュメントをロードし、ベクトルインデックスを構築し、質問をします。
# 1) インストール
# pip install llama-index llama-index-embeddings-openai llama-index-llms-openai
import os
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
# 2) モデルと埋め込みの設定
os.environ["OPENAI_API_KEY"] = "YOUR_KEY" # または、サポートされている任意の LLM/埋め込みプロバイダーを使用
llm = OpenAI(model="gpt-4o-mini")
embed_model = OpenAIEmbedding(model="text-embedding-3-small")
# 3) ドキュメントのロード (例: ./data/*.pdf, .md, .txt)
docs = SimpleDirectoryReader("./data").load_data
# 4) インデックスの構築
index = VectorStoreIndex.from_documents(docs, embed_model=embed_model)
# 5) クエリエンジンの作成と質問
query_engine = index.as_query_engine(llm=llm)
response = query_engine.query("ドキュメントに記載されている主要なセキュリティ対策は何ですか?")
print(response)
それが本質です。ここから、実際のアプリケーションは、より良いチャンク分割、リランキング、構造化されたプロンプト、そして可観測性を追加します。
取り込み:独自のデータ (BYOD) を正しい方法で
実際のデータに LlamaIndex をどのように使用するかを決定する際には、ソースに一致し、構造を維持するローダーを選択してください。
- ファイル:
SimpleDirectoryReader、PDF/HTML/Markdown リーダー
- ウェブ:
BeautifulSoupWebReader、サイトマップリーダー
- SaaS:Notion, Confluence, Slack, Google Drive (コネクタ経由)
- データベース:SQL およびベクトル DB (Pinecone, Weaviate, Chroma, Elasticsearch)
- ヒント:メタデータ(タイトル、著者、URL、created_at)を正規化します。優れたメタデータは、後でリランキングとフィルタリングを強化します。
from llama_index.core import SimpleDirectoryReader
from llama_index.readers.web import SimpleWebPageReader
file_docs = SimpleDirectoryReader("./policies").load_data
web_docs = SimpleWebPageReader(html_to_text=True).load_data
all_docs = file_docs + web_docs
チャンク分割とノードパーサー:Garbage In, Garbage Out
効果的に LlamaIndex を使う方法を学ぶ上で、チャンク分割を正しく行うことは最も重要なステップの一つです。
- なぜチャンク分割が重要なのか:大きすぎると → トークンが膨張し、無関係な検索結果になる。小さすぎると → コンテキストが断片化する。
- デフォルト:多くの場合、妥当ですが、コンテンツタイプに合わせて調整してください。
- 技術ドキュメント:512〜1024 トークンのチャンクで、10〜20%のオーバーラップ。
- FAQ:Q/A ペアをそのまま維持するために、より小さなチャンク (256〜512)。
- 法律/ポリシー:定義と条項を維持するために、より大きなチャンク (1024〜1536)。
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core import Document
parser = SentenceSplitter(chunk_size=800, chunk_overlap=100)
nodes = []
for d in all_docs:
nodes.extend(parser.get_nodes_from_documents([Document(text=d.text, metadata=d.metadata)]))
インデックス戦略:ベクトル、キーワード、またはハイブリッド?
適切なインデックスを選択することが重要です。良いニュースは、LlamaIndex ではそれらを組み合わせることができることです。
- ベクトルインデックス:セマンティック検索に最適。「X を説明する」またはあいまいなクエリに最適。
- キーワード (BM25):正確な用語、ID、エラーコード、ログに強力。
- ハイブリッド:両方を組み合わせる。LLM またはクロスエンコーダーで上位候補をリランクします。
from llama_index.core import VectorStoreIndex, SummaryIndex
from llama_index.core.retrievers import BM25Retriever
from llama_index.core.query_engine import RetrieverQueryEngine
# 事前に解析されたノードからのベクトルインデックス
v_index = VectorStoreIndex(nodes)
# BM25 キーワードリトリーバー
bm25_retriever = BM25Retriever.from_defaults(nodes=nodes, similarity_top_k=6)
# ハイブリッド:候補をマージし、リランクする
from llama_index.core.retrievers import RouterRetriever
from llama_index.retrievers.merge import MergerRetriever
v_retriever = v_index.as_retriever(similarity_top_k=6)
hybrid = MergerRetriever(retrievers=[v_retriever, bm25_retriever], top_k=8)
query_engine = RetrieverQueryEngine.from_args(retriever=hybrid)
リランキングとフィルター:過剰なコストをかけずに精度を向上させる
リランキングは、関連性に応じて検索されたチャンクを並べ替えることで、回答の品質を向上させます。
- リランクするタイミング:ユーザーがトピックから外れた引用や、長くて詰め込まれたコンテキストを報告する場合。
- クロスエンコーダー (バイエンコーダー埋め込み検索 → クロスエンコーダーリランク)
- LLM ベースのリランキング (よりコストがかかるが、ニュアンスのあるテキストに対してよりスマートな場合がある)
- メタデータフィルター (例:
source == 'handbook'、created_at > 2024-01-01)
from llama_index.postprocessor.flag_embedding_reranker import FlagEmbeddingReranker
from llama_index.core.query_engine import RetrieverQueryEngine
reranker = FlagEmbeddingReranker(top_n=5, model="BAAI/bge-reranker-base")
query_engine = v_index.as_query_engine(
similarity_top_k=12,
node_postprocessors=[reranker]
)
プロンプトとクエリエンジン:検索から回答へ
クエリエンジンは、検索と生成が出会う場所です。本番環境で LlamaIndex を使いこなすには、プロンプトと応答合成を慎重に設計してください。
- 小さなコンテキストの場合は、単純な「stuff」(連結)
- より長いコンテキストの場合は、ツリーまたはマップリデュース
from llama_index.core.response_synthesizers import get_response_synthesizer
from llama_index.core import ServiceContext
synth = get_response_synthesizer(response_mode="tree_summarize")
query_engine = v_index.as_query_engine(response_synthesizer=synth)
ans = query_engine.query("オンボーディングの手順を要約し、ソースを引用してください。")
print(ans)
- カスタムプロンプト:トーン、構造化された出力、またはガードレールを調整します。
from llama_index.core.prompts import PromptTemplate
qa_tmpl = PromptTemplate(
"""
あなたは簡潔で、証拠を重視するアシスタントです。提供されたコンテキストのみを使用してください。
不明な場合は、知らないと言ってください。キーが answer と sources の JSON を返してください。
質問:{query_str}
コンテキスト:{context_str}
"""
)
query_engine = v_index.as_query_engine(text_qa_template=qa_tmpl)
エージェントとツール:検索だけでは不十分な場合
回答によっては、SQL の実行、API の呼び出し、またはブラウジングなどのアクションが必要になる場合があります。LlamaIndex エージェントは、ツールと推論を検索パイプラインと連携させます。
- ユースケース:KPI ダッシュボード (SQL ツール)、サポートボット (チケットルックアップ API)、リサーチエージェント (ウェブ + RAG)。
from llama_index.core.agent import ReActAgent
from llama_index.tools.sql import SQLQueryEngineTool
from sqlalchemy import create_engine
engine = create_engine("sqlite:///analytics.db")
sql_tool = SQLQueryEngineTool.from_engine(engine)
agent = ReActAgent.from_tools([sql_tool], llm=llm, verbose=True)
agent.chat("2025 年第 2 四半期の月次解約率はどうでしたか?必要に応じて、DB にクエリを実行してください。")
評価:盲目的に出荷しないでください
責任を持って LlamaIndex を使う方法を学ぶということは、ロールアウト前に検索と回答の両方を検証することを意味します。
- オフライン評価:ラベル付けされたセットで検索の再現率/精度を評価します。
- オンライン評価:ユーザーのプロンプトをログに記録し、満足度、離脱率、およびハルシネーションを測定します。
- 組み込み:LlamaIndex は、信頼性と回答の関連性に関する評価ヘルパーを提供します。
from llama_index.core.evaluation import FaithfulnessEvaluator, RelevancyEvaluator
faith = FaithfulnessEvaluator(llm=llm)
rel = RelevancyEvaluator(llm=llm)
pred = query_engine.query("ポリシーの SOC 2 制御ファミリをリストしてください。")
print("faithful?", faith.evaluate_response(pred))
print("relevant?", rel.evaluate_response(pred))
- 実践的な基準:社内アシスタントの場合は、大規模なローンチの前に、上位クエリで >80% の「有用」評価を目標にしてください。
永続性とベクターストア:スケーラブルにする
インメモリで構築されたインデックスは、実際のワークロードには対応できません。ベクター DB に永続化し、増分更新を有効にします。
- 一般的なバックエンド:Pinecone, Weaviate, Chroma, Elasticsearch/OpenSearch, Qdrant。
- ヒント:テナントまたは部門ごとに名前空間を使用します。メタデータを豊富に保ちます。
# 例:Chroma
# pip install chromadb llama-index-vector-stores-chroma
from llama_index.vector_stores.chroma import ChromaVectorStore
from llama_index.core import StorageContext
import chromadb
chroma_client = chromadb.PersistentClient(path="./chroma_store")
collection = chroma_client.get_or_create_collection("company_knowledge")
vector_store = ChromaVectorStore(chroma_collection=collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(all_docs, storage_context=storage_context)
セキュリティとガバナンス:誰もが忘れる部分
- PII 処理:取り込み中に機密フィールドを編集またはハッシュ化します。
- アクセス制御:メタデータ制約を使用して、ユーザーロールでフィルタリングします。
- コンテンツの鮮度:再取り込みをスケジュールします。バージョンをマークします。
- 安全性:プロンプトに拒否ポリシーとソースのみの制約を追加します。
# 例:クエリ時のメタデータベースのフィルタリング
retriever = index.as_retriever(similarity_top_k=8)
retriever.metadata_filters = {"department": ["legal", "security"], "published": [True]}
プロトタイプから本番環境へ:デプロイメントパターン
- サーバーパターン:
/query エンドポイントを公開します。インデックスをメモリ内でウォーム状態に保ちます。
- サーバーレスの落とし穴:コールドスタート + 大規模なモデルはレイテンシーを悪化させる可能性があります。マネージド推論を検討してください。
- キャッシング:埋め込みと頻繁なクエリ結果をキャッシュします。部分的な更新を有効にします。
- 可観測性:検索されたノード、トークンの使用量、回答の長さ、およびユーザーフィードバックをログに記録します。
# 最小限の FastAPI ラッパー
# pip install fastapi uvicorn
from fastapi import FastAPI
app = FastAPI
qe = index.as_query_engine(llm=llm)
@app.post("/query")
async def query(payload: dict):
q = payload.get("q", "")
resp = qe.query(q)
return {"answer": str(resp), "sources": [s.node.metadata for s in resp.source_nodes]}
実際の設計図:あなたの道を選んでください
- インデックス:リランキング付きのハイブリッド (BM25 + ベクトル)
- ガードレール:ソースのみモード。「わからない」フォールバック
- インデックス:製品ドキュメント + リリースノート + チケット
- エージェント:注文/チケットのステータスを確認するための API ツール
- インデックス:ウェブ + PDF + メモ。強力な重複排除
- リランク:クロスエンコーダー。合成:マップリデュース
- ツール:SQL エンジン + メトリック定義に関する RAG
コストとレイテンシー:高速(かつ安価)に保つ
- 埋め込み:可能な場合はバッチ処理します。リコールにはより小さなモデルを使用し、選択的にリランクします。
- コンテキストサイズ:最も関連性の高いチャンクの 1〜2k トークンを目指します。
- キャッシング:ホットクエリの上位 K 件の検索をキャッシュします。ハッシュ化されたプロンプトで LLM 呼び出しをメモ化します。
- 並列処理:検索をファンアウト → リランクをファンインして、テールレイテンシーを短縮します。
LlamaIndex の使い方を学ぶ際の一般的な落とし穴
- 過剰なチャンク分割により、浅くてノイズの多い検索になる
- メタデータフィルターがないため、無関係なソースが紛れ込む
- すべてのコンテンツに対して単一のインデックスタイプに依存する
- インデックスが古くなるのを放置する。スケジュールされた更新がない
ちなみに:エディターでワークフローをスピードアップする
プロンプト、チャンク分割、および検索設定を反復処理する際には、Sider.ai のような AI コーディングおよびリサーチサイドバーがループを加速できることに注意する価値があります。スニペット、プロンプト、および評価ノートを手元に置いて、プロンプトの変更の差分を生成し、ブラウザを離れることなくバリエーションをすばやくテストできます。これは、さまざまな検索戦略で LlamaIndex の使い方を調整する場合に特に役立ちます。 ステップバイステップチェックリスト:ゼロから本番環境へ
- ベクトル + BM25 インデックスを構築する。ハイブリッド検索を有効にする
- プロンプトをカスタマイズする。引用と拒否ポリシーを有効にする
- 可観測性、キャッシング、および RBAC フィルターを追加する
- API でラップし、SLA を設定する。障害モードを文書化する
主なポイント
- 堅牢な RAG アプリが必要な場合は、LlamaIndex の使い方を学ぶことで、数週間のグルーエンジニアリングを節約できます。
- 単純なものから始めて、ハイブリッド検索、リランキング、および構造化されたプロンプトを重ねます。
- スケーリングする前に評価します。インデックスを永続化し、本番環境で品質を監視します。
- 最初からガバナンスを考慮して設計します。セキュリティは後付けではありません。
次のステップ
- 小さなドキュメントセットでクイックスタートをプロトタイプ作成します。
- 評価と引用を追加します。品質メトリックを追跡します。
- 永続的なベクターストアに移動し、API をデプロイします。
FAQ
Q1:RAG アプリケーションで LlamaIndex は何に使用されますか?
LlamaIndex は、取り込み、インデックス作成、および検索コンポーネントを使用して、データを LLM に接続するのに役立ちます。チャンク分割、ベクトル/キーワードインデックス、およびクエリオーケストレーションを処理することにより、RAG システムの構築を効率化します。
Q2:LlamaIndex で適切なインデックスタイプを選択するにはどうすればよいですか?
セマンティッククエリにはベクトルインデックスを使用し、ID やコードなどの正確な一致には BM25 を使用し、全体的な再現率と精度を最適にするにはハイブリッドアプローチを使用します。多くのチームは両方を組み合わせ、上位 K 件の結果に対してリランキングを追加します。
Q3: LlamaIndexを使用する際に精度を向上させるにはどうすればよいですか?
チャンクサイズを調整し、豊富なメタデータを含め、ハイブリッド検索を有効にし、リランカーを追加します。また、忠実性と関連性の評価を実装し、引用モードを使用してソースを表示します。
Q4: LlamaIndexは既存のベクターデータベースと連携できますか?
はい。LlamaIndexは、Pinecone、Weaviate、Chroma、Qdrant、Elasticsearchなどの一般的なベクターストアと統合されています。スケーラビリティとインクリメンタルアップデートのためにインデックスを保持します。
Q5: LlamaIndexアプリケーションを本番環境にデプロイするにはどうすればよいですか?
クエリエンジンをAPI(例:FastAPI)でラップし、ベクターストアにデータを保持し、キャッシュと監視機能を追加し、品質を継続的に評価します。セキュリティのために、メタデータフィルターとアクセス制御を適用します。