AIエージェント活用実践編単一エージェント実装 — ReAct ループの基本

エラー時の回復処理

無料公開レッスン / 読了目安 8


レッスン: エラー時の回復処理

学習のねらい

LLMエージェントは外部ツールの失敗や予期せぬ応答に直面することがあります。本レッスンでは、エラー発生時にエージェントが適切に対応し、タスクを中断したり回復を試みたりする仕組みを学びます。具体的には、ツール実行失敗時のリトライ、無限ループを防ぐ早期停止、ユーザーへの再質問について解説します。

ツール実行失敗時のリトライ

外部ツールは、ネットワーク問題、API障害、LLMが生成した引数の誤りなど、様々な理由で失敗します。このような場合、すぐに諦めるのではなく、リトライ (Retry) を試みることで回復できる可能性があります。

  • リトライの戦略:
    • 回数制限: 無限リトライを防ぐため、最大リトライ回数を設定します(例: 3回)。
    • 指数バックオフ (Exponential Backoff): リトライ間隔を徐々に長くすることで、ツールやネットワークへの負荷を軽減し、回復のチャンスを増やします(例: 1秒後、3秒後、9秒後…)。
    • エラー内容の分析: エラーメッセージをLLMにObservationとして渡し、LLM自身に原因を推論させ、引数を修正してリトライさせることも有効です。

リトライは一時的な問題に対応する重要な戦略ですが、永続的なエラーには効果が薄いため、適切な回数と戦略を設定することが重要です。

ループ無限化を防ぐ early stop

ReActループは、タスクが完了しない場合に無限にThought-Action-Observationを繰り返す可能性があります。これはコスト増大やリソース消費、ユーザーを待たせる原因となるため、早期停止 (Early Stop) の仕組みを導入します。

  • max_iterations (最大繰り返し回数): 最も基本的な早期停止の仕組みです。設定した回数を超えたら強制的にループを終了させます。
  • 時間制限: タスクにかけられる最大実行時間を設定し、その時間を超えたらループを終了させます。
  • 進捗の停滞: エージェントが一定回数以上同じThoughtを繰り返している、または同じObservationを受け取っているなど、進捗が見られない場合にループを終了させます。

早期停止の条件に達した場合、エージェントはこれまでの作業を破棄するか、途中までの結果を報告するか、ユーザーに再質問するなどの次のアクションを検討します。

ユーザーに再質問する条件

エージェントがタスクを解決できない、または追加情報が必要な場合に、ユーザーに再質問することは、エージェントの有用性を高める重要な回復処理です。

  • 再質問のトリガー:
    • 情報不足: ツール実行に必要な引数がプロンプトから読み取れない場合。
    • 曖昧な指示: ユーザーの指示が曖昧で、複数の解釈が可能な場合。
    • ツール実行の失敗と回復不能: リトライを試みたが、すべて失敗し、これ以上進めない場合。

ユーザーに再質問する際は、単に「分かりません」と伝えるのではなく、何が分からないのか、どのような情報が必要なのか を具体的に伝えることが重要です。例えば、「どの都市の天気予報を知りたいですか?」や「『影響』とは、経済的な影響のことですか、それとも社会的な影響のことですか?」のように、ユーザーが回答しやすいように促しましょう。

エラーハンドリングの実装パターン

これらの回復処理は、コード上で以下のようなパターンで実装されることが多いです。

def run_agent_loop(max_iterations=5):
    current_iteration = 0
    while current_iteration < max_iterations:
        try:
            thought, action = llm_call(current_context)

            if action.is_final_answer:
                return action.answer

            observation = None
            for retry_count in range(MAX_TOOL_RETRY):
                try:
                    observation = execute_tool(action.tool_name, action.tool_args)
                    break # 成功したらリトライループを抜ける
                except ToolExecutionError as e:
                    print(f"Tool execution failed: {e}. Retrying...")
                    time.sleep(2 ** retry_count) # 指数バックオフ
            
            if observation is None:
                # リトライしても失敗した場合
                print("Tool execution failed permanently. Asking user for clarification.")
                return ask_user_for_clarification(current_context)

            current_context.add(thought, action, observation)
            current_iteration += 1

        except Exception as e:
            print(f"An unexpected error occurred: {e}. Stopping agent.")
            return handle_unexpected_error(e)

    print("Max iterations reached. Stopping agent.")
    return report_partial_results(current_context)

このコード例は、max_iterations によるループ制御、try-except ブロックでのツール実行エラーハンドリング、そしてリトライロジックの概念を示しています。

まとめ

堅牢なLLMエージェントを構築するには、エラー時の回復処理が不可欠です。ツール実行失敗時にはリトライ戦略を導入し、max_iterations や時間制限で無限ループを防ぐ早期停止を実装しましょう。また、タスクを解決できない場合には、ユーザーに具体的で分かりやすい再質問をすることで、エージェントの有用性を高めることができます。

参考リンク


エラー時の回復処理 | AIエージェント活用実践編 第1章 - AI研修