🙄

LangChain超入門

2025/02/26に公開

近年、OpenAIのChatGPTやGoogleのBardに代表される「大規模言語モデル(LLM: Large Language Model)」が目覚ましい進化を遂げ、私たちの生活やビジネスに大きな変革をもたらし始めています。LLMは、まるで人間のように自然な文章を生成したり、複雑な質問に答えたり、創造的なアイデアを生み出したりと、驚くべき能力を発揮します。

しかし、LLMのポテンシャルを最大限に引き出し、実用的なAIアプリケーションを開発するとなると、途端にハードルが上がります。

「LLMをどうやって業務システムに組み込めばいいんだろう?」
「もっと複雑な処理をLLMにさせたいけど、どうすれば…?」
「毎回同じようなプロンプトを書くのが面倒…」

そんな悩みを抱えている方も多いのではないでしょうか?

そこで登場するのが「LangChain」です!

LangChainは、LLMアプリケーション開発を劇的に楽にするための強力なフレームワークです。LangChainを使えば、複雑なLLMアプリケーションも、まるでレゴブロックを組み立てるように、簡単かつ効率的に開発できるようになります。

この記事では、LangChainの基本から実践までを、AI初心者の方にも** предельно понятно и тщательно解説します。LangChainの主要な構成要素**、基本的な使い方応用的なテクニック、そしてエコシステムまで、3万文字を超えるボリュームで網羅的に解説しますので、LangChainをマスターして、あなたもLLMアプリケーション開発の最前線に飛び込みましょう!

1. LangChainとは? - LLMアプリケーション開発を「楽」にする魔法の道具

1.1 LLMアプリケーション開発の現状と課題

LLMは、テキスト生成、文章要約、質問応答、翻訳、コード生成など、様々なタスクをこなせる万能なAIです。しかし、LLMを単体で使うだけでは、実用的なアプリケーションを開発するには限界があります。

例えば、

  • 複雑なタスクの実現: LLM単体では、複数の処理を組み合わせた複雑なタスク(例:Web検索と情報抽出を組み合わせた質問応答システム)を実装するのは困難です。
  • 外部データとの連携: LLMは学習データに含まれる情報しか持っていないため、最新情報や特定のドキュメントに基づいた回答は苦手です。外部のデータベースやAPIと連携する必要があります。
  • 対話履歴の管理: チャットボットのような対話型アプリケーションでは、過去の会話履歴をLLMに記憶させ、文脈に沿った自然な対話を続ける必要があります。
  • プロンプト管理の煩雑さ: LLMの性能を最大限に引き出すには、適切なプロンプト(指示文)を作成する必要がありますが、プロンプトの作成、管理、改善は手間がかかります。

これらの課題を解決し、LLMのポテンシャルを最大限に引き出すためには、LLMアプリケーション開発を効率化するためのフレームワークが不可欠です。

1.2 LangChainが提供するソリューション - 魔法のレゴブロック

LangChainは、まさにLLMアプリケーション開発の課題を解決するために生まれたフレームワークです。LangChainは、LLMアプリケーション開発に必要な様々な**「部品(モジュール)」と、それらを「組み合わせるための仕組み」**を提供します。

LangChainを例えるなら、レゴブロックのようなものです。

  • レゴブロック(LangChainのモジュール): LLM、プロンプト、Chain、Agent、Memoryなど、LLMアプリケーション開発に必要な機能が部品化されています。
  • 組み立て説明書(LangChainのフレームワーク): これらの部品を組み合わせて、目的のアプリケーションを構築するための設計図と手順が用意されています。

LangChainを使うことで、開発者は複雑な処理を自分で実装する必要がなくなり部品を組み合わせるだけで高度なLLMアプリケーションを開発できるようになります。まるで魔法のように、LLMアプリケーション開発が**「楽」**になるのです。

1.3 LangChainでできること - 広がる可能性

LangChainを活用することで、様々なLLMアプリケーションを開発できます。具体例を見てみましょう。

  • 文書要約: 大量のテキストデータ(論文、レポート、ニュース記事など)を効率的に処理し、重要な情報を抽出して要約を作成できます。ビジネスにおける情報収集や分析業務を効率化できます。
  • 質問応答: ユーザーからの質問に対して、関連性の高い情報に基づいて正確に回答できます。FAQシステムやカスタマーサポートの自動化に活用できます。
  • チャットボット: 自然な対話を通じてユーザーをサポートし、タスクを完了させるチャットボットを開発できます。顧客対応、社内ヘルプデスク、教育など、幅広い分野で活用できます。
  • エージェント: 自律的にタスクを実行し、複雑な問題を解決するAIエージェントを開発できます。Web検索、データ分析、意思決定支援など、高度なタスクの自動化に貢献します。

これらはほんの一例です。LangChainは、あなたのアイデア次第で、無限の可能性を秘めたLLMアプリケーション開発を可能にします。

1.4 LangChainを使うメリット - 開発生産性を爆上げ

LangChainを使うことで、開発者は多くのメリットを享受できます。

  • 開発効率の向上: 共通処理を部品化することで、開発の手間を大幅に削減できます。複雑な処理も、既存のモジュールを組み合わせるだけで簡単に実装できます。
  • 高度な機能の実現: LangChainは、高度なLLMアプリケーションを開発するための様々な機能を提供します。ChainやAgentを活用することで、複雑な処理や自律的なタスク実行も実現可能です。
  • 柔軟性と拡張性: LangChainは、様々なLLM(OpenAI, Cohere, Hugging Faceなど)や外部ツール(検索エンジン、データベース、APIなど)との連携を容易にします。アプリケーションの要件に合わせて柔軟に拡張できます。
  • 最新技術のキャッチアップ: LangChainは、LLM技術の進化に迅速に対応しています。常に最新のLLMや技術を取り入れ、開発者に最新の機能を提供し続けます。
  • 活発なコミュニティ: LangChainは、世界中の開発者によって支えられています。活発なコミュニティがあり、情報交換や質問応答が盛んに行われています。

