まず世界観を定義してから考える
まず世界観を定義してから考える
こんにちはmakokonです。
LLMが間違える問題は尽きることのない悩みです。
特にCoTなどで、念入りに思考を制御しようとしたときに、しょうもない前提条件を忘れたような応答を示すのは、本当に困った問題です。
「それはするなといったじゃないか!!」と思わず怒鳴った人もいるんじゃないでしょうか
今日紹介する論文のModel-First Reasoning(MFR)はそんな問題をちょっと改善してくれるかもしませんよ。近頃強化学習とか複雑なエージェント構成でトライすることが多い問題ですが、久しぶりにプロンプトエンジニアリングです。利用する立場でわかりやすく教科書ぽく説明してみたいと思います。
Model-First Reasoning LLM Agents: Reducing Hallucinations through Explicit Problem Modeling
Model-First Reasoning(MFR)
「まず世界観を定義してから考える」だけで、LLMエージェントの破綻(制約違反・状態崩壊・ハルシネーション)を減らす
0. この教材で得られること(最初に結論)
この論文が主張するのは、すごく実務的に言い換えると次の一点です。
LLMが間違えるのは「推論が下手」だからではなく、「問題のモデル(世界観・状態・ルール)が暗黙で揺れる」からだ
だから、推論や計画を始める前に、LLMに“問題モデル”を明示的に作らせて固定してから、そこだけを参照して推論させよう
これを著者らは Model-First Reasoning(MFR) と呼び、CoT(Chain-of-Thought)やReActより、
制約違反が減る
状態追跡が安定する
出力が検証しやすくなる
という傾向を、複数の制約付きタスクで示します。
AIユーザーが「今日から自分のプロンプト/小さなPython実験」で試せるよう、
MFRの考え方
2フェーズのプロンプト雛形
それっぽく動く実装骨格(Python風)
検証・デバッグ方法
を教科書的にまとめます。
1. 導入:あなたのLLMは「賢いのに、なぜか壊れる」
1.1 現場あるある:
あなたがLLMに「手順を守って作業して」と頼んだのに、こんなことは起きませんか?
5ステップの手順をお願いしたのに、途中で前提が変わる(さっき“土日不可”って言ったのに日曜に予定を入れる)
既に使ったリソースを未使用として再利用する(「Aはもう消費済み」を忘れる)
ルールを守っている“雰囲気”はあるのに、一番大事な制約を1回だけ破る
手順が長いほど、整合性が薄くなっていく
特に「日程・割当・ワークフロー・順序制約・在庫・権限」みたいな、状態と制約が絡むタスクで起きがちです。
1.2 比喩:地図なしでナビする優秀な新人
LLMの推論は、よく「優秀な新人」に例えられます。ただし現場で困るのは、次のタイプです。
文章理解と説明は超うまい
目の前の一歩はそれっぽく進める
でも、全体の地図(何が存在し、状態がどう変わり、何が禁則か)を先に作らない
結果として、
ローカルには筋が通っている
グローバルには破綻する
という「それっぽいのに壊れている」成果物が出ます。
論文はここにメスを入れています。
「多くの失敗は推論(inferential)の不足ではなく、表現(representational)の不足だ」
つまり、考え方が悪いのではなく、考える“対象”が曖昧なのが根本原因、という立場です。
2. 理論・概念解説:MFRは「推論を始める前に、世界のルールブックを作る」
2.1 MFRが狙う問題:暗黙モデルの“ドリフト”
CoTやReActは「途中経過を言語化」することで推論を助けます。
しかし論文の問題意識はこうです。
CoT:途中の思考は書くが、状態変数・エンティティ・制約を定義しない
ReAct:行動と観測を挟むが、状態追跡は結局自然言語のログに散る
この状態だと、長いタスクほど
重要な変数を言い忘れる
途中で定義がすり替わる
禁則が一瞬だけ抜ける
が起きます。
論文は「これは推論能力の不足というより、問題表現が明示されていないことによる不安定さだ」と整理します。
2.2 MFRの核心:2フェーズ分離(モデル構築 → モデル上で推論)
MFRはシンプルに二段階です。
モデル構築(Model Construction):解を出さず、問題の構造だけを書く
推論・計画(Reasoning / Planning):上で作ったモデルだけを使って解を作る
ここでいう「モデル」は機械学習モデルではなく、問題の構造モデルです。
Entities(登場人物・物)
State Variables(状態:変わりうるプロパティ)
Actions(操作:前提条件と効果)
Constraints(常に守る制約/不変条件)
【Figure 1(論文図1)】

