Fixed llm context for turns

This commit is contained in:
Dejvino 2026-07-01 22:24:46 +02:00
parent 0140e2e8d9
commit 6403d46052
6 changed files with 14 additions and 31 deletions

View File

@ -38,6 +38,7 @@ class GameEngine:
state.append_llm_log(f"Player: {player_action}") state.append_llm_log(f"Player: {player_action}")
if recent_narrative is None: if recent_narrative is None:
recent_narrative = state.read_recent_book(2) recent_narrative = state.read_recent_book(2)
session_log = state.read_recent_log()
die_roll = random.randint(1, 6) die_roll = random.randint(1, 6)
state.append_llm_log(f"Dice: {die_roll} (1d6)") state.append_llm_log(f"Dice: {die_roll} (1d6)")
@ -51,9 +52,7 @@ class GameEngine:
on_debug("config", {"model": model, "temperature": lm.get("temperature"), "max_tokens": lm.get("max_tokens"), "strategy": "tools"}) on_debug("config", {"model": model, "temperature": lm.get("temperature"), "max_tokens": lm.get("max_tokens"), "strategy": "tools"})
if player_action: if player_action:
story = state.read_recent_book() valid, reason = validate_action(player_action, story=recent_narrative, log=session_log, on_debug=on_debug)
log = state.read_recent_log()
valid, reason = validate_action(player_action, story=story, log=log, on_debug=on_debug)
if valid: if valid:
state.append_llm_log(f"\n[VALIDATION PASSED] {reason}") state.append_llm_log(f"\n[VALIDATION PASSED] {reason}")
else: else:
@ -64,10 +63,8 @@ class GameEngine:
user_prompt=f"*Your action:\n\t\"{player_action}\"\nwas rejected:\n\t{reason}*", user_prompt=f"*Your action:\n\t\"{player_action}\"\nwas rejected:\n\t{reason}*",
) )
system = build_system_prompt() system = build_system_prompt(recent_narrative=recent_narrative, recent_log=session_log)
parts = [] parts = []
if recent_narrative:
parts.append(f"## Recent Narrative\n{recent_narrative}")
if player_action: if player_action:
parts.append(f"## Player's Request\n{player_action}") parts.append(f"## Player's Request\n{player_action}")
if not player_action and not recent_narrative: if not player_action and not recent_narrative:

View File

@ -5,12 +5,12 @@ from .prompts import SYSTEM_PROMPT
from . import state from . import state
def build_system_prompt() -> str: def build_system_prompt(recent_narrative: str | None = None, recent_log: str | None = None) -> str:
"""Assemble the system prompt with current game state.""" """Assemble the system prompt with current game state."""
char = state.read_file(CHAR_PATH) or "*No character sheet.*" char = state.read_file(CHAR_PATH) or "*No character sheet.*"
world = state.truncate_world(state.read_file(WORLD_PATH) or "") or "*No world state.*" world = state.truncate_world(state.read_file(WORLD_PATH) or "") or "*No world state.*"
log = state.read_recent_log() log = recent_log if recent_log is not None else state.read_recent_log()
story = state.read_recent_book() story = recent_narrative if recent_narrative is not None else state.read_recent_book(2)
return SYSTEM_PROMPT.substitute( return SYSTEM_PROMPT.substitute(
character=char, world=world, log=log, story=story character=char, world=world, log=log, story=story,
) )

View File

@ -40,8 +40,12 @@ def read_recent_book(max_turns: int = 1) -> str:
if not text: if not text:
return "*No prior story.*" return "*No prior story.*"
turns = text.split("\n## ") turns = text.split("\n## ")
if len(turns) <= 1:
return turns[0]
recent = turns[-max_turns:] recent = turns[-max_turns:]
return "\n## ".join(recent) if len(turns) > 1 else recent[0] if not recent[0].startswith("## "):
recent[0] = "## " + recent[0]
return "\n## ".join(recent)
def truncate_world(text: str) -> str: def truncate_world(text: str) -> str:

View File

@ -101,6 +101,4 @@ def validate_action(
return False, "Unrecognized" return False, "Unrecognized"
def auto_prompt(book_log: str = "") -> str:
"""Fallback player prompt."""
return "**What do you do?**"

View File

@ -30,7 +30,7 @@ def test_engine_import():
('engine_lib.state', ['read_file', 'apply_state', 'append_log', 'append_llm_log', 'next_turn_number']), ('engine_lib.state', ['read_file', 'apply_state', 'append_log', 'append_llm_log', 'next_turn_number']),
('engine_lib.tools_handler', ['execute_tool', 'extract_tool_calls', 'TOOL_REGISTRY']), ('engine_lib.tools_handler', ['execute_tool', 'extract_tool_calls', 'TOOL_REGISTRY']),
('engine_lib.llm', ['call_llm']), ('engine_lib.llm', ['call_llm']),
('engine_lib.validation', ['auto_prompt', 'validate_action']), ('engine_lib.validation', ['validate_action']),
('engine_lib.parsing', ['log_turn_details']), ('engine_lib.parsing', ['log_turn_details']),
('engine', ['GameEngine']), ('engine', ['GameEngine']),
] ]

View File

@ -127,20 +127,6 @@ def test_on_debug_called(mock_call_llm, mock_truncate_world, mock_read_file):
print("✓ on_debug callback receives action_validation event") print("✓ on_debug callback receives action_validation event")
def test_auto_prompt_default():
from engine_lib.validation import auto_prompt
result = auto_prompt()
assert result == "**What do you do?**"
print("✓ auto_prompt() returns default prompt")
def test_auto_prompt_with_log():
from engine_lib.validation import auto_prompt
result = auto_prompt(book_log="Some story text")
assert result == "**What do you do?**"
print("✓ auto_prompt() ignores book_log argument")
if __name__ == "__main__": if __name__ == "__main__":
test_empty_action() test_empty_action()
test_valid_action() test_valid_action()
@ -149,6 +135,4 @@ if __name__ == "__main__":
test_llm_returns_bad_json() test_llm_returns_bad_json()
test_missing_character_sheet() test_missing_character_sheet()
test_on_debug_called() test_on_debug_called()
test_auto_prompt_default()
test_auto_prompt_with_log()
print("\n✓ All validation tests passed") print("\n✓ All validation tests passed")