LlamaIndex と LangChain の選択: 包括ガイド

LlamaIndex と LangChain の選択: 包括ガイド

主なポイント

  • LlamaIndex: データの取り込み、構造化、プライベートまたはドメイン固有データの活用に特化し、高度な質問応答や文書理解などのタスクに適しています。
  • LangChain: LLM を用いたアプリケーションの開発、デプロイ、スケーリングのためのオープンソースの包括的なフレームワークを提供し、会話エージェント、翻訳、複雑なワークフローなど多様なユースケースをサポートします。
  • カスタム LLM 統合: LlamaIndex と LangChain フレームワークでカスタム LLM を実装するための詳細なコードガイドを提供し、それぞれのアプローチで Novita AI のような外部 API を統合・活用する方法を示します。

はじめに

急速に進化する人工知能・自然言語処理の分野において、大規模言語モデル(LLM)を扱う開発者向けに、LlamaIndex と LangChain という 2 つのフレームワークが強力なツールとして登場しました。このブログ記事では、LlamaIndex と LangChain の包括的な比較を行い、主要な機能、ユースケース、実践的な応用について探ります。各フレームワークの中核機能、料金モデル、統合能力を掘り下げることで、特定のニーズに最適なツールを選択するための知識を提供します。

LlamaIndex とは

LlamaIndex は、大規模言語モデル(LLM)にコンテキストに関連したユーザー固有のデータを提供することで、LLM を強化するために設計された高度なデータフレームワークです。公開データで事前学習された汎用 LLM とは異なり、LlamaIndex は API の背後、データベース内、または PDF のような非構造化形式に閉じ込められた、プライベートまたはドメイン固有のデータに LLM がアクセスして活用できるようにします。

主な機能と能力

  • データ取り込み: LlamaIndex はデータコネクタを提供し、API、PDF、SQL データベースなど様々なソースからネイティブ形式でシームレスにデータを取り込めます。
  • データ構造化: 取り込んだデータを LLM が効率的に消費できる中間表現に構造化し、高いパフォーマンスを実現します。
  • 自然言語アクセス: LlamaIndex はデータへの自然言語アクセスを提供するエンジンを備え、クエリエンジンによる質問応答やチャットエンジンによる対話的やり取りを可能にします。
  • ナレッジワーカー: フレームワークには、LLM を活用したナレッジワーカーとして機能するエージェントが含まれており、単純なヘルパーから複雑な API 統合まで様々なツールで強化されています。
  • 観測可能性と評価: 厳密な実験、評価、監視のための統合機能を備え、アプリケーションの継続的改善サイクルを実現します。

ユースケース

LlamaIndex は以下のような多様なユースケースをサポートします。

  • 高度な質問応答システムのための 検索拡張生成(RAG)
  • コンテキストを理解した有意義な対話が可能な チャットボット
  • 非構造化文書からの 文書理解 とデータ抽出
  • 研究やアクション実行が可能な 自律エージェント
  • テキストと画像など他のデータ型を統合する マルチモーダルアプリケーション
  • 特定データでのモデルファインチューニングによるパフォーマンス向上

LangChain とは

LangChain は、大規模言語モデル(LLM)を活用したアプリケーションの開発、本番化、デプロイを効率化するために設計された最先端のフレームワークです。LLM アプリケーションライフサイクルのあらゆる段階に対応する包括的なツールとライブラリを提供し、シームレスで効率的な開発プロセスを実現します。

主な機能と能力

  • 開発: LangChain はオープンソースのビルディングブロック、コンポーネント、サードパーティ統合を提供し、LLM アプリケーションの作成を簡素化します。主要コンポーネントの LangGraph は、ストリーミングデータやヒューマン・イン・ザ・ループワークフローを堅牢にサポートするステートフルエージェントの構築を可能にします。
  • 本番化: LangSmith は LLM チェーンのパフォーマンスを検査、監視、評価する強力なツールです。アプリケーションパフォーマンスの深い洞察を提供し、継続的な最適化と確実なデプロイを保証します。
  • デプロイ: LangGraph Cloud は LangGraph アプリケーションを本番環境対応の API やアシスタントに変換し、LLM アプリケーションのスケーリングや様々なシステムへの統合を容易にします。
  • 階層的構成: フレームワークは階層的に構成され、複数層にわたって相互接続された部分を持ち、モジュール性と柔軟性を確保します。

