Skip to content

Commit 72f723b

Browse files
authored
Merge pull request #77 from neph1/update-v0.27.0
Update v0.27.0
2 parents f26f006 + c0d95bb commit 72f723b

26 files changed

+399
-100
lines changed

llm_config.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@ BACKEND: "kobold_cpp" # valid options: "openai", "llama_cpp", "kobold_cpp". if u
44
MEMORY_SIZE: 512
55
UNLIMITED_REACTS: False
66
DIALOGUE_TEMPLATE: '{{"response":"may be both dialogue and action.", "sentiment":"sentiment based on response", "give":"if any physical item of {character2}s is given as part of the dialogue. Or nothing."}}'
7+
ACTION_LIST: ['move, say, attack, wear, remove, wield, take, eat, drink, emote']
78
ACTION_TEMPLATE: '{{"goal": reason for action, "thoughts":thoughts about performing action, 25 words "action":chosen action, "target":character, item or exit or description, "text": if anything is said during the action}}'
89
ITEM_TEMPLATE: '{{"name":"", "type":"", "short_descr":"", "level":int, "value":int}}'
910
CREATURE_TEMPLATE: '{{"name":"", "body":"", "mass":int(kg), "hp":int, "type":"Npc or Mob", "level":int, "unarmed_attack":One of [FISTS, CLAWS, BITE, TAIL, HOOVES, HORN, TUSKS, BEAK, TALON], "short_descr":""}}'
1011
EXIT_TEMPLATE: '{{"direction":"", "name":"name of new location", "short_descr":"exit description"}}'
11-
NPC_TEMPLATE: '{{"name":"", "sentiment":"", "race":"", "gender":"m, f, or n", "level":(int), "description":"25 words"}}'
12+
NPC_TEMPLATE: '{{"name":"", "sentiment":"", "race":"", "gender":"m, f, or n", "level":(int), "description":"25 words", "has_quest":(bool)}}'
1213
LOCATION_TEMPLATE: '{{"name": "", "exits":[], "items":[], "npcs":[]}}'
1314
ZONE_TEMPLATE: '{{"name":"", "description": "75 words", "races":[], "items":[], "mood":"5 to -5, where 5 is extremely friendly and -5 is extremely hostile.", "level":(int)}}'
1415
ITEM_TYPES: ["Weapon", "Wearable", "Health", "Money", "Trash", "Food", "Drink", "Key"]

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ smartypants>=1.8.6
66
serpent>=1.23
77
aiohttp==3.8.5
88
pillow
9-
packaging==20.3
9+
packaging>=20.3
1010
#pillow>=8.3.2
1111

1212

stories/anything/story.py

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,40 +5,23 @@
55

66
import tale
77
from tale import lang
8+
from tale import parse_utils
89
from tale.driver import Driver
9-
from tale.llm.llm_ext import DynamicStory
10+
from tale.json_story import JsonStory
1011
from tale.main import run_from_cmdline
1112
from tale.player import Player, PlayerConnection
1213
from tale.charbuilder import PlayerNaming
1314
from tale.story import *
1415
from tale.weapon_type import WeaponType
15-
from tale.zone import Zone
1616

17-
class Story(DynamicStory):
17+
class Story(JsonStory):
1818

19-
config = StoryConfig()
20-
config.name = "The Land of Anything"
21-
config.author = "Rickard Edén, github.com/neph1"
22-
config.author_address = "[email protected]"
23-
config.version = tale.__version__
24-
config.supported_modes = {GameMode.IF}
25-
config.player_money = 0
26-
config.playable_races = {"human"}
27-
config.money_type = MoneyType.FANTASY
28-
config.server_tick_method = TickMethod.TIMER
29-
config.server_tick_time = 0.5
30-
config.gametime_to_realtime = 5
31-
config.display_gametime = True
32-
config.startlocation_player = "start_zone.transit"
33-
config.startlocation_wizard = "start_zone.transit"
34-
config.zones = ["start_zone"]
35-
config.context = ""
36-
config.savegames_enabled = False
19+
20+
def __init__(self) -> None:
21+
super(Story, self).__init__('', parse_utils.load_story_config(parse_utils.load_json('story_config.json')))
3722

3823
def init(self, driver: Driver) -> None:
39-
"""Called by the game driver when it is done with its initial initialization."""
40-
self.driver = driver
41-
self._zones = dict() # type: dict(str, Zone)
24+
super(Story, self).init(driver)
4225

