LangChain の基本設計:Chains・Tools・Agents を図解で理解する

LangChain の基本設計:Chains・Tools・Agents を図解で理解する
近年の AI 技術の急速な発展により、Large Language Model(LLM)を活用したアプリケーション開発が注目を集めています。その中でも LangChain は、LLM を使った複雑なアプリケーションを効率的に構築するためのフレームワークとして、多くの開発者から支持を得ています。
本記事では、LangChain の核となる 3 つの基本コンポーネント「Chains」「Tools」「Agents」について、図解を交えながら初心者の方にもわかりやすく解説いたします。これらの概念を理解することで、AI を活用した実用的なアプリケーション開発への第一歩を踏み出せるでしょう。
背景
LangChain とは何か
LangChain は、LLM を使ったアプリケーション開発を支援するオープンソースフレームワークです。OpenAI の GPT や Anthropic の Claude といった LLM の能力を最大限に活用し、実用的なアプリケーションを構築するための豊富な機能を提供しています。
LangChain の最大の特徴は、複雑な処理を小さなコンポーネントに分割し、それらを組み合わせて大きなシステムを構築できる点にあります。これにより、開発者は再利用可能で保守性の高い AI アプリケーションを効率的に開発できるようになります。
なぜ LangChain が注目されているのか
LangChain が注目される理由は、以下のような特徴があるためです。
まず、統一されたインターフェースにより、異なる LLM プロバイダー(OpenAI、Anthropic、Google など)を同じ方法で扱えます。これにより、プロバイダーの変更や比較検討が容易になりますね。
次に、豊富なコンポーネントが用意されており、データベース接続、Web スクレイピング、API 連携など、AI アプリケーションでよく使われる機能をすぐに利用できます。
そして、モジュラー設計により、必要な機能だけを選んで組み合わせることができ、軽量で効率的なアプリケーションの構築が可能です。
基本設計の重要性
LangChain を効果的に活用するためには、その基本設計を理解することが不可欠です。特に Chains、Tools、Agents の 3 つのコンポーネントは、LangChain アプリケーションの基盤となる重要な概念です。
これらの概念を正しく理解することで、適切なアーキテクチャ設計ができるようになり、保守性が高く拡張しやすいアプリケーションを開発できるでしょう。
課題
従来の LLM 活用における限界
従来の LLM を直接利用する方法では、いくつかの制約がありました。
最も大きな制約は、一回限りの対話という点です。LLM は一度の入力に対して一度の出力を返すため、複数のステップを要する複雑なタスクを実行するのが困難でした。
また、外部データへのアクセス不可という問題もあります。LLM は学習データに基づく知識しか持たないため、リアルタイムの情報や特定のデータベースの内容を取得できませんでした。
さらに、処理結果の検証や修正も困難で、一度生成された結果を自動的にチェックして改善するような仕組みを構築するのは複雑でした。
複雑なタスクを実行するための課題
AI を活用した実用的なアプリケーションでは、以下のような複雑なタスクの実行が求められます。
多段階の推論処理が必要なケースでは、情報収集→分析→判断→実行といった一連の流れを自動化する必要があります。しかし、従来の方法では各段階を個別に実装し、手動で連携させる必要がありました。
動的な処理分岐も重要な要件です。入力内容や中間結果に応じて、次に実行する処理を動的に決定する仕組みが必要ですが、これを実現するのは容易ではありませんでした。
エラー処理と再試行の仕組みも欠かせません。AI の出力は必ずしも期待通りにならないため、適切なエラーハンドリングと再試行機能が必要です。
再利用可能なコンポーネント設計の必要性
AI アプリケーション開発では、似たような処理パターンが頻繁に登場します。例えば、「データを取得して分析し、結果をまとめる」といった処理は、多くのアプリケーションで共通して必要になります。
しかし、従来のアプローチでは、コードの重複が発生しやすく、同じような処理を何度も実装する必要がありました。
また、保守性の低下も問題となります。似たような処理が複数箇所に散らばっていると、修正や改良の際に多くの箇所を変更する必要があり、バグの原因にもなりやすいのです。
テストの困難さも課題の一つです。複雑に絡み合った処理をテストするのは困難で、品質保証が難しくなってしまいます。
解決策
LangChain は、上記の課題を解決するために、以下の 3 つの基本コンポーネントを提供しています。これらのコンポーネントを組み合わせることで、複雑で実用的な AI アプリケーションを効率的に構築できます。
以下の図は、LangChain の基本アーキテクチャを示しています。
mermaidflowchart TD
input[ユーザー入力] --> agent[Agent]
agent -->|判断| chains[Chains]
agent -->|選択| tools[Tools]
chains -->|処理連鎖| llm[LLM]
tools -->|外部連携| api[外部API/DB]
llm -->|結果| agent
api -->|データ| agent
agent -->|最終出力| output[結果]
この図から分かるように、Agent が中心的な役割を果たし、必要に応じて Chains や Tools を使い分けながら、最適な結果を生成します。
LangChain の 3 つの基本コンポーネント
Chains:処理の連鎖
Chains は、複数の処理ステップを順次実行するためのコンポーネントです。一つの Chain は、入力を受け取り、一連の処理を経て最終的な出力を生成します。
Chain の基本的な動作原理を以下の図で示します。
mermaidflowchart LR
input[入力] --> step1[ステップ1]
step1 --> step2[ステップ2]
step2 --> step3[ステップ3]
step3 --> output[出力]
subgraph chain[Chain]
step1
step2
step3
end
Sequential Chain は最も基本的な Chain で、処理を順番に実行していきます。
javascriptimport { LLMChain, SequentialChain } from 'langchain/chains';
import { OpenAI } from 'langchain/llms/openai';
import { PromptTemplate } from 'langchain/prompts';
まず、必要なモジュールをインポートします。LangChain の Chain 機能を使うために、これらのクラスが必要です。
javascript// プロンプトテンプレートの定義
const titleTemplate = new PromptTemplate({
template: "以下のトピックについて魅力的なタイトルを生成してください:{topic}",
inputVariables: ["topic"],
});
const contentTemplate = new PromptTemplate({
template: "以下のタイトルについて詳細な内容を書いてください:{title}",
inputVariables: ["title"],
});
2 つのプロンプトテンプレートを定義します。最初のテンプレートはタイトル生成用、2 つ目は内容生成用です。
javascript// LLM インスタンスの作成
const llm = new OpenAI({ temperature: 0.7 });
// 個別の Chain を作成
const titleChain = new LLMChain({
llm: llm,
prompt: titleTemplate,
outputKey: "title"
});
const contentChain = new LLMChain({
llm: llm,
prompt: contentTemplate,
outputKey: "content"
});
LLM インスタンスを作成し、各ステップに対応する Chain を定義します。outputKey により、次のステップで利用できるキー名を指定できます。
javascript// Sequential Chain で連結
const overallChain = new SequentialChain({
chains: [titleChain, contentChain],
inputVariables: ["topic"],
outputVariables: ["title", "content"]
});
// 実行
const result = await overallChain.call({
topic: "LangChain の活用方法"
});
console.log("生成されたタイトル:", result.title);
console.log("生成された内容:", result.content);
最後に、2 つの Chain を Sequential Chain で連結し、実行します。この例では、トピックからタイトルを生成し、そのタイトルを基に詳細な内容を生成する流れを自動化しています。
Tools:外部機能との連携
Tools は、LLM が外部のシステムや API と連携するためのコンポーネントです。LLM 単体では実現できない機能を拡張し、実世界のデータやサービスと接続できます。
Tools の動作メカニズムを以下の図で示します。
mermaidsequenceDiagram
participant LLM
participant Tool
participant External[外部システム]
LLM->>Tool: 機能呼び出し
Tool->>External: API リクエスト
External->>Tool: データ返却
Tool->>LLM: 処理結果
LLM->>LLM: 結果を基に推論
LLM が Tool を通じて外部システムにアクセスし、取得したデータを基にさらなる推論を行う流れです。
以下は、Web 検索機能を持つ Tool の実装例です。
javascriptimport { Tool } from 'langchain/tools';
import axios from 'axios';
Tool クラスを継承して、カスタム Tool を作成します。
javascriptclass WebSearchTool extends Tool {
name = "web_search";
description = "Web上の情報を検索するツールです。検索クエリを入力してください。";
async _call(query) {
try {
// 検索API呼び出し(例:SerpAPI)
const response = await axios.get('https://serpapi.com/search', {
params: {
q: query,
api_key: process.env.SERPAPI_KEY
}
});
return response.data.organic_results
.slice(0, 3)
.map(result => `タイトル: ${result.title}\n内容: ${result.snippet}`)
.join('\n\n');
} catch (error) {
return `検索エラーが発生しました: ${error.message}`;
}
}
}
WebSearchTool クラスでは、name と description で Tool の基本情報を定義し、_call メソッドで実際の検索処理を実装します。エラーハンドリングも含めることで、安定した動作を確保できます。
javascript// Tool の使用例
const searchTool = new WebSearchTool();
// LLM が Tool を使用できるように設定
const tools = [searchTool];
// 実際の使用
const searchResult = await searchTool._call("LangChain 使い方");
console.log(searchResult);
作成した Tool を配列に追加し、LLM が利用できるように設定します。
Agents:自律的な判断機能
Agents は、LangChain の最も高度なコンポーネントで、与えられたタスクを自律的に分析し、適切な Tools や処理手順を選択して実行します。
Agent の思考プロセスを以下の図で示します。
mermaidflowchart TD
start[タスク開始] --> think[状況分析]
think --> decide{次のアクション決定}
decide -->|Tool使用| tool[Tool実行]
decide -->|直接回答| answer[回答生成]
decide -->|追加情報必要| think
tool --> evaluate[結果評価]
evaluate --> sufficient{十分な情報?}
sufficient -->|Yes| answer
sufficient -->|No| think
answer --> done[タスク完了]
Agent は ReAct(Reasoning and Acting)パターンに基づいて動作し、推論と行動を繰り返しながら最適な結果を導き出します。
以下は、Agent の基本的な実装例です。
javascriptimport { initializeAgentExecutorWithOptions } from 'langchain/agents';
import { OpenAI } from 'langchain/llms/openai';
import { SerpAPI } from 'langchain/tools';
import { Calculator } from 'langchain/tools/calculator';
Agent の実行に必要なモジュールをインポートします。
javascript// LLM の初期化
const llm = new OpenAI({
temperature: 0, // 一貫した出力のため temperature を 0 に設定
modelName: "gpt-3.5-turbo"
});
// 利用可能な Tools の定義
const tools = [
new SerpAPI(process.env.SERPAPI_API_KEY, {
location: "Japan",
hl: "ja"
}),
new Calculator()
];
Agent が使用する LLM と Tools を定義します。この例では、Web 検索と計算機能を提供しています。
javascript// Agent の初期化
const executor = await initializeAgentExecutorWithOptions(
tools,
llm,
{
agentType: "zero-shot-react-description",
verbose: true, // デバッグ用に詳細ログを有効化
maxIterations: 5 // 無限ループ防止のため最大実行回数を設定
}
);
Agent Executor を初期化します。agentType により Agent の動作パターンを指定でき、zero-shot-react-description は最も一般的なタイプです。
javascript// Agent の実行
const result = await executor.call({
input: "2024年の日本の人口は何人ですか?また、前年比での増減率を計算してください。"
});
console.log("Agent の回答:", result.output);
複雑なクエリを Agent に与えます。この例では、情報検索と計算の両方が必要なタスクを自動的に実行してもらいます。
具体例
実際の開発シーンで、3 つのコンポーネントがどのように活用されるかを具体例で見ていきましょう。
簡単な Chain の実装例
まずは、顧客からの問い合わせを分析し、適切なカテゴリに分類する Chain を実装してみます。
javascriptimport { LLMChain } from 'langchain/chains';
import { OpenAI } from 'langchain/llms/openai';
import { PromptTemplate } from 'langchain/prompts';
分類処理に必要なモジュールをインポートします。
javascript// 問い合わせ分類用のプロンプト
const classificationPrompt = new PromptTemplate({
template: `
以下の顧客からの問い合わせを適切なカテゴリに分類してください。
問い合わせ内容: {inquiry}
カテゴリ:
1. 技術的な問題
2. 料金・請求関連
3. アカウント管理
4. 機能追加要望
5. その他
回答形式: カテゴリ番号と理由を簡潔に記載してください。
`,
inputVariables: ["inquiry"]
});
// Chain の作成
const classificationChain = new LLMChain({
llm: new OpenAI({ temperature: 0.1 }),
prompt: classificationPrompt
});
問い合わせ内容を 5 つのカテゴリに分類するためのプロンプトテンプレートを定義し、Chain を作成します。
javascript// 実行例
const inquiries = [
"パスワードを忘れてしまい、ログインできません",
"月額料金の請求書に間違いがあるようです",
"新機能として、ダークモードを追加してほしい"
];
for (const inquiry of inquiries) {
const result = await classificationChain.call({ inquiry });
console.log(`問い合わせ: ${inquiry}`);
console.log(`分類結果: ${result.text}\n`);
}
複数の問い合わせを一括で処理し、それぞれを適切なカテゴリに分類します。
Tools を使った外部 API 連携
次に、天気情報を取得する Tool を作成し、LLM と連携する例を見てみましょう。
javascriptimport { Tool } from 'langchain/tools';
import axios from 'axios';
カスタム Tool の作成に必要なモジュールです。
javascriptclass WeatherTool extends Tool {
name = "get_weather";
description = "指定された都市の現在の天気情報を取得します。都市名を日本語で入力してください。";
async _call(cityName) {
try {
const response = await axios.get(
`http://api.openweathermap.org/data/2.5/weather`,
{
params: {
q: cityName,
appid: process.env.OPENWEATHER_API_KEY,
units: 'metric',
lang: 'ja'
}
}
);
const weather = response.data;
return `${cityName}の天気: ${weather.weather[0].description}、気温: ${weather.main.temp}°C、湿度: ${weather.main.humidity}%`;
} catch (error) {
return `天気情報の取得に失敗しました: ${error.message}`;
}
}
}
WeatherTool では、OpenWeather API を使って指定された都市の天気情報を取得します。エラーハンドリングにより、API 呼び出しが失敗した場合も適切に対応できます。
javascript// Chain と Tool の組み合わせ
const weatherReportPrompt = new PromptTemplate({
template: `
以下の天気情報を基に、わかりやすい天気レポートを作成してください。
天気データ: {weather_data}
以下の要素を含めてください:
- 現在の状況
- 服装のアドバイス
- 外出時の注意点
`,
inputVariables: ["weather_data"]
});
const reportChain = new LLMChain({
llm: new OpenAI({ temperature: 0.7 }),
prompt: weatherReportPrompt
});
取得した天気データを基に、読みやすいレポートを生成する Chain を作成します。
javascript// Tool と Chain の連携実行
const weatherTool = new WeatherTool();
// 天気データ取得
const weatherData = await weatherTool._call("東京");
// レポート生成
const report = await reportChain.call({
weather_data: weatherData
});
console.log("天気レポート:", report.text);
Tool で天気データを取得し、Chain でそれを読みやすいレポートに変換する一連の処理を実行します。
Agent による自動タスク実行
Agent を使って、複雑なタスクを自律的に実行する例をご紹介します。
javascriptimport { initializeAgentExecutorWithOptions } from 'langchain/agents';
import { OpenAI } from 'langchain/llms/openai';
Agent の実行に必要な基本モジュールをインポートします。
javascript// カスタム Tool:データベース検索
class DatabaseTool extends Tool {
name = "search_database";
description = "社内データベースからユーザー情報を検索します。ユーザーIDまたは名前を入力してください。";
async _call(query) {
// 実際の実装では、データベース接続処理を記述
const mockData = {
"12345": { name: "田中太郎", department: "開発部", email: "tanaka@example.com" },
"67890": { name: "佐藤花子", department: "営業部", email: "sato@example.com" }
};
const user = mockData[query] || null;
return user ?
`ユーザー情報: 名前=${user.name}, 部署=${user.department}, Email=${user.email}` :
"該当するユーザーが見つかりませんでした";
}
}
社内データベースを模擬したカスタム Tool を作成します。実際の運用では、データベース接続ライブラリを使用してください。
javascript// Email 送信 Tool
class EmailTool extends Tool {
name = "send_email";
description = "指定されたメールアドレスにメールを送信します。recipient(宛先)とmessage(内容)をJSON形式で入力してください。";
async _call(input) {
try {
const { recipient, message } = JSON.parse(input);
// 実際の実装では、メール送信ライブラリを使用
console.log(`メール送信: ${recipient} に "${message}" を送信しました`);
return `${recipient} へのメール送信が完了しました`;
} catch (error) {
return `メール送信に失敗しました: ${error.message}`;
}
}
}
メール送信機能を持つ Tool です。JSON 形式で宛先とメッセージを受け取り、メール送信を実行します。
javascript// Agent の設定と実行
const tools = [new DatabaseTool(), new EmailTool()];
const agent = await initializeAgentExecutorWithOptions(
tools,
new OpenAI({ temperature: 0.2 }),
{
agentType: "zero-shot-react-description",
verbose: true
}
);
// 複雑なタスクの実行
const task = `
ユーザーID 12345 の情報を検索して、
そのユーザーに「システムメンテナンスのお知らせ」というメールを送信してください。
メール内容は「明日午後2時から4時まで、システムメンテナンスを実施いたします。ご迷惑をおかけして申し訳ございません。」としてください。
`;
const result = await agent.call({ input: task });
console.log("タスク実行結果:", result.output);
Agent は与えられたタスクを分析し、適切な順序で Tools を使用して目標を達成します。この例では、データベース検索とメール送信を自動的に組み合わせて実行します。
3 つのコンポーネントを組み合わせた実践例
最後に、Chains、Tools、Agents を組み合わせた総合的な例として、顧客サポートシステムを実装してみましょう。
以下の図は、システム全体のアーキテクチャを示しています。
mermaidflowchart TD
user[顧客] -->|問い合わせ| agent[Customer Support Agent]
agent -->|分類| classifyChain[分類Chain]
agent -->|検索| searchTool[ナレッジベース検索Tool]
agent -->|通知| emailTool[Email送信Tool]
agent -->|記録| dbTool[データベースTool]
classifyChain --> decision{問題の種類}
decision -->|FAQ| searchTool
decision -->|技術的| techChain[技術サポートChain]
decision -->|緊急| escalation[エスカレーション]
searchTool --> agent
techChain --> agent
escalation --> emailTool
agent -->|最終回答| user
このシステムでは、Agent が中心となって各コンポーネントを協調させ、顧客の問い合わせに対して適切な対応を自動実行します。
以下のコードで、この統合システムを実装していきます。
javascriptimport {
initializeAgentExecutorWithOptions,
AgentExecutor
} from 'langchain/agents';
import { LLMChain, SequentialChain } from 'langchain/chains';
import { OpenAI } from 'langchain/llms/openai';
import { Tool } from 'langchain/tools';
import { PromptTemplate } from 'langchain/prompts';
統合システムに必要な全てのモジュールをインポートします。
javascript// ナレッジベース検索 Tool
class KnowledgeBaseTool extends Tool {
name = "search_knowledge_base";
description = "社内ナレッジベースからFAQや技術文書を検索します。";
async _call(query) {
// モックデータ(実際はデータベースやElasticsearchなどを使用)
const knowledgeBase = {
"パスワード": "パスワードリセットは、ログイン画面の「パスワードを忘れた方」リンクから実行できます。",
"料金": "月額料金は毎月末日に自動決済されます。請求書は翌月5日にメールで送信されます。",
"API": "API利用には認証トークンが必要です。管理画面から生成できます。"
};
for (const [key, value] of Object.entries(knowledgeBase)) {
if (query.includes(key)) {
return `関連情報が見つかりました: ${value}`;
}
}
return "関連する情報が見つかりませんでした。技術サポートにお問い合わせください。";
}
}
社内のナレッジベースを検索する Tool です。実際の運用では、Elasticsearch や専用のナレッジベースシステムと連携します。
javascript// 問い合わせ記録 Tool
class TicketTool extends Tool {
name = "create_support_ticket";
description = "サポートチケットを作成します。顧客情報と問い合わせ内容をJSON形式で入力してください。";
async _call(input) {
try {
const ticketData = JSON.parse(input);
const ticketId = `TICKET-${Date.now()}`;
// 実際の実装では、チケット管理システムのAPIを呼び出し
console.log(`サポートチケット作成: ${ticketId}`, ticketData);
return `サポートチケット ${ticketId} を作成しました`;
} catch (error) {
return `チケット作成に失敗しました: ${error.message}`;
}
}
}
問い合わせ内容をサポートチケットとして記録する Tool です。チケット ID を自動生成し、適切な管理を可能にします。
javascript// 統合 Agent の構築
const supportTools = [
new KnowledgeBaseTool(),
new TicketTool(),
new EmailTool() // 前述のメール送信Tool
];
const supportAgent = await initializeAgentExecutorWithOptions(
supportTools,
new OpenAI({
temperature: 0.3,
modelName: "gpt-4" // より高度な推論能力のためGPT-4を使用
}),
{
agentType: "zero-shot-react-description",
verbose: true,
maxIterations: 8 // 複雑なタスクのため実行回数を増加
}
);
3 つの Tool を組み合わせて、総合的な顧客サポート Agent を構築します。
javascript// 実際の顧客サポート実行
const customerInquiry = `
こんにちは。APIの認証トークンの設定方法がわからなくて困っています。
管理画面を見ても該当する項目が見つからず、
明日のプレゼンテーションまでに解決したいのですが、
緊急で対応していただけますでしょうか?
`;
const supportResult = await supportAgent.call({
input: customerInquiry
});
console.log("サポート対応結果:", supportResult.output);
顧客からの実際の問い合わせに対して、Agent が自律的に適切な対応を実行します。Agent は問い合わせ内容を分析し、ナレッジベース検索、チケット作成、必要に応じてエスカレーションメールの送信まで自動で行います。
実行時の Agent の思考プロセス例:
# | ステップ | Agent の判断 |
---|---|---|
1 | 問い合わせ分析 | API認証に関する技術的な問題、緊急度が高い |
2 | ナレッジベース検索 | "API"キーワードで検索実行 |
3 | 回答生成 | 基本的な解決方法を提示 |
4 | サポートチケット作成 | 緊急案件として記録 |
5 | 最終回答 | 解決方法とフォローアップ手順を顧客に提示 |
この例では、Agent が状況を的確に判断し、複数の Tool を効果的に活用して包括的なサポートを提供していることがわかります。
まとめ
LangChain の 3 つの基本コンポーネントについて、概念から実装まで詳しく解説いたしました。
Chains は処理の流れを構造化し、複雑なタスクを段階的に実行するための仕組みです。Sequential Chain を使うことで、複数の処理ステップを自動化できます。
Tools は LLM の能力を外部システムと連携させ、実世界のデータや機能にアクセスするためのインターフェースです。カスタム Tool の作成により、様々な外部サービスとの統合が可能になります。
Agents は最も高度なコンポーネントで、与えられたタスクを自律的に分析し、適切な Tools や処理手順を選択して実行します。ReAct パターンにより、人間のような思考プロセスを実現できます。
これらのコンポーネントを理解し活用することで、単純な LLM の利用から一歩進んだ、実用的で拡張性の高い AI アプリケーションの開発が可能になります。まずは簡単な Chain から始めて、徐々に Tools や Agents を組み合わせることで、より高度なシステムを構築していってくださいね。
関連リンク
- review
今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
- review
ついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
- review
愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
- review
週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
- review
新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
- review
科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来