T-CREATOR

LlamaIndex で最小 RAG を 10 分で構築:Loader→Index→Query Engine 一気通貫

LlamaIndex で最小 RAG を 10 分で構築:Loader→Index→Query Engine 一気通貫

LLM を活用したアプリケーション開発において、RAG(Retrieval-Augmented Generation)は今や欠かせない技術となっています。自社のドキュメントや知識ベースを LLM に組み込みたい、そんなニーズに応えるのが LlamaIndex です。

本記事では、LlamaIndex を使って RAG の最小構成を 10 分で構築する方法を、Loader から Index、Query Engine まで一気通貫で解説します。初めて RAG に触れる方でも、この記事を読めば基本的な仕組みと実装方法が理解できるでしょう。

背景

RAG とは何か

RAG(Retrieval-Augmented Generation)は、外部の知識ベースから関連情報を検索(Retrieval)し、その情報を使って LLM が回答を生成(Generation)する仕組みです。

LLM は学習データに基づいて回答しますが、最新情報や企業固有の情報は持っていません。RAG を使うことで、LLM に持たせたい知識を外部から与えることができるのです。

以下の図は、RAG の基本的な処理フローを示しています。

mermaidflowchart LR
  user["ユーザー"] -->|質問| qe["Query Engine"]
  qe -->|検索| idx["Vector Index"]
  idx -->|関連文書| qe
  qe -->|文書+質問| llm["LLM"]
  llm -->|回答生成| qe
  qe -->|回答| user

図で理解できる要点

  • ユーザーの質問は Query Engine で処理されます
  • Vector Index から関連する文書を検索し取得します
  • 取得した文書と質問を LLM に渡して回答を生成します

LlamaIndex が解決すること

LlamaIndex は、RAG を簡単に実装するための Python ライブラリです。ドキュメントの読み込みからベクトル化、検索、回答生成まで、RAG に必要な一連の処理をシンプルな API で提供します。

以下の表は、LlamaIndex が提供する主要なコンポーネントです。

#コンポーネント役割主な機能
1Loaderデータ読み込みPDF、テキスト、Web ページなど多様な形式に対応
2Indexベクトル化・保存文書を埋め込みベクトルに変換して検索可能にする
3Query Engine質問応答質問に対して関連文書を検索し回答を生成

自前で実装すると複雑になる処理を、LlamaIndex なら数行のコードで実現できます。

課題

RAG 実装における典型的な課題

RAG を自力で実装しようとすると、以下のような課題に直面します。

データ読み込みの煩雑さ

様々な形式のドキュメント(PDF、Markdown、HTML など)をパースして、LLM が理解できる形式に変換する必要があります。形式ごとに異なるライブラリを使い分けるのは手間がかかるでしょう。

ベクトル化と検索の実装

文書をベクトル化して保存し、質問が来たら類似度検索を行う仕組みが必要です。Embedding モデルの選択、ベクトルデータベースの構築、検索アルゴリズムの実装など、考慮すべき点が多くあります。

LLM との統合

検索結果を適切なプロンプトに整形して LLM に渡し、回答を得る処理も実装しなければなりません。プロンプトエンジニアリングの知識も求められますね。

以下の図は、RAG 実装で必要となる処理ステップを示しています。

mermaidflowchart TD
  doc["ドキュメント<br/>(PDF, MD, HTML)"] -->|パース| text["テキスト抽出"]
  text -->|分割| chunks["チャンク化"]
  chunks -->|Embedding| vectors["ベクトル化"]
  vectors -->|保存| db[("Vector DB")]
  query["ユーザー質問"] -->|Embedding| qvec["質問ベクトル"]
  qvec -->|類似度検索| db
  db -->|関連チャンク| prompt["プロンプト生成"]
  prompt -->|API 呼び出し| llm["LLM"]
  llm -->|回答| result["最終回答"]