LangChainは、まさにLLMアプリケーション開発の「強い味方」です。LangChainを使いこなすことで、あなたはLLMアプリケーション開発の生産性を爆上げし、革新的なAIアプリケーションを次々と生み出せるようになるでしょう。

2. LangChainの主要な構成要素 - 魔法の部品たち

LangChainは、LLMアプリケーション開発に必要な機能を、モジュールと呼ばれる部品として提供しています。ここでは、LangChainの主要なモジュールを一つずつ丁寧に解説します。

2.1 LLMs - 言語モデルとのインターフェース

LLMs(Language Models)モジュールは、LangChainが連携する様々な言語モデルへの統一的なインターフェースを提供します。

LangChainは、OpenAIのGPTシリーズ、GoogleのPaLM、AnthropicのClaude、Hugging FaceのTransformersなど、多様なLLMをサポートしています。LLMsモジュールを使うことで、開発者はLLMの種類を意識することなく、同じ方法で様々なLLMを呼び出し、利用できます。

LLMsモジュールの役割:

  • LLMへの接続: 各LLMのAPIキーやエンドポイントなどの設定を管理し、LLMへの接続を確立します。
  • テキスト生成: プロンプト(指示文)をLLMに渡し、テキスト生成を実行します。
  • LLMの切り替え: アプリケーションの要件や目的に応じて、利用するLLMを簡単に切り替えることができます。

LLMsモジュールの使い方:

LangChainでLLMを利用するには、まず利用したいLLMに対応するクラスをインスタンス化します。例えば、OpenAIのGPT-3.5 Turboを利用する場合は、OpenAIクラスを以下のようにインスタンス化します。

from langchain.llms import OpenAI

llm = OpenAI(openai_api_key="YOUR_API_KEY", model_name="gpt-3.5-turbo")

openai_api_keyには、OpenAI APIのAPIキーを設定します。model_nameには、利用したいモデル名(例:gpt-3.5-turbogpt-4など)を指定します。

LLMにテキスト生成を実行させるには、predict()メソッドを使います。

output = llm.predict("猫について教えて")
print(output)

predict()メソッドにプロンプト("猫について教えて")を渡すと、LLMがテキストを生成し、その結果がoutput変数に格納されます。

LangChainは、OpenAI以外にも、Hugging Face Hubで公開されているLLMや、Cohere、AnthropicなどのLLMにも対応しています。利用したいLLMに合わせて、適切なクラスをインスタンス化し、APIキーやモデル名などを設定することで、簡単に様々なLLMを利用できます。

2.2 Prompts - LLMへの指示を自在に操る

Promptsモジュールは、LLMへの**指示文(プロンプト)**を効果的に作成、管理するための機能を提供します。

プロンプトは、LLMの挙動をコントロールするための重要な要素です。同じLLMでも、プロンプトの内容によって、出力されるテキストの質や内容が大きく変わります。プロンプトエンジニアリングと呼ばれるように、プロンプトを工夫することで、LLMの能力を最大限に引き出すことができます。

Promptsモジュールの役割:

  • PromptTemplate: プロンプトのテンプレートを作成し、再利用性を高めます。変数を使ってプロンプトをパラメータ化し、動的に内容を変化させることができます。
  • Example Selectors: プロンプトに具体的な例を含めることで、LLMの出力精度を向上させるFew-shot learningを実現します。Example Selectorsは、状況に応じて最適な例を自動的に選択する機能を提供します。
  • Output Parsers: LLMから出力されたテキストを、構造化されたデータ(JSON、リストなど)に変換します。LLMの出力を後続の処理で扱いやすくします。

Promptsモジュールの使い方:

PromptTemplateを使うと、プロンプトをテンプレート化し、変数を使って動的に内容を変化させることができます。例えば、以下の例では、{animal}という変数を定義したプロンプトテンプレートを作成しています。

from langchain.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template("日本の{animal}について教えて")

PromptTemplate.from_template()関数に、テンプレートとなるプロンプト文字列を渡します。{変数名}で変数を定義できます。

テンプレートに具体的な値を設定するには、format()メソッドを使います。

prompt = prompt_template.format(animal="猫")
print(prompt)

format()メソッドに、変数名と値をキーワード引数で渡すと、テンプレート内の変数が値に置き換えられたプロンプト文字列が生成されます。

Example Selectorsを使うと、Few-shot learningを簡単に実現できます。例えば、以下の例では、LengthBasedExampleSelectorを使って、プロンプトの長さに応じて最適な例を選択するExample Selectorを作成しています。

from langchain.prompts import PromptTemplate, FewShotPromptTemplate
from langchain.prompts.example_selector import LengthBasedExampleSelector

examples = [
    {"input": "猫", "output": "猫は気まぐれな動物です。"},
    {"input": "犬", "output": "犬は忠実な動物です。"},
    {"input": "パンダ", "output": "パンダは笹を食べる動物です。"},
    {"input": "コアラ", "output": "コアラはユーカリの葉を食べる動物です。"},
    {"input": "カピバラ", "output": "カピバラは温泉に入る動物です。"},
]

example_prompt = PromptTemplate(input_variables=["input", "output"], template="Input: {input}\nOutput: {output}")

