From 205d6923b3e894b81ac4671aa8b92139b2a98472 Mon Sep 17 00:00:00 2001 From: Sean Sube Date: Sat, 22 Jun 2024 17:00:46 -0500 Subject: [PATCH] sort systems into folders --- README.md | 63 ++++++++++++++----- taleweave/actions/{base.py => core.py} | 2 +- taleweave/actions/optional.py | 5 +- taleweave/actions/planning.py | 2 +- taleweave/main.py | 4 +- taleweave/systems/{ => core}/action.py | 0 taleweave/systems/{ => core}/planning.py | 0 taleweave/systems/{ => core}/snapshot.py | 0 .../systems/{digest.py => core/summary.py} | 2 +- taleweave/systems/environment/__init__.py | 24 +++++++ .../humidity/logic.yaml} | 0 .../environment/temperature/logic.yaml | 40 ++++++++++++ .../temperature/triggers.py} | 0 .../weather/logic.yaml} | 0 .../weather/system.py} | 4 +- taleweave/systems/{ => generic}/logic.py | 0 taleweave/systems/rpg/__init__.py | 44 ++++++++++--- .../combat/actions.py} | 0 .../actions.py} | 0 taleweave/systems/rpg/crafting/logic.yml | 0 taleweave/systems/rpg/health/logic.yml | 0 taleweave/systems/rpg/health/triggers.py | 0 .../{magic_actions.py => magic/actions.py} | 0 .../actions.py} | 0 .../quest.py => systems/rpg/quest/actions.py} | 7 ++- .../systems/{quest.py => rpg/quest/system.py} | 2 +- .../actions.py} | 18 ++++++ taleweave/systems/sim/__init__.py | 34 ++++++---- .../{hunger_actions.py => hunger/actions.py} | 0 .../{hunger_logic.yaml => hunger/logic.yaml} | 0 .../sim/{ => hygiene}/hygiene_actions.py | 0 .../sim/{ => hygiene}/hygiene_logic.yaml | 0 .../sim/{mood_logic.yaml => mood/logic.yaml} | 0 .../actions.py} | 0 .../logic.yaml} | 0 35 files changed, 204 insertions(+), 47 deletions(-) rename taleweave/actions/{base.py => core.py} (99%) rename taleweave/systems/{ => core}/action.py (100%) rename taleweave/systems/{ => core}/planning.py (100%) rename taleweave/systems/{ => core}/snapshot.py (100%) rename taleweave/systems/{digest.py => core/summary.py} (99%) create mode 100644 taleweave/systems/environment/__init__.py rename taleweave/systems/{sim/environment_logic.yaml => environment/humidity/logic.yaml} (100%) create mode 100644 taleweave/systems/environment/temperature/logic.yaml rename taleweave/systems/{sim/environment_triggers.py => environment/temperature/triggers.py} (100%) rename taleweave/systems/{weather/weather_logic.yaml => environment/weather/logic.yaml} (100%) rename taleweave/systems/{weather/__init__.py => environment/weather/system.py} (96%) rename taleweave/systems/{ => generic}/logic.py (100%) rename taleweave/systems/{sim/combat_actions.py => rpg/combat/actions.py} (100%) rename taleweave/systems/rpg/{crafting_actions.py => crafting/actions.py} (100%) create mode 100644 taleweave/systems/rpg/crafting/logic.yml create mode 100644 taleweave/systems/rpg/health/logic.yml create mode 100644 taleweave/systems/rpg/health/triggers.py rename taleweave/systems/rpg/{magic_actions.py => magic/actions.py} (100%) rename taleweave/systems/rpg/{movement_actions.py => movement/actions.py} (100%) rename taleweave/{actions/quest.py => systems/rpg/quest/actions.py} (98%) rename taleweave/systems/{quest.py => rpg/quest/system.py} (99%) rename taleweave/systems/rpg/{language_actions.py => writing/actions.py} (54%) rename taleweave/systems/sim/{hunger_actions.py => hunger/actions.py} (100%) rename taleweave/systems/sim/{hunger_logic.yaml => hunger/logic.yaml} (100%) rename taleweave/systems/sim/{ => hygiene}/hygiene_actions.py (100%) rename taleweave/systems/sim/{ => hygiene}/hygiene_logic.yaml (100%) rename taleweave/systems/sim/{mood_logic.yaml => mood/logic.yaml} (100%) rename taleweave/systems/sim/{sleeping_actions.py => sleeping/actions.py} (100%) rename taleweave/systems/sim/{sleeping_logic.yaml => sleeping/logic.yaml} (100%) diff --git a/README.md b/README.md index e48af5e..c9f6064 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,21 @@ TaleWeave AI is an open-source game engine designed for creating rich, immersive ![TaleWeave AI logo with glowing sunrise over angular castle](https://docs-cdn.taleweave.ai/taleweave-github-1280.png) +## Contents + +- [TaleWeave AI](#taleweave-ai) + - [Contents](#contents) + - [Features](#features) + - [Game Actions](#game-actions) + - [Game Systems](#game-systems) + - [Requirements](#requirements) + - [Recommended](#recommended) + - [Setup](#setup) + - [Documentation](#documentation) + - [Contributing](#contributing) + - [Support and Community](#support-and-community) + - [License](#license) + ## Features TaleWeave AI is meant for gamers, developers, and researchers. It is a: @@ -26,7 +41,7 @@ TaleWeave AI does a few things out of the box: - Generate a world from a brief text prompt - Simulate the actions of characters in that world - Allow humans to interact with each other and with NPCs -- Track detailed status for each entity: mood, hunger, thirst, hygiene, time of day, weather, etc +- Track detailed status for each entity: mood, hunger, thirst, hygiene, weather, and more - Summarize the environment into LLM prompts - Foster emergent behavior through action digests, shared environment, and note taking @@ -35,27 +50,45 @@ TaleWeave AI can: - Be modified in almost every way - everything is a plugin, including the planning and action stages that drive the simulation - Be run locally - does not require any cloud services, but does play nicely with them - Connect to your data - game systems can fetch data for RAG, making responses richer and more consistent -- Export training data - for analysis and fine tuning of character models +- Export training data - for analysis, visualization, and fine tuning of character models - Plug in to your workflow - run the simulation step by step in Jupyter notebooks using the TaleWeave AI engine as a Python library - Connect to your server and vice versa - the Discord bot is a plugin and can be replaced with your favorite chat platform -## Contents +### Game Actions -- [TaleWeave AI](#taleweave-ai) - - [Features](#features) - - [Contents](#contents) - - [Requirements](#requirements) - - [Recommended](#recommended) - - [Setup](#setup) - - [Documentation](#documentation) - - [Contributing](#contributing) - - [Support and Community](#support-and-community) - - [License](#license) +TaleWeave AI has in-game actions for: + +| Core | Life Sim | RPG | +| ------------ | --------------- | --------- | +| Planning | Hunger & Thirst | Combat | +| Conversation | Hygiene | Crafting | +| Movement | Sleeping | Magic | +| Exploration | | Movement* | +| | | Writing | + +1. The core exploration actions provide ways for characters to expand the world by finding new rooms and items. +2. The RPG movement actions provide additional situational movement like crawling, climbing, and jumping. + +### Game Systems + +TaleWeave AI has game systems for: + +| Core | Life Sim | RPG | Environment | +| -------- | --------------- | ------ | ----------- | +| Acting | Hunger & Thirst | Health | Humidity | +| Planning | Hygiene | Quests | Temperature | +| Summary | Mood | | Time of day | +| | Sleeping | | Weather | + +1. The core summary system provides character with a summary of actions taken by other characters in between turns. + +All of the game systems are optional, including the core systems, so you can configure a world where characters only +plan and never act, or vice versa. ## Requirements -- Python 3.10 -- Ollama, vLLM, or another OpenAI-compatible LLM API (including OpenAI) +- Python 3.10+ +- Ollama or an OpenAI-compatible LLM API like llama.cpp, vLLM, or OpenAI While TaleWeave AI can be run entirely on CPU, one or more GPUs are highly recommended. diff --git a/taleweave/actions/base.py b/taleweave/actions/core.py similarity index 99% rename from taleweave/actions/base.py rename to taleweave/actions/core.py index bb98231..bcbf041 100644 --- a/taleweave/actions/base.py +++ b/taleweave/actions/core.py @@ -11,7 +11,7 @@ from taleweave.context import ( world_context, ) from taleweave.errors import ActionError -from taleweave.systems.action import ACTION_SYSTEM_NAME +from taleweave.systems.core.action import ACTION_SYSTEM_NAME from taleweave.utils.conversation import loop_conversation from taleweave.utils.search import ( find_character_in_room, diff --git a/taleweave/actions/optional.py b/taleweave/actions/optional.py index e1c39f4..958dd0b 100644 --- a/taleweave/actions/optional.py +++ b/taleweave/actions/optional.py @@ -1,5 +1,4 @@ from logging import getLogger -from typing import Callable, List from packit.agent import Agent, agent_easy_connect @@ -22,7 +21,7 @@ from taleweave.generate import ( generate_room, link_rooms, ) -from taleweave.systems.action import ACTION_SYSTEM_NAME +from taleweave.systems.core.action import ACTION_SYSTEM_NAME from taleweave.utils.effect import apply_effects, is_effect_ready from taleweave.utils.search import find_character_in_room from taleweave.utils.string import normalize_name @@ -254,7 +253,7 @@ def action_use(item: str, target: str) -> str: return outcome -def init_optional() -> List[Callable]: +def init(): """ Initialize the custom actions. """ diff --git a/taleweave/actions/planning.py b/taleweave/actions/planning.py index f44cbce..7896116 100644 --- a/taleweave/actions/planning.py +++ b/taleweave/actions/planning.py @@ -8,7 +8,7 @@ from taleweave.context import ( ) from taleweave.errors import ActionError from taleweave.models.planning import CalendarEvent -from taleweave.systems.planning import PLANNING_SYSTEM_NAME +from taleweave.systems.core.planning import PLANNING_SYSTEM_NAME from taleweave.utils.planning import get_recent_notes from taleweave.utils.template import format_prompt diff --git a/taleweave/main.py b/taleweave/main.py index 37dc5ad..bfeb6aa 100644 --- a/taleweave/main.py +++ b/taleweave/main.py @@ -60,8 +60,8 @@ if True: from taleweave.models.prompt import PromptLibrary from taleweave.plugins import load_plugin from taleweave.state import save_world_state - from taleweave.systems.action import init_action - from taleweave.systems.planning import init_planning + from taleweave.systems.core.action import init_action + from taleweave.systems.core.planning import init_planning def int_or_inf(value: str) -> float | int: diff --git a/taleweave/systems/action.py b/taleweave/systems/core/action.py similarity index 100% rename from taleweave/systems/action.py rename to taleweave/systems/core/action.py diff --git a/taleweave/systems/planning.py b/taleweave/systems/core/planning.py similarity index 100% rename from taleweave/systems/planning.py rename to taleweave/systems/core/planning.py diff --git a/taleweave/systems/snapshot.py b/taleweave/systems/core/snapshot.py similarity index 100% rename from taleweave/systems/snapshot.py rename to taleweave/systems/core/snapshot.py diff --git a/taleweave/systems/digest.py b/taleweave/systems/core/summary.py similarity index 99% rename from taleweave/systems/digest.py rename to taleweave/systems/core/summary.py index e3cdaf5..ac862db 100644 --- a/taleweave/systems/digest.py +++ b/taleweave/systems/core/summary.py @@ -159,7 +159,7 @@ def init(): subscribe(GameEvent, digest_listener) return [ GameSystem( - "digest", + "summary", format=format_digest, generate=generate_digest, initialize=initialize_digest, diff --git a/taleweave/systems/environment/__init__.py b/taleweave/systems/environment/__init__.py new file mode 100644 index 0000000..c20b827 --- /dev/null +++ b/taleweave/systems/environment/__init__.py @@ -0,0 +1,24 @@ +from os import path + +from taleweave.systems.generic.logic import load_logic + + +def logic_path(system: str) -> str: + return path.join(".", "taleweave", "systems", "environment", system, "logic.yaml") + + +SYSTEM_NAMES = [ + "humidity", + "temperature", + "weather", +] + + +def init_logic(): + systems = [] + for system_name in SYSTEM_NAMES: + logic_file = logic_path(system_name) + if path.exists(logic_file): + systems.append(load_logic(logic_file)) + + return systems diff --git a/taleweave/systems/sim/environment_logic.yaml b/taleweave/systems/environment/humidity/logic.yaml similarity index 100% rename from taleweave/systems/sim/environment_logic.yaml rename to taleweave/systems/environment/humidity/logic.yaml diff --git a/taleweave/systems/environment/temperature/logic.yaml b/taleweave/systems/environment/temperature/logic.yaml new file mode 100644 index 0000000..d9cd032 --- /dev/null +++ b/taleweave/systems/environment/temperature/logic.yaml @@ -0,0 +1,40 @@ +rules: + # wet/dry logic + - group: environment-moisture + match: + type: character + wet: true + chance: 0.1 + set: + wet: false + + - group: environment-moisture + match: + type: character + wet: true + temperature: hot + chance: 0.2 + set: + wet: false + + - group: environment-temperature + match: + type: room + temperature: hot + chance: 0.2 + trigger: [taleweave.systems.sim.environment_triggers:hot_room] + + - group: environment-temperature + match: + type: room + temperature: cold + chance: 0.2 + trigger: [taleweave.systems.sim.environment_triggers:cold_room] + +labels: + - match: + type: character + wet: true + backstory: You are soaking wet. + description: They are soaking wet and dripping water. + # false intentionally omitted \ No newline at end of file diff --git a/taleweave/systems/sim/environment_triggers.py b/taleweave/systems/environment/temperature/triggers.py similarity index 100% rename from taleweave/systems/sim/environment_triggers.py rename to taleweave/systems/environment/temperature/triggers.py diff --git a/taleweave/systems/weather/weather_logic.yaml b/taleweave/systems/environment/weather/logic.yaml similarity index 100% rename from taleweave/systems/weather/weather_logic.yaml rename to taleweave/systems/environment/weather/logic.yaml diff --git a/taleweave/systems/weather/__init__.py b/taleweave/systems/environment/weather/system.py similarity index 96% rename from taleweave/systems/weather/__init__.py rename to taleweave/systems/environment/weather/system.py index f3fac4b..bd389c3 100644 --- a/taleweave/systems/weather/__init__.py +++ b/taleweave/systems/environment/weather/system.py @@ -10,14 +10,14 @@ from taleweave.context import get_dungeon_master from taleweave.game_system import GameSystem from taleweave.models.base import dataclass from taleweave.models.entity import Room, World, WorldEntity -from taleweave.systems.logic import load_logic +from taleweave.systems.generic.logic import load_logic from taleweave.utils.string import or_list logger = getLogger(__name__) LOGIC_FILES = [ - "./taleweave/systems/weather/weather_logic.yaml", + "./taleweave/systems/environment/weather/logic.yaml", ] diff --git a/taleweave/systems/logic.py b/taleweave/systems/generic/logic.py similarity index 100% rename from taleweave/systems/logic.py rename to taleweave/systems/generic/logic.py diff --git a/taleweave/systems/rpg/__init__.py b/taleweave/systems/rpg/__init__.py index 8d89e4a..2b5e1e2 100644 --- a/taleweave/systems/rpg/__init__.py +++ b/taleweave/systems/rpg/__init__.py @@ -1,21 +1,51 @@ -from .crafting_actions import action_craft -from .language_actions import action_read -from .magic_actions import action_cast -from .movement_actions import action_climb +from os import path + +from taleweave.systems.generic.logic import load_logic + +from .crafting.actions import action_craft +from .magic.actions import action_cast +from .movement.actions import action_climb +from .quest.actions import accept_quest, submit_quest +from .writing.actions import action_read, action_write + + +def logic_path(system: str) -> str: + return path.join(".", "taleweave", "systems", "rpg", system, "logic.yaml") + + +SYSTEM_NAMES = [ + "combat", + "crafting", + "health", + "magic", + "movement", + "quest", + "writing", +] def init_actions(): return [ # crafting action_craft, - # language - action_read, # magic action_cast, # movement action_climb, + # quest + accept_quest, + submit_quest, + # writing + action_read, + action_write, ] def init_logic(): - return [] + systems = [] + for system_name in SYSTEM_NAMES: + logic_file = logic_path(system_name) + if path.exists(logic_file): + systems.append(load_logic(logic_file, name_prefix=system_name)) + + return systems diff --git a/taleweave/systems/sim/combat_actions.py b/taleweave/systems/rpg/combat/actions.py similarity index 100% rename from taleweave/systems/sim/combat_actions.py rename to taleweave/systems/rpg/combat/actions.py diff --git a/taleweave/systems/rpg/crafting_actions.py b/taleweave/systems/rpg/crafting/actions.py similarity index 100% rename from taleweave/systems/rpg/crafting_actions.py rename to taleweave/systems/rpg/crafting/actions.py diff --git a/taleweave/systems/rpg/crafting/logic.yml b/taleweave/systems/rpg/crafting/logic.yml new file mode 100644 index 0000000..e69de29 diff --git a/taleweave/systems/rpg/health/logic.yml b/taleweave/systems/rpg/health/logic.yml new file mode 100644 index 0000000..e69de29 diff --git a/taleweave/systems/rpg/health/triggers.py b/taleweave/systems/rpg/health/triggers.py new file mode 100644 index 0000000..e69de29 diff --git a/taleweave/systems/rpg/magic_actions.py b/taleweave/systems/rpg/magic/actions.py similarity index 100% rename from taleweave/systems/rpg/magic_actions.py rename to taleweave/systems/rpg/magic/actions.py diff --git a/taleweave/systems/rpg/movement_actions.py b/taleweave/systems/rpg/movement/actions.py similarity index 100% rename from taleweave/systems/rpg/movement_actions.py rename to taleweave/systems/rpg/movement/actions.py diff --git a/taleweave/actions/quest.py b/taleweave/systems/rpg/quest/actions.py similarity index 98% rename from taleweave/actions/quest.py rename to taleweave/systems/rpg/quest/actions.py index d85d6a9..e5d3661 100644 --- a/taleweave/actions/quest.py +++ b/taleweave/systems/rpg/quest/actions.py @@ -1,14 +1,15 @@ from taleweave.context import action_context, get_system_data from taleweave.errors import ActionError -from taleweave.systems.quest import ( +from taleweave.utils.search import find_character_in_room +from taleweave.utils.template import format_prompt + +from .system import ( QUEST_SYSTEM, complete_quest, get_active_quest, get_quests_for_character, set_active_quest, ) -from taleweave.utils.search import find_character_in_room -from taleweave.utils.template import format_prompt def accept_quest(character: str, quest: str) -> str: diff --git a/taleweave/systems/quest.py b/taleweave/systems/rpg/quest/system.py similarity index 99% rename from taleweave/systems/quest.py rename to taleweave/systems/rpg/quest/system.py index adbb159..0fcb8d8 100644 --- a/taleweave/systems/quest.py +++ b/taleweave/systems/rpg/quest/system.py @@ -15,7 +15,7 @@ from taleweave.models.entity import ( World, WorldEntity, ) -from taleweave.systems.logic import match_logic +from taleweave.systems.generic.logic import match_logic from taleweave.utils.search import ( find_entity_reference, find_item_in_container, diff --git a/taleweave/systems/rpg/language_actions.py b/taleweave/systems/rpg/writing/actions.py similarity index 54% rename from taleweave/systems/rpg/language_actions.py rename to taleweave/systems/rpg/writing/actions.py index 520276d..819a541 100644 --- a/taleweave/systems/rpg/language_actions.py +++ b/taleweave/systems/rpg/writing/actions.py @@ -19,3 +19,21 @@ def action_read(item: str) -> str: return str(action_item.attributes["text"]) return f"The {item} has nothing to read." + + +def action_write(item: str, text: str) -> str: + """ + Write on an item like a book or a sign. + + Args: + item: The name of the item to write on. + text: The text to write. + """ + with action_context() as (_, action_character): + action_item = find_item_in_character(action_character, item) + if not action_item: + return f"You do not have a {item} to write on." + + action_item.attributes["text"] = text + broadcast(f"{action_character.name} writes on {item}") + return f"You write on the {item}." diff --git a/taleweave/systems/sim/__init__.py b/taleweave/systems/sim/__init__.py index e29b874..85a6469 100644 --- a/taleweave/systems/sim/__init__.py +++ b/taleweave/systems/sim/__init__.py @@ -1,15 +1,21 @@ -from taleweave.systems.logic import load_logic +from os import path -from .hunger_actions import action_cook, action_eat -from .hygiene_actions import action_wash -from .sleeping_actions import action_sleep +from taleweave.systems.generic.logic import load_logic -LOGIC_FILES = [ - "./taleweave/systems/sim/environment_logic.yaml", - "./taleweave/systems/sim/hunger_logic.yaml", - "./taleweave/systems/sim/hygiene_logic.yaml", - "./taleweave/systems/sim/mood_logic.yaml", - "./taleweave/systems/sim/sleeping_logic.yaml", +from .hunger.actions import action_cook, action_eat +from .hygiene.hygiene_actions import action_wash +from .sleeping.actions import action_sleep + + +def logic_path(system: str) -> str: + return path.join(".", "taleweave", "systems", "sim", system, "logic.yaml") + + +SYSTEM_NAMES = [ + "hunger", + "hygiene", + "mood", + "sleeping", ] @@ -26,4 +32,10 @@ def init_actions(): def init_logic(): - return [load_logic(filename) for filename in LOGIC_FILES] + systems = [] + for system_name in SYSTEM_NAMES: + logic_file = logic_path(system_name) + if path.exists(logic_file): + systems.append(load_logic(logic_file, name_prefix=system_name)) + + return systems diff --git a/taleweave/systems/sim/hunger_actions.py b/taleweave/systems/sim/hunger/actions.py similarity index 100% rename from taleweave/systems/sim/hunger_actions.py rename to taleweave/systems/sim/hunger/actions.py diff --git a/taleweave/systems/sim/hunger_logic.yaml b/taleweave/systems/sim/hunger/logic.yaml similarity index 100% rename from taleweave/systems/sim/hunger_logic.yaml rename to taleweave/systems/sim/hunger/logic.yaml diff --git a/taleweave/systems/sim/hygiene_actions.py b/taleweave/systems/sim/hygiene/hygiene_actions.py similarity index 100% rename from taleweave/systems/sim/hygiene_actions.py rename to taleweave/systems/sim/hygiene/hygiene_actions.py diff --git a/taleweave/systems/sim/hygiene_logic.yaml b/taleweave/systems/sim/hygiene/hygiene_logic.yaml similarity index 100% rename from taleweave/systems/sim/hygiene_logic.yaml rename to taleweave/systems/sim/hygiene/hygiene_logic.yaml diff --git a/taleweave/systems/sim/mood_logic.yaml b/taleweave/systems/sim/mood/logic.yaml similarity index 100% rename from taleweave/systems/sim/mood_logic.yaml rename to taleweave/systems/sim/mood/logic.yaml diff --git a/taleweave/systems/sim/sleeping_actions.py b/taleweave/systems/sim/sleeping/actions.py similarity index 100% rename from taleweave/systems/sim/sleeping_actions.py rename to taleweave/systems/sim/sleeping/actions.py diff --git a/taleweave/systems/sim/sleeping_logic.yaml b/taleweave/systems/sim/sleeping/logic.yaml similarity index 100% rename from taleweave/systems/sim/sleeping_logic.yaml rename to taleweave/systems/sim/sleeping/logic.yaml