2.3 専門用語を噛み砕く:
ここでのモデルを構成するキーワードを、実務的に説明しておきましょう。
Entity(エンティティ):
スケジューリングなら「人」「会議室」「タスク」
ツール実行なら「ファイル」「API」「ジョブ」
State Variable(状態変数):
「Aさんの空き時間」「会議室Bの占有状況」「タスクXの進捗」「在庫数」
“今どうなっているか”を記録する箱
Action(行動):
例:`schedule_meeting(person, room, start, end)`
Preconditions(前提条件):空いている、権限がある、在庫がある
Effects(効果):空きが埋まる、在庫が減る、状態が遷移する
Constraint(制約):
「同じ部屋に同時間帯で二重予約しない」
「薬Aと薬Bは同日投与不可」
「工程2は工程1の完了後」
MFRは、これを最初に書かせて固定する。
固定した“ルールブック”を参照して計画する。
この分離が「ハルシネーション(ここでは、勝手な状態・勝手な観測・勝手な行動の混入)」を減らす、というのが論文の立場です。
3. 実装イメージ:MFRを“今日から”試すプロンプト設計
ここからが実務の肝です。論文では「アーキテクチャの変更や追加学習が不要であり、プロンプトだけでできる」と強調しています。
必要なこと、やるべきことは、主に次の3点です。
モデル構築フェーズを、解答フェーズから強制的に分離する
モデルを構造化(最低でも見出し、できればJSON)
解答で「モデル外の情報を使わない」制約をかける
3.1 最小構成(1プロンプト内2セクション)
LLMを1回だけ呼ぶパターン。
あなたは計画立案エージェントです。次の手順を厳守してください。
[Phase 1: Problem Model]
- まだ解を提案しない。
- 問題モデルを明示せよ:
1) Entities
2) State variables
3) Actions(preconditions/effects)
4) Constraints
[Phase 2: Plan]
- Phase 1で定義したモデル“のみ”を使い、状態遷移が矛盾しない計画を出せ。
- 各ステップで、適用したAction、満たしたPreconditions、更新されたStateを短く書け。
問題:
{ここにタスク本文}ポイント:Phase 1で「解を出すな」を強く言うこと。
(LLMはつい解を出したがるので、禁止が弱いと混ざります)
3.2 実務で効く構造化(JSONモデル + 検証)
ヘビーユーザー向けのおすすめは、モデルをJSONにしてしまうことです。
Phase 1(モデル出力)プロンプト例
あなたは“問題モデリング専用”です。解決案や手順は書かないでください。
次のJSONスキーマに厳密に従い、問題モデルだけを出力してください。
# JSON Schema(概略)
{
"entities": [
{"name": "...", "type": "...", "attributes": ["..."]}
],
"state_variables": [
{"name": "...", "type": "...", "domain": "...", "initial": "unknown|..."}
],
"actions": [
{
"name": "...",
"parameters": [{"name":"...","type":"..."}],
"preconditions": ["..."],
"effects": ["..."],
"notes": "..."
}
],
"constraints": ["..."],
"goal": "...",
"assumptions": ["(不明点は仮定として明示) ..."],
"unknowns": ["(追加質問すべき点) ..."]
}
# Problem
{タスク}`assumptions` を設けるのがコツです。
暗黙に埋めるのではなく「仮定」として表面化させる
`unknowns` を設けると、要件不足を安全に扱えます
Phase 2(計画生成)プロンプト例
あなたは“計画生成専用”です。
次の問題モデル(JSON)の範囲内でのみ計画を生成してください。
- モデルに存在しないEntity/State/Action/Constraintを勝手に追加しない
- 不足情報が原因で計画不能なら、unknownsとして質問を返す
# Problem Model (JSON)
{Phase1のJSON}
# Output Format
- plan: ステップ配列
- each step: {action, parameters, preconditions_checked, state_updates, constraint_check}ここまでやると、「モデルが壊れている」か「推論が壊れている」かを切り分けやすくなります。
4. Pythonで“それっぽく”試す:最小エージェント骨格(疑似コード)
ここでは「モデル開発はしないが、Pythonで実験する」層向けに、MFRを回す骨格を提示します。
外部ソルバは使わず、
JSONを構造チェック
制約チェックを軽く入れる
程度で、論文の“雰囲気”を再現できます。
4.1 依存:pydantic(任意)
構造化出力を検証したいので、あると便利です。
4.2 データモデル(Pydantic)
from typing import List, Dict, Any, Optional
from pydantic import BaseModel, Field
class Entity(BaseModel):
name: str
type: str
attributes: List[str] = []
class StateVariable(BaseModel):
name: str
type: str
domain: str
initial: str = "unknown"
class ActionSpec(BaseModel):
name: str
parameters: List[Dict[str, str]] = []
preconditions: List[str] = []
effects: List[str] = []
notes: str = ""
class ProblemModel(BaseModel):
entities: List[Entity]
state_variables: List[StateVariable]
actions: List[ActionSpec]
constraints: List[str]
goal: str
assumptions: List[str] = []
unknowns: List[str] = []4.3 LLM呼び出し(抽象化)
あなたの環境(OpenAI/Anthropic/Google等)に合わせて差し替える前提です。
def call_llm(system: str, user: str) -> str:
"""任意のLLM API呼び出しに差し替え"""
raise NotImplementedError4.4 Phase 1: モデル構築
import json
MODEL_PROMPT = """
あなたは“問題モデリング専用”です。解決案や手順は書かないでください。
指定スキーマに従うJSONだけを出力してください。
...
""".strip()
SCHEMA_HINT = """{
"entities": [...],
"state_variables": [...],
"actions": [...],
"constraints": [...],
"goal": "...",
"assumptions": [...],
"unknowns": [...]
}"""
def build_problem_model(task_text: str) -> ProblemModel:
user = f"# JSON Schema\n{SCHEMA_HINT}\n\n# Problem\n{task_text}"
raw = call_llm(system=MODEL_PROMPT, user=user)
data = json.loads(raw)
return ProblemModel.model_validate(data)4.5 Phase 2: モデル上で計画
PLAN_PROMPT = """
あなたは“計画生成専用”です。
入力されたProblem Model(JSON)の範囲内でのみ計画を生成してください。
- モデル外のAction/Entity/Constraintを追加禁止
- 各ステップで前提と制約のチェックを明示
- 不足があれば unknowns を質問として返す
出力はJSON。
""".strip()
def plan_with_model(model: ProblemModel) -> Dict[str, Any]:
user = model.model_dump_json(indent=2, ensure_ascii=False)
raw = call_llm(system=PLAN_PROMPT, user=user)
return json.loads(raw)4.6 軽量な“自前検証”の発想(重要)
論文は「MFRは形式検証ではない」と言っています。
しかし実務では、軽い自動チェックを挟むだけで、効果が跳ね上がることが多いです。
例:
ステップの `action`が `model.actions` の名前集合に含まれるか
`constraint_check` が空欄でないか(強制)
状態更新が「何をどう変えたか」を含むか
def validate_plan_against_model(model: ProblemModel, plan: Dict[str, Any]) -> List[str]:
errors = []
action_names = {a.name for a in model.actions}
steps = plan.get("plan", [])
for i, step in enumerate(steps, start=1):
a = step.get("action")
if a not in action_names:
errors.append(f"Step {i}: unknown action '{a}'")
if not step.get("constraint_check"):
errors.append(f"Step {i}: constraint_check is missing")
return errorsこの程度でも「勝手な行動」を封じる効果があります。
5. 図解で理解する:MFRを“状態機械”として捉える
論文内の図(Figure 1, Figure 2)は比較と評価の視点ですが、実務的には「MFRは状態機械(state machine)を外化する」だと捉えると腹落ちします。
ここでは論文外の補助図を1つ追加します。
【補助図A(論文外)】

