* pytorch update

* github workflow for tests

* tests set up config

* tests download nltk punkt

* punkt_tab

* fix world state not updating on new initial  scene load

* fix new character creation from scene tools

* py 312 py 313 support
remove unreliant cuda detection and just lock poetry with cuda

* fix tests

* dont auto install cuda

* remove unused StrEnum import

* separate cuda install

* fix auto progress OFF no longer working

* fix debug logging options not sticking

* disable revision during image prompt generation

* prompt tweaks

* prompt tweaks

* fix some issues with directed character creation

* tweak the continue generation button so its less prone to pop into a new line on itsown

* fix context db filter field layout

* handle error when trying to regnerate passthrough narrator message

* prompt tweaks

* increase auto direct evaluation length

* fix node library on windows

* auto direct eval tweaks

* prompt tweaks

* prompt tweaks

* allow updationg of scene phase through director console

* add generate action to director console phase intent text fields

* prompt tweaks

* track iteration count in scene loop
always yield to user at initial start / load of a scene

* fix issue with Split and Join nodes when passed \n as delimiter

* sim suite only generate auto direct requirements if auto direct is enabled
sim suite fix issues with title generation

* autocomplete button disable until there is text to autcomplete

* update installation docs

* update scenario tools docs

* docs

* writing style phrase detection

* typo

* docs

* fix issue where deleting an applied preset group would prevent selection of a different preset group in the affected client

* fix @-Instruction is broken when using apostrophes

* editor never attempt to fix exposition on user input if input starts with command characters @, ! or /

* prompt tweaks

* editor revision: automatic revision setting, prompt tweaks, docs

* missing files

* fix issue where narration responses starting with # would result in empty messages

* prompt tweaks

* fix issue with autocomplete not working at the beginning of a scene

* fix issues where cached guidance would result in no guidance

* editor revision analysis now has access to scene analysis and director guidance if it exists

* fix issue where all nodes in the node editor would be locked on winsows OS

* add `scene/SetIntroducation` node

* fix issue where generating narration in a scene with zero characters would always come back blank

* SceneIntroduction node state output fixed

* node editor docs progress

* fix issue with loading scene from file upload no longer working

* better handling of what to do when there are no characters in a scene and no default character is defined

* typo

* silence trigger game loop debug message

* docs

* GenerateThematicList node

* docs

* docs

* stubs

* allow creation of module from existing nodes

* move function into plugin

* separate graph export functions into own .js file

* group from selected nodes

* remove debug output

* tweak create module dialog

* docs

* docs

* graph tests need to assume auto_progres True

* add ModuleProperty node

* fix some issues in the module creation modal when extending or copying a module

* include module name in module deletion confirm dialog

* fix node module copy not setting updated registry

* module property name output

* docs

* docs

* initializing a scene from a character card will no longer break the node editor

* docs

* when greeting text and intro do not match, do the greeting text first.

* intro is set during card import, there is no need to ever emit character greetings in addition to the intro, its not really something that matches talemate's design philsophy at this point

* docs

* dynamic premise modules

* tweaks

* propagate module level property defaults to node

* docs

* fix issue where the default character would get added to scenes during load even though there already was a player character

* prompt tweaks

* tweaks to generate-premise module

* docs

* infinity quest dynamic story v2

* tweaks limits

* fix line endings

* prompt tweaks

* fix some issues with node property editing

* formatting

* prompt tweaks

* group and comment

* add talemate tint node style
fix gap in nodes when there are no sockets

* node style fixes

* docs

* docs

* icon for swtich nodes

* conditional emit status node

* don't reset dynamic premise

* dynamic premise tweaks

* dynamic premis status messages

* fix issue with Input value error node

* validate that topic is specified

* fix issue where cancelling a generation triggered during scene loop init would cause the loop to reinitialize

* docs

* node error handling improvements

* docs

* better error handling in generate premise module

* a connected socket should always override a property of the same value even if the socket connection is not resolved

* dynamic premise expose intro length property

* fix some issues with node module creation and add registry path validation

* correctly title creative loop module so it can be copied

* remove debug message

* rename to dynamic storyline for clarity and so it doesn't collide with tutorial

* import dynanimc storyline node

* docs

* gracefully handle a node missing during graph load

* docs

* make agent list a bit more compact

* disable node property editing in inherited nodes

* rename editor revision events so they are inline with the other agent events

* support instruction injection for director.generate_choices action

* normalize dynamic instructions

* fix director guidance dynamic instructions

* docs

* generate choices event add choices property

* prompt tweaks

* add dynamic instruction node

* prompt tweak

* fix issue where some events could not be hooked into through event node modules

* docs

* clean response node

* docs

* docs

* docs

* module library tweaks

* fix some issues with act-as selection

* dont allow creation of new modules until scene has been saved at least once

* public node modules dir

* sim suite module styles

* remove debug messages

* fix default node titles

* fix number input vlaidation in math nodes

* context awareness in  contextual generate now includes character info

* fix dupe id warnings

* alt drag to clone multiple nodes

* alt drag to clone multiple nodes

* docs

* docs

* fix issue where some scene modules could leak across scenes

* dynamic instructions already included through extra context

* prompt tweaks

* update defaults

* docs

* make list init from json

* socs

* fix issue where not all field definitions would get sent

* docs

* fix issue causing deep analysis to loop

* case insentive regex matching

* prompt tweaks

* fix node title

* fix size issue in scene view when node editor was open on smaller resolutions

* fix issue with autocomplete sometime loosing markup

* add claude 4

* make director guidance and actor instructions available to autocomplete prompt

* fix trim node handling of \n

* extract node

* extract node trim property

* remover cruft

* charactermessage node only set character if not already part of message prefix

* editor revision unslop mode

* fix search scenes showing node module files

* prompt tweaks

* unslop support unwanted phrase detection

* define bad_prose

* </FIX> seems to get ommitted a lot so lets handle it

* cleanup

* return on no issues

* fix some issues with character creation

* fix some character creation issues

* prompt tweaks

* contewxtual generate and autocomplete signals added

* prefix revision_

* use uuidv4 which is already installed and doesnt come with compatibility issues

* editor revision support for contextual generations
normalize some event objects

* add template picker to worldstate character creation interface

* prompt tweaks

* dont unslop scene intent or story intent generation

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* prompt tweaks

* fix issue of conversation losing edits through signals

* support revisions for world state entry generation

* task_instructions

* dont show rewrite specific options if unslop method is selected

* docs

* fix issue with setting locked save file when auto saving was turned on

* don't trigger player_turn_start in creative mode

* better check for when to fire player_turn_start and when not

* node editor crash course fixes

* docs

* fix issue where sometimes wrong system prompt was selected

* add world context to contextual generate node

* fix node dragging issue when cloning multiple nodes

* support editor revision for summarization generation

* summarization support dynamic instructions

* dedicated template for summary unslop

* pass summarization_history to template vars

* prompt tweaks

* prompt tweaks

* not sure how this got blanked

* wording

* wording

* only display debug log if TALEMATE_DEBUG=1

* fix syntax

* fix syntax

* remove unused cruft

* start-debug

* log message cleanup

* docs

* tweak defaults

* sim suite polish

* remove unused images

* add writing style instructions to revision prompts

* missing endif tag

* prompt tweaks

* prompt tweaks

* prompt tweaks

* use app-busy

* prompt tweaks

* update readme and screenshots

wording

wording

* add discord link
This commit is contained in:
veguAI
2025-06-03 12:26:12 +03:00
committed by GitHub
parent 113553c306
commit 61d01984ba
732 changed files with 73352 additions and 12820 deletions