オープンソースライブラリ

  • langchain-core: 基本抽象化と LangChain Expression Language を提供し、フレームワークの基盤を担います。
  • langchain-community: サードパーティサービスとの統合を実現し、LangChain の機能を拡張します。
  • パートナーパッケージ: langchain-openai、langchain-anthropic などの軽量パッケージで、特定の統合を提供し、フレームワークの汎用性を高めます。
  • langchain: アプリケーションの認知アーキテクチャを構成するチェーン、エージェント、検索戦略を含みます。
  • LangGraph: LLM を用いたステートフルなマルチアクターアプリケーションをグラフベースのステップモデルで構築する強力なツール。LangChain と統合して、または独立して使用できます。
  • LangServe: LangChain チェーンを REST API としてデプロイし、ウェブサービスとの統合を容易にします。
  • LangSmith: LLM アプリケーションのデバッグ、テスト、評価、監視のための包括的なツールを提供する開発者プラットフォームです。

対象ユーザーとユースケース

LangChain は、LLM の力をアプリケーションで活用したい初心者から専門家まで、あらゆるレベルの開発者向けに設計されています。そのモジュール式で拡張可能なアーキテクチャは、以下のような幅広いユースケースに適しています。

  • 会話エージェントやチャットボットの構築
  • 言語翻訳・要約ツールの開発
  • コンテンツ生成・分類システムの作成
  • LLM を用いた複雑なワークフローの実装

LlamaIndex vs LangChain: 主な違い

中核機能:

  • LangChain は、大規模言語モデル(LLM)を用いたデータ認識型・エージェント型アプリケーションの作成を簡素化する包括的なフレームワークです。多様な LLM 活用アプリケーション向けのツールを幅広く提供し、柔軟性と高度な AI 機能に重点を置いています。
  • LlamaIndex(旧称 GPT Index)は、プライベートまたはドメイン固有のデータを LLM 用に取り込み、構造化し、アクセス可能にするデータフレームワークです。情報のインデックス化と検索を簡素化し、テキストベースの検索や正確な応答生成に最適です。

ユースケース:

  • LangChain は汎用性が高く、テキスト生成、言語翻訳、テキスト要約、テキスト分類など様々なアプリケーションに使用できます。優れたメモリ管理とチェーン機能により、長く文脈に関連した会話の維持に特に適しています。
  • LlamaIndex は、テキスト検索と高品質な応答が最優先されるシナリオで優れています。一般的なユースケースには、コンテンツ生成、文書検索・取得、チャットボットや仮想アシスタントの LLM 拡張などがあります。

料金と利用可能性:

  • LangChain はオープンソースで無料のツールであり、ソースコードは GitHub などのプラットフォームからダウンロード可能で、誰でも利用できます。
  • LlamaIndex は商用製品であり、料金は使用量に基づいて決まるため、アプリケーション内での利用範囲に応じてコストが発生する可能性があります。

カスタマイズと柔軟性:

  • LangChain は高度なカスタマイズオプションを提供し、特定の要件に合わせてアプリケーションを微調整する必要がある開発者に適しています。
  • LlamaIndex は、プライベートまたはドメイン固有のデータを LLM にシームレスに統合するためのユーザーフレンドリーな機能とツールを提供し、使いやすさと簡単なデータ管理に重点を置いています。

データ処理:

  • LangChain は様々なデータ型やソースを扱うように設計されており、データ整理のための Schema や効率的な情報検索のための Indexes などのコンポーネントを提供します。
  • LlamaIndex は、他のインデックスからインデックスを構成できる能力を重視しており、複数のデータソースを含む複雑なクエリやワークフローに非常に効果的です。

統合:

  • LangChain はサードパーティサービスとの統合を提供し、特定の LLM プロバイダー向けのパートナーパッケージで拡張できます。
  • LlamaIndex は様々なデータソースのシームレスな統合を実現するデータコネクタを提供し、データ品質とパフォーマンスを向上させます。

LlamaIndex vs LangChain: 実践的な例の比較

Ming 氏の Medium 記事を参考に、LlamaIndex と LangChain を比較する実践的な例をいくつか紹介します。

ローカル LLM を使ったチャットボットの作成

コード例では、両方のフレームワークで LLM を初期化し、チャットやり取りの出力を表示する方法を示しています。

LlamaIndex コード:

from llama_index.llms import ChatMessage, OpenAILike

llm = OpenAILike(
    api_base="http://localhost:1234/v1",
    timeout=600,
    api_key="loremIpsum",
    is_chat_model=True,
    context_window=32768,
)
chat_history = [
    ChatMessage(role="system", content="You are a bartender."),
    ChatMessage(role="user", content="What do I enjoy drinking?"),
]
output = llm.chat(chat_history)
print(output)

LangChain コード:

from langchain.schema import HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    openai_api_base="http://localhost:1234/v1",
    request_timeout=600,
    openai_api_key="loremIpsum",
    max_tokens=32768,
)
chat_history = [
    SystemMessage(content="You are a bartender."),
    HumanMessage(content="What do I enjoy drinking?"),
]
print(llm(chat_history))

ローカルファイル向け RAG システムの構築

コードスニペットでは、データのロード、インデックスの作成、クエリの実行方法を示しています。

LlamaIndex コード:

