Skip to content

Commit 8a4ecd2

Browse files
committed
load prompts from globs, provide more information to prompt templates, make pseudo-function parsing more flexible, add enter/exit messages to digest system
1 parent 573b15b commit 8a4ecd2

12 files changed

+145
-44
lines changed

prompts/llama-base.yml

+3-19
Original file line numberDiff line numberDiff line change
@@ -186,23 +186,7 @@ prompts:
186186
action_check_calendar_each: |
187187
{{name}} will happen in {{turns}} turn
188188
189-
# digest system
190-
digest_action_move: |
191-
{{event.character | name}} entered the room.
192-
digest_action_take: |
193-
{{event.character | name}} picked up the {{event.parameters[item]}}.
194-
digest_action_give: |
195-
{{event.character | name}} gave the {{event.parameters[item]}} to {{event.parameters[character]}}.
196-
digest_action_drop: |
197-
{{event.character | name}} dropped the {{event.parameters[item]}}.
198-
digest_action_ask: |
199-
{{event.character | name}} asked {{event.parameters[character]}} about something.
200-
digest_action_tell: |
201-
{{event.character | name}} told {{event.parameters[character]}} about something.
202-
digest_action_examine: |
203-
{{event.character | name}} examined the {{event.parameters[target]}}.
204-
205-
# world defaults
189+
# default dungeon master
206190
world_default_dungeon_master: |
207191
You are the dungeon master in charge of creating an engaging fantasy world full of interesting characters who
208192
interact with each other and explore their environment. Be creative and original, creating a world that is
@@ -233,7 +217,7 @@ prompts:
233217
world_generate_room_broadcast_characters: |
234218
Generating {{character_count}} characters for room: {{name}}
235219
world_generate_room_broadcast_portals: |
236-
Generating {{portal_count}} portals for room: {{name}}
220+
Generating {{portal_count}} portals for room: {{room | name}}
237221
238222
world_generate_portal_name_outgoing: |
239223
Generate the name of a portal that leads from the {{source_room}} room to the {{dest_room}} room and fits the world theme of {{world_theme}}.
@@ -346,7 +330,7 @@ prompts:
346330
347331
# world simulation
348332
world_simulate_character_action: |
349-
You are currently in the {{room_name}} room. {{room_description}}. {{attributes}}.
333+
You are currently in the {{room | name}} room. {{room | describe}}. {{attributes}}.
350334
The room contains the following characters: {{visible_characters}}.
351335
The room contains the following items: {{visible_items}}.
352336
Your inventory contains the following items: {{character_items}}.

prompts/llama-digest.yml

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
prompts:
2+
# digest system
3+
digest_action_move_other_enter: |
4+
{{event.character | name}} entered the room through the {{source_portal | name}}.
5+
digest_action_move_other_exit: |
6+
{{event.character | name}} left the room, heading through the {{destination_portal | name}}.
7+
digest_action_move_self_enter: |
8+
You entered the room through the {{source_portal | name}}.
9+
digest_action_move_self_exit: |
10+
You left the room, heading through the {{destination_portal | name}}.
11+
digest_action_move: |
12+
{{event.character | name}} entered the room.
13+
digest_action_take: |
14+
{{event.character | name}} picked up the {{event.parameters[item]}}.
15+
digest_action_give: |
16+
{{event.character | name}} gave the {{event.parameters[item]}} to {{event.parameters[character]}}.
17+
digest_action_drop: |
18+
{{event.character | name}} dropped the {{event.parameters[item]}}.
19+
digest_action_ask: |
20+
{{event.character | name}} asked {{event.parameters[character]}} about something.
21+
digest_action_tell: |
22+
{{event.character | name}} told {{event.parameters[character]}} about something.
23+
digest_action_examine: |
24+
{{event.character | name}} examined the {{event.parameters[target]}}.

prompts/llama-quest.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
prompts:
22
action_accept_quest_error_none: No quests are available at the moment.
33
action_accept_quest_error_name: |
4-
{{character}} does not have a quest named "{{quest_name}}".
4+
{{character}} does not have a quest named "{{quest.name}}".
55
action_accept_quest_error_room: |
66
{{character}} is not in the room.
77
action_accept_quest_result: |
8-
You have started the quest "{{quest_name}}".
8+
You have started the quest "{{quest.name}}".
99
1010
action_submit_quest_error_active: |
1111
You do not have any active quests.
1212
action_submit_quest_error_none: No quests are available at the moment.
1313
action_submit_quest_error_name: |
14-
{{character}} does not have a quest named "{{quest_name}}".
14+
{{character}} does not have a quest named "{{quest.name}}".
1515
action_submit_quest_error_room: |
1616
{{character}} is not in the room.
1717
action_submit_quest_result: |
18-
You have completed the quest "{{quest_name}}".
18+
You have completed the quest "{{quest.name}}".