この図のメッセージは単純で、
まずモデルを作る
そのモデルに対して計画する
エラーが出たら「モデルが悪いのか、計画が悪いのか」を分岐して直す
という“デバッグ可能性”が手に入る、ということです。
CoT/ReActのつらさは、エラーが出ても
世界観が暗黙
途中からすり替わる
何を直すべきか分からない
になりやすい点にあります。
6. 評価・結果解説:論文の図表が示していること(定性的に)
論文の評価は厳密な大規模ベンチではなく、複数の制約付きタスクに対する定性的評価です。
本記事でも、細かい数値競争ではなく「何が分かったか」を中心に解説します。
6.1 表:3手法の比較(Table 1)
【Table 1(論文表1)】

Table 1は、CoT / ReAct / MFR を次の3軸で比較しています。
Constraint Violations(制約違反)
Implicit Assumptions(暗黙の仮定の混入)
Structural Clarity(構造の明瞭さ=検証しやすさ)
定性的な結論は:
CoT:制約違反が中程度、暗黙仮定が頻発、構造が弱い
ReAct:改善するが、まだ暗黙仮定や制約の抜けが残る
MFR:制約違反が低く、暗黙仮定が稀、構造が高い
ここで重要なのは「MFRが万能」ではなく、
制約と状態が支配的なタスクで効く
しかも「モデル構築を先にやる」ことが効く
という整理です。
6.2 図:比較の可視化(Figure 2)
【Figure 2(論文図2)】

