Show raw AI output in Insights per turn
Store the model's literal reply (before the world-state block is stripped) in each turn's snapshot, and render it in the Insights panel when inspecting a past AI message (the 🔍 button). Makes it possible to see exactly what the model emitted — including whether it sent a state delta and with what paths — which is the fastest way to debug under-reported or misrouted stat changes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
80fb5b0c89
commit
3b03bf737a
@@ -354,6 +354,9 @@ async def generate_turn(
|
|||||||
return
|
return
|
||||||
|
|
||||||
text = "".join(chunks).strip()
|
text = "".join(chunks).strip()
|
||||||
|
# The model's literal reply, kept for the Insights "Raw AI output" view —
|
||||||
|
# this still contains any world-state block before it gets stripped below.
|
||||||
|
raw_output = text
|
||||||
if not text:
|
if not text:
|
||||||
# If the model streamed reasoning but no story text, it spent its whole
|
# If the model streamed reasoning but no story text, it spent its whole
|
||||||
# budget thinking — say so instead of a mysterious "empty response".
|
# budget thinking — say so instead of a mysterious "empty response".
|
||||||
@@ -390,6 +393,8 @@ async def generate_turn(
|
|||||||
adventure.world_state = new_world_state
|
adventure.world_state = new_world_state
|
||||||
snapshot["world_state"] = {"delta": delta, "report": ws_report, "state": new_world_state}
|
snapshot["world_state"] = {"delta": delta, "report": ws_report, "state": new_world_state}
|
||||||
|
|
||||||
|
snapshot["raw_output"] = raw_output
|
||||||
|
|
||||||
ai_action = models.Action(
|
ai_action = models.Action(
|
||||||
adventure_id=adventure.id,
|
adventure_id=adventure.id,
|
||||||
index=ai_index,
|
index=ai_index,
|
||||||
|
|||||||
@@ -130,6 +130,14 @@ def test_turn_applies_clamped_delta_and_strips_block(client):
|
|||||||
# The state block is not shown to the player.
|
# The state block is not shown to the player.
|
||||||
assert "```state" not in _last_ai_text(client.adv_id)
|
assert "```state" not in _last_ai_text(client.adv_id)
|
||||||
assert "goblin's blade" in _last_ai_text(client.adv_id)
|
assert "goblin's blade" in _last_ai_text(client.adv_id)
|
||||||
|
# ...but the raw model reply (with the block) is kept for the Insights view.
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
snap = db.get(models.Adventure, client.adv_id).actions[-1].context_snapshot
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
assert "```state" in snap["raw_output"]
|
||||||
|
assert '"player.hp": -80' in snap["raw_output"]
|
||||||
|
|
||||||
|
|
||||||
def test_world_state_endpoint(client):
|
def test_world_state_endpoint(client):
|
||||||
|
|||||||
@@ -769,6 +769,14 @@ function InsightsPanel({ advId, inspectActionId, onClearInspect, refreshKey }) {
|
|||||||
))}
|
))}
|
||||||
<ScriptReport script={report.script} />
|
<ScriptReport script={report.script} />
|
||||||
<WorldStateReport worldState={report.world_state} />
|
<WorldStateReport worldState={report.world_state} />
|
||||||
|
{report.raw_output && (
|
||||||
|
<div className="ctx-section">
|
||||||
|
<div className="ctx-header">
|
||||||
|
<span>Raw AI output (before state block was stripped)</span>
|
||||||
|
</div>
|
||||||
|
<pre>{report.raw_output}</pre>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user