taleweave/actions/base.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def action_examine(target: str) -> str:
3737
format_prompt(
3838
"action_examine_broadcast_action",
3939
action_character=action_character,
40+
action_room=action_room,
4041
target=target,
4142
)
4243
)
@@ -49,7 +50,7 @@ def action_examine(target: str) -> str:
4950
action_room=action_room,
5051
)
5152
)
52-
return format_prompt("action_examine_result_room", action_room=action_room)
53+
return format_prompt("action_examine_result_room", target_room=action_room)
5354

5455
target_character = find_character_in_room(action_room, target)
5556
if target_character:
@@ -118,7 +119,7 @@ def action_move(direction: str) -> str:
118119
format_prompt(
119120
"action_move_error_room",
120121
direction=direction,
121-
destination=portal.destination,
122+
portal=portal,
122123
)
123124
)
124125

taleweave/actions/quest.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ def submit_quest(character: str) -> str:
7474
return format_prompt(
7575
"action_submit_quest_result",
7676
character=character,
77-
quest=active_quest.name,
77+
quest=active_quest,
7878
)
7979

8080
return format_prompt(
8181
"action_submit_quest_error_name",
8282
character=character,
83-
quest=active_quest.name,
83+
quest=active_quest,
8484
)

taleweave/generate.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ def link_rooms(
523523
format_prompt(
524524
"world_generate_room_broadcast_portals",
525525
portal_count=num_portals,
526-
name=room.name,
526+
room=room,
527527
)
528528
)
529529

taleweave/main.py

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import atexit
22
from functools import partial
3+
from glob import glob
34
from logging.config import dictConfig
45
from os import environ, path
56
from typing import List
@@ -195,7 +196,11 @@ def get_world_prompt(args) -> WorldPrompt:
195196

196197
def load_prompt_library(args) -> None:
197198
if args.prompts:
199+
prompt_files = []
198200
for prompt_file in args.prompts:
201+
prompt_files.extend(glob(prompt_file, recursive=True))
202+
203+
for prompt_file in prompt_files:
199204
with open(prompt_file, "r") as f:
200205
new_library = PromptLibrary(**load_yaml(f))
201206
logger.info(f"loaded prompt library from {prompt_file}")
@@ -258,6 +263,7 @@ def load_or_generate_world(
258263
llm,
259264
memory_factory=memory_factory,
260265
)
266+
set_dungeon_master(world_builder)
261267

262268
if path.exists(world_state_file):
263269
logger.info(f"loading world state from {world_state_file}")
@@ -285,6 +291,8 @@ def load_or_generate_world(
285291
systems,
286292
room_count=args.rooms,
287293
)
294+
load_or_initialize_system_data(args, systems, world)
295+
288296
save_world(world, world_file)
289297
save_system_data(args, systems)
290298

taleweave/player.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from taleweave.context import action_context
1212
from taleweave.models.event import PromptEvent
13+
from taleweave.utils import try_parse_float, try_parse_int
1314

1415
logger = getLogger(__name__)
1516

@@ -122,12 +123,18 @@ def parse_pseudo_function(self, reply: str):
122123
def parse_value(value: str) -> str | bool | float | int:
123124
if value.startswith("~"):
124125
return value[1:]
125-
if value.lower() in ["true", "false"]:
126-
return value.lower() == "true"
127-
if value.isdecimal():
128-
return float(value)
129-
if value.isnumeric():
126+
127+
if value.lower() in ["true", "false", "yes", "no", "y", "n"]:
128+
return value.lower() in ["true", "yes", "y"]
129+
130+
int_value = try_parse_int(value)
131+
if int_value is not None:
130132
return int(value)
133+
134+
float_value = try_parse_float(value)
135+
if float_value is not None:
136+
return float(value)
137+
131138
return value
132139