図で理解できる要点

  • ドキュメント処理からベクトル化まで多段階の変換が必要です
  • 質問処理も同様にベクトル化と検索のステップが必要です
  • これらすべてを自力で実装するのは時間がかかります

初心者が直面する壁

RAG の概念は理解できても、実際に動くコードを書くのは別の話です。どのライブラリを使うべきか、どう組み合わせるべきか、迷ってしまうこともあるでしょう。

できるだけシンプルに、最小構成で動くものを作りたい。そんなニーズに LlamaIndex は最適な選択肢となります。

解決策

LlamaIndex による統一的なアプローチ

LlamaIndex は、RAG の各ステップを統一的な API で提供することで、上記の課題を解決します。

3 つのコアコンポーネント

LlamaIndex の RAG 実装は、以下の 3 つのコンポーネントで構成されます。

#コンポーネント提供される主なクラス説明
1LoaderSimpleDirectoryReaderディレクトリ内のファイルを自動読み込み
2IndexVectorStoreIndex文書をベクトル化してインデックス作成
3Query EngineQueryEngine質問に対して回答を生成

これら 3 つを順番に実行するだけで、RAG システムが完成します。

以下の図は、LlamaIndex における処理フローを示しています。

mermaidflowchart LR
  files["ファイル群"] -->|SimpleDirectoryReader| docs["Document<br/>オブジェクト"]
  docs -->|VectorStoreIndex.from_documents| idx["Vector Index"]
  idx -->|as_query_engine| qe["Query Engine"]
  question["質問"] -->|query| qe
  qe -->|response| answer["回答"]

図で理解できる要点

  • 各ステップがクラスメソッド 1 つで完結します
  • 中間の複雑な処理は LlamaIndex が自動で行います
  • 開発者は高レベルな API だけを扱えばよいのです

最小構成の実装方針

本記事では、以下の方針で最小構成を実装します。

使用する技術

  • Python 3.9 以上
  • LlamaIndex(llama-index パッケージ)
  • OpenAI API(gpt-4o-mini と text-embedding-ada-002)

対象データ

  • 簡単なテキストファイル(Markdown や txt)

実装ステップ

  1. 環境構築とパッケージインストール
  2. Loader でドキュメント読み込み
  3. Index でベクトル化とインデックス作成
  4. Query Engine で質問応答

この流れで進めれば、10 分程度で動作する RAG システムが完成します。

具体例

環境構築

まず、必要なパッケージをインストールしましょう。

bash# LlamaIndex のインストール
yarn add llama-index

# 注: Yarn はフロントエンド用なので、Python プロジェクトでは pip を使います
pip install llama-index

実際には Python プロジェクトですので、以下のコマンドを実行します。

bashpip install llama-index

LlamaIndex は内部で OpenAI の API を使用するため、環境変数に API キーを設定します。

bashexport OPENAI_API_KEY="your-api-key-here"

API キーは OpenAI のダッシュボードから取得できます。.env ファイルに保存して管理するのがおすすめですね。

プロジェクトディレクトリの準備

以下のようなディレクトリ構成を作成しましょう。

plaintextrag-project/
├── data/
│   ├── document1.txt
│   └── document2.txt
└── main.py

data​/​ ディレクトリには、RAG で使用するドキュメントを配置します。例えば、以下のような内容のテキストファイルを作成します。

data/document1.txt の例

plaintextLlamaIndex は RAG を簡単に実装するための Python ライブラリです。
ドキュメントの読み込み、ベクトル化、検索、回答生成を統一的な API で提供します。

data/document2.txt の例

plaintextRAG(Retrieval-Augmented Generation)は、外部知識を検索して LLM に与える技術です。
最新情報や企業固有の情報を LLM に組み込むことができます。

これで準備は完了です。次に実装に進みましょう。

ステップ 1:必要なモジュールのインポート

main.py に以下のコードを記述します。

python# LlamaIndex の必要なモジュールをインポート
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