4326
def init_player(self, player: Player) -> None:
4427
"""

stories/anything/story_config.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "A Tale of Anything",
3+
"author": "You",
4+
"author_address": "",
5+
"version": "1.0",
6+
"supported_modes": [
7+
"IF"
8+
],
9+
"player_name": "",
10+
"player_gender": "",
11+
"player_race": "human",
12+
"player_money": 0,
13+
"money_type": "FANTASY",
14+
"server_tick_method": "TIMER",
15+
"server_tick_time": 0.5,
16+
"gametime_to_realtime": 5,
17+
"display_gametime": true,
18+
"startlocation_player": "start_zone.transit",
19+
"startlocation_wizard": "start_zone.transit",
20+
"zones": [
21+
"start_zone"
22+
],
23+
"server_mode": "IF",
24+
"save_games_enabled": false
25+
}

stories/anything/world.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"story": {
3+
"name": "The Land of Anything"
4+
},
5+
"zones": {
6+
},
7+
"world": {
8+
},
9+
"catalogue": {
10+
}
11+
}

tale/driver.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,7 @@ def build_location(self, targetLocation: base.Location, zone: Zone, player: play
930930
# fail silently
931931
pass
932932
for npc in npcs:
933+
dynamic_story.world.add_npc(npc)
933934
if isinstance(npc, StationaryNpc) and random.random() < 0.2:
934935
new_quest = dynamic_story.generate_quest(npc)
935936
new_quest.giver = npc

tale/item_spawner.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import random
2+
3+
from tale import mud_context
4+
from tale.base import Container, Location
5+
from tale.util import call_periodically
6+
from tale.zone import Zone
7+
8+
9+
class ItemSpawner():
10+
def __init__(self, items: list, item_probabilities: list, zone: Zone, spawn_rate: int, container: Container = None, max_items: int = 1):
11+
self.items = items
12+
self.item_probabilities = item_probabilities
13+
self.zone = zone
14+
self.container = container
15+
self.max_items = max_items
16+
self.spawn_rate = spawn_rate
17+
self.time = 0
18+
mud_context.driver.register_periodicals(self)
19+
20+
@call_periodically(15)
21+
def spawn(self):
22+
self.time += 15
23+
if self.time < self.spawn_rate:
24+
return
25+
self.time -= self.spawn_rate
26+
item = random.choices(self.items, weights=self.item_probabilities)[0]
27+
28+
if self.container:
29+
self.container.insert(item, None)
30+
else:
31+
location = random.choice(list(self.zone.locations.values())) # type: Location
32+
if len(location.items) < self.max_items:
33+
location.insert(item, None)
34+
location.tell(f'{item} appears.')
35+
36+
def to_json(self):
37+
data = {
38+
'items': [item.name for item in self.items],
39+
'item_probabilities': self.item_probabilities,
40+
'zone': self.zone.name,
41+
'spawn_rate': self.spawn_rate,
42+
'container': self.container.name if self.container else None,
43+
'max_items': self.max_items
44+
}
45+
return data

tale/json_story.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ def init(self, driver) -> None:
4141
self._world.items = parse_utils.load_items(world['world']['items'].values(), self.locations)
4242
if world['world'].get('spawners', None):
4343
self._world.mob_spawners = parse_utils.load_mob_spawners(world['world']['spawners'], self.locations, self._catalogue._creatures, self._catalogue._items)
44+
if world['world'].get('item_spawners', None):
45+
self._world.item_spawners = parse_utils.load_item_spawners(world['world']['item_spawners'], self._zones, self._catalogue._items)
4446

4547
llm_cache.load(parse_utils.load_json(self.path +'llm_cache.json'))
4648

tale/llm/contexts/ActionContext.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@
77

88
class ActionContext(BaseContext):
99

10-
def __init__(self, story_context: str, story_type: str, character_name: str, character_card: str, event_history: str, location: Location):
10+
def __init__(self, story_context: str, story_type: str, character_name: str, character_card: str, event_history: str, location: Location, actions: list):
1111
super().__init__(story_context)
1212
self.story_type = story_type
1313
self.character_name = character_name
1414
self.character_card = character_card
1515
self.event_history = event_history.replace('<break>', '\n')
1616
self.location = location
17+
self.actions = actions
1718

1819

1920
def to_prompt_string(self) -> str:
20-
actions = ', '.join(['move, say, attack, wear, remove, wield, take, eat, drink, emote'])
21+
actions = ', '.join(self.actions)
2122
characters = {}
2223
for living in self.location.livings:
2324
if living.visible and living.name != self.character_name.lower():

tale/llm/io_adapters.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ def set_prompt(self, request_body: dict, prompt: str, context: str = '') -> dict
3737

3838
class KoboldCppAdapter(AbstractIoAdapter):
3939

40+
41+
4042
def __init__(self, url: str, stream_endpoint: str, data_endpoint: str, user_start_prompt: str, user_end_prompt: str):
4143
super().__init__(url, stream_endpoint, user_start_prompt, user_end_prompt)
4244
self.data_endpoint = data_endpoint
45+
self.place_context_in_memory = False
4346

4447
def stream_request(self, request_body: dict, io: PlayerConnection = None, wait: bool = False) -> str:
4548
result = asyncio.run(self._do_stream_request(self.url + self.stream_endpoint, request_body))
@@ -88,9 +91,12 @@ def set_prompt(self, request_body: dict, prompt: str, context: str = '') -> dict
8891
prompt = prompt.replace('[USER_START]', self.user_start_prompt)
8992
if self.user_end_prompt:
9093
prompt = prompt + self.user_end_prompt
91-
prompt = prompt.replace('<context>{context}</context>', '')
94+
if self.place_context_in_memory:
95+
prompt = prompt.replace('<context>{context}</context>', '')
96+
request_body['memory'] = f'<context>{context}</context>'
97+
else:
98+
prompt = prompt.replace('<context>{context}</context>', f'<context>{context}</context>')
9299
request_body['prompt'] = prompt
93-
request_body['memory'] = f'<context>{context}</context>'
94100
return request_body
95101

96102
class LlamaCppAdapter(AbstractIoAdapter):

0 commit comments

Comments
 (0)