example_selector = LengthBasedExampleSelector(
    examples=examples,
    example_prompt=example_prompt,
    max_length=25,
)

few_shot_prompt = FewShotPromptTemplate(
    example_selector=example_selector,
    example_prompt=example_prompt,
    prefix="動物に関する質問に答えてください。",
    suffix="Input: {input}\nOutput:",
    input_variables=["input"]
)

prompt = few_shot_prompt.format(input="キリン")
print(prompt)

LengthBasedExampleSelectorは、プロンプトの最大長さを指定すると、その長さに収まるように例を自動的に選択します。FewShotPromptTemplateは、Example Selectorとプロンプトテンプレートを組み合わせて、Few-shot learning用のプロンプトを作成します。

Output Parsersを使うと、LLMの出力を構造化されたデータに変換できます。例えば、以下の例では、CommaSeparatedListOutputParserを使って、LLMの出力をカンマ区切りのリストに変換しています。

from langchain.output_parsers import CommaSeparatedListOutputParser

output_parser = CommaSeparatedListOutputParser()
format_instructions = output_parser.get_format_instructions()
prompt_template = PromptTemplate(
    template="好きな色を3つ、カンマ区切りで教えてください。\n{format_instructions}",
    input_variables=[],
    partial_variables={"format_instructions": format_instructions}
)

prompt = prompt_template.format()
llm = OpenAI(openai_api_key="YOUR_API_KEY")
output = llm.predict(prompt)
parsed_output = output_parser.parse(output)
print(parsed_output)

CommaSeparatedListOutputParserは、LLMの出力をカンマ区切りのリストとしてパースします。get_format_instructions()メソッドで、LLMに出力フォーマットを指示するための文字列を取得できます。parse()メソッドで、LLMの出力をパースし、構造化されたデータ(リスト)を取得できます。

Promptsモジュールを使いこなすことで、プロンプトの作成、管理、改善を効率化し、LLMの性能を最大限に引き出すことができます。

2.3 Chains - 処理を繋げてLLMをパワーアップ

Chainsモジュールは、複数の処理連鎖させて実行するための仕組みを提供します。LangChainの中核となるモジュールの一つです。

LLMアプリケーションでは、複数の処理を組み合わせることで、より複雑なタスクを実現できます。例えば、

  • 質問応答: ユーザーの質問をLLMで解釈し、関連情報をWeb検索で取得し、取得した情報に基づいてLLMが回答を生成する。
  • 文書要約: 大量の文書を複数のLLMで並列処理し、それぞれの要約結果を統合して最終的な要約を作成する。
  • チャットボット: ユーザーの発言内容に応じて、適切なChainを動的に選択し、対話を進める。

Chainsモジュールを使うことで、これらの複雑な処理をシンプルに記述し、効率的に実行できます。

Chainsモジュールの役割:

  • 処理の連結: 複数のモジュール(LLMs, Prompts, Utilities, Agents, Memoryなど)を連結し、ワークフローを構築します。
  • 処理の抽象化: 複雑な処理をChainとしてカプセル化し、再利用性、可読性、保守性を高めます。
  • 処理の制御: Chainの実行順序、条件分岐、エラーハンドリングなどを制御できます。

Chainsモジュールの種類:

LangChainは、様々な種類のChainを提供しています。代表的なChainの種類を見てみましょう。

  • LLMChain: LLMとPromptTemplateを組み合わせた最も基本的なChain。プロンプトに基づいてLLMを呼び出し、テキスト生成を行います。
  • SimpleSequentialChain: 複数のChainを順番に実行するChain。前のChainの出力を次のChainの入力として渡します。
  • SequentialChain: SimpleSequentialChainよりも柔軟なSequential Chain。複数の入力変数と出力変数を持ち、Chain間で変数を共有できます。
  • TransformChain: 入力データを変換するChain。LLM以外の処理(例:データ加工、API呼び出し)をChainに組み込みたい場合に便利です。
  • RouterChain: 入力内容に応じて、複数のChainの中から適切なChainを動的に選択するChain。チャットボットのような対話型アプリケーションで、ユーザーの発言内容に応じて処理を切り替えたい場合に役立ちます。

Chainsモジュールの使い方:

LLMChainは、LLMとPromptTemplateを組み合わせた最も基本的なChainです。以下の例では、LLMChainを使って、指定された動物についてLLMに質問しています。

from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

llm = OpenAI(openai_api_key="YOUR_API_KEY")
prompt_template = PromptTemplate.from_template("日本の{animal}について教えて")
animal_chain = LLMChain(llm=llm, prompt=prompt_template)

output = animal_chain.run("猫")
print(output)

LLMChainクラスをインスタンス化する際に、llm引数にLLMオブジェクト、prompt引数にPromptTemplateオブジェクトを渡します。run()メソッドに、PromptTemplateの変数に渡す値をキーワード引数で渡すと、Chainが実行され、LLMの出力結果が返されます。

SimpleSequentialChainは、複数のChainを順番に実行するChainです。以下の例では、SimpleSequentialChainを使って、まず動物についてLLMに質問し、その回答を使ってさらに別の質問をしています。

from langchain.chains import SimpleSequentialChain
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

llm = OpenAI(openai_api_key="YOUR_API_KEY")

prompt1 = PromptTemplate.from_template("日本の{animal}について教えて")
chain1 = LLMChain(llm=llm, prompt=prompt1)

prompt2 = PromptTemplate.from_template("{animal}の鳴き声は?")
chain2 = LLMChain(llm=llm, prompt=prompt2)

overall_chain = SimpleSequentialChain(chains=[chain1, chain2], verbose=True)
output = overall_chain.run("猫")
print(output)

