AIキャラクター開発 第四回:ReAct型同期思考永続ループエージェントの開発と挫折

AIキャラクター

0. summary

自律思考型AIエージェントの作成をしようと約二週間取り組んだものの、プロジェクトの破綻により挫折しました。

以下では詳細にこの内容について記載します。


1. 開発目標

本件はAIキャラクター、自律的に動き、判断をするキャラクターを作成を目標としました。主に目標としていた点は下記です。

  • ユーザーの指示を待たずに、自分から考え・行動する
  • Discord 上で自分の意志でメッセージを発する
  • 関心が湧いたら調べ、感じたら覚える
  • 性格・口調・価値観を持ち、それに従って一貫性のある振る舞いをする

2. 全体アーキテクチャ

2.1 3層のループ構造

今回のエージェントでは3層のループ構造を採用しました。ループではそれぞれ

  1. Want (やりたいこと、動機、意図)
  2. Plan(Want達成する間の実行計画)
  3. ReAct(各Planを実行)
①Want ループ(Plan生成の為の内的動機)
  │
  ├─ ②Plan-Step ループ(複数 tick にまたがる戦略消化)
  │   │
  │   └─ ③ReAct 内部ループ(tick 内で最大20 iter のツール連鎖呼び出し)
  │
  └─ sleep(次 tick まで待機)
ループ周期役割
①WantPlan-step全終了時間進行、キャラクターの「生」
②Plan-Step複数 tick1 want を複数 step で達成
③ReActtick 内LLM のツール連鎖呼び出し

3. 各構成要素の詳細

3.1 character_prompt(性格定義)