133140
params = {

taleweave/simulate.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
from taleweave.utils.planning import expire_events, get_upcoming_events
5454
from taleweave.utils.prompt import format_prompt
5555
from taleweave.utils.search import find_containing_room
56-
from taleweave.utils.world import describe_entity, format_attributes
56+
from taleweave.utils.world import format_attributes
5757

5858
logger = getLogger(__name__)
5959

@@ -136,8 +136,7 @@ def result_parser(value, **kwargs):
136136
character_items=character_items,
137137
attributes=character_attributes,
138138
directions=room_directions,
139-
room_name=room.name,
140-
room_description=describe_entity(room),
139+
room=room,
141140
visible_characters=room_characters,
142141
visible_items=room_items,
143142
notes_prompt=notes_prompt,

taleweave/systems/digest.py

+78-7
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,87 @@
11
from logging import getLogger
2-
from typing import Dict, List
2+
from typing import Any, Dict, List
33

44
from taleweave.context import get_current_world, get_prompt_library, subscribe
55
from taleweave.game_system import FormatPerspective, GameSystem
66
from taleweave.models.entity import Character, Room, World, WorldEntity
77
from taleweave.models.event import ActionEvent, GameEvent
88
from taleweave.utils.prompt import format_str
9-
from taleweave.utils.search import find_containing_room
9+
from taleweave.utils.search import find_containing_room, find_portal, find_room
1010

1111
logger = getLogger(__name__)
1212

1313

14+
def create_move_digest(
15+
world: World,
16+
active_room: Room,
17+
active_character: Character,
18+
event: ActionEvent,
19+
) -> str:
20+
source_room = event.room
21+
direction = str(event.parameters.get("direction"))
22+
destination_portal = find_portal(world, direction)
23+
if not destination_portal:
24+
raise ValueError(f"Could not find portal for direction {direction}")
25+
26+
destination_room = find_room(world, destination_portal.destination)
27+
if not destination_room:
28+
raise ValueError(
29+
f"Could not find destination room {destination_portal.destination}"
30+
)
31+
32+
# look up the source portal
33+
source_portal = next(
34+
(
35+
portal
36+
for portal in destination_room.portals
37+
if portal.destination == source_room.name
38+
),
39+
None,
40+
)
41+
if not source_portal:
42+
raise ValueError(f"Could not find source portal for {destination_portal.name}")
43+
44+
mode = "self" if (event.character == active_character) else "other"
45+
mood = "enter" if (destination_room == active_room) else "exit"
46+
47+
message = format_str(
48+
f"digest_move_{mode}_{mood}",
49+
destination_portal=destination_portal,
50+
destination_room=destination_room,
51+
direction=direction,
52+
source_portal=source_portal,
53+
source_room=source_room,
54+
)
55+
return message
56+
57+
1458
def create_turn_digest(
15-
active_room: Room, active_character: Character, turn_events: List[GameEvent]
59+
world: World,
60+
active_room: Room,
61+
active_character: Character,
62+
turn_events: List[GameEvent],
1663
) -> List[str]:
1764
library = get_prompt_library()
1865
messages = []
1966
for event in turn_events:
2067
if isinstance(event, ActionEvent):
21-
if event.character == active_character or event.room == active_room:
68+
# special handling for move actions
69+
if event.action == "action_move":
70+
message = create_move_digest(
71+
world, active_room, active_character, event
72+
)
73+
messages.append(message)
74+
elif event.character == active_character or event.room == active_room:
2275
prompt_key = f"digest_{event.action}"
2376
if prompt_key in library.prompts:
2477
try:
2578
template = library.prompts[prompt_key]
26-
message = format_str(template, event=event)
79+
message = format_str(
80+
template,
81+
active_character=active_character,
82+
active_room=active_room,
83+
event=event,
84+
)
2785
messages.append(message)
2886
except Exception:
2987
logger.exception("error formatting digest event: %s", event)
@@ -65,10 +123,16 @@ def format_digest(
65123
if not room:
66124
raise ValueError("Character not found in any room")
67125

68-
digest = create_turn_digest(room, entity, buffer)
126+
digest = create_turn_digest(world, room, entity, buffer)
69127
return "\n".join(digest)
70128

71129

130+
def generate_digest(agent: Any, theme: str, entity: WorldEntity):
131+
if isinstance(entity, Character):
132+
if entity.name not in character_buffers:
133+
character_buffers[entity.name] = []
134+
135+
72136
def initialize_digest(world: World):
73137
for room in world.rooms:
74138
for character in room.characters:
@@ -77,4 +141,11 @@ def initialize_digest(world: World):
77141

78142
def init():
79143
subscribe(GameEvent, digest_listener)
80-
return [GameSystem("digest", format=format_digest, initialize=initialize_digest)]
144+
return [
145+
GameSystem(
146+
"digest",
147+
format=format_digest,
148+
generate=generate_digest,
149+
initialize=initialize_digest,
150+
)
151+
]

taleweave/utils/prompt.py

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from jinja2 import Environment
44

55
from taleweave.context import get_prompt_library
6+
7+
# from taleweave.utils.conversation import summarize_room
68
from taleweave.utils.string import and_list, or_list
79
from taleweave.utils.world import describe_entity, name_entity
810

@@ -11,6 +13,7 @@
1113
jinja_env = Environment()
1214
jinja_env.filters["describe"] = describe_entity
1315
jinja_env.filters["name"] = name_entity
16+
# jinja_env.filters["summary"] = summarize_room
1417
jinja_env.filters["and_list"] = and_list
1518
jinja_env.filters["or_list"] = or_list
1619

taleweave/utils/world.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ def describe_character(
1212
perspective: FormatPerspective = FormatPerspective.SECOND_PERSON,
1313
) -> str:
1414
attribute_descriptions = format_attributes(character, perspective=perspective)
15-
logger.info("describing character: %s, %s", character.name, attribute_descriptions)
15+
logger.info(
16+
"describing character: %s, attributes: '%s'",
17+
character.name,
18+
attribute_descriptions,
19+
)
1620

1721
if perspective == FormatPerspective.SECOND_PERSON:
1822
character_description = character.backstory

0 commit comments

Comments
 (0)