SimpleSequentialChainクラスをインスタンス化する際に、chains引数に実行したいChainオブジェクトのリストを渡します。verbose=Trueを設定すると、Chainの実行過程が詳細に表示されます。

SequentialChainは、SimpleSequentialChainよりも柔軟なSequential Chainです。以下の例では、SequentialChainを使って、動物の名前と色を入力として受け取り、動物の説明文と色の説明文を生成しています。

from langchain.chains import SequentialChain
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

llm = OpenAI(openai_api_key="YOUR_API_KEY")

prompt1 = PromptTemplate.from_template("{animal}について教えて")
chain1 = LLMChain(llm=llm, prompt=prompt1, output_key="animal_description")

prompt2 = PromptTemplate.from_template("{color}はどんな色?")
chain2 = LLMChain(llm=llm, prompt=prompt2, output_key="color_description")

overall_chain = SequentialChain(
    chains=[chain1, chain2],
    input_variables=["animal", "color"],
    output_variables=["animal_description", "color_description"],
    verbose=True
)

output = overall_chain({"animal": "猫", "color": "白色"})
print(output)

SequentialChainクラスをインスタンス化する際に、chains引数にChainオブジェクトのリスト、input_variables引数に入力変数のリスト、output_variables引数に出力変数のリストを渡します。各LLMChainのoutput_key引数で、出力変数の名前を指定します。run()メソッドではなく、()でChainを実行し、入力変数を辞書形式で渡します。出力結果は、出力変数をキーとする辞書形式で返されます。

Chainsモジュールを使いこなすことで、複雑なLLMアプリケーションを効率的に開発し、LLMの可能性をさらに広げることができます。

2.4 Agents - 自律的に考え、行動するAIエージェント

Agentsモジュールは、自律的に考え、行動するAIエージェントを構築するための機能を提供します。

Agentは、与えられたタスクを達成するために、自ら思考し、適切なツールを選択し、行動します。まるでAI秘書のように、複雑なタスクを自律的にこなすことができます。

Agentsモジュールの役割:

  • 意思決定: 与えられたタスクと現在の状況に基づいて、次に取るべき行動を決定します。
  • ツール選択: 利用可能なツールの中から、タスク達成に最適なツールを選択します。
  • ツール実行: 選択したツールを実行し、結果を取得します。
  • 反復処理: 思考、ツール選択、ツール実行、結果取得のサイクルを反復し、タスクを達成します。

Agentsモジュールの種類:

LangChainは、様々な種類のエージェントを提供しています。代表的なエージェントの種類を見てみましょう。

  • Zero-shot ReAct Agent: 事前に学習データを与えずに、プロンプトのみでタスクを実行するエージェント。ReAct(Reasoning and Acting)と呼ばれる思考プロセスに基づいて行動します。
  • Conversational Agent: 対話を通じてタスクを実行するエージェント。会話履歴を記憶し、文脈に沿った自然な対話を行います。
  • Chat Agent: チャットモデル(例:GPT-3.5 Turbo、GPT-4)に最適化されたエージェント。より自然で人間らしい対話を実現します。

Tools:

Agentが利用できるツールは、Agentsモジュールにおいて重要な役割を果たします。ツールは、Agentが外部環境とインタラクトするためのインターフェースです。

LangChainは、様々な種類のツールを標準で提供しています。

  • 検索エンジン: Web検索を行うためのツール(例:Google Search、Wikipedia)。
  • 計算機: 数値計算を行うためのツール。
  • API: 外部APIを呼び出すためのツール。
  • データベース: データベースにアクセスするためのツール。
  • ファイルシステム: ファイルシステムにアクセスするためのツール。

開発者は、これらの標準ツールを組み合わせて利用したり、カスタムツールを自作したりできます。

Agentsモジュールの使い方:

Zero-shot ReAct Agentは、最も基本的なエージェントの一つです。以下の例では、Zero-shot ReAct Agentを使って、Wikipediaで日本の首都を検索し、回答を生成しています。

from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.llms import OpenAI
from langchain.utilities import WikipediaAPIWrapper

llm = OpenAI(temperature=0, openai_api_key="YOUR_API_KEY")
wikipedia = WikipediaAPIWrapper()
tools = [
    Tool(
        name="Wikipedia",
        func=wikipedia.run,
        description="Wikipediaで情報を検索する"
    )
]
agent = initialize_agent(
    tools, 
    llm, 
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 
    verbose=True
)
output = agent.run("日本の首都は?")
print(output)

initialize_agent()関数を使って、Agentを初期化します。tools引数に、Agentが利用できるツールのリストを渡します。llm引数にLLMオブジェクト、agent引数にエージェントの種類(AgentType.ZERO_SHOT_REACT_DESCRIPTION)を指定します。verbose=Trueを設定すると、Agentの思考過程が詳細に表示されます。run()メソッドにタスク("日本の首都は?")を渡すと、Agentがタスクを実行し、結果を返します。

Agentは、複雑なタスクを自律的に実行し、人間をサポートする強力なAIシステムを構築するための鍵となります。

2.5 Memory - 会話履歴を記憶する

Memoryモジュールは、会話履歴文脈記憶するための機能を提供します。チャットボットのような対話型アプリケーションにおいて、自然でスムーズな対話を実現するために不可欠なモジュールです。

LLMは、基本的にステートレスであり、過去の会話内容を記憶しません。そのため、過去の発言内容を踏まえた応答や、文脈を理解した対話を行うためには、Memoryモジュールを使って会話履歴を明示的に管理する必要があります。

Memoryモジュールの役割:

  • 会話履歴の保存: 過去のユーザーの発言とAIの発言を記憶します。
  • 文脈の維持: 会話履歴に基づいて、対話の文脈を維持します。
  • 長期記憶: 会話履歴を長期的に保存し、過去の対話を振り返ることができます。

Memoryモジュールの種類:

LangChainは、様々な種類のMemoryを提供しています。代表的なMemoryの種類を見てみましょう。

  • ConversationBufferMemory: 会話履歴をすべてメモリに保存する最もシンプルなMemory。
  • ConversationSummaryMemory: 会話履歴を要約してメモリに保存するMemory。会話履歴が長くなっても、メモリ消費量を抑えられます。
  • ConversationBufferWindowMemory: 最新の一定数の会話履歴のみをメモリに保存するMemory。会話履歴が長くなりすぎないように制限できます。
  • ConversationTokenBufferMemory: 最新の一定トークン数の会話履歴のみをメモリに保存するMemory。トークン数で会話履歴を制限したい場合に便利です。
  • VectorStoreRetrieverMemory: 会話履歴をベクトルデータベースに保存し、類似度検索によって関連性の高い会話履歴を抽出するMemory。より高度な文脈理解を実現できます。

Memoryモジュールの使い方:

ConversationBufferMemoryは、最もシンプルなMemoryです。以下の例では、ConversationBufferMemoryを使って、チャットボットとの会話履歴を記憶し、文脈に沿った対話を実現しています。

from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
from langchain.llms import OpenAI

memory = ConversationBufferMemory()
llm = OpenAI(openai_api_key="YOUR_API_KEY")
conversation = ConversationChain(llm=llm, memory=memory, verbose=True)

print(conversation.predict(input="こんにちは!"))
print(conversation.predict(input="今日はいい天気ですね。"))
print(conversation.predict(input="どこかおすすめの場所はありますか?"))

ConversationBufferMemoryクラスをインスタンス化し、ConversationChainクラスのmemory引数に渡します。ConversationChainは、会話履歴をMemoryに保存し、過去の会話内容を踏まえた応答を生成するChainです。predict()メソッドでユーザーの発言をChainに渡すと、AIの応答が返されます。2回目以降の発言では、過去の会話履歴がMemoryに保存されているため、文脈に沿った自然な対話が実現されます。

Memoryモジュールを使いこなすことで、より人間らしい自然な対話を行うチャットボットや、文脈を理解した高度なLLMアプリケーションを開発できます。

2.6 Callbacks - 処理の実行状況を監視する

Callbacksモジュールは、LangChainの処理の実行状況監視するための機能を提供します。ChainやAgentの実行中に、様々なイベント(処理の開始、終了、エラー発生など)を検知し、ログ出力デバッグモニタリングなどに活用できます。

Callbacksモジュールは、LangChainアプリケーションの開発、デバッグ、運用を効率化するための重要なツールです。

Callbacksモジュールの役割:

  • イベント監視: ChainやAgentの実行中に発生する様々なイベントを監視します。
  • ログ出力: イベント発生時にログを出力します。処理の実行状況を記録し、デバッグや分析に役立てます。
  • デバッグ: エラー発生時に詳細な情報を出力し、デバッグを支援します。
  • モニタリング: 処理の実行時間、トークン数、コストなどを計測し、モニタリングやパフォーマンス分析に活用します。
  • カスタム処理: イベント発生時にカスタム処理を実行できます。例えば、処理の進捗状況をUIに表示したり、エラー発生時に通知を送信したりできます。

Callbacksモジュールの種類:

LangChainは、様々な種類のCallbackを提供しています。代表的なCallbackの種類を見てみましょう。

  • StdOutCallbackHandler: イベント発生時に標準出力にログを出力するCallback。最も基本的なCallbackです。
  • FileCallbackHandler: イベント発生時にファイルにログを出力するCallback。ログをファイルに保存したい場合に便利です。
  • LangChainTracer: LangChainが提供するトレース機能を利用するためのCallback。LangChainアプリケーションの実行状況をWeb UIで可視化できます。(LangSmithとの連携が必要)
  • カスタムCallback: 開発者が自作できるCallback。独自のログ出力、デバッグ処理、モニタリング処理などを実装できます。

Callbacksモジュールの使い方:

StdOutCallbackHandlerは、最もシンプルなCallbackです。以下の例では、StdOutCallbackHandlerを使って、Chainの実行状況を標準出力に表示しています。

from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from langchain.callbacks import StdOutCallbackHandler

handler = StdOutCallbackHandler()
llm = OpenAI(openai_api_key="YOUR_API_KEY")
prompt_template = PromptTemplate.from_template("日本の{animal}について教えて")
chain = LLMChain(llm=llm, prompt=prompt_template, callbacks=[handler])

output = chain.run("猫")
print(output)

StdOutCallbackHandlerクラスをインスタンス化し、Chainクラスのcallbacks引数にリスト形式で渡します。Chainを実行すると、処理の開始、プロンプトの送信、LLMの応答、処理の終了などのイベントが発生するたびに、ログが標準出力に表示されます。

カスタムCallbackを自作することもできます。Callbackクラスを継承し、イベントに対応するメソッド(on_chain_starton_llm_endなど)をオーバーライドすることで、独自の処理を実装できます。

Callbacksモジュールを使いこなすことで、LangChainアプリケーションの実行状況を詳細に把握し、開発、デバッグ、運用を効率化できます。

3. LangChainの基本的な使い方 - 実践!コードを書いてみよう

ここでは、LangChainの基本的な使い方を、コード例を交えながらステップバイステップで解説します。実際に手を動かしながら、LangChainの基本をマスターしましょう。

3.1 環境構築 - LangChainを始める準備

LangChainを使うためには、まず環境構築が必要です。以下の手順で環境構築を行いましょう。

  1. Pythonのインストール: LangChainはPython製のフレームワークです。Pythonがインストールされていない場合は、Python公式サイトからPythonをインストールしてください。(Python 3.8以上推奨)

  2. pipのインストール: pipはPythonのパッケージ管理システムです。Pythonをインストールする際にpipも一緒にインストールされることが多いですが、もしインストールされていない場合は、pipをインストールしてください。

  3. LangChainのインストール: pipを使ってLangChainをインストールします。ターミナルまたはコマンドプロンプトを開き、以下のコマンドを実行してください。

    pip install langchain
    
  4. OpenAI APIキーの設定: OpenAIのLLM(GPT-3、GPT-4など)を利用する場合は、OpenAI APIのAPIキーが必要です。OpenAI公式サイトでAPIキーを取得し、環境変数OPENAI_API_KEYに設定してください。

    • macOS/Linux:
      export OPENAI_API_KEY="YOUR_API_KEY"
      
      .bashrc.zshrcなどの設定ファイルに追記しておくと、ターミナルを再起動しても設定が保持されます。
    • Windows:
      set OPENAI_API_KEY=YOUR_API_KEY
      
      「システムのプロパティ」→「環境変数」から、環境変数を設定することもできます。

    他のLLMを利用する場合も、それぞれのLLMが提供するAPIキーや認証情報を設定する必要があります。

これでLangChainを使う準備が整いました!

3.2 簡単なLLMの呼び出し - LLMと会話してみよう

まずは、LangChainを使って簡単なLLMの呼び出しを試してみましょう。以下のコードを実行してみてください。

from langchain.llms import OpenAI

llm = OpenAI(openai_api_key="YOUR_API_KEY")
output = llm.predict("猫について教えて")
print(output)

このコードは、

  1. OpenAIクラスをインポート
  2. OpenAIクラスをインスタンス化(APIキーを設定)
  3. llm.predict()メソッドでLLMに質問("猫について教えて")を送信し、応答を取得
  4. 応答結果を標準出力に表示

という処理を行っています。

コードを実行すると、LLMが生成した「猫」に関するテキストが出力されるはずです。

llm.predict()メソッドの引数を変えることで、様々な質問をLLMに投げかけることができます。色々な質問を試して、LLMとの対話を楽しんでみてください。

3.3 PromptTemplateの利用 - プロンプトをテンプレート化する

次に、PromptTemplateを使って、プロンプトをテンプレート化してみましょう。以下のコードを実行してみてください。

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI

prompt_template = PromptTemplate.from_template("日本の{animal}について教えて")
prompt = prompt_template.format(animal="猫")
llm = OpenAI(openai_api_key="YOUR_API_KEY")
output = llm.predict(prompt)
print(output)

このコードは、

  1. PromptTemplateクラスをインポート
  2. PromptTemplate.from_template()関数でプロンプトテンプレートを作成({animal}変数を定義)
  3. prompt_template.format()メソッドで変数に値を設定し、プロンプトを生成
  4. OpenAIクラスをインスタンス化
  5. llm.predict()メソッドでLLMにプロンプトを送信し、応答を取得
  6. 応答結果を標準出力に表示

という処理を行っています。

PromptTemplateを使うことで、プロンプトをテンプレート化し、変数を埋め込むことができます。上記の例では、{animal}変数に"猫"という値を設定することで、「日本の猫について教えて」というプロンプトを生成しています。

prompt_template.format()メソッドの引数を変えることで、様々な動物についての質問をLLMに投げかけることができます。例えば、prompt_template.format(animal="犬")とすれば、「日本の犬について教えて」というプロンプトが生成されます。

PromptTemplateを使うことで、プロンプトの再利用性可読性が向上し、効率的にプロンプトを管理できるようになります。

3.4 SimpleSequentialChainの作成 - Chainを繋げて処理を連鎖させる

今度は、SimpleSequentialChainを使って、複数のChainを繋げて処理を連鎖させてみましょう。以下のコードを実行してみてください。

from langchain.chains import SimpleSequentialChain
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate

llm = OpenAI(openai_api_key="YOUR_API_KEY")

prompt1 = PromptTemplate.from_template("日本の{animal}について教えて")
chain1 = LLMChain(llm=llm, prompt=prompt1)

prompt2 = PromptTemplate.from_template("{animal}の鳴き声は?")
chain2 = LLMChain(llm=llm, prompt=prompt2)

overall_chain = SimpleSequentialChain(chains=[chain1, chain2], verbose=True)
output = overall_chain.run("猫")
print(output)

