Skip to content

Commit 9d73ede

Browse files
authored
Merge pull request #61 from neph1/update-v0.23.0
Update v0.23.0
2 parents 750617a + 7440b25 commit 9d73ede

26 files changed

+307
-74
lines changed

tale/base.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,7 @@ def __init__(self, name: str, gender: str, *, race: str="human",
10341034
self.is_pet = False # set this to True if creature is/becomes someone's pet
10351035
self.__wielding = None # type: Optional[Weapon]
10361036
self.__wearing = dict() # type: Dict[str, wearable.Wearable]
1037+
self.should_produce_remains = False
10371038

10381039
super().__init__(name, title=title, descr=descr, short_descr=short_descr)
10391040

@@ -1435,9 +1436,9 @@ def start_attack(self, victim: 'Living') -> combat.Combat:
14351436
self.stats.hp -= damage_to_attacker
14361437
victim.stats.hp -= damage_to_defender
14371438
if self.stats.hp < 1:
1438-
combat.produce_remains(util.Context, self)
1439+
self.do_on_death(util.Context)
14391440
if victim.stats.hp < 1:
1440-
combat.produce_remains(util.Context, victim)
1441+
victim.do_on_death(util.Context)
14411442
return c
14421443

14431444
def allow_give_money(self, amount: float, actor: Optional['Living']) -> None:
@@ -1563,6 +1564,16 @@ def get_wearable(self, location: wearable.WearLocation) -> Optional[Wearable]:
15631564
def get_worn_items(self) -> Iterable[Wearable]:
15641565
"""Return all items that are currently worn."""
15651566
return self.__wearing.values()
1567+
1568+
def do_on_death(self, ctx: util.Context) -> 'Container':
1569+
"""Called when the living dies."""
1570+
if not self.should_produce_remains:
1571+
return None
1572+
remains = Container(f"remains of {self.title}")
1573+
remains.init_inventory(self.inventory)
1574+
self.location.insert(remains, None)
1575+
self.destroy(ctx)
1576+
return remains
15661577

15671578

15681579
class Container(Item):

tale/cmds/wizard.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from typing import Generator, Optional
1818

1919
from tale import parse_utils
20+
from tale.llm.LivingNpc import LivingNpc
2021

2122
from . import wizcmd, disabled_in_gamemode
2223
from .. import base, lang, util, pubsub, races, __version__
@@ -852,3 +853,16 @@ def do_set_description(player: Player, parsed: base.ParseResult, ctx: util.Conte
852853
except ValueError as x:
853854
raise ActionRefused(str(x))
854855

856+
@wizcmd("set_goal")
857+
def do_set_goal(player: Player, parsed: base.ParseResult, ctx: util.Context) -> None:
858+
"""Set a goal for a LivingNpc."""
859+
if len(parsed.args) != 2:
860+
raise ParseError("You need to specify the character and the goal")
861+
try:
862+
character = player.location.search_living(parsed.args[0])
863+
if not character or not isinstance(character, LivingNpc):
864+
raise ParseError("No LivingNpc found")
865+
character.goal = parsed.args[1]
866+
player.tell("%s goal set to %s" % (character, parsed.args[1]))
867+
except ValueError as x:
868+
raise ActionRefused(str(x))

tale/combat.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,3 @@ def _round(self, actor1: 'base.Living', actor2: 'base.Living') -> ([str], int):
9191
else:
9292
texts.append(f'{actor1.title} barely misses')
9393
return texts, 0
94-
95-
def produce_remains(context: Context, actor: 'base.Living'):
96-
""" Creates a container with the inventory of the Living
97-
and places it in the living's location.
98-
"""
99-
remains = base.Container(f"remains of {actor.title}")
100-
remains.init_inventory(actor.inventory)
101-
actor.location.insert(remains, None)
102-
actor.destroy(context)
103-
return remains

tale/driver.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -952,4 +952,7 @@ def build_location(self, targetLocation: base.Location, zone: Zone, player: play
952952
else:
953953
text = self.llm_util.generate_note_lore(zone_info=zone.get_info())
954954
item.text = text
955-
return True
955+
return True
956+
957+
def do_on_player_death(self, player: player.Player) -> None:
958+
pass

tale/driver_if.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,10 @@ def _load_saved_game(self, existing_player: Player) -> Optional[Player]:
442442
if self.wizard_override:
443443
saved_player.privileges.add("wizard")
444444
return saved_player
445+
446+
def do_on_player_death(self, player: Player) -> None:
447+
self.story.story_failure()
448+
self._stop_driver()
445449

446450

447451
class SavegameExistingObjectsFinder:
@@ -488,3 +492,4 @@ def resolve_exit(self, vnum: int, name: str, classname: str, baseclassname: str)
488492
if exit.name != name or savegames.qual_baseclassname(exit) != baseclassname:
489493
raise errors.TaleError("exit/door inconsistency for vnum " + str(vnum))
490494
return exit
495+

tale/image_gen/automatic1111.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ def __init__(self, address: str = '127.0.0.1', port: int = 7860) -> None:
1717
self.config = yaml.safe_load(stream)
1818
except yaml.YAMLError as exc:
1919
print(exc)
20-
print(self.config)
2120

2221

2322
def generate_image(self, prompt: str, save_path: str, image_name: str) -> bool:

tale/llm/LivingNpc.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class LivingNpc(Living):
1616
"""An NPC with extra fields to define personality and help LLM generate dialogue"""
1717

1818
def __init__(self, name: str, gender: str, *,
19-
title: str="", descr: str="", short_descr: str="", age: int, personality: str="", occupation: str="", race: str=""):
19+
title: str="", descr: str="", short_descr: str="", age: int = -1, personality: str="", occupation: str="", race: str=""):
2020
super(LivingNpc, self).__init__(name=name, gender=gender, title=title, descr=descr, short_descr=short_descr, race=race)
2121
self.age = age
2222
self.personality = personality
@@ -211,6 +211,8 @@ def autonomous_action(self) -> str:
211211
return None
212212

213213
defered_actions = []
214+
if action.get('goal', ''):
215+
self.goal = action['goal']
214216
if action.get('text', ''):
215217
text = action['text']
216218
tell_hash = llm_cache.cache_tell('{actor.title} says: "{response}"'.format(actor=self, response=unpad_text(text)))
@@ -284,6 +286,7 @@ def character_card(self) -> str:
284286
occupation=self.occupation,
285287
race=self.stats.race,
286288
quest=self.quest,
289+
goal=self.goal,
287290
wearing=','.join([f'"{str(i.name)}"' for i in self.get_worn_items()]),
288291
items=','.join(items))
289292

tale/llm/character.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,17 +34,15 @@ def __init__(self, backend: str, io_util: IoUtil, default_body: dict):
3434

3535
def generate_dialogue(self,
3636
context: DialogueContext,
37-
conversation: str,
3837
sentiment = '',
3938
event_history = '',
4039
short_len : bool=False):
4140
prompt = self.pre_prompt
4241

4342
#formatted_conversation = llm_config.params['USER_START']
44-
formatted_conversation = conversation.replace('<break>', '\n')#llm_config.params['USER_END'] + '\n' + llm_config.params['USER_START'])
4543
prompt += self.dialogue_prompt.format(
4644
context = '{context}',
47-
previous_conversation=formatted_conversation,
45+
previous_conversation=context.conversation,
4846
character2=context.speaker_name,
4947
character1=context.target_name,
5048
dialogue_template=self.dialogue_template,

tale/llm/contexts/DialogueContext.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,15 @@ def __init__(self,
1111
speaker_card: str,
1212
speaker_name: str,
1313
target_name: str,
14-
target_description: str):
14+
target_description: str,
15+
conversation: str = '',):
1516
super().__init__(story_context)
1617
self.location_description = location_description
1718
self.speaker_card = speaker_card
1819
self.speaker_name = speaker_name
1920
self.target_name = target_name
2021
self.target_description = target_description
22+
self.conversation = conversation.replace('<break>', '\n')#llm_config.params['USER_END'] + '\n' + llm_config.params['USER_START'])
2123

2224

2325
def to_prompt_string(self) -> str:

tale/llm/io_adapters.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import requests
99

1010
from tale.errors import LlmResponseException
11+
from tale.player import PlayerConnection
1112

1213

1314
class AbstractIoAdapter(ABC):
@@ -40,7 +41,7 @@ def __init__(self, url: str, stream_endpoint: str, data_endpoint: str, user_star
4041
super().__init__(url, stream_endpoint, user_start_prompt, user_end_prompt)
4142
self.data_endpoint = data_endpoint
4243

43-
def stream_request(self, request_body: dict, io = None, wait: bool = False) -> str:
44+
def stream_request(self, request_body: dict, io: PlayerConnection = None, wait: bool = False) -> str:
4445
result = asyncio.run(self._do_stream_request(self.url + self.stream_endpoint, request_body))
4546

4647
try:
@@ -59,7 +60,7 @@ async def _do_stream_request(self, url: str, request_body: dict,) -> bool:
5960
else:
6061
print("Error occurred:", response.status)
6162

62-
def _do_process_result(self, url, io = None, wait: bool = False) -> str:
63+
def _do_process_result(self, url, io: PlayerConnection, wait: bool = False) -> str:
6364
""" Process the result from the stream endpoint """
6465
tries = 0
6566
old_text = ''
@@ -94,10 +95,10 @@ def set_prompt(self, request_body: dict, prompt: str, context: str = '') -> dict
9495

9596
class LlamaCppAdapter(AbstractIoAdapter):
9697

97-
def stream_request(self, request_body: dict, io = None, wait: bool = False) -> str:
98+
def stream_request(self, request_body: dict, io: PlayerConnection = None, wait: bool = False) -> str:
9899
return asyncio.run(self._do_stream_request(self.url + self.stream_endpoint, request_body, io = io))
99100

100-
async def _do_stream_request(self, url: str, request_body: dict, io = None) -> str:
101+
async def _do_stream_request(self, url: str, request_body: dict, io: PlayerConnection) -> str:
101102
""" Send request to stream endpoint async to not block the main thread"""
102103
request_body['stream'] = True
103104
text = ''
@@ -126,7 +127,6 @@ async def _do_stream_request(self, url: str, request_body: dict, io = None) -> s
126127
text += content
127128
while len(lines) == 0:
128129
await asyncio.sleep(0.15)
129-
130130
return text
131131

132132
def parse_result(self, result: str) -> str:
@@ -142,7 +142,7 @@ def set_prompt(self, request_body: dict, prompt: str, context: str = '') -> dict
142142
if self.user_end_prompt:
143143
prompt = prompt + self.user_end_prompt
144144
if context:
145-
prompt = prompt.replace('<context>{context}</context>', '')
146-
request_body['messages'][0]['content'] = f'<context>{context}</context>'
145+
prompt = prompt.replace('<context>{context}</context>', f'<context>{context}</context>')
146+
#request_body['messages'][0]['content'] = f'<context>{context}</context>'
147147
request_body['messages'][1]['content'] = prompt
148148
return request_body

0 commit comments

Comments
 (0)