📘

はじめてのLangChain入門:Pythonで対話型AIを作る

に公開

※本記事はChatGPTによって作成されています。内容には自動生成による情報が含まれており、正確性・網羅性を保証するものではありません。

1. はじめに

ChatGPTをはじめとした大規模言語モデル(LLM)の登場により、自然言語処理のアプリケーション開発が劇的に簡単になりました。PythonからOpenAI APIを使うことで、高性能な言語生成や要約、質問応答などが容易に実装できるようになりました。

しかし、実際のアプリケーション開発では、プロンプトの構築、応答の整形、複数ステップの処理、外部データとの連携など、LLM単体ではまかないきれない複雑な要件が登場します。

LangChainは、そうした「LLMの力を活かした複雑な処理フロー」をPythonで簡潔に記述できるフレームワークです。本記事では、LangChainの基本的な考え方から実装パターンまでを、実例を交えながら丁寧に解説していきます。

2. LangChainとは何か?

LangChainは、大規模言語モデル(LLM)を中心としたアプリケーション構築のためのPythonライブラリです。OpenAIやAnthropic、Cohereなど、さまざまなLLMサービスとシームレスに連携し、自然言語を用いたアプリケーションを迅速かつ構造的に開発するための機能を豊富に提供しています。

LangChainの主な特徴は以下の通りです。

  • PromptTemplate:再利用可能なプロンプトテンプレートを定義可能
  • Chain:複数の処理を順番につなげて実行するフレームワーク
  • Agent:条件分岐や判断ロジックを含む高度な対話設計が可能
  • Memory:会話の履歴を保持し、文脈をもとに応答を制御
  • Tool:検索エンジンや計算エンジン、外部APIとの統合

特に、PromptTemplateとChainを組み合わせることで、「ユーザー入力 → プロンプト生成 → 応答取得 → 応答加工」といった一連の流れを、簡潔で拡張性の高い形で構築できます。

LangChainは、「LLMの力を最大限に活用し、かつ管理しやすい形でアプリケーションに組み込む」ための枠組みを提供するツールです。複雑なプロンプトの切り替えやステートフルな会話、マルチステップの処理を実現したい場面で、非常に有効に機能します。

3. LangChainのセットアップ

OpenAIの設定

APIキーの取得

まず、OpenAIの公式サイトでアカウントを作成し、APIキーを取得します。ダッシュボードのAPI Keysセクションから新しいキーを生成できます。

⚠️ APIキーは個人の秘密鍵のようなものです。コードに直接書かず、環境変数などで安全に管理しましょう。

課金設定

APIの利用にはクレジットの課金が必要です。

OpenAIのBillingから任意の額をクレジットを購入してください。

Pythonでの準備

以下の手順でPython環境を構築します。

  1. 必要なパッケージをインストール:

PythonからAPIを呼び出すには、openaiライブラリをインストールします。
ここでは、.envファイルからAPIキーを読み込むために python-dotenv というライブラリも合わせてインストールします。

pip install langchain langchain_openai openai python-dotenv
  1. .envファイルを作成:

.envファイルを作成します。生成したAPIキーを設定してください。

OPENAI_API_KEY=sk-xxxxxxx...

スクリプトからは以下のように読み込みます。

from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
import os

load_dotenv()
llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o")

これでLangChainとOpenAIの準備が整いました。

4. PromptTemplateとChainの構築

LangChainを活用するうえでの中核を担うのが、「PromptTemplate」と「Chain」です。
これらを理解することで、LLMを使った高度な処理を柔軟に構築できるようになります。

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.chains.sequential import SimpleSequentialChain
from dotenv import load_dotenv
import os

# 環境変数の読み込み
load_dotenv()

# モデル準備
llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o")

# Prompt 1: トピックの概要生成
prompt1 = ChatPromptTemplate.from_template("{theme}について学生向けにわかりやすく解説してください。")
chain1 = prompt1 | llm | StrOutputParser()

# Prompt 2: FAQ生成
prompt2 = ChatPromptTemplate.from_template("次の文章をもとに5つのFAQを作ってください:{text}")
chain2 = {"text": chain1 } | prompt2 | llm | StrOutputParser()

# シーケンシャルに実行
result1 = chain1.invoke({"theme": "生成AI"})
result2 = chain2.invoke({"theme": "生成AI"})

print(result1)
print(result2)

4.1 PromptTemplate

プロンプトテンプレートは、あらかじめ文の構造を定義しておき、必要な部分だけ変数で埋め込めるようにする機能です。

prompt1 = ChatPromptTemplate.from_template("{theme}について学生向けにわかりやすく解説してください。")

このテンプレートは、theme="生成AI"などを指定することで、柔軟に再利用できます。
テンプレート化することで、構造化されたプロンプト設計が可能となり、複数のプロンプト間で共通の設計を再利用することができます。

4.2 LLM Chain

テンプレートとモデルを組み合わせてChainを作成します。
StrOutputParserを使うことで、生成されたレスポンスから必要なテキストを抽出します。

