はじめに
こんにちは。
最近、AIエージェントの開発がますます面白くなってきたので、今回はその中で得た技術的な知見やアイデアを共有したいと思います。
特に注目しているのが、「ReAct(Reason + Act)」という設計パターンを取り入れ、エージェントの推論力を強化するというアプローチです。
前回は、比較的一般的なReActの実装を紹介しましたが、今回はそこから一歩踏み込んで、より強力な推論を可能にするシステム設計について考察してみます。
ReActのおさらい
ReActパターンは、「Reason(理由付け)」、「Act(行動)」、「Observation(観察)」の3つのステップを繰り返すことで問題解決を行う手法です。
具体的には、ユーザーからのプロンプトに対してこのReAct処理を適用することで、段階的に思考を深め、複雑なタスクにも柔軟に対応できるようになります。

今回やること
私が目指しているAIエージェントは、DevinやOpenHandsのように、自律的に自己修正や検証を繰り返しながら学習・改善できるローカルLLMの開発です。
そこで、ReActパターンを応用して、自律的に修正・検証を行う擬似的なデバッグ機能を実装し、この挙動を再現できないかと考えています。
アイデア
自律的に修正・検証をしてくれる擬似的なデバッグ機能
上記の自律的修正・検証機能を再現するには、「プロンプト → 初期出力 → ReAct処理 → 最終出力」という一連の流れを設けることで、エージェントの柔軟性と解釈力を高められると考えました。
さらに、ReAct処理を複数回ループさせることで、推論力を強化することができるはずです。

