Skip to content

Commit

Permalink
sort systems into folders
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Jun 22, 2024
1 parent 37ef494 commit 205d692
Show file tree
Hide file tree
Showing 35 changed files with 206 additions and 49 deletions.
63 changes: 48 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand All @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion taleweave/actions/base.py → taleweave/actions/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
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,
Expand Down
5 changes: 2 additions & 3 deletions taleweave/actions/optional.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from logging import getLogger
from typing import Callable, List

from packit.agent import Agent, agent_easy_connect

Expand All @@ -22,7 +21,7 @@
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
Expand Down Expand Up @@ -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.
"""
Expand Down
2 changes: 1 addition & 1 deletion taleweave/actions/planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
)
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

Expand Down
4 changes: 2 additions & 2 deletions taleweave/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
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:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def init():
subscribe(GameEvent, digest_listener)
return [
GameSystem(
"digest",
"summary",
format=format_digest,
generate=generate_digest,
initialize=initialize_digest,
Expand Down
24 changes: 24 additions & 0 deletions taleweave/systems/environment/__init__.py
Original file line number Diff line number Diff line change
@@ -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
40 changes: 40 additions & 0 deletions taleweave/systems/environment/temperature/logic.yaml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
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",
]


Expand Down
File renamed without changes.
44 changes: 37 additions & 7 deletions taleweave/systems/rpg/__init__.py
Original file line number Diff line number Diff line change
@@ -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
File renamed without changes.
File renamed without changes.
Empty file.
Empty file.
Empty file.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}."
38 changes: 25 additions & 13 deletions taleweave/systems/sim/__init__.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from taleweave.systems.logic import load_logic

from .hunger_actions import action_cook, action_eat
from .hygiene_actions import action_wash
from .sleeping_actions import action_sleep

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 os import path

from taleweave.systems.generic.logic import load_logic

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",
]


Expand All @@ -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
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 205d692

Please sign in to comment.