Skip to content

Commit b0d6c21

Browse files
authored
Merge pull request #99 from neph1/update-v0.38
Update v0.38
2 parents 6a19be8 + 581be66 commit b0d6c21

File tree

10 files changed

+54
-73
lines changed

10 files changed

+54
-73
lines changed

llm_config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ DUNGEON_LOCATION_TEMPLATE: '{"index": (int), "name": "", "description": 25 words
1616
CHARACTER_TEMPLATE: '{"name":"", "description": "50 words", "appearance": "25 words", "personality": "50 words", "money":(int), "level":"", "gender":"m/f/n", "age":(int), "race":"", "occupation":""}'
1717
FOLLOW_TEMPLATE: '{{"response":"yes or no", "reason":"50 words"}}'
1818
ITEM_TYPES: ["Weapon", "Wearable", "Health", "Money", "Trash"]
19-
PRE_PROMPT: 'You are a creative game keeper for an interactive fiction story telling session. You craft detailed worlds and interesting characters with unique and deep personalities for the player to interact with. Always follow the instructions given, never acknowledge the task or speak directly to the user or respond with anything besides the request.'
19+
PRE_PROMPT: 'You are a creative game keeper for an interactive fiction story telling session. You craft detailed worlds and interesting characters with unique and deep personalities for the player to interact with. Always follow the instructions given, never acknowledge the task or speak directly to the user or respond with anything besides the request. Do not invent new characters or locations unless prompted. Use the information provided to create a rich and engaging story. Remember to keep the story consistent with the context provided.'
2020
BASE_PROMPT: '<context>{context}</context>\n[USER_START] Rewrite [{input_text}] in your own words. The information inside the <context> tags should be used to ensure it fits the story. Use about {max_words} words.'
2121
DIALOGUE_PROMPT: '<context>{context}</context>\nThe following is a conversation between {character1} and {character2}; {character2}s sentiment towards {character1}: {sentiment}. Write a single response as {character2} in third person pov, using {character2} description and other information found inside the <context> tags. If {character2} has a quest active, they will discuss it based on its status. Respond in JSON using this template: """{dialogue_template}""". [USER_START]Continue the following conversation as {character2}: {previous_conversation}'
2222
COMBAT_PROMPT: '<context>{context}</context>\nThe following is a combat scene between {attackers} and {defenders} in {location}. [USER_START] Describe the following combat result in about 150 words in vivid language, using the characters weapons and describe their health status without mentioning numbers: 1.0 is highest, 0.0 is dead. <combat result> {input_text}</combat result>'
@@ -35,14 +35,14 @@ START_LOCATION_PROMPT: '[Story context: {story_context}]; Zone info: {zone_info}
3535
STORY_PLOT_PROMPT: "[USER_START] For an RPG described as {story_type} set in a world described as {world_mood}, {world_info}. Based on the following background: {story_background} write an innovative and engaging plot that the player can become part of. Use less than 400 words."
3636
WORLD_ITEMS: '<context>{context}</context>\n[USER_START] Using the information supplied inside the <context> tags, come up with 7 common items that can be found in the world. Item example: {item_template}, type is one of: {item_types}; Reply with a list of items in JSON format and do not write anything else: {{"items": []}}.'
3737
WORLD_CREATURES: '<context>{context}</context>\n[USER_START] Using the information supplied inside the <context> tags, come up with 5 creatures of various level and sentiment that can be found in the world. Consider the role of the creature in the story and whether it will be friendly or hostile to the player. Creature example: {creature_template}. Reply with a list of creatures in JSON format and do not write anything else: {{"creatures": []}}.'
38-
GOAL_PROMPT: '[Characters:{characters}][Sentiments towards characters: {sentiments}] [Last action: {last_action}] [Location: {location}] [Known locations: {locations}][Acting character: {character}] [Actions available:{actions}] [USER_START] For {character_name}, come up with a goal that plays along with their character description that involves an item, a character or a location in the prompt. Then construct up to three tasks that will lead towards the achievement of said goal. Fill in the following JSON template: {{"goal":"", "tasks":[{"action":"", "what":""}, {"action":"", "what":""}, {"action":"", "what":""}]}}'
38+
GOAL_PROMPT: '[Characters:{characters}][Sentiments towards characters: {sentiments}] [Last action: {last_action}] [Location: {location}] [Known locations: {locations}][Acting character: {character}] [Actions available:{actions}] [USER_START] For {character_name}, describe a goal that goes along with their character description that involves an item, a character or a location in the prompt. Then construct up to three tasks that will lead towards the achievement of said goal. Fill in the following JSON template: {{"goal":"", "tasks":[{"action":"", "what":""}, {"action":"", "what":""}, {"action":"", "what":""}]}}'
3939
JSON_GRAMMAR: "root ::= object\nvalue ::= object | array | string | number | (\"true\" | \"false\" | \"null\") ws\n\nobject ::=\n \"{\" ws (\n string \":\" ws value\n (\",\" ws string \":\" ws value)*\n )? \"}\" ws\n\narray ::=\n \"[\" ws (\n value\n (\",\" ws value)*\n )? \"]\" ws\n\nstring ::=\n \"\\\"\" (\n [^\"\\\\] |\n \"\\\\\" ([\"\\\\/bfnrt] | \"u\" [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]) # escapes\n )* \"\\\"\" ws\n\nnumber ::= (\"-\"? ([0-9] | [1-9] [0-9]*)) (\".\" [0-9]+)? ([eE] [-+]? [0-9]+)? ws\n\n# Optional space: by convention, applied in this grammar after literal chars when allowed\nws ::= ([ \\t\\n] ws)?"
4040
PLAYER_ENTER_PROMPT: '<context>{context}</context> Zone info: {zone_info}; Npc example: {npc_template}.\n[USER_START] The player has just re-entered this location: {location_info}. Consider whether any items, npcs or mobs should be spawned. For mobs, only enter the name of race. Fill in this JSON template and do not write anything else: {{"items":[], "npcs":[] "mobs":[]}}.'
4141
QUEST_PROMPT: '<context>{context}</context> Zone info: {zone_info}; Character: {character_card};\n[USER_START] Using the information supplied inside the <context> tags, {character_name} needs someone to perform a task. Based on the following input, come up with a suitable reason for it, using {character_name}s personality and history. Task info: {base_quest}. Fill in this JSON template and do not write anything else: {{"reason":""}} \n\n '
4242
NOTE_QUEST_PROMPT: '<context>{context}</context> Zone info: {zone_info};\n[USER_START]Using the information supplied inside the <context> tags, generate a quest that starts from reading a note. The reader must find and talk to a person. Fill in the following JSON template and write nothing else.: {{"reason": "only what the note says. 50 words.", "type":"talk", "target":"who to talk to", "location":"", "name":"name of quest"}}'
4343
NOTE_LORE_PROMPT: '<context>{context}</context> Zone info: {zone_info};\n[USER_START]FUsing the information supplied inside the <context> tags, decide what is written on a note that has been found. Use the provided story and world information to generate a piece of lore. Use about 50 words.'
44-
ACTION_PROMPT: '<context>{context}</context>\n[USER_START]Act as as {character_name}.\nUsing the information supplied inside the <context> tag, pick an action according to {character_name}s description and mood. If suitable, select something to perform the action on (target). The action should be in the supplied list and should be related to {character_name}s goal and thoughts. Build on events in "History" without repeating them. Respond using JSON in the following format with up to 3 actions: """{action_template}""". Continue the sequence of events: {previous_events}'
45-
REQUEST_FOLLOW_PROMPT: '<context>{context}</context>\n[USER_START]Act as as {character_name}.\nUsing the information supplied inside the <context> tag. {character_name} has received a request to follow {target}. Answer based on {character_name}s description and mood. Reason given by {target}: {target_reason}. Respond using JSON in the following format: {follow_template}'
44+
ACTION_PROMPT: '<context>{context}</context>\n[USER_START]Act as as {character_name}.\nUsing the information supplied inside the <context> tags, pick an action according to {character_name}s description and mood. If suitable, select something to perform the action on (target). The action should be in the supplied list and should be related to {character_name}s goal and thoughts. Build on events in "History" without repeating them. Respond using JSON in the following format with up to 3 actions: """{action_template}""". Continue the sequence of events: {previous_events}'
45+
REQUEST_FOLLOW_PROMPT: '<context>{context}</context>\n[USER_START]Act as {character_name}.\nUsing the information supplied inside the <context> tag. {character_name} has received a request to follow {target}. Answer based on {character_name}s description and mood. Reason given by {target}: {target_reason}. Respond using JSON in the following format: {follow_template}'
4646
DAY_CYCLE_EVENT_PROMPT: '<context>{context}</context>\n[USER_START] Write up to two sentences describing the transition from {from_time} to {to_time} in {location_name}, using the information supplied inside the <context> tags.'
4747
NARRATIVE_EVENT_PROMPT: '<context>{context}</context>\n[USER_START] Write a narrative event that occurs in {location_name} using the information supplied inside the <context> tags. The event should be related to the location and the characters present. Use up to 50 words.'
4848
RANDOM_SPAWN_PROMPT: '<context>{context}</context>\n[USER_START] An npc or a mob has entered {location_name}. Select either and fill in one of the following templates using the information supplied inside the <context> tags. Respond using JSON in the following format: {npc_template}'