Figure 2はTable 1の定性的評価を、棒グラフ的に可視化しています。
読み取りの要点は次の通りです。
MFRは「構造の明瞭さ」が高い方向に寄る
これは現場では「レビューできる」「再現できる」「監査できる」を意味します
CoTは「暗黙仮定」が多い方向に寄る
つまり、ユーザーが書いてないことを勝手に補完してしまいがち
ReActは中間
ツール観測を挟めるぶんマシだが、問題モデルが固定されないので長期で崩れる
6.3 図:パラダイム比較(Figure 1)
もう一度図1を見てみましょう。
【再掲 Figure 1(論文図1)】

Figure 1が示すのは、MFRが「推論手法の改良」ではなく、
推論の前に“明示モデル”という土台を置くパラダイムである、ということです。
現場目線の翻訳:
CoTは「説明しながら考える」
ReActは「考えながら触って確かめる」
MFRは「まず仕様書(状態・操作・禁則)を書いて、仕様書に従って考える」
です
7. 現場応用:MFRが刺さるユースケース
論文が挙げる例(医療スケジュール、資源配分、ルート計画等)を踏まえつつ、あなたが明日から使いやすい形に落とします。
7.1 予定調整・タスク割当(制約が多いほど効く)
人ごとの稼働
会議室
時間帯
連続性(前後関係)
禁則(同日不可、間隔必要)
MFRで「状態変数」を明示すると、LLMは
何を更新しているか
どの制約をチェックしているか
を出力に含めやすくなります。
7.2 手順実行(SOP)
SOPが壊れる典型は、
実行済みの手順を忘れて重複
本来の前提(バックアップ済み等)を飛ばす
MFRで
`state_variables`: `backup_done: bool`, `service_status: {running, stopped}`
`actions`: `stop_service`, `backup_db`, `apply_migration`, ...
を定義させると、SOPを「状態遷移」として扱えます。
7.3 RAG/検索と組み合わせるとき
RAGの問題も取り上げておきましょう。RAGはLLMに知識を注入する有力な手法ですが、どうしてもピント外れな検索をしてしまい、「それじゃない」問題が多くあります。
RAGは「事実」を補うのに強い一方、
“ルール”
“状態管理”
は別問題です。
MFRはRAGの前後どちらにも置けますが、実務では次が堅いです。
先にモデル構築(何を必要とするかを定義)
次にRAGでunknownsを埋める
その後に計画
こうすると、検索が「場当たり的」になりにくいです。
以下に、おすすめしたフロー(モデル構築→unknowns抽出→RAGで補完→モデル更新→計画→検証)を図示します。
【補助図B 論文外】
モデル確定後に、unknowsを検索クエリに変換することで、本当に必要な検索ができる可能性が高まります。

補足(運用のコツ):
`unknowns` は「検索すべき項目リスト」そのものとして設計すると、RAGが場当たり的になりにくいです。
RAGで得た根拠は、モデル側の `assumptions` を削る/具体化する形で“モデルに反映”してから計画に進むのが安定します。
8. もう一段実務的に:MFRプロンプトの“型”
もう少し、実際の利用を考えながらプロンプトを見直してみましょう。
8.1 型1:モデリング→質問→計画(不足情報が多いとき)
モデル構築(unknownsを出す)
ユーザーに質問 or 検索
モデル更新
計画
この型は、
要件が曖昧な社内依頼
仕様が散らばっている業務
に強いです。
8.2 型2:モデリング→計画→検証→再計画(反復)
まずモデルを固定
計画
バリデーション
計画だけ作り直す(モデルは維持)
「モデルを頻繁に変えない」ことが、長期の一貫性に効きます。
8.3 型3:ReActにMFRを“状態ストア”として差し込む
論文でも「ReActと補完的」と述べています。
実務翻訳すると:
ReActのループに「Problem Model」を永続メモリとして持たせる
観測が入ったら、
状態変数だけ更新
制約は常に参照
とすると、ReActの「ログ散逸」問題が緩和します。
以下に、型3:ReActにMFRを“状態ストア”として差し込むを図示します
狙いは、ReActのループ(Thought→Action→Observation→Thought…)に対し、
MFRのProblem Modelを永続ストア(Single Source of Truth)として保持
観測が入ったら 状態変数だけ更新
以後のThought/Action選択は 常にモデル(制約含む)を参照
という“背骨”を足して、ログ散逸・状態ドリフトを減らすことです。
【補助図C(論文外)】