このインポート文だけで、RAG に必要な主要機能にアクセスできます。SimpleDirectoryReader がデータ読み込み、VectorStoreIndex がインデックス作成を担当しますね。

ステップ 2:Loader でドキュメントを読み込む

次に、data​/​ ディレクトリ内のファイルを読み込みます。

python# SimpleDirectoryReader でディレクトリ内の全ファイルを読み込み
documents = SimpleDirectoryReader("data").load_data()

この 1 行で、data​/​ ディレクトリ内のすべてのファイルが自動的に読み込まれます。documentsDocument オブジェクトのリストになり、各ドキュメントはテキスト内容とメタデータを持ちます。

SimpleDirectoryReader の特徴

  • 対応形式:txt、pdf、docx、md など
  • 自動判定:ファイル拡張子から形式を判定
  • 再帰的読み込み:サブディレクトリも読み込み可能(recursive=True オプション)

読み込まれた内容を確認してみましょう。

python# 読み込んだドキュメント数を表示
print(f"読み込んだドキュメント数: {len(documents)}")

# 最初のドキュメントの内容を表示
print(f"最初のドキュメント:\n{documents[0].text}")

このコードで、正しくファイルが読み込まれているか確認できます。

ステップ 3:Index でベクトル化とインデックス作成

読み込んだドキュメントを使って、ベクトルインデックスを作成します。

python# VectorStoreIndex でドキュメントをベクトル化してインデックス作成
index = VectorStoreIndex.from_documents(documents)

この 1 行で、以下の処理が自動的に実行されます。

#処理内容説明
1チャンク分割長い文書を適切なサイズに分割
2Embedding 生成OpenAI の text-embedding-ada-002 でベクトル化
3インデックス構築ベクトルをメモリ上のインデックスに保存

デフォルトでは OpenAI の Embedding モデルが使用されますが、他のモデル(HuggingFace など)に変更することも可能です。

インデックスの永続化

作成したインデックスはメモリ上に存在するため、プログラムを終了すると消えてしまいます。永続化したい場合は以下のように保存できます。

python# インデックスをディスクに保存
index.storage_context.persist(persist_dir="./storage")

次回起動時は、以下のコードで読み込めます。

pythonfrom llama_index.core import StorageContext, load_index_from_storage

# 保存したインデックスを読み込み
storage_context = StorageContext.from_defaults(persist_dir="./storage")
index = load_index_from_storage(storage_context)

これで毎回ベクトル化する必要がなくなり、起動時間を大幅に短縮できますね。

ステップ 4:Query Engine で質問応答

インデックスから Query Engine を作成し、質問に答えてもらいましょう。

python# Query Engine を作成
query_engine = index.as_query_engine()

as_query_engine() メソッドで、インデックスから Query Engine を生成します。このエンジンが、質問に対して関連文書を検索し、LLM に回答を生成させます。

実際に質問してみましょう。

python# 質問を投げて回答を取得
response = query_engine.query("LlamaIndex とは何ですか?")

# 回答を表示
print(response)

このコードを実行すると、以下のような回答が得られます。

plaintextLlamaIndex は RAG を簡単に実装するための Python ライブラリです。
ドキュメントの読み込み、ベクトル化、検索、回答生成を統一的な API で提供します。

Query Engine は以下の処理を自動的に行います。

以下の図は、Query Engine の内部処理フローを示しています。

mermaidsequenceDiagram
  participant User as ユーザー
  participant QE as Query Engine
  participant Idx as Vector Index
  participant LLM as OpenAI LLM

  User->>QE: query("質問")
  QE->>QE: 質問をベクトル化
  QE->>Idx: 類似文書検索
  Idx-->>QE: 関連文書リスト
  QE->>QE: プロンプト生成
  QE->>LLM: 文書+質問を送信
  LLM-->>QE: 回答テキスト
  QE-->>User: Response オブジェクト