58
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: Python Tests
on:
push:
branches: [ master, main, 'prep-*' ]
pull_request:
branches: [ master, main, 'prep-*' ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.10', '3.11', '3.12', '3.13']
fail-fast: false
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install poetry
run: |
python -m pip install --upgrade pip
pip install poetry
- name: Cache poetry dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
restore-keys: |
${{ runner.os }}-poetry-${{ matrix.python-version }}-
- name: Install dependencies
run: |
python -m venv talemate_env
source talemate_env/bin/activate
poetry config virtualenvs.create false
poetry install
- name: Setup configuration file
run: |
cp config.example.yaml config.yaml
- name: Download NLTK data
run: |
source talemate_env/bin/activate
python -c "import nltk; nltk.download('punkt_tab')"
- name: Run tests
run: |
source talemate_env/bin/activate
pytest tests/ -p no:warnings

3
.gitignore vendored
View File

@@ -17,4 +17,5 @@ scenes/
!scenes/infinity-quest-dynamic-scenario/infinity-quest.json
!scenes/infinity-quest/assets/
!scenes/infinity-quest/infinity-quest.json
tts_voice_samples/*.wav
tts_voice_samples/*.wav
third-party-docs/

View File

@@ -2,10 +2,13 @@
Roleplay with AI with a focus on strong narration and consistent world and game state tracking.
|![Screenshot 3](docs/img/ss-1.png)|![Screenshot 3](docs/img/ss-2.png)|
<div align="center">
|<img src="docs/img/ss-1.png" width="400" height="250" alt="Screenshot 1">|<img src="docs/img/ss-2.png" width="400" height="250" alt="Screenshot 2">|
|------------------------------------------|------------------------------------------|
|![Screenshot 4](docs/img/ss-4.png)|![Screenshot 1](docs/img/Screenshot_15.png)|
|![Screenshot 2](docs/img/Screenshot_16.png)|![Screenshot 3](docs/img/Screenshot_17.png)|
|<img src="docs/img/ss-3.png" width="400" height="250" alt="Screenshot 3">|<img src="docs/img/ss-4.png" width="400" height="250" alt="Screenshot 4">|
</div>
## Core Features
@@ -14,6 +17,7 @@ Roleplay with AI with a focus on strong narration and consistent world and game
- Long-term memory and passage of time tracking
- Narrative world state management to reinforce character and world truths
- Creative tools for managing NPCs, AI-assisted character, and scenario creation with template support
- Node editor for creating complex scenarios and re-usable modules
- Context management for character details, world information, past events, and pinned information
- Customizable templates for all prompts using Jinja2
- Modern, responsive UI
@@ -23,6 +27,10 @@ Roleplay with AI with a focus on strong narration and consistent world and game
- [Installation and Getting started](https://vegu-ai.github.io/talemate/)
- [User Guide](https://vegu-ai.github.io/talemate/user-guide/interacting/)
## Discord Community
Need help? Join the new [Discord community](https://discord.gg/8bGNRmFxMj)
## Supported APIs
- [OpenAI](https://platform.openai.com/overview)

View File

@@ -126,5 +126,4 @@ class RunPodVLLMClient(ClientBase):
self.model_name = kwargs["model"]
if "runpod_id" in kwargs:
self.api_auth = kwargs["runpod_id"]
log.warning("reconfigure", kwargs=kwargs)
self.set_client(**kwargs)

View File

@@ -19,7 +19,7 @@ On the right hand side click the **:material-plus-box: ADD CLIENT** button.
The client configuration window will appear. Here you can choose the type of client you want to add.
![connect a client add client modal](/talemate/img/0.26.0/connect-a-client-add-client-modal.png)
![connect a client add client modal](/talemate/img/0.30.0/connect-a-client-add-client-modal.png)
## Choose an API / Client Type
@@ -55,7 +55,7 @@ Select the API you want to use and click through to follow the instructions to c
Whenever you add your first client, Talemate will automatically assign it to all agents. Once the client is configured and assigned, all agents should have a green dot next to them. (Or grey if the agent is currently disabled)
![Connect a client assigned](/talemate/img/0.26.0/connect-a-client-ready.png)
![Connect a client assigned](/talemate/img/0.30.0/connect-a-client-ready.png)
You can tell the client is assigned to the agent by checking the tag beneath the agent name, which will contain the client name if it is assigned.

View File

@@ -1,13 +1,12 @@
## Quick install instructions
!!! warning
python 3.12 is currently not supported.
### Dependencies
--8<-- "docs/snippets/common.md:python-versions"
1. node.js and npm - see instructions [here](https://nodejs.org/en/download/package-manager/)
1. python 3.10 or 3.11 - see instructions [here](https://www.python.org/downloads/)
1. python- see instructions [here](https://www.python.org/downloads/)
### Installation

View File

@@ -1,25 +1,28 @@
## Quick install instructions
!!! warning
python 3.12 is currently not supported
1. Download and install Python 3.10 or Python 3.11 from the [official Python website](https://www.python.org/downloads/windows/).
1. Download and install Python 3.10 - 3.13 from the [official Python website](https://www.python.org/downloads/windows/).
- [Click here for direct link to python 3.11.9 download](https://www.python.org/downloads/release/python-3119/)
1. Download and install Node.js from the [official Node.js website](https://nodejs.org/en/download/prebuilt-installer). This will also install npm.
1. Download the Talemate project to your local machine. Download from [the Releases page](https://github.com/vegu-ai/talemate/releases).
1. Unpack the download and run `install.bat` by double clicking it. This will set up the project on your local machine.
1. **Optional:** If you are using an nvidia graphics card with CUDA support you may want to also run `install-cuda.bat` **afterwards**, to install the cuda enabled version of torch - although this is only needed if you want to run some bigger embedding models where CUDA can be helpful.
1. Once the installation is complete, you can start the backend and frontend servers by running `start.bat`.
1. Navigate your browser to http://localhost:8080
1. Once the talemate logo shows up, navigate your browser to http://localhost:8080
!!! note "First start up may take a while"
We have seen cases where the first start of talemate will sit at a black screen for a minute or two. Just wait it out, eventually the Talemate logo should show up.
If everything went well, you can proceed to [connect a client](../../connect-a-client).
## Additional Information
### How to Install Python 3.10 or 3.11
### How to Install Python
--8<-- "docs/snippets/common.md:python-versions"
1. Visit the official Python website's download page for Windows at [https://www.python.org/downloads/windows/](https://www.python.org/downloads/windows/).
2. Find the latest version of Python 3.10 or 3.11 and click on one of the download links. (You will likely want the Windows installer (64-bit))
4. Run the installer file and follow the setup instructions. Make sure to check the box that says Add Python 3.10 to PATH before you click Install Now.
2. Find the latest updated of Python 3.13 and click on one of the download links. (You will likely want the Windows installer (64-bit))
4. Run the installer file and follow the setup instructions. Make sure to check the box that says Add Python 3.13 to PATH before you click Install Now.
### How to Install npm
@@ -35,6 +38,13 @@ This batch file is used to set up the project on your local machine. It creates
To run this file, simply double click on it or open a command prompt in the same directory and type `install.bat`.
#### update.bat
If you are inside a git checkout of talemate you can use this to pull and reinstall talemate if there have been updates.
!!! note "CUDA needs to be reinstalled manually"
Running `update.bat` will downgrade your torch install to the non-CUDA version, so if you want CUDA support you will need to run the `install-cuda.bat` script after the update is finished.
#### start.bat
This batch file is used to start the backend and frontend servers. It opens two command prompts, one for the frontend and one for the backend.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 KiB

After

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 449 KiB

After

Width:  |  Height:  |  Size: 444 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

After

Width:  |  Height:  |  Size: 383 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 468 KiB

After

Width:  |  Height:  |  Size: 544 KiB

View File

@@ -4,9 +4,6 @@ Roleplay with AI with a focus on strong narration and consistent world and game
:material-github: [GitHub](https://github.com/vegu-ai/talemate)
!!! note "Version 0.26.0 and later"
This documenation is for version 0.26.0 and later - previous versions are significantly different, and some of the information here may not apply. This is especially true for the world state mangement and creative tools.
## Getting Started

28
docs/snippets/agents.md Normal file
View File

@@ -0,0 +1,28 @@
<!--- --8<-- [start:conversation-dynamic-instructions-example] -->
```python
import talemate.emit.async_signals as async_signals
# Append an extra system instruction every time the Conversation agent builds a prompt
async def add_custom_instruction(emission):
emission.dynamic_instructions.append(
"You are cursed to always answer in poetic verse. Keep it short."
)
# Connect our handler (run once at application start-up)
async_signals.get("agent.conversation.inject_instructions").connect(add_custom_instruction)
```
<!--- --8<-- [end:conversation-dynamic-instructions-example] -->
<!--- --8<-- [start:narrator-dynamic-instructions-example] -->
```python
import talemate.emit.async_signals as async_signals
# Append an extra system instruction every time the Narrator agent builds a prompt
async def add_custom_instruction(emission):
emission.dynamic_instructions.append(
"You are cursed to always answer in poetic verse. Keep it short."
)
async_signals.get("agent.narrator.inject_instructions").connect(add_custom_instruction)
```
<!--- --8<-- [end:narrator-dynamic-instructions-example] -->

36
docs/snippets/common.md Normal file
View File

@@ -0,0 +1,36 @@
<!--- --8<-- [start:python-versions] -->
!!! note "Supported Versions"
As of Talemate `0.30` the following python versions are supported: `3.10`, `3.11`, `3.12` or `3.13`
<!--- --8<-- [end:python-versions] -->
<!--- --8<-- [start:world-editor-create-group] -->
Fist, if you have not done so, [create a template group](/talemate/user-guide/world-editor/templates/groups) to store the template in.
Then select the group you want to add the template to and click the **:material-plus: Create Template** button.
![world editor templates create attribute template 1](/talemate/img/0.26.0/world-editor-templates-create-attribute-template-1.png)
<!--- --8<-- [end:world-editor-create-group] -->
<!--- --8<-- [start:editor-revision-unwanted-prose-requirement] -->
!!! note "Unwanted Prose Requirement"
Unwanted phrases are defined in the writing style that is currently selected in the [Scene Settings](/talemate/user-guide/world-editor/scene/settings).
See [Writing Style Templates](/talemate/user-guide/world-editor/templates/writing-style) for more information on how to create a writing style and add unwanted phrases.
<!--- --8<-- [end:editor-revision-unwanted-prose-requirement] -->
<!--- --8<-- [start:documentation-is-a-work-in-progress] -->
!!! abstract "Documentation is a work in progress"
Documentation is an ongoing effort and some parts are more complete than others, with some missing entirely. Thanks for your patience, its being worked on!
See the [Node Editor - Crash Course](/talemate/user-guide/howto/infinity-quest-dynamic/) tutorial for an extensive introduction to the node editor.
<!--- --8<-- [end:documentation-is-a-work-in-progress] -->
<!--- --8<-- [start:save-scene-project] -->
!!! success "Save!"
**:material-content-save: Save** the scene project.
<!--- --8<-- [end:save-scene-project] -->
<!--- --8<-- [start:save-graph] -->
!!! success "Save!"
**:material-check-circle-outline: Save** the module.
<!--- --8<-- [end:save-graph] -->

60
docs/style.css Normal file
View File

@@ -0,0 +1,60 @@
pre > code {
white-space: pre-wrap;
}
/* Custom load admonition */
.md-typeset .admonition.load,
.md-typeset details.load {
border-color: #9c27b0;
}
.md-typeset .load > .admonition-title,
.md-typeset .load > summary {
background-color: rgba(156, 39, 176, 0.1);
border-color: #9c27b0;
}
.md-typeset .load > .admonition-title::before,
.md-typeset .load > summary::before {
background-color: #9c27b0;
-webkit-mask-image: var(--md-admonition-icon--load);
mask-image: var(--md-admonition-icon--load);
}
/* custom event payload admonition */
.md-typeset .admonition.payload,
.md-typeset details.payload {
border-color: #616799;
}
.md-typeset .payload > .admonition-title,
.md-typeset .payload > summary {
background-color: rgba(97, 103, 153, 0.1);
border-color: #616799;
}
.md-typeset .payload > .admonition-title::before,
.md-typeset .payload > summary::before {
background-color: #616799;
-webkit-mask-image: var(--md-admonition-icon--payload);
mask-image: var(--md-admonition-icon--payload);
}
/* custom learn more admonition (605381 color) */
.md-typeset .admonition.learn-more,
.md-typeset details.learn-more {
border-color: #605381;
}
.md-typeset .learn-more > .admonition-title,
.md-typeset .learn-more > summary {
background-color: rgba(96, 83, 129, 0.1);
border-color: #605381;
}
.md-typeset .learn-more > .admonition-title::before,
.md-typeset .learn-more > summary::before {
background-color: #6f5aa3;
-webkit-mask-image: var(--md-admonition-icon--learn-more);
mask-image: var(--md-admonition-icon--learn-more);
}

View File

@@ -1,5 +1,5 @@
# Overview
The conversation agent drives the AI generated dialogue.
Also known as the **Actor** agent it is responsible for generating character driven dialogue and actions.
It rquires a text-generation client to be configured and assigned.
It requires a text-generation client to be configured and assigned.

View File

@@ -2,7 +2,7 @@
## General
![Conversation agent general settings](/talemate/img/0.29.0/conversation-general-settings.png)
![Conversation agent general settings](/talemate/img/0.30.0/conversation-general-settings.png)
!!! note "Inference perameters"
Inference parameters are NOT configured through any individual agent.
@@ -17,17 +17,11 @@ The text-generation client to use for conversation generation.
If checked and talemate detects a repetitive response (based on a threshold), it will automatically re-generate the resposne with increased randomness parameters.
##### Natural Flow
!!! note "Deprecated"
This will soon be removed in favor of the new [Editor Agent Revision Action](/talemate/user-guide/agents/editor/settings#revision)
When there are multiple characters in the scene, this will help the AI to keep the conversation flowing naturally, making sure turns are somewhat evenly distributed, and also checking that the most relevant character gets the next turn, based on the context.
##### Max. Auto turns
Maximum turns the AI gets in succession, before the player gets a turn no matter what.
##### Max. Idle turns
The maximum number of turns a character can go without speaking before the AI will force them to speak.
!!! note "Natural flow was moved"
The natural flow settings have been moved to the [Director Agent](/talemate/user-guide/agents/director) settings as part of the auto direction feature.
## Generation
@@ -64,6 +58,14 @@ General, broad isntructions for ALL actors in the scene. This will be appended t
If > 0 will offset the instructions for the actor (both broad and character specific) into the history by that many turns. Some LLMs struggle to generate coherent continuations if the scene is interrupted by instructions right before the AI is asked to generate dialogue. This allows to shift the instruction backwards.
## :material-script-text: Content
![Conversation agent content settings](/talemate/img/0.30.0/conversation-content-settings.png)
Enable this setting to apply a writing style to the generated content.
Make sure the a writing style is selected in the [Scene Settings](/talemate/user-guide/world-editor/scene/settings) to apply the writing style to the generated content.
## Long Term Memory
--8<-- "docs/snippets/tips.md:agent_long_term_memory_settings"

View File

@@ -1,5 +1,3 @@
# Overview
The creator agent is responsible for creating the AI generated content. It requires a text-generation client to be configured and assigned.
Currently exposes no settings to configure the agent itself.
Used tor most creative tasks that involves the creation of new context.

View File

@@ -0,0 +1,21 @@
# Settings
Open by clicking the **Creator** agent in the agent list.
![Creator agent item](/talemate/img/0.30.0/creator-agent-item.png)
## Long Term Memory
--8<-- "docs/snippets/tips.md:agent_long_term_memory_settings"
## Autocomplete
![Conversation agent autocomplete settings](/talemate/img/0.30.0/creator-autocomplete-settings.png)
##### Dialogue Suggestion Length
How many tokens to generate (max.) when autocompleting character actions.
##### Narrative Suggestion Length
How many tokens to generate (max.) when autocompleting narrative text.

View File

@@ -7,4 +7,10 @@ In the future it will shift / expose more of a game master role, controlling the
Will occasionally generate clickable choices for the user during scene progression. This can be used to allow the user to make choices that will affect the scene or the story in some way without having to manually type out the choice.
### Guide Scene
Will use the summarizer agent's scene analysis to guide characters and the narrator for the next generation, hopefully improving the quality of the generated content.
Will use the summarizer agent's scene analysis to guide characters and the narrator for the next generation, hopefully improving the quality of the generated content.
### Auto Direction
A very experimental feature that will cause the director to attempt to direct the scene automatically, instructing actors or the narrator to move the scene forward according to the story and scene intention.
!!! note "Experimental"
This is the first iteration of this feature and is very much a work in progress. It will likely change substantially in the future.

View File

@@ -88,4 +88,70 @@ If enabled the director will guide the narrator in the scene.
##### Max. Guidance Length
The maximum number of tokens for the guidance. (e.g., how long should the guidance be).
The maximum number of tokens for the guidance. (e.g., how long should the guidance be).
## Auto Direction
A very experimental first attempt at giving the reigns to the director to direct the scene automatically.
Currently it can only instruct actors and the narrator, but different actions will be exposed in the future. This is very early in the development cycle and will likely go through substantial changes.
!!! note "Both overall and current intent need to be set for auto-direction to be available"
If either the overall or current scene intention is not set, the auto-direction feature will not be available.
![Auto Direction Unavailable](/talemate/img/0.30.0/auto-direction-unavailable.png)
Story and scene intentions are set in the [Scene Direction](/talemate/user-guide/world-editor/scene/direction) section of the World Editor.
![Director agent auto direction settings](/talemate/img/0.30.0/director-auto-direction-settings.png)
##### Enable Auto Direction
Turn auto direction on and off.
!!! note "Auto progress needs to also be enabled"
If auto direction is enabled, auto progress needs to be enabled as well.
![Auto Progress On](/talemate/img/0.30.0/auto-progress-on.png)
#### Natural flow
Will place strict limits on actor turns based on the provided constraints. That means regardless of what the director would like to do, the actor availability will always take precedence.
##### Max. Auto turns
Maximum turns the AI gets in succession (spread accross characters). When this limit is reached, the player will get a turn no matter what.
##### Max. Idle turns
The maximum number of turns a character can go without speaking before they are automatically given a turn by the director. (per character)
##### Max. Repeat Turns
The maximum number of times a character can go in succession without speaking before the director will force them to speak. (per character)
#### Instructions
##### Instruct Actors
Allow the director to instruct actors.
##### Instruct Narrator
Allow the director to instruct the narrator.
##### Instruct Frequency
Only pass on instructions to the actors or the narrator every N turns.
!!! note "Evaluation of the scene happens regardless"
The director will evaluate the scene after each round regardless of the frequency. This setting merely controls how often the instructions are actually passed on.
##### Evaluate Scene Intention
Allows the director to evaluate the current scene phase and switch to a different scene type or set a new intention.
The number of turns between evaluations. (0 = NEVER)
!!! note "Recommended to leave at 0 (never)"
This isn't really working well at this point, so recommended to leave at 0 (never)

View File

@@ -0,0 +1,17 @@
Revisions were introduced in version `0.30.0` and allow the editor to detect and fix repetition and unwanted prose.
Please see the [settings](/talemate/user-guide/agents/editor/settings/#revision) for more information on how to configure **:material-typewriter: Revisions**.
Once automatic revisions are enabled, if the editor finds an issue in a message you will see the following status updates:
![Editor revision status](/talemate/img/0.30.0/editor-revision-issue-identified.png)
![Editor revision status](/talemate/img/0.30.0/editor-revision-rewriting.png)
Once the revision is complete the editor agent will indicate that that it made some changes by showing the :material-message-text-outline: icon next to its name.
![Editor revision status](/talemate/img/0.30.0/editor-has-messages.png)
Click the :material-message-text-outline: icon to open the Agent Messages dialog to view the changes.
![Editor revision messages](/talemate/img/0.30.0/editor-revision-history.png)

View File

@@ -1,5 +1,7 @@
# Settings
## General
![Editor agent settings](/talemate/img/0.29.0/editor-agent-settings.png)
##### Fix exposition
@@ -20,12 +22,125 @@ Applies the same rules as above to the user input messages.
Will take the generate message and attempt to add more detail to it.
##### Fix continuity errors
## Long Term Memory
Will attempt to fix continuity errors in the generated text.
--8<-- "docs/snippets/tips.md:agent_long_term_memory_settings"
!!! example "Experimental, and doesn't work most of the time"
There is something about accurately identifying continuity errors that is currently very
difficult for AI to do. So this feature is very hit and miss. More miss than hit.
## Revision
Also takes long to process, so probably leave it turned off.
![Editor agent revision settings](/talemate/img/0.30.0/editor-revision-settings-dedupe.png)
When :material-typewriter: revision is enabled the editor will analyze and attempt to fix character messages, narrator messages, and contextual generation (such as character attributes, details, world context, etc.).
Currently it can detect the following issues:
- Repetition of phrases / concepts
- Unwanted prose as defined in the writing style
The revision action is split into three parts:
- Find any issues through fuzzy, regex and semantic similarity (embeddings) matching
- Analyze the issues and plan a fix
- Apply the fix
This means it comes at a noticable delay IF it finds issues, but the improvements may be worth it.
##### Enable Revision
Check this to enable revision.
##### Automatic Revision
Check this to enable automatic revision - this will analyze each incoming actor or narrator message and attempt to fix it if there are issues.
##### Automatic Revision Targets
When automatic revision is enabled, you can choose which types of messages to automatically revise:
- **Character Messages** - Automatically revise actor actions and dialogue
- **Narration Messages** - Automatically revise narrator actions and descriptions
- **Contextual generation** - Automatically revise generated context such as character attributes, details, world context, scene intros, etc.
By default, both Character Messages and Narration Messages are enabled. You can enable or disable each type independently based on your preferences.
##### Revision Method
Which method to use to fix issues.
- `Dedupe (Fast and dumb)` - this is the default
- `Unslop (AI assisted)` - calls 1 additional prompt after generation to remove repetition, purple prose, unnatural dialogue, and over-description
- `Targeted Rewrite (AI assisted)` - analyzes text for specific issues and rewrites only problematic parts
**Dedupe (Fast and dumb)**
![Editor agent revision settings - Dedupe](/talemate/img/0.30.0/editor-revision-settings-dedupe.png)
When **Dedupe** is active it will be restricted to finding repetition and removing it without replacing it with something else, nor understanding the intent or context, so it may sometimes cause disjointed dialogue. This method is much faster as it will never prompt the AI for analysis and fixes. (If repetition detection is set to semantic similarity, it will still use the embedding function to find repetition, but it will not prompt the AI for analysis and fixes.)
**Unslop (AI assisted)**
![Editor agent revision settings - Unslop](/talemate/img/0.30.0/editor-revision-settings-unslop.png)
When **Unslop** is active, it calls 1 additional prompt after a generation and will attempt to remove repetition, purple prose, unnatural dialogue, and over-description. May cause details to be lost. This is a general-purpose cleanup method that can also use unwanted prose detection when enabled.
**Targeted Rewrite (AI assisted)**
![Editor agent revision settings - Targeted Rewrite](/talemate/img/0.30.0/editor-revision-settings-rewrite.png)
When **Targeted Rewrite** is active, unwanted prose detection becomes available and when issues are detected the AI will attempt to rewrite the message to fix the issues. This method checks for specific problems first, then only rewrites if enough issues are found.
#### Repetition
##### Repetition Detection Method
How is repetition detected.
- `Fuzzy` - fuzzy matching will match based on character-level similarity, finding text that is approximately the same with small differences (like typos, missing letters, or minor variations). This is faster but less context-aware than semantic matching.
- `Semantic Similarity` - will match based on the semantic meaning of the text using the Memory Agent's embedding function. (default)
!!! warning "Semantic Similarity"
Uses the memory agent's embedding function to compare the text. Will use batching when available, but has the potential to do A LOT of calls to the embedding model.
##### Similarity Threshold
How similar does the text need to be to be considered repetitive. (50 - 100%)
You want to keep this relatively high.
##### Repetition Range
This is the number of **MESSAGES** to consider in the history when checking for repetition.
At its default of `15` it means the last 15 messages will be considered.
##### Repetition Min. Length
The minimum length of a phrase (in characters) to be considered for repetition. Shorter phrases will be ignored.
### AI-Assisted Methods (Unslop & Targeted Rewrite)
Once switched to either **Unslop** or **Targeted Rewrite** mode, additional settings become available.
#### Preferences for Rewriting (Targeted Rewrite only)
##### Test parts of sentences, split on commas
If active this means that when a sentence doesn't produce a hit, if it has one or more commas it will split the sentence on the commas and test each part individually.
##### Minimum issues
The minimum amount of issues that need to be detected to trigger a rewrite.
#### Unwanted Prose (Both Unslop & Targeted Rewrite)
##### Detect Unwanted Prose
Check this to enable unwanted prose detection. Available for both **Unslop** and **Targeted Rewrite** methods.
--8<-- "docs/snippets/common.md:editor-revision-unwanted-prose-requirement"
##### Unwanted Prose Threshold
Similarity threshold for unwanted prose detection. (0.4 - 1.0)
You want to keep this relatively high.

View File

@@ -14,6 +14,10 @@ Used for creative tasks like scene and character generation
Will eventually become a Game Master type agent. Right now used for some very rudimentary scene direction. Allows complex scene control via the scoped api scripting.
### Editor
Will try to correct markup and optionally revise text to fix repetition and unwanted prose.
### Long-term Memory
Attempts to select and add relevant information to the current context window.

View File

@@ -21,6 +21,12 @@ Sentence transformer model that is decently fast and accurate and will likely be
### Instructor Models
!!! warning "Support of these likely deprecated"
Its become increasingly difficult to install support for these while keeping other dependencies up to date.
See [this issue](https://github.com/vegu-ai/talemate/issues/176) for more details.
Use the `Alibaba-NLP/Gte-Base-En-V1.5` embedding instead, its pretty close in accuracy and much smaller.
Instructor embeddings, coming in three sizes: `base`, `large`, and `xl`. XL is the most accurate but also has the biggest memory footprint and is the slowest. Using `cuda` is recommended for the `xl` and `large` models.
### OpenAI text-embedding-3-small

View File

@@ -8,9 +8,9 @@ If you wish to alter the inference parameters sent with the generation requests
![open settings](/talemate/img/0.26.0/open-settings.png)
Navigate to the :material-tune: **Presets** tab then select the preset you wish to edit.
Navigate to the :material-tune: **Presets** tab then select the :material-matrix: **Inference** tab.
![selected preset](/talemate/img/0.26.0/inference-presets-1.png)
![selected preset](/talemate/img/0.30.0/inference-presets-1.png)
!!! warning
Not all clients support all parameters, and generally it is assumed that the client implementation handles the parameters in a sane way, especially if values are passed for all of them. All presets are used and will be selected depending on the action the agent is performing. If you don't know what these mean, it is recommended to leave them as they are.
@@ -52,4 +52,28 @@ Used mostly for the director when directing the scene flow. Need to be creative
### Summarization
Used for summarizing the scene progress into narrative text.
Used for summarizing the scene progress into narrative text.
## Preset Groups
Initially there is a `Default` group in which the presets are edited, but if you want you can create additional groups to create - for example - model / client specific presets.
To add a new group, type the title in to the **New Group Name** field in the upper right and press `Enter`.
![new group](/talemate/img/0.30.0/inference-presets-custom-group-1.png)
The new group will be added and automatically selected for editing.
![new group](/talemate/img/0.30.0/inference-presets-custom-group-2.png)
Once you have adjusted the presets to your liking you can save the group by clicking the :material-content-save: **Save** button.
### Setting the group for the client
In the client listing find the :material-tune: selected preset and click it to expand the meny containing the groups.
![select group](/talemate/img/0.30.0/inference-preset-group-apply.png)
![select group](/talemate/img/0.30.0/inference-preset-group-applied.png)

View File

@@ -0,0 +1,19 @@
# Rate Limiting
You can rate limit a client to N requests per minute.
![Rate limit](/talemate/img/0.30.0/client-ratelimit.png)
Once the limit is hit you will get a popup notification.
![Rate limit popup](/talemate/img/0.30.0/client-ratelimit-popup.png)
Here you can either choose to wait for the rate limit to reset, or to abort the generation.
If you abort the generation, the current stack of actions will be canceled and control will be given back to the user. This is essentially the same as Cancelling the generation through normal means.
If you chose to wait the notification will collapse to the top of the screen with a timer counting down the remaining time.
Clicking the notification will expand it again.
![Rate limit notification](/talemate/img/0.30.0/client-ratelimit-notification.png)

View File

@@ -0,0 +1,4 @@
nav:
- Creating a basic scene: create-a-new-scene
- Dynamic storylines: use-dynamic-story-module
- Node Editor - Crash Course: infinity-quest-dynamic

View File

@@ -0,0 +1,3 @@
nav:
- Overview: index.md
- ...

View File

@@ -0,0 +1,24 @@
<!--- --8<-- [start:load-scene-loop] -->
!!! load "Open the `scene-loop` module"
![Scene Loop](./img/load-module-scene-loop.png)
<!--- --8<-- [end:load-scene-loop] -->
<!--- --8<-- [start:load-on-scene-init] -->
!!! load "Open the `on-scene-init` module"
![On Scene Init](./img/load-module-on-scene-init.png)
<!--- --8<-- [end:load-on-scene-init] -->
<!--- --8<-- [start:load-generate-premise] -->
!!! load "Open the `generate-premise` module"
![Generate Premise](./img/load-module-generate-premise.png)
<!--- --8<-- [end:load-generate-premise] -->
<!--- --8<-- [start:load-scene-loop] -->
!!! load "Open the `scene-loop` module"
![Scene Loop](./img/load-module-scene-loop.png)
<!--- --8<-- [end:load-scene-loop] -->
<!--- --8<-- [start:load-dynamic-premise] -->
!!! load "Open the `dynamic-premise` module"
![Dynamic Premise](./img/load-module-dynamic-premise.png)
<!--- --8<-- [end:load-dynamic-premise] -->

View File

@@ -0,0 +1,76 @@
# 1 - Scene Project
## 1.1 - Create the scene project
On the Talemate **:material-home: Home** tab find the **Create :material-plus:** button in the left sidebar.
![Create Scene Project](./img/1-btn-create-scene.png)
Click it and wait a moment for the blank scene to load.
Click the **:material-earth-box: World Editor** tab.
Fill in `Title`, `Description` and `Content Context`
---
**Title**: `Infinity Quest Dynamic`
**Content Context**: `an epic sci-fi adventure`
**Description**:
```
Captain Elmer Farstield and his trusty first officer, Kaira, embark upon a daring mission into uncharted space. Their small but mighty exploration vessel, the Starlight Nomad, is equipped with state-of-the-art technology and crewed by an elite team of scientists, engineers, and pilots. Together they brave the vast cosmos seeking answers to humanity's most pressing questions about life beyond our solar system.
```
---
![Save Scene Project](./img/1-save-project.png)
Then click the **Save** button. Enter a file name `infinity-quest-dynamic` and click **Save**.
## 1.2 - Lets import characters
Since this is going to be a dynamic version of the existing `Infinity Quest` project, we can just import the two main characters from the existing project.
Head over to the **Characters** tab and click the **Import Character** button on the left.
![Import Characters](./img/1-0001.png)
In the modal that opens up, search for the `infinity-quest.json` scene file and then select the `Elmer` character.
![Import Elmer](./img/1-0002.png)
Click **Import**.
Repeat the process for the `Kaira` character.
Both characters should now be in the character list.
![Import Kaira](./img/1-0003.png)
Make sure to then also activate both characters. Click on each name in the character list and then click the **Activate** button.
![Activate Characters](./img/1-0007.png)
--8<-- "docs/snippets/common.md:save-scene-project"
## 1.3 - Finalize
When working on a scene you should always do two things:
1. Lock the save file - this will prevent auto-saving of any progress in the scene that may happen during testing. When a save is locked a save outside of the world editor will always trigger a `Save As` dialog, forcing you to save the scene under a new name.
2. Set a restoration file - set this to the file we just saved at `infinity-quest-dynamic.json`.
Head over to **Scene**, then **Settings** and set both fields accordingly:
![Lock Save](./img/1-0004.png)
![Set Restoration File](./img/1-0005.png)
--8<-- "docs/snippets/common.md:save-scene-project"
### Optionally
I also like to disable `auto progress` while working on the scene, unless its something that needs to be tested specifically. You can do that back in the main screen above the message input field.
![Disable Auto Progress](./img/1-0006.png)

View File

@@ -0,0 +1,292 @@
# 2 - Initial Nodes
## 2.1 - Scene Loop
In the **Infinity Quest Dynamic** tab you will see the node editor on the left and the scene history on the right.
To begin with we need to ensure that our scene has a custom `Scene Loop`.
The `Scene Loop` is the main node that will be used to drive the scene. It is where turn selection and other scene logic is handled.
For this scene we are interested in setting up the initial story premise in a dynamic way.
We **do not** care about changing any of the actual loop logic.
With this in mind we can extend a new scene loop from the default talemate loop. This will give us a copy of the default loop that we can add to while keeping the rest of the loop logic up to date with any future improvements.
The `scene-loop` module should already be selected in the **:material-group: Modules** library.
![Scene Loop](./img/2-0001.png)
Click the **:material-plus: Create Module** button and in the menu select **:material-source-fork: Extend Current**.
![Extend Current - Scene Loop](./img/2-0002.png)
In the modal **leave everything as is** and click **Continue**.
This will create a copy of the scene loop node and add it to the scene.
This copy is owned by the scene and you can modify it.
The node editor will automatically open to the copy.
![Scene Loop - Extended](./img/2-0003.png)
!!! info "Module colors"
- Modules owned by the scene are colored purple.
- Modules imported from the templates directory are colored brown.
- Modules owned by talemate are colored grey.
!!! info "Editor navigation"
- Hold mouse and drag to pan the canvas.
- Mousewheel to zoom in and out.
!!! info "Locked groups"
In the node window you will see a bunch of `(Inherited, Locked)` groups. These come from the default talemate loop that was extended and cannot be edited or changed in this copy.
**The benefit:** If the default talemate loop is changed in the future, this copy will automatically inherit the changes to these nodes.
![Scene Loop - Extended - Node Editor view](./img/2-0020.png)
Read the [Node Editor - Inheritance](/talemate/user-guide/node-editor/core-concepts/module-inheritance/) documentation for more information about how inheritance works in the node editor.
## 2.2 - Hooking into scene initialisation
Generating a story premise is something that must happen at the start of the scene.
We need to somehow hook into the scene initialisation.
We can do this using an event module.
!!! info "Event modules"
`Events` are signals sent by talemate during the scene loop. There are many different events and the `Event` module is a node module that can listen to a specific event and do stuff when it happens.
Learn more about events in the [Events](/talemate/user-guide/node-editor/core-concepts/events/) documentation.
!!! warning "Clear selection"
If you have any nodes selected from your earlier playing around and familiarizing yourself with the node editor, make sure you deselect them now.
Just click on an empty space in the canvas to deselect all nodes.
Find the **:material-plus: Create Module** button and select **:material-alpha-e-circle:Event**.
![Create Event](./img/2-0004.png)
In the modal fill in the `Name` and `Registry` fields:
- **Name**: `On Scene Init`
- **Registry**: `infinity-quest-dynamic/$N`
The `registry` value determines where in the node creation menu the new module will exist. Its also a unique id for the module itself. `$N` will be replaced with a normalized version of `Name`.
![Create Event Module - Modal](./img/2-0005.png)
Click **Continue**.
The event module will be created and automatically loaded. You should be presented with an empty node canvas.
![Event Module - Created](./img/2-0006.png)
For now, go back to the `Scene Loop` by clicking on it in the **:material-group: Modules** library.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-scene-loop"
Double click the canvas above the `Prevent Infinite AI Turns` group.
The **Search for Node** window will open up.
Type `on scene` into the **Search** field and select the `On Scene Init` node that we created moments ago.
![Scene Loop - On Scene Init](./img/2-0007.png)
!!! note "Alternatively - Right click for node context menu"
You can also right click on the canvas above the nodes and select **Add Node** to add a new node.
The path should be `Add Node > infinity-quest > On Scene Init`
![Scene Loop - Right click for node context menu](./img/2-0008.png)
!!! tip "When extending a module - place custom nodes above the inherited nodes"
Its good practice to place custom nodes above the inherited nodes.
The idea being that the original node will extend down the canvas and the space above will be available for custom nodes.
Once the `On Scene Init` node is added, it should appear where your mouse was when you initiated the node creation.
![Scene Loop - On Scene Init](./img/2-0009.png)
Click on the `event_name` node property and type in `scene_loop_init`.
![Scene Loop - On Scene Init](./img/2-0010.png)
Next click **Save** in the top right of the node editor. ![Save Graph button on upper right of node editor](/talemate/img/0.30.0/save-graph.png)
--8<-- "docs/snippets/common.md:save-graph"
We are now hooked into the scene initialisation and can start working on dynamic scene creation.
## 2.3 - Testing the scene initialisation
Lets test that this works by adding some simple generated narration on scene initialisation.
Open the `On Scene Init` node module.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
Search for the following nodes and (remember double click for search or right click for node context menu) add them to the canvas:
- `Generate Progress Narration` - This node will be used to generate the introduction text, using the narrator agent.
- `Make Bool` - We will use this as a basic **ON** state for the generation node.
- `Make Text` - This will be used for us to provide instructions to the narrator agent.
- `Set Introduction` - This will store the generated introduction text with the scene and update it in the scene history.
Once you have added all the nodes, hook them up like so:
![Scene Loop - On Scene Init](./img/2-0011.png)
!!! note "How to connect nodes"
Nodes have `input` and `output` sockets.
Output sockets are on the right and input sockets are on the left.
Drag from the right-side socket of the node you want to connect from to the left-side socket of the node you want to connect to.
In the `Make Text` node click on the `value` node property and type in
```
Generate the introduction to a random exciting scenario
for the crew of the Starlight Nomad
```
Hit `Ctrl`+`Enter` to submit the instruction.
--8<-- "docs/snippets/common.md:save-graph"
Click the **:material-play:** button in the top right of the node editor.
![Play Button](./img/2-0012.png)
If everything is hooked up correctly you should see the `Generate Progress Narration` node work for a bit and then the introduction text should be updated from its generation.
![Scene Loop - On Scene Init](./img/2-0013.png)
![Updated introduction](./img/2-0014.png)
Keep playing the module to see the introduction text being updated with each new generation.
You can then also test this outside of the node editor by switching to gameplay mode in the scene tools.
![Gameplay Mode](./img/2-0015.png)
It will load the scene and the intro text should update once more.
Switch back to the node editor using the same menu.
## 2.4 - Ok, but this happens every time the scene is loaded?
Currently - yes. Which is not what we want.
So lets change that.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
In order for this to happen only once during the lifetime of the scene, we need to do a couple of things.
1. Once we generate an introduction, we need to set a permanent state variable to indicate that we have already generated an introduction.
2. Check if the introduction is already set. If it is, we skip the generation.
First lets organize the nodes a bit. Its generally recommended to use groups liberally and as soon as possible, as it keeps the canvas clean and easy to understand.
!!! note "Groups"
Groups are a way to organize nodes in the node editor.
They are useful for keeping the canvas clean and easy to understand.
They can be resized and moved around like any other node, all nodes within a group will be moved together.
:material-resize: To resize a group, drag its lower right corner.
:material-cursor-move: To move a group click on a blank area in it and drag.
Right click the canvas and click `Add Group`.
Resize and move the Group so it encompasses the current nodes.
!!! note "Alternatively"
Hold `ctrl` and drag a rectangle to select all 4 nodes.
Then right click the canvas and select `Create group from selection`. Deselect the nodes after.
Then right click the group and select `Edit Group > Title` and title it "Generate Introduction".
![Introduction Group](./img/2-0016.png)
Next remove the `Make Bool` node as we will not be needing it. (Select it and press the **Delete** key)
Find and add the following nodes to the canvas:
- `Get State` - We will use this to check if the introduction has been generated.
- `Set State` - We will use this to set the introduction as generated.
- `Switch` - We will use this to only generate the introduction if it has not been generated yet.
!!! learn-more "Learn more about states and switches"
- [State Management](/talemate/user-guide/node-editor/core-concepts/states/)
- [Switches and conditional routing](/talemate/user-guide/node-editor/core-concepts/switches/)
### 2.4.1 - Setting the state
!!! note "Instructions going forward"
Going forward node connection instructions will be provided in the format:
`<Node>.output_name` :material-transit-connection-horizontal: `<Node>.input_name`
1. `<Set Introduction>.state` :material-transit-connection-horizontal: `<Set State>.value`
1. In the `Set State` node set the `name` field to `intro_generated` and the `scope` to `game`.
1. `Shift+Click` the `Set State` node title to auto-title it.
!!! note "Auto titling"
This is a feature **some** nodes have that automatically titles the node based on the value of their properties. In the case of the `Set State` node, it will title the node to `SET {scope}.{name}`, so in this case `SET game.intro_generated`.
Hold `Shift` and click the node **title** to auto-title it.
With this we're essentially saying if the `Set Introduction` node is executed set the `intro_generated` state variable to `true`.
### 2.4.2 - Checking the state
1. `<Get State>.value` :material-transit-connection-horizontal: `<Switch>.value`
1. In the `Switch` node set the `pass_through` field to `false`.
1. `<Switch>.no` :material-transit-connection-horizontal: `<Generate Progress Narration>.state`
1. `<Switch>.no` :material-transit-connection-horizontal: `<Set Introduction>.state`
1. In the `Get State` node set the `name` field to `intro_generated` and the `scope` to `game`.
1. `Shift+Click` the `Get State` node title to auto-title it.
Here we are using the `Switch` node to only route to the `Generate Progress Narration` node if the `intro_generated` state variable is `false` or not set. (or not truthy, for people familiar with this concept)
!!! note "State socket"
The state socket is a REQUIRED pass-through socket that can be fed any value.
Its main purpose is to control the activation of a node. If the node has a state socket and the state socket is not connected or the connection is not active the node will not be executed.
![Scene Loop - On Scene Init](./img/2-0017.png)
!!! tip "Double check!"
Reminder to double check that you have set the `scope` to `game` in both the `Get State` and `Set State` nodes.
--8<-- "docs/snippets/common.md:save-graph"
Now clicking the **:material-play:** button should only generate the introduction text once.
And you can verify that the game state has been saved by opening the **Debug Tools** and then the **Edit Scene State** window.
![Open Scene State Editor](./img/2-0018.png)
![Scene State Editor](./img/2-0019.png)
!!! info "Debug Tools"
The **Debug Tools** are a set of tools that are used to debug the scene, AI prompts and other things.
They are accessible by clicking the **:material-bug:** button in the top right of the talemate window.

View File

@@ -0,0 +1,225 @@
# 3 - Improvements
Right now we have a version of Infinity Quest that when started queries whatever AI model you have setup to randomly generate a random scene introduction based on what little scene information is available, hopefully delivering something that could start off an interesting story.
Kinda cool, but we can do better.
## 3.1 - Use context generation instead of narrator generation
Talemate already has a dedicated node to generate the scene introduction text, which considers a bunch of factors that may be important specifically when generating a story introduction.
We should use this node instead of the narrator generation node.
Load the `On Scen Init` module that we made in part 2.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
1. Remove the `Generate Progress Narration` node.
1. Add a `Contextual Generate` node.
1. `<Switch>.no` :material-transit-connection-horizontal: `<Contextual Generate>.state`
1. `<Contextual Generate>.text` :material-transit-connection-horizontal: `<Set Introduction>.introduction`
1. `<Make Text>.value` :material-transit-connection-horizontal: `<Contextual Generate>.instructions`
Then in the `Contextual Generate` node's properties:
1. Set `context_type` to `scene intro`
1. Set `context_name` to `general` (value doesn't matter for this, just fill in something)
1. Set `length` to `256` (or whatever you want the max. length of the introduction to be, tokens)
![Contextual Generate](./img/3-0001.png)
--8<-- "docs/snippets/common.md:save-graph"
In order to test this, because of the state check we added earlier, depending on if you've run the scene already, you may need to either reload the scene or edit the scene state through the debug tools. We will address the awkwardness of this in the next section, so you can also just skip this step for now.
If you do test this, the result should hopefully a bit more fitting for a story introduction text (or it may not be, AI things!)
![Contextual Generate - Result](./img/3-0002.png)
## 3.2 - Make testing this.. not awkward.
Right now since we are only allowing one introduction to be generated, for testing it'd be helpful if we could simply toggle the check for this on or off, so we can regenerate the introduction as many times as we want, while we're working on this.
We can do this by staging out the module execution into two separate stages.
Stage 0 - reset the game state for `intro_generated` IF we manually flip a switch.
Stage 1 - generate the introduction as we do now.
### Stage 0 - Reset the `intro_generated` state
Add the following nodes:
1. `Stage` (x2)
1. `Make Bool`
1. `Unset State (Conditional)` - Make sure its the `Conditional` version, not the `Unset State` version.
1. `Switch`
!!! tip "ALt click and drag to clone a node"
You can hold `alt` and click and drag a node to clone it.
Connect the nodes:
1. `<Make Bool>.value` :material-transit-connection-horizontal: `<Switch>.value`
1. `<Switch>.yes` :material-transit-connection-horizontal: `<Unset State (Conditional)>.state`
1. `<Unset State (Conditional)>.state` :material-transit-connection-horizontal: `<Stage>.state`
---
**Unset State (Conditional)**
- **name**: `intro_generated`
- **scope**: `game`
---
1. Shift click the `Stage` node title to auto title it to `Stage 0`
1. Shift click the `Unset State (Conditional)` node title to auto title it to `UNSET game.intro_generated`
1. Right click the `Make Bool` node and select `Title` and change it to `RESET`.
![Stage 0](./img/3-0005.png)
### Stage 1 - Generate the introduction
1. `<SET game.intro_generated>.value` :material-transit-connection-horizontal: `<Stage>.state`
2. Set `Stage.stage` to `1`
3. Shift click the `Stage` node title to auto title it to `Stage 1`
4. Click the node icon to minimize it
![Stage 1](./img/3-0003.png)
![Stage 1 - Minimized](./img/3-0004.png)
!!! learn-more "Staging out the module execution"
A node chain connected to a stage node will be executed in order of the stage number. The node chain at Stage 0 runs before the node chain at Stage 1. This allows control over the flow of the module execution.
- [Stages](/talemate/user-guide/node-editor/core-concepts/staging)
Now when the `RESET` switch is flipped, the `intro_generated` state will be unset, and since that happens before the `Generate Progress Narration` node runs, it will trigger a new introduction to be generated.
![Reset](./img/3-0006.png)
--8<-- "docs/snippets/common.md:save-graph"
## 3.3 - Something odd.
You may realize that as you click regenerate the introduction may become stale or change very little.
This is because once we have generated an introduction that introduction will be part of the context for the next generation and will influence it.
The severity of this problem will vary from model to model.
The fix is easy, simply wipe the introduction before generating a new one.
Hold `Alt` and drag the `Set Introduction` node to clone it, then hook the clone inbetween the `UNSET game.intro_generated` and `Stage 0` nodes.
Make sure to edit it's `introduction` input to be a blank string.
![Wipe Introduction](./img/3-0012.png)
--8<-- "docs/snippets/common.md:save-graph"
## 3.4 - Oh look, its another gravity well!
Anyone who has asked AI to generate novel story beats knows that its not always... great. It will repeat the same concepts a lot and be off to trope-land in no time. Obviously this depends on the model, but we can do some stuff to increase our odds of getting something interesting!
If we were to give the AI a random concept to inform the generation, that's one way to to steer it off its biases.
### Random theme to inform the generation
1. Generate a list of concepts (using the creator agent)
1. Pick a random concept from the list
1. Format the instructions so it includes the concept
Add the following nodes:
1. `Generate Thematic List` - this prompts the creator agent to generate a list of concepts
1. `Random` - this picks a random concept from the list
1. `Dict Set` - this sets the `theme` state variable to the random concept
1. `Format` - this formats the instructions so it includes the concept
---
!!! payload "Generate Thematic List - Properties"
- **instructions**
```
A list of sci-fi topics. Keep each item short (1-3 words).
```
---
!!! payload "Random - Properties"
- **method**: `choice`
---
Connect the nodes:
1. `<Switch>.no` :material-transit-connection-horizontal: `<Generate Thematic List>.state`
1. `<Generate Thematic List>.list` :material-transit-connection-horizontal: `<Random>.choices`
---
![Random](./img/3-0007.png)
---
!!! payload "Dict Set - Properties"
- **key**: `theme`
---
!!! payload "Make Text - Properties"
- **value**:
```
Generate the introduction to a random exciting scenario
for the crew of the Starlight Nomad, based on the topic: `{theme}`
```
---
Connect the nodes:
1. `<Random>.result` :material-transit-connection-horizontal: `<Dict Set>.value`
1. `<Make Text>.value` :material-transit-connection-horizontal: `<Format>.template`
1. `<Dict Set>.dict` :material-transit-connection-horizontal: `<Format>.variables`
1. `<Format>.result` :material-transit-connection-horizontal: `<Contextual Generate>.instructions`
---
![Format](./img/3-0008.png)
---
Finally add a `Watch` node and connect it:
- `<Random>.result` :material-transit-connection-horizontal: `<Watch>.value`
Change it's title to `Theme`.
This allows you to watch the `theme` state variable and see the changes as we pick a new random theme.
--8<-- "docs/snippets/common.md:save-graph"
Lets run to test this out.
So here it generated a list of sci-fi topics, picked "Black hole" and then generated the introduction based on this selection:
![Theme](./img/3-0010.png)
![Theme - Result](./img/3-0011.png)
!!! tip "Increase the number of items in the list"
You can increase the iterations of the list generation by editing the `iterations` property of the `Generate Thematic List` node.
The first iteration will generate 20 items and any additional iterations will add 10 items to the list. Each iteration is a separate request to the creator agent and there are likely diminishing returns the more iterations you do. (there are only so many topics..)
!!! tip "Maintain a manual list"
You don't have to use the creator agent to generate a list of themes. You can maintain a manual list of themes by using the `Make List` node, which allows you to edit a list using JSON.

View File

@@ -0,0 +1,150 @@
# 4 - Get organized
Before increasing the complexity of the current graph any further, lets do a couple things.
## 4.1 - Create a new submodule
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
As graphs get more complex it may make sense to split out certain parts of the graph into separate node modules.
Hold `Ctrl` and drag a rectangle to select node chain from `<Generate Thematic List>` to `<Contextual Generate|>`.
![node chain selected](./img/4-0001.png)
Then click the **:material-plus: CREATE MODULE** button and select **Module**.
![create module](./img/4-0002.png)
When a group of nodes is selected and you create a new module, the nodes will be copied into the new module. The `Create new module` dialog that appears will state:
> You are creating a new module from a selection of 10 nodes.
!!! note "Number of nodes"
Make sure its 10 nodes, if you have more or less, your selection is not correct.
Fill in the `Name` and `Registry` fields and click **Continue**.
- Name: `Generate Premise`
- Registry: `infinity-quest-dynamic/$N`
![create module](./img/4-0003.png)
Click **Continue** to create the module.
You will be taken to the new module.
![new module](./img/4-0004.png)
As we can see it has copied the nodes, but it has also created some input and output socket nodes.
![Input socket](./img/4-0005.png) ![Output socket](./img/4-0006.png)
It will do its best to label and type those correctly, but we will need to do some cleaning up.
### Regroup
We lost the group, so select all the nodes (hold `Ctrl` and drag a rectangle around them) then right click the canvas and select **Creater group from selection**.
You may also want to move some of the nodes around to tidy up the group, especially the automatically generated input and output socket nodes may be positioned poorly.
Title the group to `Generate Premise`.
### Fixing the input sockets
The `IN - state` socket it created can stay as is. It will be `state` socket that we will feed the switch condition into.
But hold on, it looks like it created two `IN - state` sockets. We only need one.
Delete the other and connect the first one in its place.
### Fixing the output sockets
The `OUT - text` socket is good as is, it will pipe the result from the `<Contextual Generate>` node into a `text` socket.
### Cleaned up!
Your cleaned up module should look like this:
![cleaned up module](./img/4-0007.png)
--8<-- "docs/snippets/common.md:save-graph"
### Replace in `On Scene Init`
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
Replace the node chain we just made into a submodule with the submodule.
First select the node chain we want to replace.
![node chain selected](./img/4-0001.png)
Then hit the `delete` key.
Find the `Generate Premise` node and add it to the graph.
1. `<Switch>.no` :material-transit-connection-horizontal: `<Generate Premise>.state`
1. `<Generate Premise>.text` :material-transit-connection-horizontal: `<Set Introduction>.introduction`
![replaced module](./img/4-0008.png)
--8<-- "docs/snippets/common.md:save-graph"
Push the :material-play: button to confirm it still works.
![play](./img/4-0009.png)
Looking good.
## 4.2 - Some polish
Lets improve the module a bit.
- Style the node so its more obvious its going to call agent actions.
- Add an output socket for the `theme` so we can investigate what theme was generated.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-generate-premise"
Hold `Alt` and drag the existing `OUT text` node to clone it.
Change the `output_name` to `theme`.
Increase the `num` to `1`.
Hold `Shift` and click the title to auto title it to `OUT theme`.
- `<Theme>.value` :material-transit-connection-horizontal: `<OUT Theme>.value`
![theme output](./img/4-0011.png)
--8<-- "docs/snippets/common.md:save-graph"
Add a **Module Style** node to the graph and place it anywhere. It does not need to be connected to anything.
Right click the node and Select `Style Presets` -> `Agent Generation`.
![module style](./img/4-0012.png)
![applied style](./img/4-0013.png)
--8<-- "docs/snippets/common.md:save-graph"
---
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
Confirm that the `Generate Premise` node now has a theme output and a color style applied. (You may need to resize the node to fit the new output socket.)
![style applied](./img/4-0014.png)
Add a new `Watch` node, set its title to `Theme` and connect it:
- `<Generate Premise>.theme` :material-transit-connection-horizontal: `<Watch>.value`
![watch node](./img/4-0015.png)
--8<-- "docs/snippets/common.md:save-graph"
Lets :material-play: play it. And we once again can observe what theme was generated.
![play](./img/4-0016.png)

View File

@@ -0,0 +1,567 @@
# 5 - Agentic Flow
In part 3 we left off at generating a random story premise for the crew of the Starlight Nomad.
To recap - We are using the `Creator` agent to generate a list of sci-fi topics and then picking a random one to inform the generation of the introduction.
We can leverage additional agents to further improve the quality of the introduction.
One of the biggest improvements of quality I've personally seen is when an instruction is first separately analyzed and clarified by a more analytical agent like the Summarizer or the Director to help inform the instruction given to the creative agent.
For example, if we get the theme "Quantum flux", we could ask the `Summarizer` to analyze and brainstorm what to do with the theme, before we clarify it into an instruction to give to the `Creator` agent to set up the premise.
## 5.1 - Plan
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-generate-premise"
![generate-premise-graph](./img/4-0011.png)
Right now the module has one stage that generated a random theme and then generates a premise based on that theme.
For a multi agent approach this needs to be broken up into two stages, so we can insert the new analyzation stage between them.
!!! learn-more "Stages instead of long, convoluted node-chains"
While it may be tempting to just chain up the nodes into a long, convoluted node-chain, it is better to break it up into stages.
Stages make a graph behave similar to function execution, where the stage index determines the order of execution (e.g., top to bottom).
We can use local variable states to cleanly pass data between stages.
- [Stages](/talemate/user-guide/node-editor/core-concepts/staging)
So we need to:
1. Break out the Theme generation into a new stage. (Stage 1)
1. Break out the Introduction generation into a new stage. (Stage 3)
1. Add a new stage between them to analyze the theme. (Stage 2)
## 5.2 - Break out the Theme generation into a new stage. (Stage 1)
Hold `Shift` and **click the title** of the `Generate Premise` Group to create a similarly sized group right beneath it.
Retitle the new group to `Generate Theme`.
![generate-theme-group](./img/5-0001.png)
Select the three relevant theme generation nodes (Hold `Ctrl` or `Shift` and click the nodes)
- `Generate Thematic List`
- `Random`
- `Theme`
![select-nodes](./img/5-0002.png)
Then press `Ctrl+C` to copy them.
Then press `Ctrl+V` to paste them.
Immediately drag the new nodes into the `Generate Theme` group. Hold `Shift` while dragging to drag all of them at once.
![generate-theme-group](./img/5-0003.png)
Next add the following nodes to the `Generate Theme` group:
- `Set State`
- `Stage`
- `Make Bool`
Then connect them:
- `<Make Bool>.value` :material-transit-connection-horizontal: `<Generate Thematic List>.state`
- `<Theme>.value` :material-transit-connection-horizontal: `<Set State>.value`
- `<Set State>.value` :material-transit-connection-horizontal: `<Stage>.state`
---
!!! payload "Set State - Properties"
- **name**: `theme`
- **scope**: `local`
`Shift` click the title to auto title it to `SET local.theme`.
---
!!! payload "Make Bool - Properties"
- **value**: `true`
`Shift` click the title to auto title it to `true`.
---
!!! payload "Stage - Properties"
- **stage**: `1`
`Shift` click the title to auto title it to `Stage 1`.
!!! learn-more "Local scope"
The local state only exists for the duration of the module execution, so its ideal for passing data between stages.
- [State Management](/talemate/user-guide/node-editor/core-concepts/states)
![generate theme group](./img/5-0004.png)
## 5.3 - Break out the Introduction generation into a new stage. (Stage 3)
Hold `Shift` and click the title of the `Generate Theme` Group to create a similarly sized group right beneath it.
Retitle the new group to `Generate Introduction`.
![generate-introduction-group](./img/5-0005.png)
Select the 4 relevant introduction generation nodes (Hold `Ctrl` or `Shift` and click the nodes)
- `Make Text`
- `Dict Set`
- `Format`
- `Contextual Generate`
![select-nodes](./img/5-0006.png)
Hold `Alt` and drag to clone all 4 nodes and immediately drag the new nodes into the `Generate Introduction` group.
You can then `Ctrl` click the group title to auto fit the group to the nodes.
![generate-introduction-group](./img/5-0007.png)
Add the following nodes to the `Generate Introduction` group:
- `Get State`
- `Set State`
- `Stage`
- `Make Bool`
Then connect them:
- `<Get State>.value` :material-transit-connection-horizontal: `<Dict Set>.value`
- `<Make Bool>.value` :material-transit-connection-horizontal: `<Contextual Generate>.state`
- `<Contextual Generate>.text` :material-transit-connection-horizontal: `<Set State>.value`
- `<Set State>.value` :material-transit-connection-horizontal: `<Stage>.state`
---
!!! payload "Get State - Properties"
- **name**: `theme`
- **scope**: `local`
`Shift` click the title to auto title it to `GET local.theme`.
---
!!! payload "Make Bool - Properties"
- **value**: `true`
`Shift` click the title to auto title it to `true`.
---
!!! payload "Set State - Properties"
- **name**: `intro`
- **scope**: `local`
`Shift` click the title to auto title it to `SET local.intro`.
---
!!! payload "Stage - Properties"
- **stage**: `3`
`Shift` click the title to auto title it to `Stage 3`.
---
Retitle the `Make Text` node to `Instruction Template`.
---
![generate introduction group](./img/5-0008.png)
--8<-- "docs/snippets/common.md:save-graph"
## 5.4 - Reorganize inputs and outputs
Hold `Shift` and click the title of the `Generate Introduction` Group to create a similarly sized group right beneath it.
Retitle the new group to `Sockets`, Color it green.
Hold `Alt` and drag the existing `IN state` node to clone it and move the clone to the `Sockets` group.
Do the same for the existing output nodes `OUT text` and `OUT theme`.
Alt drag one of the output nodes again to clone it and make an `OUT state` node from it. Set the `output_name` to `state` and the `output_type` to `any`.
Renumber the output nodes so its:
- `OUT state.num` = `0`
- `OUT text.num` = `1`
- `OUT theme.num` = `2`
You should have something like this
![sockets group](./img/5-0009.png)
You can connect the `IN state` node to the `OUT state` node.
Next add two `Get State` nodes to the `Sockets` group.
---
!!! payload "First Get State - Properties"
- **name**: `theme`
- **scope**: `local`
`Shift` click the title to auto title it to `GET local.theme`.
---
!!! payload "Second Get State - Properties"
- **name**: `intro`
- **scope**: `local`
`Shift` click the title to auto title it to `GET local.intro`.
Connect them to their respective output nodes.
![connected sockets](./img/5-0010.png)
!!! learn-more "No stage node required"
We want sockets to be evaluated at the END of the module execution, so we don't need a stage node.
!!! learn-more "Why does `IN state` not need to be connected to anything else?"
Since the `IN state` node is a required input socket, it already fulfills its purpose as serving as an activator for the module execution.
If the node connecting into the state socket is not active then due to the state being required the module execution will be blocked.
Passing the state to the `OUT state` is not a requirement, but it is a good practice to do so.
--8<-- "docs/snippets/common.md:save-graph"
## 5.5 - Delete the original `Generate Premise` group
We have moved all the nodes and can now delete the original `Generate Premise` group.
Move the `Module Style` node out of the group first - that one we want to keep.
Then hold `Ctrl` and drag rectangle to select the nodes in the `Generate Premise` group and press the `Delete` key.
Then right click the `Generate Premise` group and select `Edit Group / Remove`.
You should now be left with three groups:
- `Generate Theme`
- `Generate Introduction`
- `Sockets`
and a `Module Style` node somewhere.
![three groups](./img/5-0011.png)
--8<-- "docs/snippets/common.md:save-graph"
## 5.6 - Quick test
Lets verify quick that the graph is working as expected.
This time instead of going back to the `On Scene Init` module and playing that we can just start the entire scene loop.
Since the `On Scene Init` module is invoked when the scene is loaded, it will run and call the `Generate Premise` module.
Click the **:material-movie-play:** icon in the top right corner of the graph to start the scene loop.
![start scene loop](./img/5-0012.png)
!!! note "Testing via scene loop requires a save."
If you are inside of a sub-module and are testing by starting the scene loop, the child module **needs** to be saved first, otherwise changes will not be reflected in the test run.
Once the introduction is generated, we now need to manually stop the scene loop test, by pressing the **:material-stop:** icon in the top right corner of the graph.
![stop scene loop](./img/5-0013.png)
## 5.7 - Add a new stage to analyze the theme. (Stage 2)
Hold `Shift` and click the title of the `Generate Introduction` Group to create a similarly sized group right beneath it.
Retitle the new group to `Analyze Theme`.
Add the following nodes to the `Analyze Theme` group:
- `Get State`
- `Get Agent`
- `Prompt from Template`
- `Generate Response`
- `Make Text`
- `Make Bool`
- `Set State`
- `Stage`
- `Dict Set`
Then connect them:
- `<Get State>.value` :material-transit-connection-horizontal: `<Dict Set>.value`
- `<Make Text>.value` :material-transit-connection-horizontal: `<Prompt from Template>.template_text`
- `<Dict Set>.dict` :material-transit-connection-horizontal: `<Prompt from Template>.variables`
- `<Prompt from Template>.prompt` :material-transit-connection-horizontal: `<Generate Response>.prompt`
- `<Make Bool>.value` :material-transit-connection-horizontal: `<Generate Response>.state`
- `<Get Agent>.agent` :material-transit-connection-horizontal: `<Generate Response>.agent`
- `<Generate Response>.response` :material-transit-connection-horizontal: `<Set State>.value`
- `<Set State>.value` :material-transit-connection-horizontal: `<Stage>.state`
---
!!! payload "Get State - Properties"
- **name**: `theme`
- **scope**: `local`
`Shift` click the title to auto title it to `GET local.theme`.
---
!!! payload "Get Agent - Properties"
- **agent_name**: `Summarizer`
`Shift` click the title to auto title it to `summarizer`.
---
!!! payload "Make Text - Properties"
- **value**:
```
Analyze the following sci-fi theme:
{{theme}}
Provide a detailed exploration of this theme, including:
1. Key concepts or technologies involved
2. Potential storylines or conflicts
3. How it might affect the crew of the Starlight Nomad
Your analysis will be used to set up the premise for the next storyline in the Infinity Quest series.
```
Retitle the `Make Text` node to `Theme Analysis Template`.
!!! note "Prompt from Template.template_text expects a jinja2 template"
This means variable names need to be wrapped in `{{}}` to be interpreted as variables.
So `{{ theme }}` instead of `{theme}` like we used before when passing to the string `Format` node.
---
!!! payload "Dict Set - Properties"
- **key**: `theme`
---
!!! payload "Make Bool - Properties"
- **value**: `true`
`Shift` click the title to auto title it to `true`.
---
!!! payload "Generate Response - Properties"
- **response_length**: `768`
- **action_type**: `analyze`
---
!!! payload "Set State - Properties"
- **name**: `theme_analysis`
- **scope**: `local`
`Shift` click the title to auto title it to `SET local.theme_analysis`.
---
!!! payload "Stage - Properties"
- **stage**: `2`
`Shift` click the title to auto title it to `Stage 2`.
---
![analyze theme group](./img/5-0014.png)
--8<-- "docs/snippets/common.md:save-graph"
Lets test the graph again.
We want to see somewhere what analysis the `Summarizer` agent has generated.
We could add another `Watch` node, but there is also a debug logging feature in the node editor that can be handy for this.
Open the node-editor :material-bug: debug options menu and check the checkbox next to `Set State` in the `Debug Logging` section:
![debug logging](./img/5-0015.png)
Now every `Set State` node will log its value to the editor log, including our `theme_analysis` state.
:material-movie-play: Start the scene loop again and you should see the `Summarizer` agent's analysis in the debug log.
![debug log](./img/5-0016.png)
--8<-- "docs/snippets/common.md:save-graph"
## 5.8 - Use the analysis
Now that we have all three stages in place, the thing left to do is make sure that Stage 3 uses the analysis from Stage 2 to generate the introduction.
To begin with, if you followed along exactly, the groups are currently out of order:
1. Generate Theme
1. Generate Introduction
1. Analyze Theme
!!! note "The order does not matter"
Technically the order of the groups does not matter, but it helps a lot with understanding the flow of the graph. If the groups are lined out in order of the stage execution.
I also like to mention the stage of each group in the group title, once the stages are solidified.
You can move each group easily enough, just drag the groups into the correct order so its:
1. Generate Theme
1. Analyze Theme
1. Generate Introduction
Leaving you with a graph that looks like this:
![correct order](./img/5-0017.png)
Now, in the `Generate Introduction` group, we need to use the `theme_analysis` state to generate the introduction.
Add another `Get State` node to the `Generate Introduction` group.
---
!!! payload "Get State - Properties"
- **name**: `theme_analysis`
- **scope**: `local`
`Shift` click the title to auto title it to `GET local.theme_analysis`.
---
Hold `Alt` and drag the `Dict Set` node to clone it.
---
Connect the nodes:
- `<GET local.theme_analysis>.value` :material-transit-connection-horizontal: `<Dict Set>.value`
- `<GET local.theme_analysis>.name` :material-transit-connection-horizontal: `<Dict Set>.key`
- `<Dict Set>.dict` :material-transit-connection-horizontal: `<Dict Set>.dict`: feeding the new dict into the old dict
Lets also connect the `name` field of the `<GET local.theme>` node to the `key` field of its `<Dict Set>` node.
- `<GET local.theme>.name` :material-transit-connection-horizontal: `<Dict Set>.key`
![dict set node](./img/5-0018.png)
Next go to the `Instruction Template` node and update the template text to:
```
Generate the introduction to a random exciting scenario
for the crew of the Starlight Nomad.
The theme is: "{theme}"
Use the following analysis to guide your creation of the scenario premise:
{theme_analysis}
```
--8<-- "docs/snippets/common.md:save-graph"
:material-movie-play: Start the scene loop again and you should see the `Generate Introduction` stage use the `theme_analysis` state to generate the introduction.
Lets look what the final prompt to the `Creator` agent looks like.
!!! tip "Inspecting prompts"
You can open the talemate **:material-bug:** debug tools and click on any of the prompts to inspect them.
![debug tools](./img/debug-tools-prompt-inspect.png)
```
... Other context ...
## Task
Generate the introduction for the scene. This is the first text that is shown to Elmer when they start the scene.
It must contain enough context for the reader to dive right in. Assume that the reader has not looked at the character or scene descriptions.
It must setup an interesting entry point for the reader to participate in the scene and interact with the other characters and the environment.
### Editorial Instructions
Generate the introduction to a random exciting scenario
for the crew of the Starlight Nomad.
The theme is: "Quantum entanglement"
Use the following analysis to guide your creation of the scenario premise:
### Analysis of Quantum Entanglement Theme
#### 1. Key Concepts or Technologies Involved
**Quantum Entanglement:**
- **Definition:** Quantum entanglement is a physical phenomenon which occurs when pairs or groups of particles are generated, interact, or share spatial proximity in ways such that the quantum state of each particle cannot be described independently of the state of the others, even when the particles are separated by a large distance.
- **Key Properties:**
- **Instantaneous Correlation:** Changes to one particle's state instantly affect the entangled partner, regardless of distance.
- **Superposition:** Entangled particles exist in multiple states simultaneously until measured.
- **Non-locality:** The effect is independent of the distance between the particles.
**Technologies Involved:**
- **Quantum Communicators:** Devices that use entangled particles to transmit information instantly across vast distances.
- **Quantum Computers:** Utilize entanglement for unprecedented processing power and problem-solving capabilities.
- **Entanglement-based Sensors:** Highly sensitive devices for detection and measurement, using the properties of entangled particles to achieve precision beyond classical limits.
#### 2. Potential Storylines or Conflicts
**Storyline 1: The Entangled Spy**
- **Premise:** A rogue AI creates a network of entangled spies across the galaxy, using quantum entanglement to transmit information instantly and securely.
- **Conflict:** The crew of the Starlight Nomad discovers that one of their own has been entangled with a spy device, unwittingly leaking critical information.
- **Resolution:** The crew must find a way to disrupt the entanglement without harming their comrade, while also tracking down the source of the spy network.
**Storyline 2: Lost in Superposition**
- **Premise:** During a routine mission, the Starlight Nomad encounters an ancient quantum experiment that has created a stable superposition of multiple realities.
- **Conflict:** The crew becomes trapped in a loop of overlapping realities, where their actions in one reality affect others in unpredictable ways.
- **Resolution:** They must navigate the complexities of quantum superposition to find a way back to their original reality, using their knowledge of entanglement to stabilize the experiment.
**Storyline 3: The Quantum Heist**
- **Premise:** A valuable quantum artifact, capable of controlling entanglement, is stolen from a research facility.
- **Conflict:** The thieves use the artifact to create a network of entangled traps, making it dangerous for the crew to pursue them directly.
- **Resolution:** The crew must outsmart the thieves by creating their own entangled devices to counter the traps and recover the artifact.
#### 3. How It Might Affect the Crew of the Starlight Nomad
**Technological Advantages:**
- **Instant Communication:** The crew can stay connected across vast distances, ensuring coordinated actions even in deep space.
- **Enhanced Sensing:** Entanglement-based sensors can provide early warnings of dangers, such as asteroid fields or enemy ships.
**Potential Challenges:**
- **Entanglement Malfunctions:** If an entangled device malfunctions, it could lead to miscommunications or false alarms, causing confusion and potential danger.
- **Quantum Interference:** Other quantum phenomena could interfere with their entangled devices, leading to unexpected outcomes.
- **Psychological Impact:** Crew members might feel a sense of dislocation or uncertainty due to the non-local nature of entanglement, affecting their mental health and decision-making.
**Character Development:**
- **Trust Issues:** The crew might become paranoid about who to trust if entanglement is used for spying, leading to internal conflicts and alliances.
- **Problem-Solving:** They will need to develop new strategies and technologies to handle quantum-based threats and opportunities[/INST]scene introduction:
```

View File

@@ -0,0 +1,728 @@
# 6 - Reusable Module
## Recap
In the previous parts of this guide, we've built a dynamic story premise generator for our Infinity Quest project:
1. **Part 1**: Created the scene project, imported characters from the original Infinity Quest, and set up basic scene settings.
2. **Part 2**: Set up the Scene Loop by extending the default Talemate loop, created an event module to hook into scene initialization, and implemented logic to generate a dynamic introduction that only happens once when the scene is first loaded.
3. **Part 3**: Improved the introduction generation by switching to contextual generation, added a reset mechanism for testing, and implemented random theme generation to guide the premise creation and reduce AI bias.
4. **Part 4**: Organized our node graph by moving the premise generation logic into a separate submodule, added styling to visually identify agent actions, and improved the module interface.
5. **Part 5**: Implemented a multi-agent workflow with staging where:
- Stage 1: Generates a random sci-fi theme
- Stage 2: Uses the Summarizer agent to analyze the theme in depth
- Stage 3: Uses the analysis to guide the creation of an introduction text
At this point, we have a fully functional random premise generator for the Infinity Quest project. However, one of the most powerful features of the Talemate node editor is the ability to create modular, reusable components that can be shared across different scenes and projects.
In this part, we'll transform our premise generator from a scene-specific module into a standalone, reusable component that can be plugged into any scene.
## 6.0 Backup
We're going to be moving and renaming stuff going forward, so you should backup your project.
Either copy the entire `scenes/infinity-quest-dynamic` folder somewhere or at least grab the `nodes` subfolder.
## 6.1 Starting Point
We've done quite a bit of work at this point, so lets quickly go over what we have:
### Event Module
![Event Module](./img/load-module-on-scene-init.png)
This module is responsible for generating the dynamic introduction that only happens once when the scene is first loaded.
![Event Module](./img/6-0001.png)
### Scene Loop Extension
![Scene Loop Module](./img/load-module-scene-loop.png)
An extension of the default Talemate scene loop where we added an instance of the on-scene-init event module.
![Scene Loop Extension](./img/6-0002.png)
### Premise Generation Module
![Premise Generation Module](./img/load-module-generate-premise.png)
This module is responsible for generating the a scene introduction based on random sci-fi theme with the help of the Summarizer agent for additional exploration of the concept.
---
![Premise Generation Module](./img/6-0003.png)
## 6.2 Plan
In order to make our premise generator a standalone module, there are a few things we need to consider:
1. Rename the event module so its less generic as it will be the entry point for the module.
1. Right now the premise generator has some hardcoded values that make sense for the Infinity Quest project (sci-fi themed, star trek type of story). We need to be able to expose this from the premise module all the way to the scene loop extension as configurable properties.
1. A toggle for turning analyzation on and off.
1. Make the module available as a Talemate module, so it can be plugged into any new scene project.
## 6.1 Renaming the Event Module
Currently there is no good way to rename a module through the node editor. (Still early in the development of the node editor, so this will be added in the future.)
For now the easiest way to rename it is to simply create a copy.
So load the `on-scene-init` module and create a copy of it.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-on-scene-init"
Click the **:material-plus: CREATE MODULE** button and then **Copy current**.
![Copy current module](./img/6-0004.png)
In the modal change
- **Name**: `Dynamic Premise`
- **Registry**: `scene/$N`
![Rename module](./img/6-0005.png)
Now load the `scene-loop` module and replace the `On Scene Init` module with the new `Dynamic Premise` module.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-scene-loop"
![Scene Loop Extension](./img/6-0002.png)
Select the `On Scene Init` module and press the `delete` key.
Then add the `Dynamic Premise` module to the scene loop and set the `event_name` to `scene_loop_init`.
![Scene Loop Extension](./img/6-0006.png)
--8<-- "docs/snippets/common.md:save-graph"
**:material-movie-play:** Start the scene loop to test that everything's still working.
Then find the old `on-scene-init` module in the :material-group: Modules library and press the :material-close-circle-outline: button to delete it. Confirm the action.
![Delete module](./img/6-0007.png)
## 6.2 Exposing a Reset Toggle
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-dynamic-premise"
We have the node chain that lets us reset the premise generation.
![Reset node chain](./img/6-0008.png)
It'd be practical for this to be a simple switch on the event node.
Create a new group somewhere in the module and call it `Properties`. Color it `cyan`.
Add the following nodes to the group:
- `Module Property`
- `Set State`
- `Stage`
Connect the nodes as follows:
- `<Module Property>.name` :material-transit-connection-horizontal: `<Set State>.name`
- `<Module Property>.value` :material-transit-connection-horizontal: `<Set State>.value`
- `<Set State>.value` :material-transit-connection-horizontal: `<Stage>.state`
---
!!! payload "Module Property - Properties"
- **property_name**: `reset`
- **property_type**: `bool`
- **default**: `false`
`Shift` click the title to auto-title it to `PROP reset`.
Leave the `Set State` node as is, but change its title to `SET local.reset`.
Make sure the `scope` is set to `local`.
!!! note "Can't auto-title the Set State node in this case"
Since we are plugging the `name` output of the `Module Property` node into the `name` input of the `Set State` node, auto titling the Set State node currently doesn't work, so do it manually.
In the `Stage` node set the following:
- **stage**: `-1`
`Shift` click the title to auto-title it to `Stage -1`.
![Reset toggle](./img/6-0009.png)
Next go back to the `Generate Introduction` group and add the following nodes:
- `Get State`
Replace the existing `Make Bool` (titled `RESET`) node with the `Get State` node, connecting it's value output to the `Switch.value` input.
- `<Get State>.value` :material-transit-connection-horizontal: `<Switch>.value`
---
!!! payload "Get State - Properties"
- **name**: `reset`
- **scope**: `local`
`Shift` click the title to auto-title it to `GET local.reset`.
![Properties group and updated reset toggle](./img/6-0010.png)
--8<-- "docs/snippets/common.md:save-graph"
---
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-scene-loop"
Confirm that the `Dynamic Premise` node now has a `reset` property that is a boolean on / off switch.
![Dynamic Premise node with reset toggle](./img/6-0011.png)
Turn it on since we will want to test the module still while working on it.
--8<-- "docs/snippets/common.md:save-graph"
## 6.3 Fixing the registry path for the Generate Premise Module
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-dynamic-premise"
Still in the `Dynamic Premise` module, looking at the `Generate Premise` node, it currently exposes no properties to edit.
![Generate Premise node](./img/6-0012.png)
But, hold on, its path still is registered as `infinity-quest-dynamic/generatePremise` - that wont do for a reusable module.
So we need to change it.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-generate-premise"
Create a copy of the module. (Same as before)
This time in the modal you can leave the **Name** as is, and simply replace the `infinity-quest-dynamic` portion of the **Registry** with `scene` so it reads `scene/generatePremise`.
![Change registry](./img/6-0013.png)
Click **Continue** to create the copy.
Since we are keeping the name the same, it will simply replace the existing `generate-premise` module in the library. However, the `dynamic-premise` module is still referencing the old `generate-premise` module.
!!! warning "Dont restart talemate right now"
Currently the old reference is still loaded in talemate, so we can load the `dynamic-premise` module without any issues and remove it. Restarting talemate will cause the old reference to be removed and the dynamic premise module may no longer load.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-dynamic-premise"
Delete the old `Generate Premise` node.
--8<-- "docs/snippets/common.md:save-graph"
Add the new `Generate Premise` node and connect it like how the old one was connected.
![Scene Loop Extension](./img/6-0015.png)
--8<-- "docs/snippets/common.md:save-graph"
!!! bug "The node editor can be a bit buggy here (v0.30.0)"
It may be that when searching for the new node you will find the old one as well (or even multiples of it). Just make sure you select the one that has the path as `scene/generatePremise`.
![Buggy search results](./img/6-0014.png)
The issue will go away the next time talemate is restarted.
## 6.4 Content control inputs
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-generate-premise"
### Investigating the current properties
Lets look which things we need to expose to allow us to control what kind of themes can be generated.
---
`<Generate Theme>.<Generate Thematic List>.instructions`
This controls the overarching theme topic. (sci-fi currenly)
```
A list of sci-fi topics. Keep each item short (1-3 words).
```
---
`<Analyze Theme>.<Theme Analysis Template>.value`
The **jinja2** prompt template for the theme analysis.
```
Analyze the following sci-fi theme:
{{theme}}
Provide a detailed exploration of this theme, including:
1. Key concepts or technologies involved
2. Potential storylines or conflicts
3. How it might affect the crew of the Starlight Nomad
Your analysis will be used to set up the premise for the next storyline in the Infinity Quest series.
```
---
`<Generate Introduction>.<Instruction Template>.value`
The prompt template for the introduction generation.
```
Generate the introduction to a random exciting scenario
for the crew of the Starlight Nomad.
The theme is: "{theme}"
Use the following analysis to guide your creation of the scenario premise:
{theme_analysis}
```
---
So looking at the above, it seems we will need:
- A `topic` input that is a string.
- A `analysis_instructions` input that is a string
We will also rewrite the templates a bit to make them more flexible.
### Input Nodes
Create a new group somewhere in the module and call it `Inputs`. Color it `blue`.
Add the following nodes to the group:
- `Input Socket` (x2)
- `Set State` (x2)
- `Stage`
---
!!! payload "First Input Socket - Properties"
- **input_type**: `str`
- **input_name**: `topic`
`Shift` click the title to auto-title it to `IN topic`.
---
!!! payload "Second Input Socket - Properties"
- **input_type**: `str`
- **input_name**: `analysis_instructions`
`Shift` click the title to auto-title it to `IN analysis_instructions`.
---
!!! payload "First Set State - Properties"
- **name**: `topic`
- **scope**: `local`
`Shift` click the title to auto-title it to `SET local.topic`.
---
!!! payload "Second Set State - Properties"
- **name**: `analysis_instructions`
- **scope**: `local`
`Shift` click the title to auto-title it to `SET local.analysis_instructions`.
---
!!! payload "Stage - Properties"
- **stage**: `-1`
`Shift` click the title to auto-title it to `Stage -1`.
---
Connect the nodes as follows:
- `<IN topic>.value` :material-transit-connection-horizontal: `<SET local.topic>.value`
- `<SET local.topic>.value` :material-transit-connection-horizontal: `<Stage>.state`
- `<IN analysis_instructions>.value` :material-transit-connection-horizontal: `<SET local.analysis_instructions>.value`
- `<SET local.analysis_instructions>.value` :material-transit-connection-horizontal: `<Stage>.state_b`
![Module Properties](./img/6-0016.png)
--8<-- "docs/snippets/common.md:save-graph"
### Adjusting the Generate Theme stage
The topic of the theme will be set in `local.topic`, we need to get this and incorporate it into the `Generate Thematic List` node. We will also change to use the appropriate prompting nodes to build the prompt. So this will now use a jinja2 template syntax.
In the `Generate Theme` group add the following nodes:
- `Get State`
- `Make Text`
- `Prompt from Template`
- `Render Prompt`
- `Dict Set`
---
!!! payload "Get State - Properties"
- **name**: `topic`
- **scope**: `local`
`Shift` click the title to auto-title it to `GET local.topic`.
---
!!! payload "Make Text - Properties"
I am chosing to rewrite the instructions to be a bit more compatible with what a user might type into the `topic` input.
Its good to keep in mind that a user doesn't know what the entire prompt looks like, so their input may not always be ideal. Of course if you're just using this for yourself, this matters less.
- **value**
```
A list of topics to use for brain storming. The overarching theme is described as "{{ topic }}". Keep each item short (1-3 words). One of these items will be chosen to bootstrap a new story line.
```
Retitle to `Instructions`
---
Connect the nodes as follows:
- `<GET local.topic>.value` :material-transit-connection-horizontal: `<Dict Set>.value`
- `<GET local.topic>.name` :material-transit-connection-horizontal: `<Dict Set>.key`
- `<Instructions>.value` :material-transit-connection-horizontal: `<Prompt from Template>.template_text`
- `<Dict Set>.dict` :material-transit-connection-horizontal: `<Prompt from Template>.variables`
- `<Prompt from Template>.prompt` :material-transit-connection-horizontal: `<Render Prompt>.prompt`
- `<Render Prompt>.rendered` :material-transit-connection-horizontal: `<Generate Thematic List>.instructions`
![Generate Theme](./img/6-0017.png)
--8<-- "docs/snippets/common.md:save-graph"
### Adjusting the Analyze Theme stage
We will do the same for the `Analyze Theme` stage, conveniently this is already using `Prompt from Template` node, but the template itself is about to get a bit of a makeover, so there is a bit of work ahead of us.
However here I also want to include some extra context in the instructions to help improve the quality of the analysis.
In the `Analyze Theme` group add the following nodes:
- `Get State` (x2)
- `Dict Set` (x2)
- `Template variables`
---
!!! payload "First Get State - Properties"
- **name**: `analysis_instructions`
- **scope**: `local`
`Shift` click the title to auto-title it to `GET local.analysis_instructions`.
---
!!! payload "Second Get State - Properties"
- **name**: `topic`
- **scope**: `local`
`Shift` click the title to auto-title it to `GET local.topic`.
---
!!! payload "Theme Analysis Template"
Here I want to add the scene `description` and the characters `description` to the template, thinking it will influence the analysis within the context of the story baseline. Knowing the characters will also help the agent come up with potenial storyline suggestions.
Additionally I am deciding to coerce the response to be a bit more concise and to the point. In my testing I found that the agent was getting a bit verbose and even with a 1024 token limit it was getting cut off.
- **value**
```
<|SECTION:STORY BASELINE|>
{{ scene.description }}
<|SECTION:PROTAGONISTS|>
{% for character in scene.characters %}
### {{ character.name }}
{{ character.description }}
{% endfor %}
<|SECTION:CONTEXT OF YOUR TASK|>
A topic description of "{{ topic }}" was given and a random theme was picked to bootstrap a new storyline: "{{ theme }}".
<|SECTION:TASK|>
Analyze the theme "{{ theme }}" in the context of the topic "{{ topic }}".
Provide a brief exploration of this theme, including:
1. Key concepts or ideas involved and how they fit the context
2. Potential storylines or conflicts
3. How it might affect the protagonists of the story
{% if analysis_instructions %}
{{ analysis_instructions }}
{% endif %}
Keep your analysis concise and to the point.
Your analysis will be used to set up the premise for the next storyline in the `{{ scene.name }}` series.
```
!!! learn-more "Template variables"
Its the `Template variables` node that is responsible for adding variables like `scene` to the template
scope.
- [Prompt Templating](/talemate/user-guide/node-editor/core-concepts/prompt-templates)
---
Connect the nodes as follows:
- `<GET local.analysis_instructions>.value` :material-transit-connection-horizontal: `<Dict Set>.value`
- `<GET local.analysis_instructions>.name` :material-transit-connection-horizontal: `<Dict Set>.key`
---
- `<GET local.topic>.value` :material-transit-connection-horizontal: `<Dict Set>.value`
- `<GET local.topic>.name` :material-transit-connection-horizontal: `<Dict Set>.key`
---
Chain all three `Dict Set` nodes together (the 2 new ones plus the 1 existing one), with each connecting to the `dict` input of the next and the last one connecting to the `merge_with` input of the `Template variables` node.
Then connect the remaining nodes as follows:
---
- `<summarizer>.agent` :material-transit-connection-horizontal: `<Template variables>.agent`
- `<Template variables>.agent` :material-transit-connection-horizontal: `<Generate Response>.agent`
- `<Template variables>.variables` :material-transit-connection-horizontal: `<Prompt From Template>.variables`
---
![Analyze Theme](./img/6-0018.png)
--8<-- "docs/snippets/common.md:save-graph"
### Adjusting the Generate Introduction stage
This i will leave as is for now, but i will update the `Instruction Template` text to remove the infinity quest reference.
```
Generate the introduction to a random exciting story-line.
The theme is: "{theme}"
Use the following analysis to guide your creation of the scenario premise:
{theme_analysis}
```
--8<-- "docs/snippets/common.md:save-graph"
## 6.5 - A switch for analysis
My general approach is that i want to be able to turn off long running queries to the agents.
So lets do this for the analysis.
The obvious splace to add this is the `state` input of the `Generate Response` node in the `Analyze Theme` group.
It is currently connected to a `Make Bool` node that is set to `true`.
![Make bool connected to state](./img/6-0019.png)
To build a switch add the following nodes to the `Analyze Theme` group:
- `Get State`
- `Switch`
---
!!! payload "Get State - Properties"
- **name**: `analysis_enabled`
- **scope**: `local`
`Shift` click the title to auto-title it to `GET local.analysis_enabled`.
---
!!! payload "Switch - Properties"
- **pass_through**: `false`
---
Connect the nodes as follows:
- `<GET local.analysis_enabled>.value` :material-transit-connection-horizontal: `<Switch>.value`
- `<Switch>.yes` :material-transit-connection-horizontal: `<Generate Response>.state`
![Switch connected to state](./img/6-0020.png)
Delete the `Make Bool` node that was connected to the `state` input of the `Generate Response` node.
--8<-- "docs/snippets/common.md:save-graph"
Next we need to add an `Input` node to expose this new `analysis_enabled` property.
Add the following nodes to the `Inputs` group:
- `Input Socket`
- `As Bool`
- `Set State`
---
!!! payload "Input Socket - Properties"
- **input_type**: `bool`
- **input_name**: `analysis_enabled`
`Shift` click the title to auto-title it to `IN analysis_enabled`.
---
!!! payload "As Bool - Properties"
- **default**: `true`
---
!!! payload "Set State - Properties"
- **name**: `analysis_enabled`
- **scope**: `local`
`Shift` click the title to auto-title it to `SET local.analysis_enabled`.
---
Connect the nodes as follows:
- `<IN analysis_enabled>.value` :material-transit-connection-horizontal: `<As Bool>.value`
- `<As Bool>.value` :material-transit-connection-horizontal: `<SET local.analysis_enabled>.value`
- `<SET local.analysis_enabled>.value` :material-transit-connection-horizontal: `<Stage>.state_c`
---
![Module Properties](./img/6-0021.png)
--8<-- "docs/snippets/common.md:save-graph"
## 6.6 - Propagating through Dynamic Premise
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-dynamic-premise"
Good news! Looks like the `Generate Premise` node is exposing the 3 new socket inputs we added to the `generate-premise` module.
![Generate Premise node](./img/6-0022.png)
!!! bug "If the `Generate Premise` node looks a bit glitchy"
If you notice that our `Generate Premise` node looks a bit glitchy, where its size is not correct, causing the new widgets to overflow, simply resize it to fix this.
But, we need those properties to be propagated one more level, so someone can simply add the `Dynamic Premise` module to their scene loop and then be able to edit everything from there.
Easy enough, just do the now familiar flow of adding three `Module Property` nodes, `Set State` nodes to the existing `Properties` group and connect them to the stage.
- `analysis_enabled`: `bool` - default `true`
- `topic`: `str` - default blank string
- `analysis_instructions`: `text` - default blank string
![Module Properties](./img/6-0023.png)
--8<-- "docs/snippets/common.md:save-graph"
Now add three `Get State` nodes to the `Generate Introduction` group and connect them to the `topic`, `analysis_instructions` and `analysis_enabled` inputs of the `Generate Premise` node.
![Generate Introduction](./img/6-0024.png)
--8<-- "docs/snippets/common.md:save-graph"
## 6.7 - Testing
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-scene-loop"
Confirm the `Dynamic Premise` node now is exposing:
- `reset` - a boolean toggle to reset the premise generation (useful for testing)
- `analysis_instructions` - a text input to control the analysis instructions
- `analysis_enabled` - a boolean toggle to control whether the analysis is enabled (default `true`)
- `topic` - a string input to control the topic of the theme
![Dynamic Premise node](./img/6-0025.png)
Fill in a `topic`.
> sci-fi with eldritch and cosmic horror elements
--8<-- "docs/snippets/common.md:save-graph"
**:material-movie-play:** Start the scene loop to test that everything's still working.
## 6.8 - Making it a Talemate Module
Currently there is no UX for making a module a Talemate module.
While we work on the tooling for this, here is how to do it manually.
In the `talemate` directory find the `scenes` directory, and there find the folder for this project.
So if you followed the example to the point, it should be `scenes/infinity-quest-dynamic`.
In there find the `nodes` directory.
It should have three files in it:
- `dynamic-premise.json`
- `generate-premise.json`
- `scene-loop.json`
Copy **both** the `dynamic-premise.json` and `generate-premise.json` files to the `templates/modules` directory. (relative to the talemate folder)
!!! note
If the `modules` directory does not exist, create it.
Restart talemate.
To test that this worked, create a new scene project.
Filter the **Modules** library for `premise` and both should be available. (albeit locked for editing)
![Modules library showing both modules](./img/6-0026.png)
Extend the scene loop so we can edit it. (Remember how we did this in [part 1](./1-scene-project.md))
Search for the `Dynamic Premise` node and add it to the scene loop.
![Search for Dynamic Premise](./img/6-0027.png)
![Added Dynamic Premise](./img/6-0028.png)
Looking good!
!!! tip "Keep editing through the original infinity-quest-dynamic scene"
Since the `Infinity Quest Dynamic` scene still has its own copies of these modules, you can come back to it and make changes.
The load order of modules assures that modules living with the scene take precedence over the ones in the `templates/modules` directory.
So a good workflow is to make and test changes in a dedicated scene project and whenever you are happy with it copy the new modules to the `templates/modules` directory.
This works as long as the module title and registry values are the same.

View File

@@ -0,0 +1,222 @@
# 7 - Polish
Some things I am doing as i am wrapping up this tutorial and the `Dynamic Story` module to ship with the next `0.30` release.
This part is going to be a bit more scattered as i am doing it on the fly as I finish the implementation.
I don't think you need to do all (or even any) of these, but it's going to be beneficial to review the process and understand the concepts.
1. Status indication
1. Comments
1. Error Handling
1. Generate story intention
1. Defaulting to the `scene_loop_init` event
## 7.1 - Status Indication
We want to show some status indication wile the `Dynamic Premise` node is working.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-generate-premise"
Looking at the stages we have Input processing at stage `-1` and then `Theme Generation` at stage `1`.
This makes stage `0` an ideal place to handle status indication.
Create a new group called `Init - Stage 0` and color it `yellow`.
Add the following nodes to the group:
- `Emit Status`
- `Stage`
---
**Emit Status**
- **message**: `Generating a new story line...`
- **status**: `busy`
- **as_scene_message**: `true`
---
**Stage**
- **stage**: `0`
---
Connect the nodes as follows:
- `<Emit Status>.emitted` :material-transit-connection-horizontal: `<Stage>.state`
I am also dragging the existing `Module Style` node into this group as well, just to make it more tidy.
![Init - Stage 0](./img/7-0001.png)
--8<-- "docs/snippets/common.md:save-graph"
**:material-movie-play:** Start the scene loop to test.
![Scene loop showing status indication](./img/7-0002.png)
## 7.2 - Comments
I am not going to go through all the comments i am adding, but i want to point out that you CAN in fact add comments to your modules.
`Right click` anywhere on the canvas and select **Comment**.
Then `double click` the comment to edit it.
![Comments](./img/7-0003.png)
## 7.3 - Error Handling
Right now if something goes wrong in the `Generate Premise` node, the status emission will stick around.
Lets fix that.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-generate-premise"
Add a new group called `Error Handling` and color it `red`.
Add the following nodes to the group:
- `Emit Status (Conditional)` x2 - Will be used to send a new status message
- `Argument` - Error handlers are function definitions, we need an argument to pass the exception to
- `Unpack Exception` - Unpacks the exception into a name and message
- `core/Case` - Used to select which message to emit based on the exception name
- `Coallesce` - Coallesce into single return value
- `Return` - Return value for the error handler function (needs to be True to indicate error was caught)
- `Define Function` - Defines the error handler function
- `Get Function` - Retrieves the error handler function
- `Error Handler`
---
**Argument**
- **name**: `exc`
`Shift` + click the node title to auto-title it to `exc`.
---
**Case**
- **case_a**: `GenerationCancelled`
---
**Emit Status (Conditional) - Generation Cancelled**
- **message**: `Generation cancelled`
- **status**: `warning`
- **as_scene_message**: `true`
---
**Emit Status (Conditional) - Generation Failed**
- **message**: `Something went wrong.`
- **status**: `error`
- **as_scene_message**: `true`
---
**Define Function**
- **name**: `error_handler`
`Shift` + click the node title to auto-title it to `DEF error_handler`.
---
**Get Function**
- **name**: `error_handler`
`Shift` + click the node title to auto-title it to `FN error_handler`.
---
Then connect the nodes as follows:
- `<exc>.value` :material-transit-connection-horizontal: `<Unpack Exception>.exc`
- `<Unpack Exception>.name` :material-transit-connection-horizontal: `<Case>.value`
- `<Case>.a` :material-transit-connection-horizontal: `<Emit Status (Conditional) - Generation Cancelled>.state`
- `<Case>.none` :material-transit-connection-horizontal: `<Emit Status (Conditional) - Generation Failed>.state`
- `<Emit Status (Conditional) - Generation Cancelled>.state` :material-transit-connection-horizontal: `<Coallesce>.a`
- `<Emit Status (Conditional) - Generation Failed>.state` :material-transit-connection-horizontal: `<Coallesce>.b`
- `<Coallesce>.value` :material-transit-connection-horizontal: `<Return>.value`
- `<Return>.value` :material-transit-connection-horizontal: `<DEF error_handler>.nodes`
---
- `<FN error_handler>.fn` :material-transit-connection-horizontal: `<Error Handler>.fn`
![Error Handling](./img/7-0004.png)
--8<-- "docs/snippets/common.md:save-graph"
!!! note "Learn more about functions and error handling"
Learn more about functions and error handling in the [Functions](/talemate/user-guide/node-editor/core-concepts/functions/) and [Error Handling](/talemate/user-guide/node-editor/core-concepts/error-handling/) sections of the documentation.
## 7.4 - Generate Story Intention
Story intention is a feature that was also added with `0.30`. Its main purpose at this point is to aid the new `auto-direction` feature.
However since it is included in most contex, we can also use it to ensure the initial theme selection and proposed story line isn't lost past the introductory text. There is only so much information the intro text can hold.
I am doing this as the 4th stage in the `Generate Premise` module.
It's revisiting already learned concepts, so i won't go through the entire process. Hopefully at this point you can look at the image below and understand what is going on.
I will note that i am adding another `Set State` node to `Stage 3` to store the template variables we generate there, just so i don't have to repeat the same nodes in `Stage 4`.
![New set state node in stage 3](./img/7-0005.png)
![Stage 4 to generate story intention](./img/7-0006.png)
## 7.5 - Defaulting to the `scene_loop_init` event
The user shouldn't have to manually set the `scene_loop_init` event for the `Dynamic Premise` module to work.
Good thing we can set a default.
--8<-- "docs/user-guide/howto/infinity-quest-dynamic/.snippets.md:load-dynamic-premise"
Find the `Properties` panel in the upper left corner of the node editor and expand it.
Enter `scene_loop_init` in the `Event to listen for` field.
![Set default event](./img/7-0007.png)
--8<-- "docs/snippets/common.md:save-graph"
I am also noting that there are 3 unlabled inputs in that panel from the `Module Property` nodes we have added.
To fix this, simply set the description of each of the `Module Property` nodes.
![Set descriptions](./img/7-0008.png)
--8<-- "docs/snippets/common.md:save-graph"
**Reload** the module.
![Properties panel inputs now properly labeled](./img/7-0009.png)
If we add a new `Dynamic Premise` node to a scene loop, we can see that the `event_name` property is now set to `scene_loop_init` by default.
![Scene loop showing default event](./img/7-0010.png)
## 7.6 - Final thoughts
### A missing stage and some reorganization
After testing the module for a bit, i am noting that story intention should be generated before the introduction.
There could also be a benefit of adding another stage after analysis that picks and expands on one of the story line suggestions put forth by the analysis.
I will likely do this, but since none of this introduces any new concepts it will not be part of the tutorial.
You can always open up the final `generate-storyline` module and see how it is put together in the end.

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Some files were not shown because too many files have changed in this diff Show More