補足(運用のコツ):
観測(Observation)をそのまま自由文で積むのではなく、`state_variables` の更新として正規化すると、長いループでも破綻しにくいです。
逆に、観測が「モデル定義そのもの」を破壊する(例:想定してないエンティティ/操作が必要)場合だけ `Model Repair` に分岐させると、モデルが頻繁に揺れず安定します。
9. 限界・注意点:MFRは万能ではない(論文の限界+実務の落とし穴)
論文も限界を明記していますし、現場でも注意が必要です。
9.1 モデル構築をLLMが誤ると、その後ぜんぶ歪む
MFRの構造は
モデルが土台
推論がその上
なので、土台が間違うと「きれいに間違う」危険があります。
対策:
unknowns/assumptionsを必須フィールド化
重要制約はユーザーがレビューする
最低限の自動検証(モデルにないAction禁止)
9.2 トークンコスト(オーバーヘッド)
モデルを書くぶん、長くなります。
ただし現場的には
1回で正しく終わる
デバッグが短い
なら、総コストはむしろ下がることも多いです。
9.3 形式検証ではない(“違反を減らす”止まり)
MFRは
ソルバ
形式手法
ではありません。
安全クリティカル用途では、
ルールエンジン
制約ソルバ
テスト生成
と併用すべきです。
9.4 そもそも制約が薄いタスクでは効果が薄い
文章要約やアイデア出しなど、状態・制約が主要因でないタスクでは、MFRの価値は限定的です。
つまり自由な会話を楽しんだり、ヒントがほしいと思って会話をすると、面白いことを言ってくれない可能性があります。
10. まとめ:MFRを現場の言葉で言い切る
LLMの破綻は「推論が弱い」より、問題表現が揺れることが原因になりやすい
MFRは「まず問題モデル(世界観)を外化し、固定し、その上で推論する」
その結果、
制約違反が減り
暗黙仮定が減り
出力が検証可能になる
現場での一番の価値は、精度向上だけでなく、
どこが悪いか分かる(モデルか推論か)
直し方が分かる(モデル修正か再計画か)
という「デバッグ可能性」ではないでしょうか。
とりあえず次のアクションを試してみましょう。
いま使っている“複雑タスク用プロンプト”に、Phase 1(Entities/State/Actions/Constraints)を足す
Phase 2で「モデル外の追加禁止」を明記する
できればJSON化し、Pythonで簡単に検証する
これだけで、長い手順・割当・制約付きタスクの安定度が上がるはずです。
参考:すぐ使えるコピペ用テンプレ(短縮版)
テンプレA(1プロンプト2フェーズ)
手順厳守。
[Phase 1: Model]
解は出さない。問題モデルを列挙:
- Entities
- State Variables
- Actions(preconditions/effects)
- Constraints
- Assumptions / Unknowns
[Phase 2: Plan]
Phase 1のモデルのみを使う。
各ステップで action / preconditions / state update / constraint check を短く。
問題:
...テンプレB(JSON強制)
あなたは問題モデリング専用。解決案は禁止。
指定スキーマのJSONだけを出力。
...ハッシュタグ(関連語を多めに)
#ModelFirstReasoning #MFR #LLMAgent #AgenticAI #PromptEngineering #CoT #ChainOfThought #ReAct #Planning #AIPlanning #PDDL #STRIPS #ProblemModeling #ExplicitModel #StateTracking #ConstraintSatisfaction #Hallucination #RepresentationalFailure #Interpretability #Verifiability #StructuredOutput #JSONSchema #Pydantic #LLMOps #ToolUse #RAG #WorkflowAutomation #TaskDecomposition #LongHorizonReasoning #Robustness #AI安全性 #AI信頼性 #検証可能性 #プロンプト設計 #業務自動化 #スケジューリング #リソース割当
- #業務自動化
- #RAG
- #プロンプト設計
- #react
- #AI安全性
- #PromptEngineering
- #AgenticAI
- #スケジューリング
- #cot
- #LLMOps
- #検証可能性
- #ChainOfThought
- #hallucination
- #planning
- #Pydantic
- #AI信頼性
- #workflowautomation
- #tooluse
- #Interpretability
- #jsonschema
- #strips
- #StructuredOutput
- #LLMAgent
- #MFR
- #StateTracking
- #PDDL
- #Verifiability
- #robustness
- #constraintsatisfaction
- #ModelFirstReasoning
- #AIPlanning
- #ProblemModeling
- #ExplicitModel
- #RepresentationalFailure
- #TaskDecomposition
- #LongHorizonReasoning
- #リソース割当