sort systems into folders
This commit is contained in:
parent
37ef494796
commit
205d6923b3
63
README.md
63
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)
|
![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
|
## Features
|
||||||
|
|
||||||
TaleWeave AI is meant for gamers, developers, and researchers. It is a:
|
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
|
- Generate a world from a brief text prompt
|
||||||
- Simulate the actions of characters in that world
|
- Simulate the actions of characters in that world
|
||||||
- Allow humans to interact with each other and with NPCs
|
- 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
|
- Summarize the environment into LLM prompts
|
||||||
- Foster emergent behavior through action digests, shared environment, and note taking
|
- 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 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
|
- 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
|
- 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
|
- 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
|
- 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)
|
TaleWeave AI has in-game actions for:
|
||||||
- [Features](#features)
|
|
||||||
- [Contents](#contents)
|
| Core | Life Sim | RPG |
|
||||||
- [Requirements](#requirements)
|
| ------------ | --------------- | --------- |
|
||||||
- [Recommended](#recommended)
|
| Planning | Hunger & Thirst | Combat |
|
||||||
- [Setup](#setup)
|
| Conversation | Hygiene | Crafting |
|
||||||
- [Documentation](#documentation)
|
| Movement | Sleeping | Magic |
|
||||||
- [Contributing](#contributing)
|
| Exploration | | Movement* |
|
||||||
- [Support and Community](#support-and-community)
|
| | | Writing |
|
||||||
- [License](#license)
|
|
||||||
|
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
|
## Requirements
|
||||||
|
|
||||||
- Python 3.10
|
- Python 3.10+
|
||||||
- Ollama, vLLM, or another OpenAI-compatible LLM API (including OpenAI)
|
- 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.
|
While TaleWeave AI can be run entirely on CPU, one or more GPUs are highly recommended.
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ from taleweave.context import (
|
||||||
world_context,
|
world_context,
|
||||||
)
|
)
|
||||||
from taleweave.errors import ActionError
|
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.conversation import loop_conversation
|
||||||
from taleweave.utils.search import (
|
from taleweave.utils.search import (
|
||||||
find_character_in_room,
|
find_character_in_room,
|
|
@ -1,5 +1,4 @@
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from typing import Callable, List
|
|
||||||
|
|
||||||
from packit.agent import Agent, agent_easy_connect
|
from packit.agent import Agent, agent_easy_connect
|
||||||
|
|
||||||
|
@ -22,7 +21,7 @@ from taleweave.generate import (
|
||||||
generate_room,
|
generate_room,
|
||||||
link_rooms,
|
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.effect import apply_effects, is_effect_ready
|
||||||
from taleweave.utils.search import find_character_in_room
|
from taleweave.utils.search import find_character_in_room
|
||||||
from taleweave.utils.string import normalize_name
|
from taleweave.utils.string import normalize_name
|
||||||
|
@ -254,7 +253,7 @@ def action_use(item: str, target: str) -> str:
|
||||||
return outcome
|
return outcome
|
||||||
|
|
||||||
|
|
||||||
def init_optional() -> List[Callable]:
|
def init():
|
||||||
"""
|
"""
|
||||||
Initialize the custom actions.
|
Initialize the custom actions.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,7 +8,7 @@ from taleweave.context import (
|
||||||
)
|
)
|
||||||
from taleweave.errors import ActionError
|
from taleweave.errors import ActionError
|
||||||
from taleweave.models.planning import CalendarEvent
|
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.planning import get_recent_notes
|
||||||
from taleweave.utils.template import format_prompt
|
from taleweave.utils.template import format_prompt
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,8 @@ if True:
|
||||||
from taleweave.models.prompt import PromptLibrary
|
from taleweave.models.prompt import PromptLibrary
|
||||||
from taleweave.plugins import load_plugin
|
from taleweave.plugins import load_plugin
|
||||||
from taleweave.state import save_world_state
|
from taleweave.state import save_world_state
|
||||||
from taleweave.systems.action import init_action
|
from taleweave.systems.core.action import init_action
|
||||||
from taleweave.systems.planning import init_planning
|
from taleweave.systems.core.planning import init_planning
|
||||||
|
|
||||||
|
|
||||||
def int_or_inf(value: str) -> float | int:
|
def int_or_inf(value: str) -> float | int:
|
||||||
|
|
|
@ -159,7 +159,7 @@ def init():
|
||||||
subscribe(GameEvent, digest_listener)
|
subscribe(GameEvent, digest_listener)
|
||||||
return [
|
return [
|
||||||
GameSystem(
|
GameSystem(
|
||||||
"digest",
|
"summary",
|
||||||
format=format_digest,
|
format=format_digest,
|
||||||
generate=generate_digest,
|
generate=generate_digest,
|
||||||
initialize=initialize_digest,
|
initialize=initialize_digest,
|
|
@ -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
|
|
@ -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
|
|
@ -10,14 +10,14 @@ from taleweave.context import get_dungeon_master
|
||||||
from taleweave.game_system import GameSystem
|
from taleweave.game_system import GameSystem
|
||||||
from taleweave.models.base import dataclass
|
from taleweave.models.base import dataclass
|
||||||
from taleweave.models.entity import Room, World, WorldEntity
|
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
|
from taleweave.utils.string import or_list
|
||||||
|
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
LOGIC_FILES = [
|
LOGIC_FILES = [
|
||||||
"./taleweave/systems/weather/weather_logic.yaml",
|
"./taleweave/systems/environment/weather/logic.yaml",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,51 @@
|
||||||
from .crafting_actions import action_craft
|
from os import path
|
||||||
from .language_actions import action_read
|
|
||||||
from .magic_actions import action_cast
|
from taleweave.systems.generic.logic import load_logic
|
||||||
from .movement_actions import action_climb
|
|
||||||
|
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():
|
def init_actions():
|
||||||
return [
|
return [
|
||||||
# crafting
|
# crafting
|
||||||
action_craft,
|
action_craft,
|
||||||
# language
|
|
||||||
action_read,
|
|
||||||
# magic
|
# magic
|
||||||
action_cast,
|
action_cast,
|
||||||
# movement
|
# movement
|
||||||
action_climb,
|
action_climb,
|
||||||
|
# quest
|
||||||
|
accept_quest,
|
||||||
|
submit_quest,
|
||||||
|
# writing
|
||||||
|
action_read,
|
||||||
|
action_write,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def init_logic():
|
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
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
from taleweave.context import action_context, get_system_data
|
from taleweave.context import action_context, get_system_data
|
||||||
from taleweave.errors import ActionError
|
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,
|
QUEST_SYSTEM,
|
||||||
complete_quest,
|
complete_quest,
|
||||||
get_active_quest,
|
get_active_quest,
|
||||||
get_quests_for_character,
|
get_quests_for_character,
|
||||||
set_active_quest,
|
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:
|
def accept_quest(character: str, quest: str) -> str:
|
|
@ -15,7 +15,7 @@ from taleweave.models.entity import (
|
||||||
World,
|
World,
|
||||||
WorldEntity,
|
WorldEntity,
|
||||||
)
|
)
|
||||||
from taleweave.systems.logic import match_logic
|
from taleweave.systems.generic.logic import match_logic
|
||||||
from taleweave.utils.search import (
|
from taleweave.utils.search import (
|
||||||
find_entity_reference,
|
find_entity_reference,
|
||||||
find_item_in_container,
|
find_item_in_container,
|
|
@ -19,3 +19,21 @@ def action_read(item: str) -> str:
|
||||||
return str(action_item.attributes["text"])
|
return str(action_item.attributes["text"])
|
||||||
|
|
||||||
return f"The {item} has nothing to read."
|
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}."
|
|
@ -1,15 +1,21 @@
|
||||||
from taleweave.systems.logic import load_logic
|
from os import path
|
||||||
|
|
||||||
from .hunger_actions import action_cook, action_eat
|
from taleweave.systems.generic.logic import load_logic
|
||||||
from .hygiene_actions import action_wash
|
|
||||||
from .sleeping_actions import action_sleep
|
|
||||||
|
|
||||||
LOGIC_FILES = [
|
from .hunger.actions import action_cook, action_eat
|
||||||
"./taleweave/systems/sim/environment_logic.yaml",
|
from .hygiene.hygiene_actions import action_wash
|
||||||
"./taleweave/systems/sim/hunger_logic.yaml",
|
from .sleeping.actions import action_sleep
|
||||||
"./taleweave/systems/sim/hygiene_logic.yaml",
|
|
||||||
"./taleweave/systems/sim/mood_logic.yaml",
|
|
||||||
"./taleweave/systems/sim/sleeping_logic.yaml",
|
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():
|
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
|
||||||
|
|
Loading…
Reference in New Issue