LLMエージェントのワークフローパターン
効率的なエージェントを開発するための考え方とパターンをまとめた資料(Building effective agents)をAnthropic 社が発表しました。この資料は、どういうタスクには対してはどういうエージェントが適しているかという観点から、エージェントの設計についての指針を提供しています。
本記事は、この資料を3つのストーリーポイントに分けてキャッチアップしたもののひとつになります。
LLMエージェントのワークフローパターン
TypeScriptコード例と実践的な活用法
LLM(Large Language Model)エージェントを最大限に活用するには、タスクの性質に応じた適切なワークフロー設計が不可欠です。本記事では、主要なワークフローパターンを解説し、TypeScriptのコード例を交えて、それぞれの特性と活用方法を紹介します。
プロンプトチェイニング(Prompt Chaining)
タスクを複数のステップに分解し、各ステップごとにLLMを呼び出す手法です。
コード例
async function promptChaining(input: string): Promise<string> {
const step1Output = await callLLM(`ステップ1: ${input} に基づいて概要を作成してください。`);
if (!isValidOutline(step1Output)) throw new Error("無効な概要です。");
return await callLLM(`ステップ2: ${step1Output} を詳細に展開してください。`);
}
ポイント
✅ メリット: タスクの精度向上・管理しやすい構造
❌ デメリット: ステップ数が増えると処理時間が長くなる
ルーティング(Routing)
入力を分類し、適切な処理に振り分けるワークフローです。
コード例
async function routing(input: string): Promise<string> {
const category = await classifyInput(input);
switch (category) {
case "general": return await handleGeneralQuery(input);
case "refund": return await handleRefundRequest(input);
case "technical": return await handleTechnicalSupport(input);
default: throw new Error("未知のカテゴリです。");
}
}
ポイント
✅ メリット: 入力ごとに最適な処理を適用可能
❌ デメリット: 分類の精度が低いと誤った処理が実行される
並列化(Parallelization)
タスクを分割し、並行処理で効率化を図る手法です。
セクション化の例(異なる処理を並行実行)
コード例
async function parallelSectioning(input: string): Promise<string[]> {
return await Promise.all([
processUserQuery(input),
screenInappropriateContent(input),
]);
}
投票の例(同じ処理を複数回実行して最適解を抽出)
コード例
async function parallelVoting(input: string, numRuns: number): Promise<string[]> {
return await Promise.all(
Array(numRuns).fill(null).map(() => reviewCodeVulnerabilities(input))
);
}
ポイント
✅ メリット: 高速処理・多様な結果の獲得
❌ デメリット: 並列処理のコスト増大
オーケストレーターワーカー(Orchestrator-Worker)
中央のLLMがタスクを細分化し、個別のワーカーLLMに委任する手法です。
コード例
async function orchestratorWorker(input: string): Promise<string> {
const subtasks = await orchestratorLLM(`タスクを分割: ${input}`);
const results = await Promise.all(subtasks.map((task) => workerLLM(task)));
return synthesizeResults(results);
}
ポイント
✅ メリット: 複雑なタスクを動的に処理可能
❌ デメリット: 中央LLMの判断精度に依存
評価者オプティマイザー(Evaluator-Optimizer)
生成した応答を別のLLMが評価・改善する反復的なプロセスです。
コード例
async function evaluatorOptimizer(input: string): Promise<string> {
let response = await generatorLLM(input);
for (let i = 0; i < maxIterations; i++) {
const feedback = await evaluatorLLM(`評価してください: ${response}`);
if (isSatisfactory(feedback)) break;
response = await generatorLLM(`改善: ${response}, フィードバック: ${feedback}`);
}
return response;
}
ポイント
✅ メリット: 応答の品質向上
❌ デメリット: 改善効果が限定的な場合も
実践的な考慮事項
🔹 シンプルな設計: 複雑すぎるワークフローは管理が困難
🔹 透明性の確保: 計画ステップを明示し、ユーザーの信頼を獲得
🔹 適切なエージェント設計: 文書化・テストを徹底し、最適なACI(Agent-Computer Interface)を構築
🔹 継続的な改善: ワークフローは定期的な評価とチューニングが必要
まとめ
ワークフロー | 概要 | メリット | デメリット |
---|---|---|---|
プロンプトチェイニング | ステップごとにLLMを呼び出す | 精度向上 | 処理遅延 |
ルーティング | 入力を分類し適切な処理を実行 | 効率化 | 誤分類のリスク |
並列化 | タスクを並行処理 | 高速化 | コスト増大 |
オーケストレーターワーカー | 中央LLMがワーカーLLMを管理 | 柔軟なタスク処理 | 中央LLMに依存 |
評価者オプティマイザー | 応答の評価・改善を繰り返す | 品質向上 | 効果が限定的な場合も |
この記事がLLMエージェントの設計・実装の参考になれば幸いです! 🚀
Discussion