実装
モデルへのプロンプト生成
AIエージェントでは、モデルがどのような形式で出力を行うか、そのフォーマットをプログラム側で定義できます。
今回はReActパターンを採用しているため、モデルに対して「どのように思考し、どのように行動するか」を指示するプロンプトを設計しました。
prompt = f"""
あなたは以下のモデル出力をより良い回答にするために、ReActパターン(Reason-Act-Observe)を使用してください。
初期モデル出力:
{model_output}
現在のイテレーション: {iteration}/5
以下の形式で応答してください:
Reason: [この問題について考える理由や分析]
Act: [実行するアクション - search[クエリ] または calc[計算式] または FINISH]
利用可能なアクション:
- search[検索クエリ]: DuckDuckGoで検索でき、結果とURLを返せます
- calc[数式]: 計算を実行
- FINISH: 最終回答を提供
注意:
- 初期モデル出力が既に十分な場合は、すぐにFINISHを選択できます
- 追加情報が必要な場合のみ、searchやcalcを使用してください
- ReAct処理を最大5回のループで完了してください
"""
Actフェーズ
ReActパターンを調べていく中で、特にActフェーズが非常に重要であることが分かりました。
例えば、「プリンを作って」というプロンプトを入力した場合、モデルはActフェーズで「cook[pudding]」のように解釈します。ここで「cook」が命令の種類を表し、「pudding」というトークンが具体的な対象を指します。
モデルの出力を受けてプログラム側がこの「cook[pudding]」を理解し、実際の処理を実行するという役割を担っているのがActフェーズです。つまり、モデルの指示をプログラムが正しく実行可能な形に読み解く重要な段階と言えます。
search_match = re.search(r'search\[(.*?)\]', act_part, re.IGNORECASE)
if search_match:
return "search", search_match.group(1)
calc_match = re.search(r'calc\[(.*?)\]', act_part, re.IGNORECASE)
if calc_match:
return "calc", calc_match.group(1)
ReActループの中核
現在、AIエージェントは誰でも気軽に利用できるツールとなっています。
ユーザーがスムーズにモデルとの対話を続けられるのは、AIエージェントが「何を言ったか」「何を返したか」という履歴を適切に保持・引き継いでいるからです。
では、今回のシステムでも同様に履歴を引き継げば良いのかというと、ReActパターンの場合はそれに加えて、モデルが実行した「形式」ごとに情報を次のプロンプトに引き継ぐ構造になっているため、これが推論力の向上につながります。
current_context += f"\n\nイテレーション {iteration}:\nReason: {reason_part}\nAction: {action}[{parameter}]\nObservation: {observation}"
出力結果の比較
では通常の回答とReActによる回答の差を比較してみましょう。
プロンプトの内容は本文中でも例に挙げた「プリンの作り方」で試してみましょう。
通常回答
材料(4個分)
カラメルソース用:
砂糖:大さじ3
水:大さじ1
お湯:大さじ1
プリン液用:
卵:2個
牛乳:200ml
砂糖:大さじ3
バニラエッセンス:数滴(お好みで)
作り方
1. カラメルソースを作る
小鍋に砂糖と水を入れ、中火で加熱
茶色く色づいてきたら火を止め、お湯を加えて混ぜる
プリンカップに等分して入れる
2. プリン液を作る
牛乳を人肌程度に温める
ボウルで卵と砂糖をよく混ぜる
温めた牛乳を少しずつ加えて混ぜる
茶こしでこして滑らかにする
3. 蒸す
プリン液をカラメルの上に静かに注ぐ
アルミホイルで蓋をする
蒸し器で弱火で15-20分蒸す
竹串を刺して液が出なければ完成
4. 冷やす
粗熱が取れたら冷蔵庫で2-3時間冷やす
コツ
卵液は必ずこすことで滑らかな仕上がりに
強火で蒸すと「す」が入るので弱火で
冷やしてから型から外すと綺麗に仕上がります
ReAct回答
材料(4個分)
カラメルソース用:
砂糖:大さじ3
水:大さじ1
お湯:大さじ1
プリン液用:
卵:2個
牛乳:200ml
砂糖:大さじ3
バニラエッセンス:数滴(お好みで)
作り方
1. カラメルソースを作る
小鍋に砂糖と水を入れ、中火で加熱
⚠️ 注意: 砂糖が溶けて泡立ち始めても混ぜずに、鍋を軽く揺する程度に
茶色く色づいてきたら火を止め、やけどに注意してお湯を加えて混ぜる
プリンカップに等分して入れ、冷まして固める
2. プリン液を作る
牛乳を人肌程度(約40℃)に温める
ボウルで卵と砂糖をよく混ぜる(泡立てすぎないよう注意)
温めた牛乳を少しずつ加えて混ぜる
重要: 茶こしで2回こして滑らかにする
3. 調理する
蒸し器の場合:
プリン液をカラメルの上に静かに注ぐ
アルミホイルで蓋をする
蒸し器で弱火で15-20分蒸す
竹串を刺して液が出なければ完成
オーブンの場合(湯煎焼き):
160℃に予熱したオーブンで、天板にお湯を張り30-35分焼く
より安定した仕上がりになります
4. 冷やす
粗熱が取れたら冷蔵庫で2-3時間以上冷やす
型から外す時は、カップの周りを軽く温めると外しやすくなります
失敗しないコツ
🔥 カラメルソース
焦げやすいので目を離さない
色が薄いと苦味が少なく、濃いと大人の味に
🥚 プリン液
卵液は必ずこすことで滑らかな仕上がりに
泡が入ると「す」の原因になるので、泡立てすぎない
🔥 加熱
強火は絶対NG! 「す」が入る原因になります
弱火でじっくり加熱することが成功の秘訣
❄️ 仕上げ
完全に冷えてから型から外すと綺麗に仕上がります
急いで外そうとすると崩れやすいので注意
よくある失敗と対処法
「す」が入った場合: 火が強すぎたか、加熱時間が長すぎた可能性
固まらない場合: 加熱不足なので、追加で5-10分加熱
カラメルが固くなった場合: 少量のお湯で溶かし直す
このレシピなら初心者の方でも美味しいプリンが作れます!
結果
二つの出力結果を比較してみると、ReActで得た回答の方が”失敗しないためのコツ”や、”よくある失敗と対処法”を提示してたりと、通常の回答ではみられない出力を得ることができました。
また、前回取り組んだReActパターンよりも明確に推論力が上がっていると思います。
今後の課題
今回の取り組みで推論力については十分得られました。
一方で、コーディングAIとして実用を想定しているため、今後はファイルを出力する方法や、Git hubとの連携方法について取り組んでいきたいと思います。
今回作成したソースコードは現状では共有ができないため、しばらくお待ちください!
参考URL