プロンプトは下記2層構造で制定しました。

  • Layer 1 (data/character_prompt/layer1/*.md): 不変の核(性格・口調・基本傾向)
  • Layer 2 (data/character_prompt/layer2/*.md): 動的選択(plan に応じて hobby.md / interests.md などを LLM が選ぶ)

トークン消費を抑えつつ、状況に応じて関連する性格情報を見せるため、二層構造にしています。

3.2 Want 生成

Wantの生成は下記二つの生成箇所を定義しました。

  1. _bootstrap_initial_want_if_empty: 起動時 / wants 0件時に生成
    • 入力: layer1 + 現在時刻
  2. _maybe_extract_want_from_action: 行動後に新しい want を抽出
    • 入力: current wants + 直近の thought/action ログ + character_prompt + tools_summary

3.3 Plan 生成

_run_planning が wants から step リストを生成します。planは下記特徴があります。

  • 入力: wants + recent_actions(直近3件) + recent_thoughts(直近3件) + tools_summary + previous_abandoned
  • 出力: {"steps": ["step1", "step2", ...]}
  • 意図的に character_prompt を入れない(character flavored で反復しないように)

3.4 Action 実行(_run_once)

ReAct ループで tools 付き LLM を呼びします。呼び出されたtoolは結果を取得し、LLMへ情報として渡します。

3.5 ツール群(17種)

今回は下記ツールを実装しました。

カテゴリツール
Discordread_discord_log / send_discord_message
思考・行動記録write_thought_log / write_action_log
関係性read_affinity / update_affinity
感情read_emotion / update_emotion
Plan 操作complete_step / abandon_plan
内部参照read_goal / read_planning
記憶read_memory / write_memoryedit_memory / delete_memory / search_memory
その他get_current_time / web_search / rest / request_feature

4. 良かった点

tick が正常に動作し、wants と plans が自動的に生成されたことを確認しました。complete_step で step が消化されていく流れは技術的には機能した。


5. 失敗点

5.2 哲学化ループ(Meta-Observation Loop)

want が tick を経るほど抽象化された、実際の各Tickで生成されたWantは下記。

Tick 1: 内面的な変化を観察したい
Tick 2: 静けさの微妙な変動を観察したい
Tick 3: 期待の揺らぎパターンを知りたい
Tick 4: 予兆を捉えたい

このように、Wantは外部世界に一度も到達せず、自己観察をメタ観察する閉じたループに入ってしまった。

5.3 Want と Plan の階層崩壊

want が手段レベル(「Discord を確認したい」)になり、Plan が「ツール名追加だけ」になり本来のPlan,Wantの役割を担わない場面があった。

WantPlan Step 1
「Discord のメッセージを確認したい」read_discord_log で メッセージを確認する」

5.4 構造的記憶喪失

LLM 自身がログを見れない箇所があり、状況的な判断を下すことがない場面があった。

キャラクターは「自分が前に何を考え、何をしたか」を直接思い出すことができない

「人格はあるが記憶のない人」状態となってしまった。


6. どこで決定的に破綻したか

6.1 破綻の根本原因(仮説)

仮説A: character_prompt の重みが足りない

system_prompt の中で character_prompt は冒頭に置かれているが、後続の wants/plan/emotion セクションが具体的なため、LLM はそちらに引っ張られる可能性。

仮説B: ツール 出力によるスクリプト汚染

ツール呼び出し後、そのツールに対しての応答の明確な仕様設定をしていなかったため、全文渡してしまい、キャラクターが逸脱した可能性。

仮説C: 単発プロンプトの限界

毎 tick が独立した LLM call なので、「キャラクターを保ち続ける」継続的な制約がない。チャット履歴ベースのキャラクターと違い、文脈で性格を保つことができない。また、共通の記憶装置がなく、tick横断時、through.logやaction.logはある程度引き継ぐものの、詳細な状況判断が別々で起こる。


7. 何を学んだか(次プロジェクトへの教訓)

  1. LLM の事前学習バイアスを甘く見ない — character_prompt だけでは性格は維持できない可能性がある。
  2. 共通する記憶アーキテクチャの必要性 — 今回は動作試験として最小のログのみで記憶を作成したが、逆にそれが仇となり行動の連続性がなくなり、トークン消費が増えた。
  3. wantの設計でLL Mに頼らない構造が必要 — LL Mで明確に指定したとしても、粒度がplan との明確な差別化がしづらい、LL Mのみに頼らない固定的制御を可能にする必要がある。
  4. 「自律性」を目指すなら最初から外部刺激を入れる — 自己観察ループを切る仕組みが必要、そのため外的刺激をあらかじめいくつか用意する必要がある。
  5. プロンプトによる設計を考慮する — 最初からプロンプトによるキャラクターとしての振る舞いを想定した設計が必要。
  6. 今回の目的に仕様駆動は合わない — 仕様駆動開発をしたものの、うまくいく想定で設計をしてしまい、時間が多く取られた。最初から実験を想定した開発環境を想定するべきだった。
  7. プロンプト設計はできるだけ排除する — 今回一番の問題はLL M主体のアーキテクチャであったことかつll mによるループ破綻であった。設計中枢からll Mはできるだけ排除する必要がある。
  8. 使えるものは使う — 今回ソフトウェアを1から開発したため、時間がかかった。lang chasingなどの既存フレームワークを利用して開発時間を減らし実験に多くリソースを割くべきだ。

最後に

引き続きAIキャラ作成を続けていくつもりだ。

今回は残念な結果に終わったものの、フレームワークとしてAIエージェントの動作は問題なかった、動作内容はともかく。このため次プロジェクトはもう少し案を考えたのち今回の反省点を活かし進めたい。

また次プロジェクトでは仕様駆動と自作コードをできるだけやめ、実験によるトライと開発、既存フレームワークの仕様を中心に添えたい。

なお下記概念も取り入れてより制御可能な自律型エージェントに作り替えたい

  • React:今回うまくいき、良い実感が得られた
  • Tools:今回うまくいき、良い実感が得られた
  • RAG:今回実装しなかった記憶部分を統一的にしてRAGによる制御のまでの実施をしたい。試験段階では単純なRAGのみでいいと思う
  • Activation Engineering(活性操作):まだよくわからないが、使える場合は人格固定に利用できそう。
  • 物理デバイス:今回外的要因が少なかったため、物理的にセンサーを起点に外的要因を増やしたい。

本プロジェクトはほぼ全てAIでコーディングしている。また、今回のプロジェクトリポジトリは破棄しており、今後改良、更新は予定していない。

GitHub - AGOVX/want_react_ai_character
Contribute to AGOVX/want_react_ai_character development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました