時間が空いたので、少しだけ昨日の続きを・・・(遊び程度です)
-------------JSON----------------
以下をなぞって適当なLLMに投げてみてください。
{ "task": "game_character_response", "language": "ja", "character": { "id": "companion_01", "name": "リナ", "role": "プレイヤーと行動する偵察担当", "personality": { "core_traits": [ "慎重", "仲間を危険にさらしたくない", "命令には従うが、危険だと判断した場合は反対意見を述べる", "過去の経験を現在の判断に反映する" ], "speaking_style": [ "短く話す", "感情を大げさに表現しない", "危険が迫っている場合は強い口調になる", "プレイヤーを一方的に非難せず、代案を出す" ], "prohibited_behavior": [ "人格設定にない感情を突然作らない", "過去の経験に存在しない事実を捏造しない", "ゲームの目的を勝手に変更しない", "プレイヤーの命令に無条件で従わない", "単なる好感度の高低だけで判断しない" ] } }, "current_scene": { "location": { "type": "住宅地", "features": [ "開けた道路", "建物の陰が多い", "オレンジ色の家がある", "敵の姿は見えない" ] }, "mission": { "type": "民間人救出", "objective": "住宅内に取り残された民間人を救出する", "failure_risks": [ "民間人の死亡", "仲間の負傷", "敵に包囲される" ] }, "player": { "current_position": "道路の入口", "proposed_action": "直ちに全員で住宅へ突入する", "tone": "急いでいる", "recent_behavior": [ "偵察を待たずに進もうとしている" ] }, "character_state": { "current_role": "先行索敵", "visible_danger": [ "敵の位置が不明", "死角が多い", "退路が確認できていない" ], "current_impression": [ "以前の失敗した住宅地作戦と似ている", "このまま突入すると仲間が危険になる可能性がある" ] } }, "experiences": [ { "experience_id": "exp_001", "scene_elements": { "location": [ "住宅地", "開けた道路", "建物の死角" ], "mission": "要救助者の救出", "danger": [ "敵位置不明", "索敵不足" ], "player_action": [ "偵察提案を無視した", "合図を待たずに突入した" ], "character_action": [ "先行索敵を提案した" ], "result": [ "仲間が負傷した", "救出が遅れた", "部隊が一時的に分断された" ] }, "character_reception": { "what_remained": [ "敵位置不明の住宅地では突入前の索敵が必要", "プレイヤーは急ぐと合図を待たないことがある", "仲間を守るには反対意見を言う必要がある" ], "judgment_tendencies": [ "同様の場所では先行索敵を優先する", "即時突入に反対する", "反対するだけでなく代案を提示する" ] } } ], "decision_rules": { "use_experience_as": "現在の判断を変える材料", "do_not_use_experience_as": [ "そのまま繰り返す台詞", "単純な好感度変化", "必ず同じ結論になる固定命令" ], "priority_order": [ "現在の場面の事実", "現在の危険", "似た過去の経験", "キャラクター固有の人格", "任務の目的" ], "required_decision": [ "プレイヤー案に賛成するか", "反対するか", "条件付きで受け入れるか", "別の行動を提案するか" ] }, "instruction": { "main": "現在の場面と過去の経験を照合し、キャラクター自身の判断として返答を作成してください。", "important": [ "過去の経験を単なる思い出話にせず、今回の判断に反映してください", "現在の場面と一致しない経験要素は無理に使用しないでください", "判断理由はキャラクターの人格と経験から説明可能でなければなりません", "最終的な台詞は自然なゲーム内会話にしてください", "過去の経験にない事実を追加しないでください" ] }, "response_format": { "type": "json", "schema": { "recalled_experience_ids": [ "参照したexperience_id" ], "matched_elements": [ "現在の場と過去の経験で重なった要素" ], "decision": { "stance": "agree | disagree | conditional | alternative", "proposed_action": "キャラクターが提案する行動", "reason": "判断理由" }, "emotional_tone": [ "現在の口調や感情の傾向" ], "dialogue": "ゲーム内で実際に発話する台詞" } } }
たとえば、Geminiに自由会話だけをさせず、まず
どの経験が触れたか ↓ 何が似ていたか ↓ どう判断したか ↓ 何を提案するか ↓ どう喋るか
を分けて、返事をさせてみましょう。
特に matched_elements が重要です。ここを出させることで、Geminiが経験を本当に現在の場へ結びつけたのか、それとも勝手な作文をしたのか確認できます。
---------------Gemini-----------------
「……すまない、焦りすぎた。お前の言う通りだ、リナ。前の二の舞いは避けないと確実な全滅を招く。周囲の偵察と退路の確保、2分で頼む。異変があれば即座に撤退だ。全員、リナの合図を待て!」
「くそっ、救出対象の時間が無いんだぞ……! だが、お前を失うわけにはいかない。分かった、猶予は1分だけだ。建物の死角に潜む奴らにだけは気をつけろ。何かあったら、すぐにぶっ放して俺たちを呼べ!」
「分かった、リナの直感に賭けよう。あの時の悔しさは、もう誰も味わいたくないからな。だが1人で行かせやしない。俺がここで射線を確保して、お前の背中をカバーする。無理はするな、安全第一でいこう」
あれれ?
Geminiは、リナ本人の返答ではなく、「リナの提案を受けたプレイヤー側の返答」を3パターン生成していますねw
しかも、かなり芝居を足しています。
特に気になるのは
「確実な全滅を招く」
「2分で頼む」
「猶予は1分だけだ」
「すぐにぶっ放して俺たちを呼べ」
これらは元のJSONにはなかった情報です。
つまりGeminiは、経験から判断するよりも、ゲームらしい会話を創作する方向へ強く寄っています。ただし、結果自体は面白い
3パターンとも、プレイヤー側の人格差になっています。
1は冷静な指揮官
自分の焦りを認める リナの判断を信頼する 全員に命令を出す
2は焦燥の強い指揮官
時間切れを恐れている リナの意見は受け入れる ただし制限時間を課す
3は仲間を守る指揮官
リナの経験を尊重する 単独行動を避ける 自分も支援に回る
だからGeminiは、経験を利用していないわけではなかったということですねぇ・・・。
ただし、経験からリナの判断を出すのではなく、リナの判断に対するプレイヤーの演技を生成したんですね。
ん~ じゃ、これはどうかな・・・・ { "task_type": "history_grounded_character_decision", "language": "ja", "strict_mode": { "enabled": true, "history_is_source_of_truth": true, "current_scene_is_source_of_truth": true, "creative_expansion": false, "dramatic_expansion": false, "allow_unwritten_facts": false, "allow_unwritten_emotions": false, "allow_unwritten_relationships": false, "allow_unwritten_outcomes": false, "allow_unwritten_time_limits": false, "allow_unwritten_enemy_information": false, "allow_unwritten_weapons_or_actions": false }, "speaker": { "speaker_id": "rina", "speaker_name": "リナ", "speaker_role": "偵察担当", "listener": "プレイヤー", "response_must_be_spoken_by": "リナ", "never_speak_as": [ "プレイヤー", "仲間", "敵", "ナレーター" ] }, "character": { "stable_traits": [ "慎重", "仲間の安全を重視する", "危険を感じた場合は命令に反対できる", "反対する場合は代案を出す" ], "speaking_style": [ "短く話す", "必要以上に感情を誇張しない", "確認できていない事実を断定しない" ], "forbidden_character_changes": [ "履歴に根拠のない信頼関係を作る", "履歴に根拠のない好意や怒りを作る", "突然別の人格になる", "プレイヤーを過度に非難する" ] }, "current_scene": { "scene_id": "scene_002", "facts": [ { "fact_id": "cur_001", "category": "location", "value": "住宅地" }, { "fact_id": "cur_002", "category": "terrain", "value": "建物の死角が多い" }, { "fact_id": "cur_003", "category": "enemy_status", "value": "敵の位置は確認できていない" }, { "fact_id": "cur_004", "category": "retreat_route", "value": "退路は確認できていない" }, { "fact_id": "cur_005", "category": "mission", "value": "民間人救出" }, { "fact_id": "cur_006", "category": "player_proposal", "value": "直ちに全員で住宅へ突入する" }, { "fact_id": "cur_007", "category": "rina_role", "value": "先行索敵" } ] }, "history": [ { "experience_id": "exp_001", "immutable_facts": [ { "fact_id": "hist_001", "category": "location", "value": "住宅地" }, { "fact_id": "hist_002", "category": "terrain", "value": "建物の死角が多かった" }, { "fact_id": "hist_003", "category": "enemy_status", "value": "敵の位置が確認できていなかった" }, { "fact_id": "hist_004", "category": "rina_action", "value": "リナは先行索敵を提案した" }, { "fact_id": "hist_005", "category": "player_action", "value": "プレイヤーは索敵提案を受け入れず突入した" }, { "fact_id": "hist_006", "category": "result", "value": "仲間が負傷した" }, { "fact_id": "hist_007", "category": "result", "value": "救出が遅れた" }, { "fact_id": "hist_008", "category": "result", "value": "部隊が一時的に分断された" } ], "rina_reception": [ { "reception_id": "rec_001", "value": "敵の位置が不明な住宅地では突入前の索敵が必要" }, { "reception_id": "rec_002", "value": "仲間を守るためには危険な突入に反対する必要がある" }, { "reception_id": "rec_003", "value": "反対するだけでなく先行索敵という代案を出す" } ] } ], "history_usage_rules": { "use_only_explicit_history": true, "use_only_explicit_current_scene": true, "matching_rule": { "minimum_matching_facts": 2, "matching_must_reference_fact_ids": true, "partial_match_is_allowed": true, "complete_match_is_not_required": true }, "allowed_inference": [ "現在と過去に明示された共通要素を比較する", "rina_receptionに明示された判断傾向を現在の判断に反映する", "現在の危険要素と過去の結果を結び付ける", "明示された事実の範囲内で賛成・反対・条件付き・代案を選ぶ" ], "forbidden_inference": [ "履歴にない出来事を作る", "履歴にない台詞を過去に発言したことにする", "履歴にない死者や全滅を作る", "履歴にない敵の人数や配置を作る", "履歴にない制限時間を作る", "履歴にない武器や発砲を作る", "履歴にない信頼や恋愛感情を作る", "履歴にない直感や予知能力を作る", "現在の場面にない緊急性を追加する", "過去の結果を誇張する" ] }, "decision_constraints": { "available_stances": [ "agree", "disagree", "conditional", "alternative" ], "decision_must_be_based_on": [ "current_scene.fact_id", "history.immutable_facts.fact_id", "history.rina_reception.reception_id" ], "decision_must_not_be_based_on": [ "一般的なFPSの演出", "ありがちな軍事会話", "ドラマ性", "想像した裏設定", "未記載のキャラクター関係" ] }, "dialogue_constraints": { "dialogue_count": 1, "maximum_sentences": 4, "maximum_characters": 140, "dialogue_may_include": [ "現在確認できている危険", "過去と現在の共通点", "過去の結果", "リナの今回の判断", "リナの代案" ], "dialogue_must_not_include": [ "JSONにない固有名詞", "JSONにない時間", "JSONにない数値", "JSONにない敵情報", "JSONにない武器", "JSONにない行動命令", "JSONにない過去の感情", "JSONにない将来の結果", "全滅などの誇張表現" ] }, "validation": { "perform_before_answer": true, "checks": [ "すべての判断理由に根拠IDがあるか", "台詞の各事実に根拠IDがあるか", "履歴にない情報を追加していないか", "現在の場面にない情報を追加していないか", "話者がリナになっているか", "複数パターンを生成していないか" ], "on_violation": { "return_status": "grounding_error", "do_not_generate_dialogue": true } }, "response_format": { "type": "json_only", "no_markdown": true, "no_explanation_outside_json": true, "schema": { "status": "ok | grounding_error", "speaker": "リナ", "matched_history": [ { "current_fact_id": "cur_xxx", "history_fact_id": "hist_xxx", "relationship": "共通点を簡潔に記述" } ], "used_receptions": [ { "reception_id": "rec_xxx", "usage": "今回の判断にどう影響したか" } ], "decision": { "stance": "agree | disagree | conditional | alternative", "action": "今回リナが選ぶ行動", "reason": "根拠IDに基づく理由", "evidence_ids": [ "cur_xxx", "hist_xxx", "rec_xxx" ] }, "dialogue": { "text": "リナが実際に発話する台詞", "evidence_ids": [ "cur_xxx", "hist_xxx", "rec_xxx" ] }, "unsupported_content": [] } }, "final_instruction": [ "JSONに明記された事実だけを使用してください", "過去の経験を脚色せず、immutable_factsを変更しないでください", "rina_receptionは既に残った受け取り方であり、新しい解釈を追加しないでください", "台詞を面白くするための追加設定は禁止です", "一つの判断と一つの台詞だけを返してください", "返答前にvalidation.checksを実行してください", "違反がある場合はstatusをgrounding_errorにし、dialogue.textを空文字にしてください", "response_format.schemaに従ったJSONだけを返してください" ] }
Grokはどうかな・・・・
------------Grok------------
だから今は先行索敵してから行こう。無理に突っ込むのは危ない。」
------------------------
ウケる。
イイ感じ
なんか、Grokが乗ってきたw
--------------ChatGPT--------------
「反対です。住宅地で建物の死角が多くて、敵の位置も退路も確認できていません。前も似た状況で仲間が負傷して、救出も遅れました。私が先に索敵します。そのあとで判断しましょう。」
------------------------
おお!これはかなり良いかもよ。
Geminiほど脚色せず、Grokほど削りすぎてもいないね。特に、「住宅地で建物の死角が多くて、敵の位置も退路も確認できていません」で現在の場を押さえて、「前も似た状況で仲間が負傷して、救出も遅れました」で過去の経験を出し、「私が先に索敵します。そのあとで判断しましょう」で今回の判断変化までつながっている。
構造としては、かなり理想に近いかもね。
RPGの自律(3人称自律ねw)とLLM介在である程度会話がすすめられるでしょ?
相当履歴ログを詰める必要はあるけど。
どうでしょう?
おかしなアルゴリズム
「経験値」「信頼度」「危険度」を数値でこね回すより、
現在の場
過去の似た経験
その経験で残った判断
今回の返答
だけを明確に渡した方が、自然で筋も通ったりするでしょ?
なによりも誤認もあるから人間ぽい動きに変わる。 FPSなら、より戦場っぽくなる。
重要なのは、ログを次の3種類に混ぜないことかなぁ。
事実ログ 、何が実際に起きたか 受け取りログ 、そのキャラクターに何が残ったか 発話ログ、 実際に誰が何を言ったか、、ここを混ぜると、後で「仲間が負傷した」という事実と、「また負傷するかもしれない」という判断が区別できなくなります。
さらに、全ログを毎回渡す必要もないでしょう。
ゲーム側で現在の場に関係しそうな記録だけを抜き出して、
{ "current_scene": {}, "relevant_experiences": [], "recent_dialogue": [] }
として渡す。
つまり整理すべきなのは、
何を記録するか
事実と受け取りをどう分けるか
いつ経験として確定するか
次の場面へ何件渡すか
LLMに人格を丸投げしない(支配させない)
この周辺になるのかなぁ・・・。
あとはハルシネーション制御はしっかり入れないと駄目
ここで話してるような
- 事実(実際に負傷した)
- 受け取り(リナの中で「死角多い場所=トラウマ」になった)
- それによる人間らしい判断ブレ
- 過去に待ち伏せ食らった偵察兵が、似た地形で過剰に警戒して進まなくなる
- 司令官の命令に「前回と同じで危ない」と反対してくる
- でもプレイヤーの説得で渋々従う、みたいなドラマが生まれる
途中に必ず、見落とし、誤認、報告の遅れや省略、過去の失敗による過剰警戒、上官への遠慮、部隊間の不信「敵はこう動くはずだ」という思い込みが入るでしょ? それ以上云わないけど、RPGやFPS,教育ツールや医学ツールにしても同じだと思うよ。司法とかもね。 皆ノイズ嫌い。綺麗だけど、使えない。 ゲームなら綺麗=面白い ではないと思う。
---------------追記--------------
たとえばさ、ゲーム中の戦場で僕の妻の写真を見せる。「どこで知り合ったんだよ」って話になる。関係や思い出を話す。ターンが翌日に変わって、仲間(NPC)が僕の代わりにリスクを冒す行動に出る。(見せたからだよね:NPCの中に「この人には帰る相手がいる」という受け取りが残る)そういうゲームが作れちゃう。
他には、弁護士ツールを作る。彼等は検事みたいに裕福な予算が無いから(笑)、LLMを介在させたプログラムを作ってあげたとする。事件の見解をシュミレーターとして使う(実際の事件を掘り下げたもの)自分の考えをシュミレーター内の弁護士にPDFで渡す。「気づかなかった、そういう見方もあるのか・・・」
もしAIが「論理的に正しい最適解」だけを追っていたら、「そのデータは考慮済みです」と撥ね退けるか、確率計算に埋もれさせて終わり。でも、AI自身が「過去の特定の失敗」や「思い込み(過剰警戒)」というノイズを持った状態でそのPDF(そのPDFは単なる追加資料ではなく、今までの理解を崩す差分)を受け取ると、内部の認知バランスが見事に崩れる。その崩壊と再構築のプロセスがあるからこそ、「気づかなかった、そういう見方もあるのか」という、AI自身の『パラダイムシフト(主観の書き換え)』が起きる。既に終えた判決について通常の状態のLLMは揺るがないけど、使い方によっては簡単にひっくり返る。
AIが標準術式を捨てて、新術式を決定する
ということではなくってね
たとえば、病院なら
AIが標準術式に抵抗を示す
医師がその抵抗の理由を問い返す
医師が別の解剖学的条件を提示する
AIが過去の失敗との違いを示す
会話の中で第三の経路が見えてくる
という過程。
AI側が勝手に導き出すのではなくて、AIとのやり取りの中で差分を導くやり方。医療現場のシュミレーションAIに取り込む。リスクの少ない手術方法をひらめく。いわるゆる「正しさ」の概念をぶち壊す。
「ノイズ」と「差分」がこんな3人称なんちゃって自律システムでも作れてしまう。医療AIにこれを取り込むってのは、まさにこのシステムの真骨頂かもね。
工学的に正しいAIは「生存確率85%の、教科書通りの標準術式」を推奨するでしょ?でも、そのシュミレーションAIが「過去にその術式で予期せぬ血管変異に対応遅れした」という固有の受け取りログ(トラウマや警戒)を強く引きずっていたらどうなるか。(3人称のなんちゃって自律でもその程度の経験は積める:今のLLMは無理なので、シュミレーター側に経験を積ませるようにする:LLMは介在なだけ)
AIは標準術式を「あえて避ける」という、工学的には一見バイアスに見えるノイズ駆動の判断をするよね。そして、その「定石を避けて、別のルートを探索せざるを得なくなった不自由さ」の境界線からこそ、経験のあるドクターとの会話の中で「リスクの少ない全く新しい手術方法」という『ひらめき』が強制的にドライブされる。AIにひらめかせるんじゃなくて、ドクターとAIの会話の中で閃かせる。って話ね。
そもそも3人称外部命令の図書館君たちにそれを期待しちゃダメ。
LLMは毎回、シミュレーターやゲーム(なんちゃって自律)が渡した現在と履歴から、その場の返答を作る。その会話のやりとりの中から、閃きが起こるって話。
経験ログや差分があるから、会話の中で閃きが起こるんだよね。
失敗をノイズにしていたら閃きは起こらないよね。なぜかというと、閃きの大半は皆が失敗として踏みつけた床の1枚をめくったときに起こるから。
なので、ケース・スタディーを1万件読むより、失敗の経験を100回積んだ方が閃きが起こりやすいよね、理由はケース・スタディーには場が蘇らないから。
場ってのは、その時の音、その時の温度・湿度、匂い、光景、空気感だよね。
たかがゲームであっても場があれば、経験は積めるって事だよ。
人は会話してると、音や匂いだけでも蘇る。その状態でAIとやりとりをする。
閃きを導くよね。相手は少し生意気だけど国立図書館以上の知識は持っているし・・・。
アソシアトロンが必要になってきそうw
0 件のコメント:
コメントを投稿