chain1 = prompt1 | llm | StrOutputParser()

このパイプラインにより、入力→出力までの処理が明確かつ再利用しやすく構築できます。

4.3 Chainの連結

chainの出力を次のchainの入力とすることで、複数の処理を連結させることができます。

chain2 = {"text": chain1 } | prompt2 | llm | StrOutputParser()

このような形で処理をつなぐことで、「解説文を生成 → その内容からFAQを生成」という一連の流れを自動化できます。

5. 応用機能:Agent・Tool・Memoryの活用

LangChainの真価が発揮されるのは、LLMをただ使うだけでなく、AgentやTool、Memoryといった仕組みを組み合わせて、より複雑で柔軟なアプリケーションを構築できる点にあります。

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_core.chat_history import InMemoryChatMessageHistory
from dotenv import load_dotenv
import os

# 環境変数読み込み
load_dotenv()

# モデル準備
llm = ChatOpenAI(model="gpt-4o", api_key=os.getenv("OPENAI_API_KEY"))

# Tool定義
@tool
def double(num: int) -> int:
    """数値を2倍にするツール"""
    return num * 2

@tool
def triple(num: int) -> int:
    """数値を3倍にするツール"""
    return num * 3

# Agent構築
prompt = ChatPromptTemplate.from_messages([
        ('system', "あなたは親切なアシスタントです。"),
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}"),
    ]
)
agent = create_tool_calling_agent(llm, tools=[double, triple], prompt=prompt)
executor = AgentExecutor(agent=agent, tools=[double], verbose=True)

# Memoryの準備
message_histories = {}

def get_history(session_id: str):
    if session_id not in message_histories:
        message_histories[session_id] = InMemoryChatMessageHistory()
    return message_histories[session_id]

agent_with_memory = RunnableWithMessageHistory(
    executor,
    lambda session_id: get_history(session_id),
    input_messages_key="input",
    history_messages_key="chat_history",
)

# 実行
result1 = agent_with_memory.invoke({"input": "5を2倍にして、その結果を3倍にして"}, config={"configurable": {"session_id": "user-1"}})
result2 = agent_with_memory.invoke({"input": "さっきの結果を教えて"}, config={"configurable": {"session_id": "user-1"}})

print(result1)
print(result2)

5.1 Tool

Toolは、LLM単体では対応できない外部処理を行う関数です。例えば「数値を2倍にする」「外部APIからデータを取得する」といった処理を、Toolとして登録します。LLMは自然言語入力から適切なToolを呼び出し、その結果を応答に組み込みます。

@tool
def double(num: int) -> int:
    """数値を2倍にするツール"""
    return num * 2

@tool
def triple(num: int) -> int:
    """数値を3倍にするツール"""
    return num * 3

このように、任意のPython関数をToolに変換できます。

5.2 Agent

Agentは、入力内容に応じて「どのToolを使うべきか」を判断する役割を持ちます。これにより、開発者が処理フローを細かく定義しなくても、LLMが自律的に適切な処理を選択して実行できます。たとえば「5を2倍にして」と指示すると、Agentはdouble Toolを選び、「その結果を3倍にして」と言えばtriple Toolを呼び出すように指示します。

# Agent構築
prompt = ChatPromptTemplate.from_messages([
        ('system', "あなたは親切なアシスタントです。"),
        ("human", "{input}"),
        ("placeholder", "{agent_scratchpad}"),
    ]
)
agent = create_tool_calling_agent(llm, tools=[double, triple], prompt=prompt)

5.3 Memory

Memoryは、ユーザーとの会話履歴を保持し、過去の応答内容を参照して文脈を維持します。これにより、「さっきの結果は?」といった質問にも対応可能です。Memoryを組み込むことで、より自然で一貫性のある応答が可能になります。

message_histories = {}

def get_history(session_id: str):
    if session_id not in message_histories:
        message_histories[session_id] = InMemoryChatMessageHistory()
    return message_histories[session_id]

agent_with_memory = RunnableWithMessageHistory(
    executor,
    lambda session_id: get_history(session_id),
    input_messages_key="input",
    history_messages_key="chat_history",
)

処理フロー

この仕組みを理解することで、エンジニアはLangChainを活用してLLMに柔軟な処理や会話の記憶機能を組み込む具体的な方法を把握できます。

おわりに

本記事では、LangChainの概要から基本的な使い方、そしてChainの連携による応用までを解説しました。

LangChainは、プロンプトの設計や複雑な処理の組み立てを抽象化し、LLMを活用したアプリケーションを効率的に構築できる強力なツールです。

今後、LangChainを活用することで、RAG(検索拡張生成)やマルチエージェント設計など、さらに高度なAIシステムの開発も視野に入ってくるでしょう。

まずは今回紹介した基礎をしっかり理解し、自分のプロジェクトにLangChainをどのように活かせるか、ぜひ試してみてください。

Discussion