from llama_index import ServiceContext, SimpleDirectoryReader, VectorStoreIndex

service_context = ServiceContext.from_defaults(  
    embed_model="local",  
    llm=llm, # This should be the LLM initialized in the task above.
)  
documents = SimpleDirectoryReader(
    input_dir="mock_notebook/",
).load_data()  
index = VectorStoreIndex.from_documents(  
    documents=documents,
    service_context=service_context,
)
engine = index.as_query_engine(  
    service_context=service_context,  
)
output = engine.query("What do I like to drink?")  
print(output)

LangChain コード:

from langchain_community.document_loaders import DirectoryLoader  
  
# pip install "unstructured[md]"  
loader = DirectoryLoader("mock_notebook/", glob="*.md")  
docs = loader.load()  
  
from langchain.text_splitter import RecursiveCharacterTextSplitter  
  
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)  
splits = text_splitter.split_documents(docs)  
  
from langchain_community.embeddings.fastembed import FastEmbedEmbeddings  
from langchain_community.vectorstores import Chroma  
  
vectorstore = Chroma.from_documents(documents=splits, embedding=FastEmbedEmbeddings())  
retriever = vectorstore.as_retriever()  
  
from langchain import hub  
  
# pip install langchainhub  
prompt = hub.pull("rlm/rag-prompt")  
  
  
def format_docs(docs):  
    return "\
\
".join(doc.page_content for doc in docs)  
  
  
from langchain_core.runnables import RunnablePassthrough  
  
rag_chain = (  
    {"context": retriever | format_docs, "question": RunnablePassthrough()}  
    | prompt  
    | llm # This should be the LLM initialized in the task above.
)  
print(rag_chain.invoke("What do I like to drink?"))

比較から、RAG システムに焦点を当てた LlamaIndex はよりシンプルなアプローチを提供する一方、LangChain はより抽象度の高い方法を提供していることがわかります。

LlamaIndex vs LangChain: LlamaIndex でカスタム LLM を使用する方法

Novita AI の LLM API を LlamaIndex と統合するには、Novita AI の API 呼び出しを LlamaIndex フレームワーク 内でラップするカスタムアダプタを作成する必要があります。以下にその概念的な例を示します。この例では、API と LlamaIndex フレームワークの基本的な理解を前提としています。

ステップ 1: Novita AI LLM 用カスタムアダプタの定義

まず、Novita AI LLM 用のカスタムアダプタを定義します。

class NovitaAILLM:
    def __init__(self, api_key):
        from openai import OpenAI
        self.client = OpenAI(api_key=api_key, base_url="https://api.novita.ai/v3/openai")

    def complete_chat(self, messages, stream=False, max_tokens=512):
        response = self.client.chat.completions.create(
            model="Nous-Hermes-2-Mixtral-8x7B-DPO",
            messages=messages,
            stream=stream,
            max_tokens=max_tokens
        )
        return response

ステップ 2: LlamaIndex サービスコンテキストへの統合

次に、このアダプタを LlamaIndex のサービスコンテキストに統合します。以下はその概念的な例です。

from llama_index import (
    KeywordTableIndex,
    SimpleDirectoryReader,
    ServiceContext,
)
from llama_index.llms import LLM

class NovitaAILLMAdapter(LLM):
    def __init__(self, api_key):
        self.novitailm = NovitaAILLM(api_key)

    def generate_text(self, prompt, stop_sequences=None, **kwargs):
        # Prepare the messages for the chat completion
        messages = [
            {"role": "system", "content": prompt}
        ]
        # Call the Novita AI LLM to complete the chat
        response = self.novitailm.complete_chat(messages)
        if isinstance(response, list):  # If streaming, collect all chunks
            return "".join([chunk.choices[0].delta.content for chunk in response])
        else:
            return response.choices[0].message.content

# Initialize the Novita AI LLM adapter with your API key
novitailm_adapter = NovitaAILLMAdapter(api_key="<YOUR Novita AI API Key>")

# Create the service context with the custom LLM adapter
service_context = ServiceContext.from_defaults(llm=novitailm_adapter)

# Load documents and build the index as before
documents = SimpleDirectoryReader("data").load_data()
index = KeywordTableIndex.from_documents(documents, service_context=service_context)

# Now you can use the index with the custom LLM for queries
query_engine = index.as_query_engine()
response = query_engine.query("What did the author do after his time at Y Combinator?")
print(response)

この例では、Novita AI の LLM 用カスタムアダプタを作成し、LlamaIndex フレームワークに統合する方法を示しています。<YOUR Novita AI API Key> は実際の Novita AI の API キーに置き換えてください。

これは概念的な例であり、使用しているライブラリのバージョンや Novita AI の LLM の詳細な API 仕様に合わせて調整が必要になる場合があります。最新かつ正確な情報については、常に公式ドキュメントを参照してください。

