LangChain と LlamaIndex の設計比較:API 哲学・RAG 構成・運用コストを検証

大規模言語モデル(LLM)を活用したアプリケーション開発において、LangChain と LlamaIndex は二大フレームワークとして多くの開発者に利用されています。両者とも RAG(Retrieval-Augmented Generation)システムの構築を得意としていますが、その設計思想やアプローチは大きく異なります。本記事では、API の哲学、RAG 構成の違い、そして運用コストの観点から両フレームワークを詳しく比較し、プロジェクトに最適な選択をするための判断材料を提供します。
背景
LLM アプリケーションフレームワークの登場
LLM の実用化が進む中、開発者は単なる API 呼び出しだけでなく、より複雑なワークフローやデータ統合が必要になってきました。LangChain は 2022 年に登場し、LLM を中心とした汎用的なアプリケーション構築を可能にするフレームワークとして急速に普及しました。一方、LlamaIndex(旧 GPT Index)は同時期に、データインデックス作成と検索に特化したフレームワークとして開発されました。
両フレームワークの位置づけ
LangChain は「LLM を使ったあらゆるアプリケーション」を対象とし、チェーン、エージェント、メモリ、ツールなど幅広い機能を提供します。対して LlamaIndex は「データと LLM を繋ぐ」ことに焦点を当て、インデックス構築とクエリ処理を最適化しています。
以下の図は、両フレームワークの基本的な位置づけを示したものです。
mermaidflowchart TB
llm["LLM<br/>(GPT-4, Claude など)"]
subgraph langchain["LangChain の領域"]
direction TB
lc_chain["チェーン"]
lc_agent["エージェント"]
lc_memory["メモリ"]
lc_tool["ツール"]
lc_rag["RAG"]
end
subgraph llamaindex["LlamaIndex の領域"]
direction TB
li_index["インデックス"]
li_retriever["リトリーバー"]
li_query["クエリエンジン"]
li_rag["RAG 特化"]
end
app["アプリケーション"]
app --> langchain
app --> llamaindex
langchain --> llm
llamaindex --> llm
style langchain fill:#e3f2fd
style llamaindex fill:#fff3e0
この図から、LangChain は広範な機能セットを提供する一方、LlamaIndex はデータインデックスと検索に集中していることがわかります。両者とも最終的には LLM を活用しますが、そこに至るまでのアプローチが異なるのです。
選択の重要性
プロジェクトの性質によって最適なフレームワークは変わります。複雑なワークフローやマルチステップの処理が必要な場合は LangChain が適していますし、大量のドキュメントから効率的に情報を取り出す RAG システムを構築したい場合は LlamaIndex が有利です。
課題
フレームワーク選択の難しさ
多くの開発者が直面する課題は、プロジェクト開始時にどちらのフレームワークを選ぶべきか判断が難しいことです。両者とも RAG システムを構築できるため、表面的には似た機能を提供しているように見えます。しかし、実装の詳細や運用フェーズでの違いは大きく、途中での乗り換えはコストがかかります。
設計思想の理解不足
単に「どちらが優れているか」という比較ではなく、それぞれの設計思想を理解することが重要です。LangChain の柔軟性が必要なケースもあれば、LlamaIndex のシンプルさが求める要件に合致することもあります。
以下の図は、フレームワーク選択時に考慮すべき主要な観点を示しています。
mermaidflowchart TD
start["フレームワーク選択"]
start --> api["API 哲学<br/>の理解"]
start --> rag["RAG 構成<br/>の比較"]
start --> cost["運用コスト<br/>の評価"]
api --> api_result["実装スタイル<br/>の違い"]
rag --> rag_result["アーキテクチャ<br/>の違い"]
cost --> cost_result["保守性・学習<br/>コストの違い"]
api_result --> decision["最適な選択"]
rag_result --> decision
cost_result --> decision
style start fill:#ffebee
style decision fill:#c8e6c9
この図が示すように、API 哲学、RAG 構成、運用コストという 3 つの軸から両者を比較することで、より適切な判断ができるようになります。
運用フェーズでの課題
開発初期には気づきにくいのが、運用フェーズでの違いです。デバッグのしやすさ、パフォーマンスチューニングの柔軟性、チームメンバーの学習コストなど、長期的な視点での比較が不足しがちです。
解決策
API 哲学の比較
両フレームワークの根本的な違いは、API 設計の哲学にあります。これを理解することで、どちらが自分のプロジェクトに適しているかが見えてきます。
LangChain: コンポーネント志向とチェーン
LangChain は「コンポーネントを組み合わせてワークフローを構築する」という思想を持っています。LLM、プロンプトテンプレート、出力パーサー、メモリなど、各要素を独立したコンポーネントとして扱い、それらをチェーンで繋ぎます。
以下は LangChain の基本的な構成要素です。
typescriptimport { ChatOpenAI } from '@langchain/openai';
import { PromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
// LLM コンポーネントの定義
const model = new ChatOpenAI({
modelName: 'gpt-4',
temperature: 0.7,
});
この例では、LLM コンポーネントを独立して定義しています。温度パラメータなどの設定も明示的に指定できます。
次に、プロンプトテンプレートを定義します。
typescript// プロンプトテンプレートの定義
const promptTemplate = PromptTemplate.fromTemplate(
'次の質問に答えてください: {question}'
);
プロンプトテンプレートは再利用可能で、変数を動的に埋め込むことができます。
そして、出力パーサーを用意します。
typescript// 出力パーサーの定義
const outputParser = new StringOutputParser();
これらのコンポーネントをチェーンで繋ぎます。
typescript// コンポーネントをチェーンで連結
const chain = promptTemplate.pipe(model).pipe(outputParser);
// チェーンの実行
const result = await chain.invoke({
question: 'LangChain の主な特徴は何ですか?',
});
console.log(result);
このコードでは、pipe()
メソッドを使ってコンポーネントを順番に繋いでいます。データは左から右へと流れ、各コンポーネントで処理されていきます。
この設計の利点は、各コンポーネントを独立してテストでき、再利用性が高いことです。また、チェーンの途中に新しいコンポーネントを挿入することも容易です。
LlamaIndex: データ中心とクエリエンジン
LlamaIndex は「データをインデックス化し、効率的に検索する」という明確な目的を持っています。API はシンプルで、インデックス作成とクエリ実行の 2 つのステップに集約されています。
まず、ドキュメントの読み込みとインデックス作成を行います。
typescriptimport { VectorStoreIndex, Document } from 'llamaindex';
// ドキュメントの準備
const documents = [
new Document({
text: 'LlamaIndex はデータインデックス作成に特化しています。',
}),
new Document({ text: '効率的な検索と取得が可能です。' }),
];
ドキュメントは Document
クラスでラップされ、メタデータも含めることができます。
次に、インデックスを作成します。
typescript// インデックスの作成(自動的にベクトル化と保存を実行)
const index = await VectorStoreIndex.fromDocuments(
documents
);
この一行で、ドキュメントのベクトル化、インデックス構築、保存が自動的に行われます。内部的には埋め込みモデルの呼び出しやベクトルストアへの保存が実行されていますが、開発者はその詳細を意識する必要がありません。
クエリエンジンを作成し、質問を投げます。
typescript// クエリエンジンの作成
const queryEngine = index.asQueryEngine();
// クエリの実行
const response = await queryEngine.query({
query: 'LlamaIndex の特徴は?',
});
console.log(response.toString());
asQueryEngine()
メソッドは、インデックスから最適なクエリエンジンを自動的に生成します。開発者はリトリーバーの設定やプロンプトの構築を明示的に行う必要がなく、すぐに使い始めることができます。
この設計の利点は、コード量が少なく、初心者でもすぐに RAG システムを構築できることです。一方、細かいカスタマイズが必要な場合は、LangChain のような柔軟性には劣ります。
API 哲学の比較表
以下の表は、両フレームワークの API 哲学を比較したものです。
# | 観点 | LangChain | LlamaIndex |
---|---|---|---|
1 | 設計思想 | コンポーネント志向 | データ中心 |
2 | 抽象度 | 低~中(詳細な制御が可能) | 高(自動化が進んでいる) |
3 | コード量 | 多め(明示的な定義が必要) | 少なめ(デフォルト設定が充実) |
4 | 学習曲線 | やや急(概念が多い) | 緩やか(シンプルな API) |
5 | カスタマイズ性 | 高い(各コンポーネントを置き換え可能) | 中程度(主要な部分は変更可能) |
この表から、LangChain は柔軟性と制御を重視し、LlamaIndex は使いやすさと速さを重視していることがわかります。
RAG 構成の比較
RAG システムは、情報検索と生成を組み合わせた手法です。両フレームワークとも RAG を実装できますが、そのアーキテクチャは異なります。
LangChain の RAG 構成
LangChain では、RAG システムを構築するために複数のコンポーネントを組み合わせます。ベクトルストア、リトリーバー、チェーンなどを明示的に定義し、それらを繋ぎ合わせます。
まず、ドキュメントの読み込みと分割を行います。
typescriptimport { TextLoader } from 'langchain/document_loaders/fs/text';
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
// ドキュメントの読み込み
const loader = new TextLoader('./documents/sample.txt');
const docs = await loader.load();
// テキストの分割
const textSplitter = new RecursiveCharacterTextSplitter({
chunkSize: 1000,
chunkOverlap: 200,
});
const splitDocs = await textSplitter.splitDocuments(docs);
この例では、テキストファイルを読み込み、1000 文字のチャンクに分割しています。チャンク間には 200 文字のオーバーラップを設けることで、文脈の分断を防いでいます。
次に、ベクトルストアを作成します。
typescriptimport { MemoryVectorStore } from 'langchain/vectorstores/memory';
import { OpenAIEmbeddings } from '@langchain/openai';
// 埋め込みモデルの定義
const embeddings = new OpenAIEmbeddings();
// ベクトルストアの作成
const vectorStore = await MemoryVectorStore.fromDocuments(
splitDocs,
embeddings
);
ここでは OpenAI の埋め込みモデルを使用していますが、他のモデルに簡単に置き換えることができます。ベクトルストアも、メモリベースから Pinecone や Chroma などの外部ストアに変更可能です。
リトリーバーを作成します。
typescript// リトリーバーの作成
const retriever = vectorStore.asRetriever({
k: 3, // 上位3件を取得
});
このリトリーバーは、クエリに対して最も関連性の高い 3 つのドキュメントを取得します。
最後に、RAG チェーンを構築します。
typescriptimport { ChatOpenAI } from '@langchain/openai';
import {
ChatPromptTemplate,
MessagesPlaceholder,
} from '@langchain/core/prompts';
import { createStuffDocumentsChain } from 'langchain/chains/combine_documents';
import { createRetrievalChain } from 'langchain/chains/retrieval';
// LLM の定義
const llm = new ChatOpenAI({ modelName: 'gpt-4' });
// プロンプトテンプレートの定義
const prompt = ChatPromptTemplate.fromMessages([
[
'system',
'以下の文脈を使って質問に答えてください:\n{context}',
],
['human', '{input}'],
]);
// ドキュメント結合チェーンの作成
const combineDocsChain = await createStuffDocumentsChain({
llm,
prompt,
});
// RAG チェーンの作成
const ragChain = await createRetrievalChain({
retriever,
combineDocsChain,
});
この構成では、リトリーバーが取得したドキュメントをプロンプトに埋め込み、LLM に渡す一連の流れを定義しています。
クエリを実行します。
typescript// クエリの実行
const result = await ragChain.invoke({
input: 'LangChain の主な用途は何ですか?',
});
console.log(result.answer);
console.log('参照ドキュメント:', result.context);
この実装の特徴は、各ステップを明示的に定義しているため、デバッグがしやすく、各コンポーネントの挙動を細かく制御できることです。例えば、リトリーバーのアルゴリズムを変更したり、プロンプトテンプレートを調整したりすることが容易です。
LlamaIndex の RAG 構成
LlamaIndex では、RAG システムの構築がより簡潔です。多くの設定がデフォルトで最適化されており、数行のコードで動作するシステムを作れます。
ドキュメントの読み込みとインデックス作成を行います。
typescriptimport {
VectorStoreIndex,
SimpleDirectoryReader,
} from 'llamaindex';
// ドキュメントの読み込み(ディレクトリから自動読み込み)
const documents =
await new SimpleDirectoryReader().loadData({
directoryPath: './documents',
});
SimpleDirectoryReader
は、指定したディレクトリ内のファイルを自動的に読み込み、適切な形式に変換します。PDF、テキストファイル、Markdown など、複数の形式に対応しています。
インデックスを作成します。
typescript// インデックスの作成(チャンク分割、埋め込み、保存を自動実行)
const index = await VectorStoreIndex.fromDocuments(
documents
);
この一行で、LangChain で行った複数のステップ(テキスト分割、埋め込み生成、ベクトルストア作成)がすべて自動的に実行されます。デフォルト設定が実用的なため、多くの場合はこれで十分です。
クエリエンジンを作成し、質問します。
typescript// クエリエンジンの作成
const queryEngine = index.asQueryEngine();
// クエリの実行
const response = await queryEngine.query({
query: 'LlamaIndex の主な用途は何ですか?',
});
console.log(response.toString());
LlamaIndex の RAG システムは、このようにシンプルです。内部では適切なリトリーバーの選択、プロンプトの構築、LLM への呼び出しが自動的に行われています。
カスタマイズが必要な場合は、以下のように設定を変更できます。
typescriptimport { Settings } from 'llamaindex';
// グローバル設定のカスタマイズ
Settings.chunkSize = 512;
Settings.chunkOverlap = 50;
Settings.llm = new OpenAI({
model: 'gpt-4',
temperature: 0.5,
});
// カスタマイズされたクエリエンジンの作成
const queryEngine = index.asQueryEngine({
similarityTopK: 5, // 上位5件を取得
});
LlamaIndex も細かいカスタマイズは可能ですが、基本的には「すぐに動くものを作る」という哲学が貫かれています。
RAG アーキテクチャの可視化
以下の図は、両フレームワークにおける RAG システムのデータフローを比較したものです。
mermaidflowchart TB
subgraph langchain_rag["LangChain の RAG フロー"]
direction TB
lc_doc["ドキュメント"]
lc_split["TextSplitter<br/>(明示的に定義)"]
lc_embed["Embeddings<br/>(モデル選択)"]
lc_vector["VectorStore<br/>(ストア選択)"]
lc_retriever["Retriever<br/>(k, フィルタ設定)"]
lc_prompt["PromptTemplate<br/>(カスタム定義)"]
lc_llm["LLM<br/>(モデル選択)"]
lc_answer["回答"]
lc_doc --> lc_split
lc_split --> lc_embed
lc_embed --> lc_vector
lc_vector --> lc_retriever
lc_retriever --> lc_prompt
lc_prompt --> lc_llm
lc_llm --> lc_answer
end
subgraph llamaindex_rag["LlamaIndex の RAG フロー"]
direction TB
li_doc["ドキュメント"]
li_auto["自動処理<br/>(分割・埋め込み・保存)"]
li_index["VectorStoreIndex"]
li_qe["QueryEngine<br/>(自動最適化)"]
li_answer["回答"]
li_doc --> li_auto
li_auto --> li_index
li_index --> li_qe
li_qe --> li_answer
end
style langchain_rag fill:#e3f2fd
style llamaindex_rag fill:#fff3e0
この図から、LangChain は各ステップを明示的に定義する一方、LlamaIndex は多くのステップを自動化していることがわかります。LangChain は制御の細かさを、LlamaIndex は開発速度を優先しています。
RAG 構成の比較表
以下の表は、RAG システム構築における両フレームワークの違いをまとめたものです。
# | 観点 | LangChain | LlamaIndex |
---|---|---|---|
1 | セットアップ | 各コンポーネントを明示的に定義 | 自動化されたワンステップ |
2 | チャンク分割 | TextSplitter を明示的に設定 | デフォルト設定で自動実行 |
3 | 埋め込み生成 | Embeddings クラスを選択・設定 | デフォルトモデルで自動実行 |
4 | ベクトルストア | 多様なストアから選択可能 | 主要なストアをサポート |
5 | リトリーバー | 詳細な設定が可能 | シンプルな API で自動最適化 |
6 | プロンプト | カスタムテンプレートを定義 | デフォルトで最適化済み |
7 | デバッグ | 各ステップを個別に検証可能 | 統合されたログ出力 |
この表から、プロジェクトの要件に応じてどちらを選ぶべきかが見えてきます。細かい制御が必要なら LangChain、迅速な構築が目的なら LlamaIndex が適しています。
運用コストの比較
フレームワークの選択は、開発時だけでなく運用フェーズでも影響を及ぼします。ここでは、学習コスト、保守性、パフォーマンスチューニングの観点から比較します。
学習コスト
LangChain は機能が豊富な分、学習すべき概念が多くあります。チェーン、エージェント、メモリ、ツール、コールバックなど、様々なコンポーネントの理解が必要です。公式ドキュメントも膨大で、初学者が全体像を掴むまでに時間がかかります。
一方、LlamaIndex は「インデックスとクエリ」という明確な 2 つのステップに集約されているため、学習曲線が緩やかです。基本的な使い方は数時間で習得でき、すぐに実用的なシステムを構築できます。
保守性とデバッグ
LangChain の明示的な設計は、デバッグがしやすいという利点があります。各コンポーネントが独立しているため、問題が発生した際にどのステップで起きているかを特定しやすいです。
typescript// LangChain でのデバッグ例
const retriever = vectorStore.asRetriever({
k: 3,
callbacks: [
{
handleRetrieverEnd(documents) {
console.log(
'取得したドキュメント数:',
documents.length
);
console.log('ドキュメント内容:', documents);
},
},
],
});
このように、コールバックを使って各ステップの出力を確認できます。問題の切り分けが容易で、大規模なシステムでも保守しやすいです。
LlamaIndex も、デバッグ用のユーティリティを提供しています。
typescriptimport { Settings } from 'llamaindex';
// デバッグモードの有効化
Settings.callbackManager.on('llm-start', (event) => {
console.log('LLM 呼び出し開始:', event);
});
Settings.callbackManager.on('llm-end', (event) => {
console.log('LLM 呼び出し終了:', event);
});
ただし、内部的に多くの処理が自動化されているため、細かい挙動を追跡するのは LangChain よりもやや難しくなります。
パフォーマンスチューニング
大規模なシステムでは、パフォーマンスチューニングが重要になります。LangChain は各コンポーネントを個別に最適化できるため、ボトルネックを特定して改善することが容易です。
例えば、リトリーバーのアルゴリズムを変更する場合:
typescriptimport { VectorStoreRetriever } from 'langchain/vectorstores/base';
// カスタムリトリーバーの実装
class CustomRetriever extends VectorStoreRetriever {
async getRelevantDocuments(query: string) {
// カスタムロジックの実装
// 例: 特定のメタデータでフィルタリング
const results = await this.vectorStore.similaritySearch(
query,
this.k,
{
filter: { source: 'official_docs' },
}
);
return results;
}
}
このように、特定のコンポーネントだけを置き換えることができます。
LlamaIndex でも、パフォーマンスチューニングは可能です。
typescriptimport { VectorStoreIndex } from 'llamaindex';
// インデックス設定のカスタマイズ
const index = await VectorStoreIndex.fromDocuments(
documents,
{
// インデックス構築時のバッチサイズを調整
insertBatchSize: 100,
// 並列処理数の設定
numWorkers: 4,
}
);
// クエリ時のパフォーマンス設定
const queryEngine = index.asQueryEngine({
similarityTopK: 10,
responseSynthesizer: {
responseMode: 'compact', // レスポンスモードの最適化
},
});
ただし、カスタマイズできる範囲は LangChain よりも限定的です。
コスト面での考慮事項
LLM の API 呼び出しコストも重要な要素です。両フレームワークとも、適切な設定で不要な API 呼び出しを減らすことができます。
LangChain では、キャッシュを明示的に設定できます。
typescriptimport { ChatOpenAI } from '@langchain/openai';
import { InMemoryCache } from '@langchain/core/caches';
// キャッシュの有効化
const llm = new ChatOpenAI({
cache: new InMemoryCache(),
modelName: 'gpt-4',
});
LlamaIndex でも、キャッシュ機能が組み込まれています。
typescriptimport { Settings } from 'llamaindex';
// キャッシュの設定
Settings.cacheDir = './.cache';
運用コストの比較表
以下の表は、運用面での両フレームワークの特性をまとめたものです。
# | 観点 | LangChain | LlamaIndex |
---|---|---|---|
1 | 学習時間 | 数日~数週間 | 数時間~ 1 日 |
2 | コード量 | 多い(明示的な定義が必要) | 少ない(自動化が進んでいる) |
3 | デバッグ容易性 | 高い(各ステップを追跡可能) | 中程度(統合されたログ) |
4 | カスタマイズ性 | 非常に高い | 中程度 |
5 | パフォーマンス最適化 | 詳細な調整が可能 | 主要な設定は変更可能 |
6 | チーム協業 | 明示的な設計で共有しやすい | シンプルで理解しやすい |
7 | 長期保守 | コンポーネント単位で更新可能 | 全体的な更新が必要 |
この表から、LangChain は長期的なプロジェクトや大規模チームに適している一方、LlamaIndex は小規模プロジェクトや迅速なプロトタイピングに向いていることがわかります。
具体例
ここでは、実際のユースケースに基づいて、どちらのフレームワークが適しているかを検討します。
ケース 1: 社内ドキュメント検索システム
要件:
- 数千件の社内ドキュメントから情報を検索
- シンプルな Q&A 形式
- 迅速な開発が求められる
- 運用は少人数
推奨: LlamaIndex
このケースでは、LlamaIndex が適しています。シンプルな RAG システムを迅速に構築でき、運用も容易です。
実装例を見てみましょう。
typescriptimport {
VectorStoreIndex,
SimpleDirectoryReader,
Settings,
} from 'llamaindex';
// OpenAI の設定
Settings.llm = new OpenAI({ model: 'gpt-4' });
// ドキュメントの読み込み
async function setupDocumentSearch() {
// 社内ドキュメントディレクトリから自動読み込み
const documents =
await new SimpleDirectoryReader().loadData({
directoryPath: './company_docs',
});
console.log(
`${documents.length} 件のドキュメントを読み込みました`
);
// インデックスの作成
const index = await VectorStoreIndex.fromDocuments(
documents
);
return index;
}
この数行のコードで、ドキュメントの読み込みとインデックス作成が完了します。
クエリシステムを構築します。
typescript// クエリシステムの構築
async function createQuerySystem() {
const index = await setupDocumentSearch();
const queryEngine = index.asQueryEngine({
similarityTopK: 3,
});
return queryEngine;
}
// 使用例
async function main() {
const queryEngine = await createQuerySystem();
const questions = [
'休暇申請の手順は?',
'経費精算の期限は?',
'リモートワーク規定について教えて',
];
for (const question of questions) {
const response = await queryEngine.query({
query: question,
});
console.log(`質問: ${question}`);
console.log(`回答: ${response.toString()}\n`);
}
}
main();
この実装は非常にシンプルで、初心者でも理解しやすく、保守も容易です。社内ドキュメント検索のような用途では、LlamaIndex の自動化された設計が大きな利点となります。
ケース 2: カスタマーサポートチャットボット
要件:
- 複数のデータソース(FAQ、過去のチケット、マニュアル)を統合
- ユーザーの質問に応じてツール(チケット作成、エスカレーション)を呼び出す
- 会話履歴を保持
- 複雑なワークフロー
推奨: LangChain
このケースでは、LangChain の柔軟性が必要です。エージェント機能、メモリ、ツール統合など、複雑な要件に対応できます。
まず、メモリ機能を実装します。
typescriptimport { BufferMemory } from 'langchain/memory';
import { ConversationChain } from 'langchain/chains';
import { ChatOpenAI } from '@langchain/openai';
// 会話履歴を保持するメモリの作成
const memory = new BufferMemory({
returnMessages: true,
memoryKey: 'chat_history',
});
// LLM の定義
const llm = new ChatOpenAI({
modelName: 'gpt-4',
temperature: 0.7,
});
メモリ機能により、過去の会話を考慮した応答が可能になります。
次に、カスタムツールを定義します。
typescriptimport { DynamicTool } from '@langchain/core/tools';
// チケット作成ツール
const createTicketTool = new DynamicTool({
name: 'create_ticket',
description:
'ユーザーのサポートチケットを作成します。問題の詳細を引数として受け取ります。',
func: async (input: string) => {
// 実際のチケット作成ロジック(API 呼び出しなど)
console.log('チケット作成:', input);
return `チケット #12345 を作成しました: ${input}`;
},
});
// エスカレーションツール
const escalateTool = new DynamicTool({
name: 'escalate',
description:
'複雑な問題を上位サポートにエスカレーションします。',
func: async (input: string) => {
console.log('エスカレーション:', input);
return `問題をレベル2サポートにエスカレーションしました`;
},
});
// FAQ 検索ツール
const searchFAQTool = new DynamicTool({
name: 'search_faq',
description: 'FAQ データベースから関連情報を検索します。',
func: async (query: string) => {
// FAQ 検索ロジック
return `FAQ からの回答: ${query} に関する情報が見つかりました`;
},
});
これらのツールをエージェントに統合します。
typescriptimport { initializeAgentExecutorWithOptions } from 'langchain/agents';
// エージェントの作成
async function createSupportAgent() {
const tools = [
createTicketTool,
escalateTool,
searchFAQTool,
];
const executor = await initializeAgentExecutorWithOptions(
tools,
llm,
{
agentType: 'chat-conversational-react-description',
memory,
verbose: true,
}
);
return executor;
}
最後に、チャットボットのメインロジックを実装します。
typescript// チャットボットの実行
async function runChatbot() {
const agent = await createSupportAgent();
// ユーザーからの質問例
const conversation = [
'商品の返品方法を教えてください',
'返品期限は過ぎているのですが、どうすればいいですか?',
'それでは上位サポートに問い合わせたいです',
];
for (const input of conversation) {
console.log(`ユーザー: ${input}`);
const result = await agent.call({
input,
});
console.log(`ボット: ${result.output}\n`);
}
}
runChatbot();
この実装では、エージェントが状況に応じて適切なツールを選択し、会話履歴を保持しながら対応します。このような複雑なワークフローは、LangChain の強みが発揮される領域です。
ケース 3: 技術ブログの AI アシスタント
要件:
- 大量の技術記事から情報を検索
- コード例の抽出と説明
- 関連記事の推薦
- 段階的な学習パスの提案
推奨: LlamaIndex(カスタマイズ付き)
このケースでは、LlamaIndex をベースにしつつ、カスタマイズを加える方法が効果的です。
まず、カスタムメタデータを使ったインデックス作成を行います。
typescriptimport {
VectorStoreIndex,
Document,
Settings,
} from 'llamaindex';
// 技術記事の読み込みとメタデータ付加
async function loadTechArticles() {
const articles = [
{
title: 'React Hooks 完全ガイド',
content: 'React Hooks は...',
category: 'Frontend',
difficulty: 'Intermediate',
tags: ['React', 'JavaScript', 'Hooks'],
},
{
title: 'TypeScript 型システム入門',
content: 'TypeScript の型システムは...',
category: 'Language',
difficulty: 'Beginner',
tags: ['TypeScript', 'Types'],
},
];
// Document オブジェクトに変換し、メタデータを付加
const documents = articles.map(
(article) =>
new Document({
text: `${article.title}\n\n${article.content}`,
metadata: {
title: article.title,
category: article.category,
difficulty: article.difficulty,
tags: article.tags,
},
})
);
return documents;
}
メタデータを活用したクエリシステムを構築します。
typescript// カスタムクエリエンジンの作成
async function createTechBlogAssistant() {
const documents = await loadTechArticles();
const index = await VectorStoreIndex.fromDocuments(
documents
);
// メタデータフィルタリングを含むクエリエンジン
const queryEngine = index.asQueryEngine({
similarityTopK: 5,
// レスポンス合成モードの設定
responseSynthesizer: {
responseMode: 'tree_summarize', // 複数ドキュメントを階層的に要約
},
});
return queryEngine;
}
難易度別の学習パス提案機能を追加します。
typescript// 学習パスの提案
async function suggestLearningPath(
topic: string,
level: string
) {
const documents = await loadTechArticles();
// 難易度でフィルタリングされたドキュメント
const filteredDocs = documents.filter(
(doc) =>
doc.metadata.difficulty === level &&
doc.metadata.tags.some((tag) =>
tag.toLowerCase().includes(topic.toLowerCase())
)
);
const index = await VectorStoreIndex.fromDocuments(
filteredDocs
);
const queryEngine = index.asQueryEngine();
const response = await queryEngine.query({
query: `${topic} について ${level} レベルの学習パスを提案してください`,
});
return response.toString();
}
// 使用例
async function main() {
const assistant = await createTechBlogAssistant();
// 一般的な質問
const response1 = await assistant.query({
query: 'React Hooks の使い方を教えてください',
});
console.log('回答:', response1.toString());
// 学習パスの提案
const learningPath = await suggestLearningPath(
'React',
'Beginner'
);
console.log('学習パス:', learningPath);
}
main();
この実装では、LlamaIndex のシンプルさを保ちつつ、メタデータフィルタリングや学習パス提案などのカスタム機能を追加しています。
ユースケース別の選択指針
以下の図は、プロジェクトの特性に応じた選択指針を示しています。
mermaidflowchart TD
start["プロジェクト開始"]
start --> complexity{"ワークフローの<br/>複雑さは?"}
complexity -->|シンプルな RAG| simple["LlamaIndex<br/>を検討"]
complexity -->|複雑なフロー| complex["LangChain<br/>を検討"]
simple --> customize{"カスタマイズ<br/>の必要性は?"}
customize -->|最小限| li_basic["LlamaIndex<br/>デフォルト設定"]
customize -->|中程度| li_custom["LlamaIndex<br/>カスタマイズ版"]
customize -->|高度| reconsider["LangChain<br/>再検討"]
complex --> team{"チームの<br/>規模・経験は?"}
team -->|小規模・初心者| lc_learning["学習コスト<br/>を考慮"]
team -->|大規模・経験者| lc_advanced["LangChain<br/>フル活用"]
lc_learning --> hybrid["ハイブリッド<br/>アプローチ"]
li_basic --> result_li["LlamaIndex 採用"]
li_custom --> result_li
lc_advanced --> result_lc["LangChain 採用"]
reconsider --> result_lc
hybrid --> result_hybrid["両者を併用"]
style result_li fill:#fff3e0
style result_lc fill:#e3f2fd
style result_hybrid fill:#f3e5f5
この図は、プロジェクトの特性(ワークフローの複雑さ、カスタマイズの必要性、チームの規模)に基づいて、どちらのフレームワークを選ぶべきかの判断フローを示しています。
重要なのは、「どちらが優れているか」ではなく、「プロジェクトに何が適しているか」を見極めることです。
まとめ
LangChain と LlamaIndex は、どちらも優れた LLM アプリケーションフレームワークですが、その設計思想と適用領域は大きく異なります。
主要な違いのまとめ
LangChain:
- コンポーネント志向の柔軟な設計
- 詳細な制御とカスタマイズが可能
- 複雑なワークフローやエージェントシステムに最適
- 学習コストは高いが、大規模プロジェクトで力を発揮
- デバッグと保守がしやすい
LlamaIndex:
- データ中心のシンプルな設計
- 迅速な開発と導入が可能
- RAG システムに特化した最適化
- 学習曲線が緩やかで、初心者にも扱いやすい
- デフォルト設定が実用的
選択のポイント
以下の表は、選択時の判断基準をまとめたものです。
# | 状況 | 推奨フレームワーク |
---|---|---|
1 | シンプルな Q&A システム | LlamaIndex |
2 | 複数ツールを統合するエージェント | LangChain |
3 | 迅速なプロトタイピング | LlamaIndex |
4 | 複雑なワークフロー | LangChain |
5 | 小規模チーム・初心者中心 | LlamaIndex |
6 | 大規模チーム・長期保守 | LangChain |
7 | データ検索に特化したシステム | LlamaIndex |
8 | 会話型 AI・マルチステップ処理 | LangChain |
ハイブリッドアプローチ
実は、両者を組み合わせることも可能です。LlamaIndex でインデックスを作成し、LangChain でそれを利用する、といった使い方もできます。
typescriptimport { VectorStoreIndex } from 'llamaindex';
import { ChatOpenAI } from '@langchain/openai';
import { VectorStoreRetriever } from 'langchain/vectorstores/base';
// LlamaIndex でインデックス作成
const llamaIndex = await VectorStoreIndex.fromDocuments(
documents
);
// LangChain でリトリーバーとして利用
const retriever = llamaIndex.asRetriever();
// LangChain のチェーンに統合
// (実装の詳細は省略)
このように、それぞれの強みを活かした組み合わせも検討する価値があります。
最終的なアドバイス
フレームワークの選択は、プロジェクトの初期段階で慎重に行うべきですが、途中での変更も不可能ではありません。まずは小さく始めて、要件の変化に応じて柔軟に対応することが重要です。
どちらのフレームワークも活発に開発が進んでおり、新しい機能が次々と追加されています。公式ドキュメントやコミュニティの動向をチェックし、最新のベストプラクティスを取り入れることで、より効果的な LLM アプリケーションを構築できるでしょう。
最も重要なのは、両者の設計思想を理解し、自分のプロジェクトに何が必要かを見極めることです。この記事が、その判断の一助となれば幸いです。
関連リンク
- article
LangChain と LlamaIndex の設計比較:API 哲学・RAG 構成・運用コストを検証
- article
LangChain ハイブリッド検索設計:BM25 +ベクトル+再ランキングで精度を底上げ
- article
LangChain LCEL 実用テンプレ 30:map/branch/batch/select の書き方速見表
- article
Dify と LangGraph/LangChain を比較:表現力・保守性・学習コストのリアル
- article
LangChain を Edge で走らせる:Cloudflare Workers/Deno/Bun 対応の初期配線
- article
LangChain を“1 枚絵”で理解する:データ取り込み → 前処理 → 推論 → 評価 → 運用の全体像
- article
Convex で実践する CQRS/イベントソーシング:履歴・再生・集約の設計ガイド
- article
LangChain と LlamaIndex の設計比較:API 哲学・RAG 構成・運用コストを検証
- article
Jotai が再レンダリング地獄に?依存グラフの暴走を止める診断手順
- article
成果が出る GPT-5-Codex 導入ロードマップ:評価指標(ROI/品質/速度)と失敗しない運用フロー
- article
Jest expect.extend チートシート:実務で使えるカスタムマッチャー 40 連発
- article
Astro の View Transitions 徹底解説:SPA 並みの滑らかなページ遷移を実装するコツ
- blog
iPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
- blog
Googleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
- blog
【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
- blog
Googleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
- blog
Pixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
- blog
フロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来