図で理解できる要点

  • 質問は自動的にベクトル化されて検索されます
  • 検索結果とともに適切なプロンプトが生成されます
  • LLM が文脈を考慮して回答を生成します

完全なコード例

ここまでのコードをまとめると、以下のようになります。

python# 必要なモジュールのインポート
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

# ステップ1: ドキュメントを読み込み
documents = SimpleDirectoryReader("data").load_data()
print(f"読み込んだドキュメント数: {len(documents)}")

インデックスの作成部分は以下のとおりです。

python# ステップ2: ベクトルインデックスを作成
index = VectorStoreIndex.from_documents(documents)
print("インデックスの作成が完了しました")

Query Engine の作成と質問応答部分は以下のとおりです。

python# ステップ3: Query Engine を作成
query_engine = index.as_query_engine()

# ステップ4: 質問して回答を取得
response = query_engine.query("LlamaIndex とは何ですか?")
print(f"\n回答:\n{response}")

追加の質問も試してみましょう。

python# 別の質問を試す
response2 = query_engine.query("RAG はどのような技術ですか?")
print(f"\n回答2:\n{response2}")

このコードを実行すると、2 つの質問に対して、それぞれ適切な回答が返ってきます。

実行結果の例

実際に実行すると、以下のような出力が得られます。

plaintext読み込んだドキュメント数: 2
インデックスの作成が完了しました

回答:
LlamaIndex は RAG を簡単に実装するための Python ライブラリです。
ドキュメントの読み込み、ベクトル化、検索、回答生成を統一的な API で提供します。

回答2:
RAG(Retrieval-Augmented Generation)は、外部知識を検索して LLM に与える技術です。
最新情報や企業固有の情報を LLM に組み込むことができます。

わずか数行のコードで、RAG システムが動作していることが確認できますね。

カスタマイズのポイント

基本的な実装ができたら、以下のようなカスタマイズも可能です。

検索結果の数を調整

python# 検索する関連文書の数を指定
query_engine = index.as_query_engine(similarity_top_k=3)

similarity_top_k パラメータで、検索する文書の数を指定できます。デフォルトは 2 ですが、より多くの文脈が必要な場合は増やすとよいでしょう。

使用する LLM モデルを変更

pythonfrom llama_index.core import Settings
from llama_index.llms.openai import OpenAI

# 使用する LLM モデルを指定
Settings.llm = OpenAI(model="gpt-4o", temperature=0.1)

# この設定でインデックスを作成すると、指定したモデルが使われる
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()

より高性能な GPT-4o モデルや、コスト効率の良い gpt-4o-mini などに変更できます。

チャンクサイズの調整

pythonfrom llama_index.core.node_parser import SimpleNodeParser

# チャンクサイズを指定してノードパーサーを作成
node_parser = SimpleNodeParser.from_defaults(chunk_size=512, chunk_overlap=50)

# ドキュメントをノードに分割
nodes = node_parser.get_nodes_from_documents(documents)

# ノードからインデックスを作成
index = VectorStoreIndex(nodes)

文書が長い場合、適切なサイズに分割することで検索精度が向上します。chunk_overlap で前後のチャンクをオーバーラップさせると、文脈が途切れにくくなりますね。

まとめ

本記事では、LlamaIndex を使って RAG の最小構成を 10 分で構築する方法を解説しました。

重要なポイント

  • LlamaIndex は RAG 実装を簡単にする Python ライブラリです
  • Loader、Index、Query Engine の 3 つのコンポーネントで構成されます
  • わずか数行のコードで動作する RAG システムが完成します
  • カスタマイズも柔軟に行えます

RAG は複雑に見えますが、LlamaIndex を使えば初心者でも簡単に始められます。まずは最小構成で動かしてみて、その後で段階的に機能を追加していくのがおすすめです。

この記事をきっかけに、あなたも RAG アプリケーションの開発にチャレンジしてみてはいかがでしょうか。LLM の可能性が大きく広がるはずです。

関連リンク