tale/driver.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import appdirs
2626
from tale.items.basic import Note
2727

28+
from tale.llm import llm_config
2829
from tale.llm.LivingNpc import LivingNpc
2930
from tale.npc_defs import StationaryNpc
3031
from tale.zone import Zone
@@ -908,7 +909,7 @@ def prepare_combat_prompt(self,
908909
defender_titles.append(defender_title)
909910

910911

911-
return self.llm_util.combat_prompt.format(attackers=attacker_names,
912+
return llm_config.params['COMBAT_PROMPT'].format(attackers=attacker_names,
912913
defenders=defender_titles,
913914
location=location_title,
914915
input_text=combat_result,

tale/llm/LivingNpc.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ def character_card(self) -> str:
373373
items = []
374374
for i in self.inventory:
375375
items.append(f'"{str(i.name)}"')
376-
return '{{"name":"{name}", "gender":"{gender}","age":{age},"occupation":"{occupation}","personality":"{personality}","appearance":"{description}","items":[{items}], "race":"{race}", "quest":"{quest}", "example_voice":"{example_voice}", "wearing":"{wearing}", "wielding":"{wielding}"}}'.format(
376+
return '{{"name":"{name}", "gender":"{gender}","age":{age},"occupation":"{occupation}","personality":"{personality}","appearance":"{description}","items":[{items}], "race":"{race}", "quest":"{quest}", "goal":"{goal}", "example_voice":"{example_voice}", "wearing":"{wearing}", "wielding":"{wielding}"}}'.format(
377377
name=self.title,
378378
gender=lang.gender_string(self.gender),
379379
age=self.age,

tale/llm/contexts/ActionContext.py

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
3-
import json
41
import random
52
from tale.base import Location
63
from tale.llm.contexts.BaseContext import BaseContext
@@ -20,13 +17,13 @@ def __init__(self, story_context: str, story_type: str, character_name: str, cha
2017

2118
def to_prompt_string(self) -> str:
2219
actions = ', '.join(self.actions)
23-
characters = {}
20+
characters = []
2421
for living in self.location.livings:
25-
if living.visible and living.name != self.character_name.lower():
26-
if living.alive:
27-
characters[living.name] = living.short_description
28-
else:
29-
characters[living.name] = f"{living.short_description} (dead)"
22+
if living.visible and not living.hidden and living.name != self.character_name.lower():
23+
character = f"{living.name}: {living.short_description}"
24+
if not living.alive:
25+
character = character + " (dead)"
26+
characters.append(character)
3027
exits = self.location.exits.keys()
3128
items = [item.name for item in self.location.items if item.visible]
3229
examples = []
@@ -35,5 +32,5 @@ def to_prompt_string(self) -> str:
3532
if len(exits) > 0:
3633
examples.append(f'{{"goal":"", "thoughts":"I want to go there.", "action":"move", "target":{random.choice(list(exits))}, "text":""}}')
3734
if len(characters) > 0:
38-
examples.append(f'{{"goal":"", "thoughts":"", "action":"say", "target":{random.choice(list(characters.values()))}, "text":""}}')
39-
return f"Story context:{self.story_context}; Story type:{self.story_type}; Available actions: {actions}; Location:{self.location.name}, {self.location.description}; Available exits: {exits}; Self({self.character_name}): {self.character_card}; Present items: {items}; Present characters: {json.dumps(characters)}; History:{self.event_history}; Example actions: {', '.join(examples)};"
35+
examples.append(f'{{"goal":"", "thoughts":"", "action":"say", "target":{random.choice(characters)}, "text":""}}')
36+
return f"Story context:{self.story_context}; Story type:{self.story_type}; Available actions: {actions}; Location: {self.location.name}, {self.location.description}; Available exits: {exits}; Self({self.character_name}): {self.character_card}; Present items: {items}; Present characters: {characters}; History:{self.event_history}; Example actions: {', '.join(examples)};"

tale/llm/llm_utils.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,9 @@ def __init__(self, io_util: IoUtil = None):
4848
self.default_body = json.loads(backend_config['DEFAULT_BODY'])
4949
self.memory_size = llm_config.params['MEMORY_SIZE']
5050
self.pre_prompt = llm_config.params['PRE_PROMPT'] # type: str
51-
self.evoke_prompt = llm_config.params['BASE_PROMPT'] # type: str
52-
self.combat_prompt = llm_config.params['COMBAT_PROMPT'] # type: str
5351
self.word_limit = llm_config.params['WORD_LIMIT']
5452
self.short_word_limit = llm_config.params['SHORT_WORD_LIMIT']
55-
self.story_background_prompt = llm_config.params['STORY_BACKGROUND_PROMPT'] # type: str
56-
self.day_cycle_event_prompt = llm_config.params['DAY_CYCLE_EVENT_PROMPT'] # type: str
57-
self.narrative_event_prompt = llm_config.params['NARRATIVE_EVENT_PROMPT']
53+
5854
self.__story = None # type: DynamicStory
5955
self.io_util = io_util or IoUtil(config=llm_config.params, backend_config=backend_config)
6056
self.stream = backend_config['STREAM']
@@ -63,7 +59,7 @@ def __init__(self, io_util: IoUtil = None):
6359
self.__story_context = ''
6460
self.__story_type = ''
6561
self.__world_info = ''
66-
self.action_list = llm_config.params['ACTION_LIST']
62+
#self.action_list = llm_config.params['ACTION_LIST']
6763
json_grammar_key = backend_config['JSON_GRAMMAR_KEY']
6864

6965
#self._look_hashes = dict() # type: dict[int, str] # location hashes for look command. currently never cleared.
@@ -108,7 +104,7 @@ def evoke(self, message: str, short_len: bool=False, rolling_prompt: str = '', a
108104
history=rolling_prompt if not (skip_history or alt_prompt) else '',
109105
extra_context=extra_context)
110106
prompt = self.pre_prompt
111-
prompt += (alt_prompt or self.evoke_prompt).format(
107+
prompt += (alt_prompt or llm_config.params['BASE_PROMPT']).format(
112108
context = '{context}',
113109
max_words=self.word_limit if not short_len else self.short_word_limit,
114110
input_text=str(trimmed_message))
@@ -290,7 +286,7 @@ def free_form_action(self, location: Location, character_name: str, character_c
290286
character_card=character_card,
291287
event_history=event_history,
292288
location=location,
293-
actions=self.action_list)
289+
actions=llm_config.params['ACTION_LIST'])
294290
return self._character.free_form_action(action_context)
295291

296292
def request_follow(self, actor: MudObject, character_name: str, character_card: str, event_history: str, location: Location, asker_reason: str):
@@ -308,7 +304,7 @@ def describe_day_cycle_transition(self, player: PlayerConnection, from_time: str
308304
prompt = self.pre_prompt
309305
location = player.player.location
310306
context = self._get_world_context()
311-
prompt += self.day_cycle_event_prompt.format(
307+
prompt += llm_config.params['DAY_CYCLE_EVENT_PROMPT'].format(
312308
context= '{context}',
313309
location_name=location.name,
314310
from_time=from_time,
@@ -325,7 +321,7 @@ def describe_day_cycle_transition(self, player: PlayerConnection, from_time: str
325321
def generate_narrative_event(self, location: Location) -> str:
326322
prompt = self.pre_prompt
327323
context = self._get_world_context()
328-
prompt += self.narrative_event_prompt.format(
324+
prompt += llm_config.params['NARRATIVE_EVENT_PROMPT'].format(
329325
context= '{context}',
330326
location_name=location.name)
331327
request_body = deepcopy(self.default_body)

tale/llm/quest_building.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,10 @@ def __init__(self, backend: str, io_util: IoUtil, default_body: dict, json_gramm
1717
self.io_util = io_util
1818
self.json_grammar = llm_config.params['JSON_GRAMMAR']
1919
self.json_grammar_key = json_grammar_key # Type: str
20-
self.quest_prompt = llm_config.params['QUEST_PROMPT']
21-
self.note_quest_prompt = llm_config.params['NOTE_QUEST_PROMPT']
22-
self.note_lore_prompt = llm_config.params['NOTE_LORE_PROMPT']
2320

2421
def generate_quest(self, base_quest: dict, character_name: str, location: Location, context: WorldGenerationContext, character_card: str = '', story_type: str = '', world_info: str = '', zone_info: str = '') -> Quest:
2522
prompt = self.pre_prompt
26-
prompt += self.quest_prompt.format(
23+
prompt += llm_config.params['QUEST_PROMPT'].format(
2724
context='{context}',
2825
base_quest=base_quest,
2926
location_name=location.name,
@@ -36,7 +33,7 @@ def generate_quest(self, base_quest: dict, character_name: str, location: Locati
3633

3734
def generate_note_quest(self, context: WorldGenerationContext, zone_info: str) -> Quest:
3835
prompt = self.pre_prompt
39-
prompt += self.note_quest_prompt.format(
36+
prompt += llm_config.params['NOTE_QUEST_PROMPT'].format(
4037
context='{context}',
4138
zone_info=zone_info)
4239
request_body = deepcopy(self.default_body)

0 commit comments

Comments
 (0)