このコードは、

  1. SimpleSequentialChainLLMChainクラスをインポート
  2. OpenAIクラスをインスタンス化
  3. 1つ目のプロンプトテンプレートとLLMChainを作成(chain1
  4. 2つ目のプロンプトテンプレートとLLMChainを作成(chain2
  5. SimpleSequentialChainを作成し、chain1chain2を連結(overall_chain
  6. overall_chain.run()メソッドでChainを実行(入力は"猫")
  7. Chainの実行結果を標準出力に表示

という処理を行っています。

SimpleSequentialChainを使うことで、複数のChainを順番に実行できます。上記の例では、まずchain1で「日本の猫について」LLMに質問し、その応答結果(猫に関する説明文)をchain2の入力として渡し、chain2で「猫の鳴き声は?」とLLMに質問しています。

overall_chain.run("猫")を実行すると、まずchain1が実行され、猫に関する説明文が生成されます。次に、chain2が実行され、chain1の出力結果(猫に関する説明文)から動物名("猫")を抽出し、「猫の鳴き声は?」というプロンプトを生成してLLMに送信します。最終的に、猫の鳴き声に関するテキストが出力されます。

SimpleSequentialChainを使うことで、複数の処理を組み合わせた複雑なタスクを、シンプルに記述できるようになります。

3.5 Zero-shot ReAct Agentの実行 - Agentにタスクを実行させてみる

最後に、Zero-shot ReAct Agentを実行して、Agentにタスクを実行させてみましょう。以下のコードを実行してみてください。

from langchain.agents import initialize_agent, Tool
from langchain.agents import AgentType
from langchain.llms import OpenAI
from langchain.utilities import WikipediaAPIWrapper

llm = OpenAI(temperature=0, openai_api_key="YOUR_API_KEY")
wikipedia = WikipediaAPIWrapper()
tools = [
    Tool(
        name="Wikipedia",
        func=wikipedia.run,
        description="Wikipediaで情報を検索する"
    )
]
agent = initialize_agent(
    tools, 
    llm, 
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION, 
    verbose=True
)
output = agent.run("日本の首都は?")
print(output)

このコードは、

  1. initialize_agentToolAgentTypeクラスをインポート
  2. OpenAIクラスをインスタンス化
  3. WikipediaAPIWrapperをインスタンス化し、Wikipedia検索ツールを作成
  4. initialize_agent()関数でZero-shot ReAct Agentを初期化(ツール、LLM、エージェントタイプを設定)
  5. agent.run()メソッドでAgentにタスク("日本の首都は?")を実行させる
  6. Agentの実行結果を標準出力に表示

という処理を行っています。

initialize_agent()関数を使って、Agentを初期化する際に、ツールLLMエージェントタイプを指定します。上記の例では、Wikipedia検索ツール、OpenAIのLLM、Zero-shot ReAct Agentを指定しています。

agent.run("日本の首都は?")を実行すると、Agentはまず「日本の首都は?」という質問を理解し、Wikipedia検索ツールを使ってWikipediaで「日本の首都」を検索することを決定します。次に、Wikipedia検索ツールを実行し、検索結果を取得します。そして、検索結果に基づいて「日本の首都は東京です。」という回答を生成し、出力します。

Agentを使うことで、自律的にタスクを実行するAIシステムを構築できます。上記の例は簡単な例ですが、Agentとツールを組み合わせることで、より複雑で高度なタスクをAgentに実行させることができます。

4. LangChainの応用的な使い方 - さらに高度なテクニック

LangChainの基本をマスターしたあなたは、さらに応用的な使い方を学ぶことで、LangChainの可能性を最大限に引き出せるようになります。ここでは、LangChainの応用的なテクニックをいくつか紹介します。

4.1 より複雑なChainの構築 - Sequential Chain, Router Chain

SimpleSequentialChain以外にも、LangChainは様々な種類のChainを提供しています。

Sequential Chainは、SimpleSequentialChainよりも柔軟なChainです。複数の入力変数と出力変数を持ち、Chain間で変数を共有できます。複雑なデータフローを持つワークフローを構築したい場合に役立ちます。

Router Chainは、入力内容に応じて、複数のChainの中から適切なChainを動的に選択するChainです。チャットボットのように、ユーザーの発言内容に応じて処理を切り替えたい場合に便利です。

これらのChainを組み合わせることで、より複雑で高度な処理をLangChainで実現できます。

4.2 Memoryの活用 - 様々なMemoryを使いこなす

Memoryモジュールには、ConversationBufferMemory以外にも、様々な種類のMemoryが用意されています。

  • ConversationSummaryMemory: 会話履歴を要約してメモリに保存するMemory。長文の会話履歴を効率的に管理したい場合に役立ちます。
  • ConversationBufferWindowMemory: 最新の一定数の会話履歴のみをメモリに保存するMemory。メモリ消費量を抑えたい場合に便利です。
  • VectorStoreRetrieverMemory: 会話履歴をベクトルデータベースに保存し、類似度検索によって関連性の高い会話履歴を抽出するMemory。より高度な文脈理解を実現したい場合に有効です。

これらのMemoryを適切に使い分けることで、アプリケーションの要件や目的に合わせて、最適な会話履歴管理を実現できます。

4.3 Agentの高度な利用 - カスタムツール、エージェントタイプ

Agentモジュールをさらに深く掘り下げることで、より高度なAgentアプリケーションを開発できます。

  • カスタムツールの作成: LangChain標準のツール以外にも、独自のツールを自作できます。APIクライアント、データベースアクセス、ファイル操作など、アプリケーション固有の処理をツールとして実装し、Agentに利用させることができます。
  • エージェントタイプの選択: LangChainは、Zero-shot ReAct Agent以外にも、Conversational AgentChat Agentなど、様々なエージェントタイプを提供しています。エージェントタイプを適切に選択することで、アプリケーションの目的に最適なAgentを構築できます。
  • Agentのカスタマイズ: Agentの思考プロセス行動戦略をカスタマイズすることで、より高度で洗練されたAgentを開発できます。

これらの高度なテクニックを駆使することで、高度な自律性問題解決能力を備えたAIエージェントを開発し、様々な分野で活用できます。

4.4 応用例 - 文書要約、質問応答、チャットボット開発

LangChainは、様々なLLMアプリケーション開発に活用できます。ここでは、代表的な応用例をいくつか紹介します。

  • 文書要約: LangChainのChainとPromptTemplateを組み合わせることで、長文の文書(論文、レポート、ニュース記事など)を自動的に要約できます。ビジネスにおける情報収集や分析業務を効率化できます。
  • 質問応答: LangChainのRetrievalQA ChainやVectorDBQA Chainを使うことで、特定の知識ベース(ドキュメント、Webサイト、データベースなど)に基づいて質問応答システムを構築できます。FAQシステムやカスタマーサポートの自動化に活用できます。
  • チャットボット開発: LangChainのConversational AgentとMemoryモジュールを使うことで、自然な対話を行うチャットボットを開発できます。顧客対応、社内ヘルプデスク、教育など、幅広い分野で活用できます。

これらの応用例はほんの一例です。LangChainは、あなたのアイデア次第で、無限の可能性を秘めたLLMアプリケーション開発を可能にします。

5. LangChainのエコシステムと今後の展望 - 広がるLangChainの世界

LangChainは、フレームワーク本体だけでなく、エコシステムも充実しています。LangChainのエコシステムを活用することで、より効率的にLangChainアプリケーションを開発し、運用できます。

5.1 LangChain Hub - プロンプト、Chain、Agentの共有プラットフォーム

LangChain Hubは、LangChainのプロンプトChainAgent共有するためのプラットフォームです。世界中の開発者が作成した様々なテンプレートやサンプルコードを検索利用できます。

LangChain Hubを活用することで、開発効率を大幅に向上させることができます。ゼロから全てを開発するのではなく、LangChain Hubで公開されているテンプレートやサンプルコードを再利用したり、参考にしたりすることで、開発の手間を大幅に削減できます。

また、LangChain Hubは、コミュニティとの連携を促進する役割も担っています。LangChain Hubを通じて、他の開発者と知識ノウハウを共有したり、協力してアプリケーションを開発したりできます。

5.2 LangSmith - LangChainアプリケーションの監視、デバッグ、評価ツール

LangSmithは、LangChainチームが開発するLangChainアプリケーション監視デバッグ評価ツールです。(現在ベータ版)

LangSmithを使うことで、LangChainアプリケーションの実行状況詳細に可視化し、パフォーマンス分析できます。また、エラー検出デバッグを効率化し、アプリケーションの品質向上させることができます。

LangSmithは、LangChainアプリケーションの開発サイクル全体をサポートする強力なツールとなるでしょう。

5.3 LangChainの今後の展望 - さらなる進化へ

LangChainは、急速に進化を続けているフレームワークです。今後も、新機能追加既存機能改善エコシステム拡充などが期待されます。

LangChainの今後の展望としては、

  • さらなるモジュール、機能の拡充: 新しい種類のChain、Agent、Memory、Callbacksなどのモジュールが追加され、より多様なLLMアプリケーション開発に対応できるようになるでしょう。
  • LLM技術の進化への対応: LLM技術は日々進化しており、LangChainも最新のLLM技術に迅速に対応していくでしょう。より高性能なLLM、新しいLLM API、新しいLLMの活用方法などがLangChainに統合されていくと予想されます。
  • 開発者コミュニティの拡大: LangChainは、世界中の開発者によって支えられており、今後もコミュニティはさらに拡大していくでしょう。コミュニティの活発化は、LangChainの進化を加速し、より多くの開発者にとってLangChainが不可欠なツールとなるでしょう。
  • エンタープライズ向け機能の強化: LangChainは、個人開発者だけでなく、企業での利用も増えています。エンタープライズ向けの機能(セキュリティ、スケーラビリティ、管理機能など)が強化され、より多くの企業でLangChainが採用されるようになるでしょう。

LangChainは、LLMアプリケーション開発のデファクトスタンダードとなる可能性を秘めています。LangChainの進化から目が離せません。

6. まとめ - LangChainでLLMアプリケーション開発を始めよう!

この記事では、LangChainの基本から応用まで、** предельно понятно и тщательно解説しました。LangChainの主要な構成要素**、基本的な使い方応用的なテクニック、そしてエコシステムについて、理解を深めていただけたかと思います。

LangChainは、LLMアプリケーション開発を「楽」にする魔法の道具です。 LangChainを使うことで、複雑なLLMアプリケーションも、まるでレゴブロックを組み立てるように、簡単かつ効率的に開発できるようになります。

LangChainをマスターすれば、あなたもLLMアプリケーション開発の最前線に立つことができます。 革新的なAIアプリケーションを次々と生み出し、社会に貢献できる可能性が広がります。

さあ、あなたもLangChainの世界へ飛び込み、LLMアプリケーション開発を始めましょう!

今後の学習ステップ:

  • LangChain公式ドキュメント: LangChainの公式ドキュメントは、最も信頼できる情報源です。詳細なAPIリファレンス、チュートリアル、サンプルコードなどが豊富に掲載されています。
  • LangChainチュートリアル: LangChainのチュートリアルは、LangChainの基本を体系的に学ぶのに最適です。ステップバイステップでLangChainの使い方を学ぶことができます。
  • LangChainコミュニティ: LangChainのコミュニティは、世界中の開発者が集まる活発な場所です。質問応答、情報交換、最新情報のキャッチアップなど、コミュニティに参加することで、より深くLangChainを理解し、スキルアップできます。
  • GitHubリポジトリ: LangChainのGitHubリポジトリには、ソースコード、issue tracker、pull requestなどが公開されています。LangChainの開発に貢献したり、最新の情報をいち早く入手したりできます。

LangChainは、LLMアプリケーション開発の未来を切り拓くフレームワークです。 LangChainを学び、使いこなすことで、あなた自身の未来も切り拓いていきましょう!

この記事が、あなたのLangChain学習の第一歩となることを願っています。

Let's build with LangChain!

Discussion