LlamaIndex vs LangChain: LangChain でカスタム LLM を使用する方法

Novita AI LLM API** カスタム LLM** を用いて LangChain と統合するには、LangChain の LLM クラスを拡張し、Novita AI の API をロジックに使用するカスタムクラスを作成する必要があります。

以下にその手順を示します。

ステップ 1: OpenAI Python ライブラリのインストール

まず、Novita AI の API とのやり取りに使用する OpenAI ライブラリがインストールされていることを確認します。

pip install 'openai>=1.0.0'

ステップ 2: 必要なライブラリのインポート

LangChain と OpenAI ライブラリから必要なモジュールをインポートします。

from typing import Any, Dict, Iterator, List, Optional
from langchain_core.callbacks.manager import CallbackManagerForLLMRun
from langchain_core.language_models.llms import LLM
from langchain_core.outputs import GenerationChunk
from openai import OpenAI

ステップ 3: カスタム LLM クラスの定義

LLM クラスを拡張して、Novita AI の API を使用するカスタム LLM を作成します。

class NovitaAILLM(LLM):
    def __init__(self, api_key: str, model_name: str = "Nous-Hermes-2-Mixtral-8x7B-DPO"):
        self.api_key = api_key
        self.model_name = model_name
        self.client = OpenAI(api_key=api_key, base_url="https://api.novita.ai/v3/openai")

    def _call(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> str:
        """Run the LLM on the given input."""
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": prompt}],
            stream=False,
            max_tokens=512,
        )
        return response.choices[0].message.content

    def _stream(
        self,
        prompt: str,
        stop: Optional[List[str]] = None,
        run_manager: Optional[CallbackManagerForLLMRun] = None,
        **kwargs: Any,
    ) -> Iterator[GenerationChunk]:
        """Stream the LLM on the given prompt."""
        response = self.client.chat.completions.create(
            model=self.model_name,
            messages=[{"role": "user", "content": prompt}],
            stream=True,
            max_tokens=512,
        )
        for chunk in response:
            chunk_text = chunk.choices[0].delta.content or ""
            yield GenerationChunk(text=chunk_text)

    @property
    def _identifying_params(self) -> Dict[str, Any]:
        """Return a dictionary of identifying parameters."""
        return {
            "model_name": self.model_name,
        }

    @property
    def _llm_type(self) -> str:
        """Get the type of language model used by this chat model. Used for logging purposes only."""
        return "NovitaAILLM"

ステップ 4: カスタム LLM の初期化と使用

Novita AI の API キーを使ってカスタム LLM のインスタンスを作成し、テキスト生成に使用します。

# Replace with your actual Novita AI API key
novita_api_key = "<YOUR Novita AI API Key>"

# Initialize the custom LLM
novita_llm = NovitaAILLM(api_key=novita_api_key)

# Generate text
prompt = "Hi there!"
response = novita_llm._call(prompt=prompt)
print(response)

# Or stream the response
for chunk in novita_llm._stream(prompt=prompt):
    print(chunk.text, end="")

このコードは、Novita AI の API を使用して与えられたプロンプトに基づいてテキストを生成するカスタム LLM を設定します。_call メソッドは非ストリーミング応答用、_stream メソッドはストリーミング応答用です。Novita AI の API ドキュメントと特定の要件に基づいて、model_name やその他のパラメータを適宜調整してください。

結論

LlamaIndex と LangChain はどちらも大規模言語モデルを扱うための貴重なツールであり、それぞれ明確な強みを持っています。LlamaIndex はデータの取り込みと検索に優れており、特定のデータの効率的な処理や高度な質問応答システムを必要とするプロジェクトに最適です。LangChain は、モジュール式アーキテクチャと広範な統合機能を備え、LLM アプリケーションの開発・デプロイのためのより包括的なフレームワークを提供します。どちらを選ぶかはプロジェクトの具体的なニーズによります。

よくある質問

LangChain と LlamaIndex は一緒に使えますか?

はい。LLM プロジェクトの具体的なニーズによります。

LangChain は本番環境に適していますか?

はい、LangChain 0.1 以降は本番環境で使用可能です。

RAG に適しているのは LlamaIndex と LangChain のどちらですか?

データ検索・検索機能が主な焦点であれば LlamaIndex をお勧めします。複雑なワークフローを処理できる柔軟なフレームワークが必要な場合は LangChain の方が適しています。

Novita AI は、AI の野望を実現するオールインワンのクラウドプラットフォームです。統合 API、サーバーレス、GPU インスタンス — コスト効率の高いツールを提供します。インフラストラクチャ不要、無料で始めて、AI ビジョンを現実に。

おすすめの記事

LangChain で LLM を作成する方法:ステップバイステップガイド

ストリーミング LangChain をマスター:LLM との対話のヒント