Compare commits

..

12 Commits

Author SHA1 Message Date
vegu-ai-tools
d009dbe39d notes 2025-08-24 17:03:05 +03:00
vegu-ai-tools
211870c59b fix nodeeditor context menu issues 2025-08-24 17:00:52 +03:00
vegu-ai-tools
4f47f9d986 set 0.33.0 2025-08-23 19:40:46 +03:00
veguAI
eddddd5034 0.32.2 (#216)
* fix api url error in koboldcpp

* set 0.32.2

* relock

* add 0.32.2 note
2025-08-23 19:20:39 +03:00
veguAI
25e646c56a 0.32.1 (#213)
* GLM 4.5 templates

* set 0.33 and relock

* fix issues with character creation

* relock

* prompt tweaks

* fix lmstudio

* fix issue with npm on windows failing on paths
set 0.32.1

* linting

* update what's new

* #214 (#215)

* max-height and overflow

* max-height and overflow

* v-tabs to list and offset new scrollbar at the top so it doesnt overlap into the divider

* tweaks

* tweaks

* prompt tweaks

---------

Co-authored-by: Iceman Oakenbear <89090218+IcemanOakenbear@users.noreply.github.com>
2025-08-23 01:16:18 +03:00
veguAI
ce4c302d73 0.32.0 (#208)
* separate other tts apis and improve chunking

* move old tts config to voice agent config and implement config widget ux elements for table editing

* elevenlabs updated to use their client and expose model selection

* linting

* separate character class into character.pt and start on voice routing

* linting

* tts hot swapping and chunking improvements

* linting

* add support for piper-tts

* update gitignore

* linting

* support google tts
fix issue where quick_toggle agent config didnt work on standard config items

* linting

* only show agent quick toggles if the agent is enabled

* change elevenlabs to use a locally maintained voice list

* tts generate before / after events

* voice library refactor

* linting

* update openai model and voices

* tweak configs

* voice library ux

* linting

* add support for kokoro tts

* fix add / remove voice

* voice library tags

* linting

* linting

* tts api status

* api infos and add more kokoro voices

* allow voice testing before saving a new voice

* tweaks to voice library ux and some api info text

* linting

* voice mixer

* polish

* voice files go into /tts instead of templates/voice

* change default narrator voice

* xtts confirmation note

* character voice select

* koboldai format template

* polish

* skip empty chunks

* change default voice

* replace em-dash with normal dash

* adjust limit

* replace libebreaks

* chunk cleanup for whitespace

* info updated

* remove invalid endif tag

* sort voices by ready api

* Character hashable type

* clarify set_simulated_environment use to avoid unwanted character deactivated

* allow manual generation of tts and fix assorted issues with tts

* tts websocket handler router renamed

* voice mixer: when there are only 2 voices auto adjust the other weight as needed

* separate persist character functions into own mixin

* auto assign voices

* fix chara load and auto assign voice during chara load

* smart speaker separation

* tts speaker separation config

* generate tts for intro text

* fix prompting issues with anthropic, google and openrouter clients

* decensor flag off again

* only to ai assisted voice markup on narrator messages

* openrouter provider configuration

* linting

* improved sound controls

* add support for chatterbox

* fix info

* chatterbox dependencies

* remove piper and xtts2

* linting

* voice params

* linting

* tts model overrides and move tts info to tab

* reorg toolbar

* allow overriding of test text

* more tts fixes, apply intensity, chatterbox voices

* confirm voice delete

* lintinG

* groq updates

* reorg decorators

* tts fixes

* cancelable audio queue

* voice library uploads

* scene voice library

* Config refactor (#13)

* config refactor progres

* config nuke continues

* fix system prompts

* linting

* client fun

* client config refactor

* fix kcpp auto embedding selection

* linting

* fix proxy config

* remove cruft

* fix remaining client bugs from config refactor
always use get_config(), dont keep an instance reference

* support for reasoning models

* more reasoning tweaks

* only allow one frontend to connect at a time

* fix tests

* relock

* relock

* more client adjustments

* pattern prefill

* some tts agent fixes

* fix ai assist cond

* tts nodes

* fix config retrieval

* assign voice node and fixes

* sim suite char gen assign voice

* fix voice assign template to consider used voices

* get rid of auto break repetition which wasn't working right for a while anyhow

* linting

* generate tts node
as string node

* linting

* voice change on character event

* tweak chatterbox max length

* koboldai default template

* linting

* fix saving of existing voice

* relock

* adjust params of eva default voice

* f5tts support

* f5tts samples

* f5tts support

* f5tts tweaks

* chunk size per tts api and reorg defaul f5tts voices

* chatterbox default voice reog to match f5-tts default voices

* voice library ux polish pass

* cleanup

* f5-tts tweaks

* missing samples

* get rid of old save cmd

* add chatterbox and f5tts

* housekeeping

* fix some issues with world entry editing

* remove cruft

* replace exclamation marks

* fix save immutable check

* fix replace_exclamation_marks

* better error handling in websocket plugins and fix issue with saves

* agent config save on dialog close

* ctrl click to disable / enable agents

* fix quick config

* allow modifying response size of focal requests

* sim suite set goal always sets story intent, encourage calling of set goal during simulation start

* allow setting of model

* voice param tweaks

* tts tweaks

* fix character card load

* fix note_on_value

* add mixed speaker_separation mode

* indicate which message the audio is for and provide way to stop audio from the message

* fix issue with some tts generation failing

* linting

* fix speaker separate modes

* bad idea

* linting

* refactor speaker separation prompt

* add kimi think pattern

* fix issue with unwanted cover image replacemenT

* no scene analysis for visual promp generation (for now)

* linting

* tts for context investigation messages

* prompt tweaks

* tweak intro

* fix intro text tts not auto playing sometimes

* consider narrator voice when assigning voice tro a character

* allow director log messages to go only into the director console

* linting

* startup performance fixes

* init time

* linting

* only show audio control for messagews taht can have it

* always create story intent and dont override existing saves during character card load

* fix history check in dynamic story line node
add HasHistory node

* linting

* fix intro message not having speaker separation

* voice library character manager

* sequantial and cancelable auto assign all

* linting

* fix generation cancel handling

* tooltips

* fix auto assign voice from scene voices

* polish

* kokoro does not like lazy import

* update info text

* complete scene export / import

* linting

* wording

* remove cruft

* fix story intent generation during character card import

* fix generation cancelled emit status inf loop

* prompt tweak

* reasoning quick toggle, reasoning token slider, tooltips

* improved reasoning pattern handling

* fix indirect coercion response parsing

* fix streaming issue

* response length instructions

* more robust streaming

* adjust default

* adjust formatting

* litning

* remove debug output

* director console log function calls

* install cuda script updated

* linting

* add another step

* adjust default

* update dialogue examples

* fix voice selection issues

* what's happening here

* third time's the charm?

* Vite migration (#207)

* add vite config

* replace babel, webpack, vue-cli deps with vite, switch to esm modules, separate eslint config

* change process.env to import.meta.env

* update index.html for vite and move to root

* update docs for vite

* remove vue cli config

* update example env with vite

* bump frontend deps after rebase to 32.0

---------

Co-authored-by: pax-co <Pax_801@proton.me>

* properly referencer data type

* what's new

* better indication of dialogue example supporting multiple lines, improve dialogue example display

* fix potential issue with cached scene anlysis being reused when it shouldn't

* fix character creation issues with player character toggle

* fix issue where editing a message would sometimes lose parts of the message

* fix slider ux thumb labels (vuetify update)

* relock

* narrative conversation format

* remove planning step

* linting

* tweaks

* don't overthink

* update dialogue examples and intro

* dont dictate response length instructions when data structures are expected

* prompt tweaks

* prompt tweaks

* linting

* fix edit message not handling : well

* prompt tweaks

* fix tests

* fix manual revision when character message was generated in new narrative mode

* fix issue with message editing

* Docker packages relese (#204)

* add CI workflow for Docker image build and MkDocs deployment

* rename CI workflow from 'ci' to 'package'

* refactor CI workflow: consolidate container build and documentation deployment into a single file

* fix: correct indentation for permissions in CI workflow

* fix: correct indentation for steps in deploy-docs job in CI workflow

* build both cpu and cuda image

* docs

* docs

* expose writing style during state reinforcement

* prompt tweaks

* test container build

* test container  image

* update docker compose

* docs

* test-container-build

* test container build

* test container build

* update docker build workflows

* fix guidance prompt prefix not being dropped

* mount tts dir

* add gpt-5

* remove debug output

* docs

* openai auto toggle reasoning based on model selection

* linting

---------

Co-authored-by: pax-co <123330830+pax-co@users.noreply.github.com>
Co-authored-by: pax-co <Pax_801@proton.me>
Co-authored-by: Luis Alexandre Deschamps Brandão <brandao_luis@yahoo.com>
2025-08-08 13:56:29 +03:00
vegu-ai-tools
685ca994f9 linting can be done at merge 2025-07-06 20:32:40 +03:00
vegu-ai-tools
285b0699ab contributing.md 2025-07-06 18:41:44 +03:00
vegu-ai-tools
7825489cfc add contributing.md 2025-07-06 18:37:00 +03:00
veguAI
fb2fa31f13 linting
* precommit

* linting

* add linting to workflow

* ruff.toml added
2025-06-29 19:51:08 +03:00
veguAI
9eb4c48d79 0.31.0 (#193)
* some prompt cleanup

* prompt tweaks

* prompt tweaks

* prompt tweaks

* set 0.31.0

* relock

* rag queries add brief analysis

* brief analysis before building rag questions

* rag improvements

* prompt tweaks

* address circular import issues

* set 0.30.1

* docs

* numpy to 2

* docs

* prompt tweaks

* prompt tweak

* some template cleanup

* prompt viewer increase height

* fix codemirror highlighting not working

* adjust details height

* update default

* change to log debug

* allow response to scale to max height

* template cleanup

* prompt tweaks

* first progress for installing modules to scene

* package install logic

* package install polish

* package install polish

* package install polish and fixes

* refactor initial world state update and expose setting for it

* add `num` property to ModuleProperty to control order of widgets

* dynamic storyline package info

* fix issue where deactivating player character would cause inconsistencies in the creative tools menui

* cruft

* add openrouter support

* ollama support

* refactor how model choices are loaded, so that can be done per client instance as opposed to just per client type

* set num_ctx

* remove debug messages

* ollama tweaks

* toggle for whether or not default character gets added to blank talemate scenes

* narrator prompt tweaks and template cleanup

* cleanup

* prompt tweaks and template cleanup

* prompt tweaks

* fix instructor embeddings

* add additional error handling to prevent broken world state templates from breaking the world editor side menu

* fix openrouter breaking startup if not configured

* remove debug message

* promp tweaks

* fix example dialogue generation no longer working

* prompt tweaks and better showing of dialogue examples in conversation instructions

* prompt tweak

* add initial startup message

* prompt tweaks

* fix asset error

* move complex acting instructions into the task block

* fix content input socket on DynamicInstructions node

* log.error with traceback over log.exception since that has a tendency to explode and hang everything

* fix usse with number nodes where they would try to execute even if the incoming wire wasnt active

* fix issue with editor revision events missing template_vars

* DynamicInstruction node should only run if both header and content can resolve

* removed remaining references to 90s adventure game writing style

* prompt tweaks

* support embeddings via client apis (koboldcpp)

* fix label on client-api embeddings

* fix issue where adding / removing an embedding preset would not be reflected immediately in the memory agent config

* remove debug output

* prompt tweaks

* prompt tweaks

* autocomplete passes message object

* validate group names to be filename valid

* embedded winsows env installs and up to poetry2

* version config

* get-pip

* relock

* pin runpod

* no longer needed

* remove rapidfuzz dependency

* nodejs directly into embedded_node without a versioned middleman dir - also remove defunct local-tts install script

* fix update script

* update script error handling

* update.bat error handling

* adjust wording

* support loading jinja2 templates node modules in templates/modules

* update google model list

* client t/s and business indicator - also switch all clients to async streaming

* formatting

* support coercion for anthropic / google
switch to the new google genai sdk
upgrade websockets

* more coercion fixes

* gracefully handle keyboard interrupt

* EmitSystemMessage node

* allow visual prompt generation without image generation

* relock

* chromadb to v1

* fix error handling

* fix issue where adding client model list would be empty

* supress pip install warnings

* allow overriding of base urls

* remove key from log

* add fade effect

* tweak request info ux

* further clarification of endpoint override api key

* world state manager: fix issue that caused max changes setting to disappear from character progress config

* fix issue with google safety settings off causing generation failures

* update to base url should always reset the client

* getattr

* support v3 chara card version and attempt to future proof

* client based embeddings improvements

* more fixes for client based embeddings

* use client icon

* history management tools progress

* history memory ids fixed and added validation

* regenerate summary fixes

* more history regeneration fixes

* fix layered history gen and prompt twweaks

* allow regeneration of individual layered history entries

* return list of LayeredArchiveEntry

* reorg for less code dupelication

* new scene message renderer based on marked

* add inspect functionality to history viewer

* message if no history entries yet

* allow adding of history entries manually

* allow deletion of history

* summarization unslop improvements

* fix make charcter real action from worldstate listing

* allow overriding length in all context generation isntructioon dialogs

* fix issue where extract_list could fail with an unhandled error if the llm response didnt contain a list

* update whats'new

* fix issues with the new history management tools

* fix check

* Switch dependency handling to UV (#202)

* Migrate from Poetry to uv package manager            (#200)

* migrate from poetry to uv package manager

* Update all installation and startup scripts for uv migration

* Fix pyproject.toml for uv - allow direct references for hatchling

* Fix PR feedback: Restore removed functionality

- Restored embedded Python/Node.js functionality in install.bat and update.bat
- Restored environment variable exposure in docker-compose.yml (CUDA_AVAILABLE, port configs)
- Fixed GitHub Actions branches (main, prep-* instead of main, dev)
- Restored fail-fast: false and cache configuration in test.yml

These changes preserve all the functionality that should not be removed
during the migration from Poetry to uv.

---------

Co-authored-by: Ztripez von Matérn <ztripez@bobby.se>

* remove uv.lock from .gitignore

* add lock file

* fix install issues

* warn if unable to remove legacy poetry virt env dir

* uv needs to be explicitly installed into the .venv so its available

* third time's the charm?

* fix windows install scripts

* add .venv guard to update.bat

* call :die

* fix docker venv install

* node 21

* fix cuda install

* start.bat calls install if needed

* sync start-local to other startup scripts

* no need to activate venv

---------

Co-authored-by: Ztripez <reg@otherland.nu>
Co-authored-by: Ztripez von Matérn <ztripez@bobby.se>

* ignore hfhub symlink warnings

* add openrouter and ollama mentions

* update windows install documentation

* docs

* docs

* fix issue with memory agent fingerprint

* removing a client that supports embeddings will also remove any embedding functions it created

* on invalid embeddings reset to default

* docs

* typo

* formatting

* docs

* docs

* install package

* adjust topic

* add more obvious way to exit creative mode

* when importing character cards immediately persist a usable save after the restoration save

---------

Co-authored-by: Ztripez <reg@otherland.nu>
Co-authored-by: Ztripez von Matérn <ztripez@bobby.se>
2025-06-29 18:06:11 +03:00
veguAI
e4d465ba42 0.30.1 (#190)
* address circular import issues

* set 0.30.1

* docs

* numpy to 2

* docs
2025-06-10 21:05:46 +03:00
488 changed files with 68334 additions and 32185 deletions

View File

@@ -1,30 +1,57 @@
name: ci
name: ci
on:
push:
branches:
- master
- main
- prep-0.26.0
- master
release:
types: [published]
permissions:
contents: write
packages: write
jobs:
deploy:
container-build:
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Git Credentials
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
- uses: actions/setup-python@v5
- name: Log in to GHCR
uses: docker/login-action@v3
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
push: true
tags: |
ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ github.ref_name }}
deploy-docs:
if: github.event_name == 'release'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure Git credentials
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- uses: actions/setup-python@v5
with: { python-version: '3.x' }
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
restore-keys: |
mkdocs-material-
restore-keys: mkdocs-material-
- run: pip install mkdocs-material mkdocs-awesome-pages-plugin mkdocs-glightbox
- run: mkdocs gh-deploy --force

View File

@@ -0,0 +1,32 @@
name: test-container-build
on:
push:
branches: [ 'prep-*' ]
permissions:
contents: read
packages: write
jobs:
container-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build & push
uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile
push: true
# Tag with prep suffix to avoid conflicts with production
tags: |
ghcr.io/${{ github.repository }}:${{ github.ref_name }}

View File

@@ -2,9 +2,9 @@ name: Python Tests
on:
push:
branches: [ master, main, 'prep-*' ]
branches: [ main, 'prep-*' ]
pull_request:
branches: [ master, main, 'prep-*' ]
branches: [ main, 'prep-*' ]
jobs:
test:
@@ -23,25 +23,29 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install poetry
- name: Install uv
run: |
python -m pip install --upgrade pip
pip install poetry
pip install uv
- name: Cache poetry dependencies
- name: Cache uv dependencies
uses: actions/cache@v4
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ matrix.python-version }}-${{ hashFiles('**/poetry.lock') }}
path: ~/.cache/uv
key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-poetry-${{ matrix.python-version }}-
${{ runner.os }}-uv-${{ matrix.python-version }}-
- name: Install dependencies
run: |
python -m venv talemate_env
source talemate_env/bin/activate
poetry config virtualenvs.create false
poetry install
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
- name: Run linting
run: |
source .venv/bin/activate
uv run pre-commit run --all-files
- name: Setup configuration file
run: |
@@ -49,10 +53,10 @@ jobs:
- name: Download NLTK data
run: |
source talemate_env/bin/activate
source .venv/bin/activate
python -c "import nltk; nltk.download('punkt_tab')"
- name: Run tests
run: |
source talemate_env/bin/activate
source .venv/bin/activate
pytest tests/ -p no:warnings

15
.gitignore vendored
View File

@@ -8,8 +8,20 @@
talemate_env
chroma
config.yaml
.cursor
.claude
# uv
.venv/
templates/llm-prompt/user/*.jinja2
templates/world-state/*.yaml
tts/voice/piper/*.onnx
tts/voice/piper/*.json
tts/voice/kokoro/*.pt
tts/voice/xtts2/*.wav
tts/voice/chatterbox/*.wav
tts/voice/f5tts/*.wav
tts/voice/voice-library.json
scenes/
!scenes/infinity-quest-dynamic-scenario/
!scenes/infinity-quest-dynamic-scenario/assets/
@@ -18,4 +30,5 @@ scenes/
!scenes/infinity-quest/assets/
!scenes/infinity-quest/infinity-quest.json
tts_voice_samples/*.wav
third-party-docs/
third-party-docs/
legacy-state-reinforcements.yaml

16
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,16 @@
fail_fast: false
exclude: |
(?x)^(
tests/data/.*
|install-utils/.*
)$
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.12.1
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format

1
.python-version Normal file
View File

@@ -0,0 +1 @@
3.11

64
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,64 @@
# Contributing to Talemate
## About This Project
Talemate is a **personal hobbyist project** that I maintain in my spare time. While I appreciate the community's interest and contributions, please understand that:
- This is primarily a passion project that I enjoy working on myself
- I have limited time for code reviews and prefer to spend that time developing fixes or new features myself
- Large contributions require significant review and testing time that takes away from my own development
For these reasons, I've established contribution guidelines that balance community involvement with my desire to actively develop the project myself.
## Contribution Policy
**I welcome small bugfix and small feature pull requests!** If you've found a bug and have a fix, or have a small feature improvement, I'd love to review it.
However, please note that **I am not accepting large refactors or major feature additions** at this time. This includes:
- Major architectural changes
- Large new features or significant functionality additions
- Large-scale code reorganization
- Breaking API changes
- Features that would require significant maintenance
## What is accepted
**Small bugfixes** - Fixes for specific, isolated bugs
**Small features** - Minor improvements that don't break existing functionality
**Documentation fixes** - Typo corrections, clarifications in existing docs
**Minor dependency updates** - Security patches or minor version bumps
## What is not accepted
**Major features** - Large new functionality or systems
**Large refactors** - Code reorganization or architectural changes
**Breaking changes** - Any changes that break existing functionality
**Major dependency changes** - Framework upgrades or replacements
## Submitting a PR
If you'd like to submit a bugfix or small feature:
1. **Open an issue first** - Describe the bug you've found or feature you'd like to add
2. **Keep it small** - Focus on one specific issue or small improvement
3. **Follow existing code style** - Match the project's current patterns
4. **Don't break existing functionality** - Ensure all existing tests pass
5. **Include tests** - Add or update tests that verify your fix or feature
6. **Update documentation** - If your changes affect behavior, update relevant docs
## Testing
Ensure all tests pass by running:
```bash
uv run pytest tests/ -p no:warnings
```
## Questions?
If you're unsure whether your contribution would be welcome, please open an issue to discuss it first. This saves everyone time and ensures alignment with the project's direction.

View File

@@ -1,15 +1,19 @@
# Stage 1: Frontend build
FROM node:21 AS frontend-build
ENV NODE_ENV=development
FROM node:21-slim AS frontend-build
WORKDIR /app
# Copy the frontend directory contents into the container at /app
COPY ./talemate_frontend /app
# Copy frontend package files
COPY talemate_frontend/package*.json ./
# Install all dependencies and build
RUN npm install && npm run build
# Install dependencies
RUN npm ci
# Copy frontend source
COPY talemate_frontend/ ./
# Build frontend
RUN npm run build
# Stage 2: Backend build
FROM python:3.11-slim AS backend-build
@@ -22,31 +26,17 @@ RUN apt-get update && apt-get install -y \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Install poetry
RUN pip install poetry
# Install uv
RUN pip install uv
# Copy poetry files
COPY pyproject.toml poetry.lock* /app/
# Copy installation files
COPY pyproject.toml uv.lock /app/
# Create a virtual environment
RUN python -m venv /app/talemate_env
# Activate virtual environment and install dependencies
RUN . /app/talemate_env/bin/activate && \
poetry config virtualenvs.create false && \
poetry install --only main --no-root
# Copy the Python source code
# Copy the Python source code (needed for editable install)
COPY ./src /app/src
# Conditional PyTorch+CUDA install
ARG CUDA_AVAILABLE=false
RUN . /app/talemate_env/bin/activate && \
if [ "$CUDA_AVAILABLE" = "true" ]; then \
echo "Installing PyTorch with CUDA support..." && \
pip uninstall torch torchaudio -y && \
pip install torch~=2.4.1 torchaudio~=2.4.1 --index-url https://download.pytorch.org/whl/cu121; \
fi
# Create virtual environment and install dependencies (includes CUDA support via pyproject.toml)
RUN uv sync
# Stage 3: Final image
FROM python:3.11-slim
@@ -57,8 +47,11 @@ RUN apt-get update && apt-get install -y \
bash \
&& rm -rf /var/lib/apt/lists/*
# Install uv in the final stage
RUN pip install uv
# Copy virtual environment from backend-build stage
COPY --from=backend-build /app/talemate_env /app/talemate_env
COPY --from=backend-build /app/.venv /app/.venv
# Copy Python source code
COPY --from=backend-build /app/src /app/src
@@ -83,4 +76,4 @@ EXPOSE 5050
EXPOSE 8080
# Use bash as the shell, activate the virtual environment, and run backend server
CMD ["/bin/bash", "-c", "source /app/talemate_env/bin/activate && python src/talemate/server/run.py runserver --host 0.0.0.0 --port 5050 --frontend-host 0.0.0.0 --frontend-port 8080"]
CMD ["uv", "run", "src/talemate/server/run.py", "runserver", "--host", "0.0.0.0", "--port", "5050", "--frontend-host", "0.0.0.0", "--frontend-port", "8080"]

View File

@@ -39,12 +39,14 @@ Need help? Join the new [Discord community](https://discord.gg/8bGNRmFxMj)
- [Cohere](https://www.cohere.com/)
- [Groq](https://www.groq.com/)
- [Google Gemini](https://console.cloud.google.com/)
- [OpenRouter](https://openrouter.ai/)
Supported self-hosted APIs:
- [KoboldCpp](https://koboldai.org/cpp) ([Local](https://koboldai.org/cpp), [Runpod](https://koboldai.org/runpodcpp), [VastAI](https://koboldai.org/vastcpp), also includes image gen support)
- [oobabooga/text-generation-webui](https://github.com/oobabooga/text-generation-webui) (local or with runpod support)
- [LMStudio](https://lmstudio.ai/)
- [TabbyAPI](https://github.com/theroyallab/tabbyAPI/)
- [Ollama](https://ollama.com/)
Generic OpenAI api implementations (tested and confirmed working):
- [DeepInfra](https://deepinfra.com/)

20
docker-compose.manual.yml Normal file
View File

@@ -0,0 +1,20 @@
version: '3.8'
services:
talemate:
build:
context: .
dockerfile: Dockerfile
ports:
- "${FRONTEND_PORT:-8080}:8080"
- "${BACKEND_PORT:-5050}:5050"
volumes:
- ./config.yaml:/app/config.yaml
- ./scenes:/app/scenes
- ./templates:/app/templates
- ./chroma:/app/chroma
- ./tts:/app/tts
environment:
- PYTHONUNBUFFERED=1
- PYTHONPATH=/app/src:$PYTHONPATH
command: ["uv", "run", "src/talemate/server/run.py", "runserver", "--host", "0.0.0.0", "--port", "5050", "--frontend-host", "0.0.0.0", "--frontend-port", "8080"]

View File

@@ -2,11 +2,7 @@ version: '3.8'
services:
talemate:
build:
context: .
dockerfile: Dockerfile
args:
- CUDA_AVAILABLE=${CUDA_AVAILABLE:-false}
image: ghcr.io/vegu-ai/talemate:latest
ports:
- "${FRONTEND_PORT:-8080}:8080"
- "${BACKEND_PORT:-5050}:5050"
@@ -15,7 +11,8 @@ services:
- ./scenes:/app/scenes
- ./templates:/app/templates
- ./chroma:/app/chroma
- ./tts:/app/tts
environment:
- PYTHONUNBUFFERED=1
- PYTHONPATH=/app/src:$PYTHONPATH
command: ["/bin/bash", "-c", "source /app/talemate_env/bin/activate && python src/talemate/server/run.py runserver --host 0.0.0.0 --port 5050 --frontend-host 0.0.0.0 --frontend-port 8080"]
command: ["uv", "run", "src/talemate/server/run.py", "runserver", "--host", "0.0.0.0", "--port", "5050", "--frontend-host", "0.0.0.0", "--frontend-port", "8080"]

View File

@@ -1,60 +1,63 @@
import os
import re
import subprocess
from pathlib import Path
import argparse
def find_image_references(md_file):
"""Find all image references in a markdown file."""
with open(md_file, 'r', encoding='utf-8') as f:
with open(md_file, "r", encoding="utf-8") as f:
content = f.read()
pattern = r'!\[.*?\]\((.*?)\)'
pattern = r"!\[.*?\]\((.*?)\)"
matches = re.findall(pattern, content)
cleaned_paths = []
for match in matches:
path = match.lstrip('/')
if 'img/' in path:
path = path[path.index('img/') + 4:]
path = match.lstrip("/")
if "img/" in path:
path = path[path.index("img/") + 4 :]
# Only keep references to versioned images
parts = os.path.normpath(path).split(os.sep)
if len(parts) >= 2 and parts[0].replace('.', '').isdigit():
if len(parts) >= 2 and parts[0].replace(".", "").isdigit():
cleaned_paths.append(path)
return cleaned_paths
def scan_markdown_files(docs_dir):
"""Recursively scan all markdown files in the docs directory."""
md_files = []
for root, _, files in os.walk(docs_dir):
for file in files:
if file.endswith('.md'):
if file.endswith(".md"):
md_files.append(os.path.join(root, file))
return md_files
def find_all_images(img_dir):
"""Find all image files in version subdirectories."""
image_files = []
for root, _, files in os.walk(img_dir):
# Get the relative path from img_dir to current directory
rel_dir = os.path.relpath(root, img_dir)
# Skip if we're in the root img directory
if rel_dir == '.':
if rel_dir == ".":
continue
# Check if the immediate parent directory is a version number
parent_dir = rel_dir.split(os.sep)[0]
if not parent_dir.replace('.', '').isdigit():
if not parent_dir.replace(".", "").isdigit():
continue
for file in files:
if file.lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.svg')):
if file.lower().endswith((".png", ".jpg", ".jpeg", ".gif", ".svg")):
rel_path = os.path.relpath(os.path.join(root, file), img_dir)
image_files.append(rel_path)
return image_files
def grep_check_image(docs_dir, image_path):
"""
Check if versioned image is referenced anywhere using grep.
@@ -65,33 +68,46 @@ def grep_check_image(docs_dir, image_path):
parts = os.path.normpath(image_path).split(os.sep)
version = parts[0] # e.g., "0.29.0"
filename = parts[-1] # e.g., "world-state-suggestions-2.png"
# For versioned images, require both version and filename to match
version_pattern = f"{version}.*{filename}"
try:
result = subprocess.run(
['grep', '-r', '-l', version_pattern, docs_dir],
["grep", "-r", "-l", version_pattern, docs_dir],
capture_output=True,
text=True
text=True,
)
if result.stdout.strip():
print(f"Found reference to {image_path} with version pattern: {version_pattern}")
print(
f"Found reference to {image_path} with version pattern: {version_pattern}"
)
return True
except subprocess.CalledProcessError:
pass
except Exception as e:
print(f"Error during grep check for {image_path}: {e}")
return False
def main():
parser = argparse.ArgumentParser(description='Find and optionally delete unused versioned images in MkDocs project')
parser.add_argument('--docs-dir', type=str, required=True, help='Path to the docs directory')
parser.add_argument('--img-dir', type=str, required=True, help='Path to the images directory')
parser.add_argument('--delete', action='store_true', help='Delete unused images')
parser.add_argument('--verbose', action='store_true', help='Show all found references and files')
parser.add_argument('--skip-grep', action='store_true', help='Skip the additional grep validation')
parser = argparse.ArgumentParser(
description="Find and optionally delete unused versioned images in MkDocs project"
)
parser.add_argument(
"--docs-dir", type=str, required=True, help="Path to the docs directory"
)
parser.add_argument(
"--img-dir", type=str, required=True, help="Path to the images directory"
)
parser.add_argument("--delete", action="store_true", help="Delete unused images")
parser.add_argument(
"--verbose", action="store_true", help="Show all found references and files"
)
parser.add_argument(
"--skip-grep", action="store_true", help="Skip the additional grep validation"
)
args = parser.parse_args()
# Convert paths to absolute paths
@@ -118,7 +134,7 @@ def main():
print("\nAll versioned image references found in markdown:")
for img in sorted(used_images):
print(f"- {img}")
print("\nAll versioned images in directory:")
for img in sorted(all_images):
print(f"- {img}")
@@ -133,9 +149,11 @@ def main():
for img in unused_images:
if not grep_check_image(docs_dir, img):
actually_unused.add(img)
if len(actually_unused) != len(unused_images):
print(f"\nGrep validation found {len(unused_images) - len(actually_unused)} additional image references!")
print(
f"\nGrep validation found {len(unused_images) - len(actually_unused)} additional image references!"
)
unused_images = actually_unused
# Report findings
@@ -148,7 +166,7 @@ def main():
print("\nUnused versioned images:")
for img in sorted(unused_images):
print(f"- {img}")
if args.delete:
print("\nDeleting unused versioned images...")
for img in unused_images:
@@ -162,5 +180,6 @@ def main():
else:
print("\nNo unused versioned images found!")
if __name__ == "__main__":
main()
main()

View File

@@ -4,12 +4,12 @@ from talemate.events import GameLoopEvent
import talemate.emit.async_signals
from talemate.emit import emit
@register()
class TestAgent(Agent):
agent_type = "test"
verbose_name = "Test"
def __init__(self, client):
self.client = client
self.is_enabled = True
@@ -20,7 +20,7 @@ class TestAgent(Agent):
description="Test",
),
}
@property
def enabled(self):
return self.is_enabled
@@ -36,7 +36,7 @@ class TestAgent(Agent):
def connect(self, scene):
super().connect(scene)
talemate.emit.async_signals.get("game_loop").connect(self.on_game_loop)
async def on_game_loop(self, emission: GameLoopEvent):
"""
Called on the beginning of every game loop
@@ -45,4 +45,8 @@ class TestAgent(Agent):
if not self.enabled:
return
emit("status", status="info", message="Annoying you with a test message every game loop.")
emit(
"status",
status="info",
message="Annoying you with a test message every game loop.",
)

View File

@@ -19,14 +19,17 @@ from talemate.config import Client as BaseClientConfig
log = structlog.get_logger("talemate.client.runpod_vllm")
class Defaults(pydantic.BaseModel):
max_token_length: int = 4096
model: str = ""
runpod_id: str = ""
class ClientConfig(BaseClientConfig):
runpod_id: str = ""
@register()
class RunPodVLLMClient(ClientBase):
client_type = "runpod_vllm"
@@ -49,7 +52,6 @@ class RunPodVLLMClient(ClientBase):
)
}
def __init__(self, model=None, runpod_id=None, **kwargs):
self.model_name = model
self.runpod_id = runpod_id
@@ -59,12 +61,10 @@ class RunPodVLLMClient(ClientBase):
def experimental(self):
return False
def set_client(self, **kwargs):
log.debug("set_client", kwargs=kwargs, runpod_id=self.runpod_id)
self.runpod_id = kwargs.get("runpod_id", self.runpod_id)
def tune_prompt_parameters(self, parameters: dict, kind: str):
super().tune_prompt_parameters(parameters, kind)
@@ -88,32 +88,37 @@ class RunPodVLLMClient(ClientBase):
self.log.debug("generate", prompt=prompt[:128] + " ...", parameters=parameters)
try:
async with aiohttp.ClientSession() as session:
endpoint = runpod.AsyncioEndpoint(self.runpod_id, session)
run_request = await endpoint.run({
"input": {
"prompt": prompt,
run_request = await endpoint.run(
{
"input": {
"prompt": prompt,
}
# "parameters": parameters
}
#"parameters": parameters
})
while (await run_request.status()) not in ["COMPLETED", "FAILED", "CANCELLED"]:
)
while (await run_request.status()) not in [
"COMPLETED",
"FAILED",
"CANCELLED",
]:
status = await run_request.status()
log.debug("generate", status=status)
await asyncio.sleep(0.1)
status = await run_request.status()
log.debug("generate", status=status)
response = await run_request.output()
log.debug("generate", response=response)
return response["choices"][0]["tokens"][0]
except Exception as e:
self.log.error("generate error", e=e)
emit(

View File

@@ -9,6 +9,7 @@ class Defaults(pydantic.BaseModel):
api_url: str = "http://localhost:1234"
max_token_length: int = 4096
@register()
class TestClient(ClientBase):
client_type = "test"
@@ -22,14 +23,13 @@ class TestClient(ClientBase):
self.client = AsyncOpenAI(base_url=self.api_url + "/v1", api_key="sk-1111")
def tune_prompt_parameters(self, parameters: dict, kind: str):
"""
Talemate adds a bunch of parameters to the prompt, but not all of them are valid for all clients.
This method is called before the prompt is sent to the client, and it allows the client to remove
any parameters that it doesn't support.
"""
super().tune_prompt_parameters(parameters, kind)
keys = list(parameters.keys())
@@ -41,11 +41,10 @@ class TestClient(ClientBase):
del parameters[key]
async def get_model_name(self):
"""
This should return the name of the model that is being used.
"""
return "Mock test model"
async def generate(self, prompt: str, parameters: dict, kind: str):

View File

@@ -0,0 +1,166 @@
# Adding a new world-state template
I am writing this up as I add phrase detection functionality to the `Writing Style` template, so that in the future, hopefully when new template types need to be added this document can just given to the LLM of the month, to do it.
## Introduction
World state templates are reusable components that plug in various parts of talemate.
At this point there are following types:
- Character Attribute
- Character Detail
- Writing Style
- Spice (for randomization of content during generation)
- Scene Type
- State Reinforcement
Basically whenever we want to add something reusable and customizable by the user, a world state template is likely a good solution.
## Steps to creating a new template type
### 1. Add a pydantic schema (python)
In `src/talemate/world_state/templates` create a new `.py` file with reasonable name.
In this example I am extending the `Writing Style` template to include phrase detection functionality, which will be used by the `Editor` agent to detect certain phrases and then act upon them.
There already is a `content.py` file - so it makes sense to just add this new functionality to this file.
```python
class PhraseDetection(pydantic.BaseModel):
phrase: str
instructions: str
# can be "unwanted" for now, more added later
classification: Literal["unwanted"] = "unwanted"
@register("writing_style")
class WritingStyle(Template):
description: str | None = None
phrases: list[PhraseDetection] = pydantic.Field(default_factory=list)
def render(self, scene: "Scene", character_name: str):
return self.formatted("instructions", scene, character_name)
```
If I were to create a new file I'd still want to read one of the existing files first to understand imports and style.
### 2. Add a vue component to allow management (vue, js)
Next we need to add a new vue component that exposes a UX for us to manage this new template type.
For this I am creating `talemate_frontend/src/components/WorldStateManagerTemplateWritingStyle.vue`.
## Bare Minimum Understanding for New Template Components
When adding a new component for managing a template type, you need to understand:
### Component Structure
1. **Props**: The component always receives an `immutableTemplate` prop with the template data.
2. **Data Management**: Create a local copy of the template data for editing before saving back.
3. **Emits**: Use the `update` event to send modified template data back to the parent.
### Core Implementation Requirements
1. **Template Properties**: Always include fields for `name`, `description`, and `favorite` status.
2. **Data Binding**: Implement two-way binding with `v-model` for all editable fields.
3. **Dirty State Tracking**: Track when changes are made but not yet saved.
4. **Save Method**: Implement a `save()` method that emits the updated template.
### Component Lifecycle
1. **Initialization**: Use the `created` hook to initialize the local template copy.
2. **Watching for Changes**: Set up a watcher for the `immutableTemplate` to handle external updates.
### UI Patterns
1. **Forms**: Use Vuetify form components with consistent validation.
2. **Actions**: Provide clear user actions for editing and managing template items.
3. **Feedback**: Give visual feedback when changes are being made or saved.
The WorldStateManagerTemplate components follow a consistent pattern where they:
- Display and edit general template metadata (name, description, favorite status)
- Provide specialized UI for the template's unique properties
- Handle the create, read, update, delete (CRUD) operations for template items
- Maintain data integrity by properly handling template updates
You absolutely should read an existing component like `WorldStateManagerTemplateWritingStyle.vue` first to get a good understanding of the implementation.
## Integrating with WorldStateManagerTemplates
After creating your template component, you need to integrate it with the WorldStateManagerTemplates component:
### 1. Import the Component
Edit `talemate_frontend/src/components/WorldStateManagerTemplates.vue` and add an import for your new component:
```javascript
import WorldStateManagerTemplateWritingStyle from './WorldStateManagerTemplateWritingStyle.vue'
```
### 2. Register the Component
Add your component to the components section of the WorldStateManagerTemplates:
```javascript
components: {
// ... existing components
WorldStateManagerTemplateWritingStyle
}
```
### 3. Add Conditional Rendering
In the template section, add a new conditional block to render your component when the template type matches:
```html
<WorldStateManagerTemplateWritingStyle v-else-if="template.template_type === 'writing_style'"
:immutableTemplate="template"
@update="(template) => applyAndSaveTemplate(template)"
/>
```
### 4. Add Icon and Color
Add cases for your template type in the `iconForTemplate` and `colorForTemplate` methods:
```javascript
iconForTemplate(template) {
// ... existing conditions
else if (template.template_type == 'writing_style') {
return 'mdi-script-text';
}
return 'mdi-cube-scan';
},
colorForTemplate(template) {
// ... existing conditions
else if (template.template_type == 'writing_style') {
return 'highlight5';
}
return 'grey';
}
```
### 5. Add Help Message
Add a help message for your template type in the `helpMessages` object in the data section:
```javascript
helpMessages: {
// ... existing messages
writing_style: "Writing style templates are used to define a writing style that can be applied to the generated content. They can be used to add a specific flavor or tone. A template must explicitly support writing styles to be able to use a writing style template.",
}
```
### 6. Update Template Type Selection
Add your template type to the `templateTypes` array in the data section:
```javascript
templateTypes: [
// ... existing types
{ "title": "Writing style", "value": 'writing_style'},
]
```

View File

@@ -10,28 +10,27 @@ To run the server on a different host and port, you need to change the values pa
#### :material-linux: Linux
Copy `start.sh` to `start_custom.sh` and edit the `--host` and `--port` parameters in the `uvicorn` command.
Copy `start.sh` to `start_custom.sh` and edit the `--host` and `--port` parameters.
```bash
#!/bin/sh
. talemate_env/bin/activate
python src/talemate/server/run.py runserver --host 0.0.0.0 --port 1234
uv run src/talemate/server/run.py runserver --host 0.0.0.0 --port 1234
```
#### :material-microsoft-windows: Windows
Copy `start.bat` to `start_custom.bat` and edit the `--host` and `--port` parameters in the `uvicorn` command.
Copy `start.bat` to `start_custom.bat` and edit the `--host` and `--port` parameters.
```batch
start cmd /k "cd talemate_env\Scripts && activate && cd ../../ && python src\talemate\server\run.py runserver --host 0.0.0.0 --port 1234"
uv run src\talemate\server\run.py runserver --host 0.0.0.0 --port 1234
```
### Letting the frontend know about the new host and port
Copy `talemate_frontend/example.env.development.local` to `talemate_frontend/.env.production.local` and edit the `VUE_APP_TALEMATE_BACKEND_WEBSOCKET_URL`.
Copy `talemate_frontend/example.env.development.local` to `talemate_frontend/.env.production.local` and edit the `VITE_TALEMATE_BACKEND_WEBSOCKET_URL`.
```env
VUE_APP_TALEMATE_BACKEND_WEBSOCKET_URL=ws://localhost:1234
VITE_TALEMATE_BACKEND_WEBSOCKET_URL=ws://localhost:1234
```
Next rebuild the frontend.
@@ -71,8 +70,7 @@ Copy `start.sh` to `start_custom.sh` and edit the `--frontend-host` and `--front
```bash
#!/bin/sh
. talemate_env/bin/activate
python src/talemate/server/run.py runserver --host 0.0.0.0 --port 5055 \
uv run src/talemate/server/run.py runserver --host 0.0.0.0 --port 5055 \
--frontend-host localhost --frontend-port 8082
```
@@ -81,7 +79,7 @@ python src/talemate/server/run.py runserver --host 0.0.0.0 --port 5055 \
Copy `start.bat` to `start_custom.bat` and edit the `--frontend-host` and `--frontend-port` parameters.
```batch
start cmd /k "cd talemate_env\Scripts && activate && cd ../../ && python src\talemate\server\run.py runserver --host 0.0.0.0 --port 5055 --frontend-host localhost --frontend-port 8082"
uv run src\talemate\server\run.py runserver --host 0.0.0.0 --port 5055 --frontend-host localhost --frontend-port 8082
```
### Start the backend and frontend
@@ -98,5 +96,4 @@ Start the backend and frontend as usual.
```batch
start_custom.bat
```
```

View File

@@ -1,22 +1,15 @@
!!! example "Experimental"
Talemate through docker has not received a lot of testing from me, so please let me know if you encounter any issues.
You can do so by creating an issue on the [:material-github: GitHub repository](https://github.com/vegu-ai/talemate)
## Quick install instructions
1. `git clone https://github.com/vegu-ai/talemate.git`
1. `cd talemate`
1. copy config file
1. linux: `cp config.example.yaml config.yaml`
1. windows: `copy config.example.yaml config.yaml`
1. If your host has a CUDA compatible Nvidia GPU
1. Windows (via PowerShell): `$env:CUDA_AVAILABLE="true"; docker compose up`
1. Linux: `CUDA_AVAILABLE=true docker compose up`
1. If your host does **NOT** have a CUDA compatible Nvidia GPU
1. Windows: `docker compose up`
1. Linux: `docker compose up`
1. windows: `copy config.example.yaml config.yaml` (or just copy the file and rename it via the file explorer)
1. `docker compose up`
1. Navigate your browser to http://localhost:8080
!!! info "Pre-built Images"
The default setup uses pre-built images from GitHub Container Registry that include CUDA support by default. To manually build the container instead, use `docker compose -f docker-compose.manual.yml up --build`.
!!! note
When connecting local APIs running on the hostmachine (e.g. text-generation-webui), you need to use `host.docker.internal` as the hostname.

View File

@@ -1,4 +1,3 @@
## Quick install instructions
### Dependencies
@@ -7,6 +6,7 @@
1. node.js and npm - see instructions [here](https://nodejs.org/en/download/package-manager/)
1. python- see instructions [here](https://www.python.org/downloads/)
1. uv - see instructions [here](https://github.com/astral-sh/uv#installation)
### Installation
@@ -25,19 +25,15 @@ If everything went well, you can proceed to [connect a client](../../connect-a-c
1. Open a terminal.
2. Navigate to the project directory.
3. Create a virtual environment by running `python3 -m venv talemate_env`.
4. Activate the virtual environment by running `source talemate_env/bin/activate`.
3. uv will automatically create a virtual environment when you run `uv venv`.
### Installing Dependencies
1. With the virtual environment activated, install poetry by running `pip install poetry`.
2. Use poetry to install dependencies by running `poetry install`.
1. Use uv to install dependencies by running `uv pip install -e ".[dev]"`.
### Running the Backend
1. With the virtual environment activated and dependencies installed, you can start the backend server.
2. Navigate to the `src/talemate/server` directory.
3. Run the server with `python run.py runserver --host 0.0.0.0 --port 5050`.
1. You can start the backend server using `uv run src/talemate/server/run.py runserver --host 0.0.0.0 --port 5050`.
### Running the Frontend
@@ -45,4 +41,4 @@ If everything went well, you can proceed to [connect a client](../../connect-a-c
2. If you haven't already, install npm dependencies by running `npm install`.
3. Start the server with `npm run serve`.
Please note that you may need to set environment variables or modify the host and port as per your setup. You can refer to the `runserver.sh` and `frontend.sh` files for more details.
Please note that you may need to set environment variables or modify the host and port as per your setup. You can refer to the various start scripts for more details.

View File

@@ -2,12 +2,9 @@
## Windows
### Installation fails with "Microsoft Visual C++" error
If your installation errors with a notification to upgrade "Microsoft Visual C++" go to https://visualstudio.microsoft.com/visual-cpp-build-tools/ and click "Download Build Tools" and run it.
### Frontend fails with errors
- During installation make sure you select the C++ development package (upper left corner)
- Run `reinstall.bat` inside talemate directory
- ensure none of the directories leading to your talemate directory have special characters in them, this can cause issues with the frontend. so no `(1)` in the directory name.
## Docker

View File

@@ -1,52 +1,32 @@
## Quick install instructions
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. Once the talemate logo shows up, navigate your browser to http://localhost:8080
1. Download the latest Talemate release ZIP from the [Releases page](https://github.com/vegu-ai/talemate/releases) and extract it anywhere on your system (for example, `C:\Talemate`).
2. Double-click **`start.bat`**.
- On the very first run Talemate will automatically:
1. Download a portable build of Python 3 and Node.js (no global installs required).
2. Create and configure a Python virtual environment.
3. Install all back-end and front-end dependencies with the included *uv* and *npm*.
4. Build the web client.
3. When the console window prints **"Talemate is now running"** and the logo appears, open your browser at **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.
!!! note "First start can take a while"
The initial download and dependency installation may take several minutes, especially on slow internet connections. The console will keep you updated just wait until the Talemate logo shows up.
If everything went well, you can proceed to [connect a client](../../connect-a-client).
### Optional: CUDA support
## Additional Information
If you have an NVIDIA GPU and want CUDA acceleration for larger embedding models:
### How to Install Python
1. Close Talemate (if it is running).
2. Double-click **`install-cuda.bat`**. This script swaps the CPU-only Torch build for the CUDA 12.8 build.
3. Start Talemate again via **`start.bat`**.
--8<-- "docs/snippets/common.md:python-versions"
## Maintenance & advanced usage
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 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.
| Script | Purpose |
|--------|---------|
| **`start.bat`** | Primary entry point performs the initial install if needed and then starts Talemate. |
| **`install.bat`** | Runs the installer without launching the server. Useful for automated setups or debugging. |
| **`install-cuda.bat`** | Installs the CUDA-enabled Torch build (run after the regular install). |
| **`update.bat`** | Pulls the latest changes from GitHub, updates dependencies, rebuilds the web client. |
### How to Install npm
1. Download Node.js from the official site [https://nodejs.org/en/download/prebuilt-installer](https://nodejs.org/en/download/prebuilt-installer).
2. Run the installer (the .msi installer is recommended).
3. Follow the prompts in the installer (Accept the license agreement, click the NEXT button a bunch of times and accept the default installation settings).
### Usage of the Supplied bat Files
#### install.bat
This batch file is used to set up the project on your local machine. It creates a virtual environment, activates it, installs poetry, and uses poetry to install dependencies. It then navigates to the frontend directory and installs the necessary npm packages.
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.
To run this file, simply double click on it or open a command prompt in the same directory and type `start.bat`.
No system-wide Python or Node.js is required Talemate uses the embedded runtimes it downloads automatically.

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

BIN
docs/img/0.31.0/history.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View File

@@ -0,0 +1,25 @@
# KoboldCpp Embeddings
Talemate can leverage an embeddings model that is already loaded in your KoboldCpp instance.
## 1. Start KoboldCpp with an embeddings model
Launch KoboldCpp with the `--embeddingsmodel` flag so that it loads an embeddings-capable GGUF model alongside the main LLM:
```bash
koboldcpp_cu12.exe --model google_gemma-3-27b-it-Q6_K.gguf --embeddingsmodel bge-large-en-v1.5.Q8_0.gguf
```
## 2. Talemate will pick it up automatically
When Talemate starts, the **Memory** agent probes every connected client that advertises embedding support. If it detects that your KoboldCpp instance has an embeddings model loaded:
1. The Memory backend switches the current embedding to **Client API**.
2. The `client` field in the agent details shows the name of the KoboldCpp client.
3. A banner informs you that Talemate has switched to the new embedding. <!-- stub: screenshot -->
![Memory agent automatically switched to KoboldCpp embeddings](/talemate/img/0.31.0/koboldcpp-embeddings.png)
## 3. Reverting to a local embedding
Open the memory agent settings and pick a different embedding. See [Memory agent settings](/talemate/user-guide/agents/memory/settings).

View File

@@ -0,0 +1,58 @@
# Chatterbox
Local zero shot voice cloning from .wav files.
![Chatterbox API settings](/talemate/img/0.32.0/chatterbox-api-settings.png)
##### Device
Auto-detects best available option
##### Model
Default Chatterbox model optimized for speed
##### Chunk size
Split text into chunks of this size. Smaller values will increase responsiveness at the cost of lost context between chunks. (Stuff like appropriate inflection, etc.). 0 = no chunking
## Adding Chatterbox Voices
### Voice Requirements
Chatterbox voices require:
- Reference audio file (.wav format, 5-15 seconds optimal)
- Clear speech with minimal background noise
- Single speaker throughout the sample
### Creating a Voice
1. Open the Voice Library
2. Click **:material-plus: New**
3. Select "Chatterbox" as the provider
4. Configure the voice:
![Add Chatterbox voice](/talemate/img/0.32.0/add-chatterbox-voice.png)
**Label:** Descriptive name (e.g., "Marcus - Deep Male")
**Voice ID / Upload File** Upload a .wav file containing the voice sample. The uploaded reference audio will also be the voice ID.
**Speed:** Adjust playback speed (0.5 to 2.0, default 1.0)
**Tags:** Add descriptive tags for organization
**Extra voice parameters**
There exist some optional parameters that can be set here on a per voice level.
![Chatterbox extra voice parameters](/talemate/img/0.32.0/chatterbox-parameters.png)
##### Exaggeration Level
Exaggeration (Neutral = 0.5, extreme values can be unstable). Higher exaggeration tends to speed up speech; reducing cfg helps compensate with slower, more deliberate pacing.
##### CFG / Pace
If the reference speaker has a fast speaking style, lowering cfg to around 0.3 can improve pacing.

View File

@@ -1,7 +1,41 @@
# ElevenLabs
If you have not configured the ElevenLabs TTS API, the voice agent will show that the API key is missing.
Professional voice synthesis with voice cloning capabilities using ElevenLabs API.
![Elevenlaps api key missing](/talemate/img/0.26.0/voice-agent-missing-api-key.png)
![ElevenLabs API settings](/talemate/img/0.32.0/elevenlabs-api-settings.png)
See the [ElevenLabs API setup](/talemate/user-guide/apis/elevenlabs/) for instructions on how to set up the API key.
## API Setup
ElevenLabs requires an API key. See the [ElevenLabs API setup](/talemate/user-guide/apis/elevenlabs/) for instructions on obtaining and setting an API key.
## Configuration
**Model:** Select from available ElevenLabs models
!!! warning "Voice Limits"
Your ElevenLabs subscription allows you to maintain a set number of voices (10 for the cheapest plan). Any voice that you generate audio for is automatically added to your voices at [https://elevenlabs.io/app/voice-lab](https://elevenlabs.io/app/voice-lab). This also happens when you use the "Test" button. It is recommended to test voices via their voice library instead.
## Adding ElevenLabs Voices
### Getting Voice IDs
1. Go to [https://elevenlabs.io/app/voice-lab](https://elevenlabs.io/app/voice-lab) to view your voices
2. Find or create the voice you want to use
3. Click "More Actions" -> "Copy Voice ID" for the desired voice
![Copy Voice ID](/talemate/img/0.32.0/elevenlabs-copy-voice-id.png)
### Creating a Voice in Talemate
![Add ElevenLabs voice](/talemate/img/0.32.0/add-elevenlabs-voice.png)
1. Open the Voice Library
2. Click "Add Voice"
3. Select "ElevenLabs" as the provider
4. Configure the voice:
**Label:** Descriptive name for the voice
**Provider ID:** Paste the ElevenLabs voice ID you copied
**Tags:** Add descriptive tags for organization

View File

@@ -0,0 +1,78 @@
# F5-TTS
Local zero shot voice cloning from .wav files.
![F5-TTS configuration](/talemate/img/0.32.0/f5tts-api-settings.png)
##### Device
Auto-detects best available option (GPU preferred)
##### Model
- F5TTS_v1_Base (default, most recent model)
- F5TTS_Base
- E2TTS_Base
##### NFE Step
Number of steps to generate the voice. Higher values result in more detailed voices.
##### Chunk size
Split text into chunks of this size. Smaller values will increase responsiveness at the cost of lost context between chunks. (Stuff like appropriate inflection, etc.). 0 = no chunking
##### Replace exclamation marks
If checked, exclamation marks will be replaced with periods. This is recommended for `F5TTS_v1_Base` since it seems to over exaggerate exclamation marks.
## Adding F5-TTS Voices
### Voice Requirements
F5-TTS voices require:
- Reference audio file (.wav format, 10-30 seconds)
- Clear speech with minimal background noise
- Single speaker throughout the sample
- Reference text (optional but recommended)
### Creating a Voice
1. Open the Voice Library
2. Click "Add Voice"
3. Select "F5-TTS" as the provider
4. Configure the voice:
![Add F5-TTS voice](/talemate/img/0.32.0/add-f5tts-voice.png)
**Label:** Descriptive name (e.g., "Emma - Calm Female")
**Voice ID / Upload File** Upload a .wav file containing the **reference audio** voice sample. The uploaded reference audio will also be the voice ID.
- Use 6-10 second samples (longer doesn't improve quality)
- Ensure clear speech with minimal background noise
- Record at natural speaking pace
**Reference Text:** Enter the exact text spoken in the reference audio for improved quality
- Enter exactly what is spoken in the reference audio
- Include proper punctuation and capitalization
- Improves voice cloning accuracy significantly
**Speed:** Adjust playback speed (0.5 to 2.0, default 1.0)
**Tags:** Add descriptive tags (gender, age, style) for organization
**Extra voice parameters**
There exist some optional parameters that can be set here on a per voice level.
![F5-TTS extra voice parameters](/talemate/img/0.32.0/f5tts-parameters.png)
##### Speed
Allows you to adjust the speed of the voice.
##### CFG Strength
A higher CFG strength generally leads to more faithful reproduction of the input text, while a lower CFG strength can result in more varied or creative speech output, potentially at the cost of text-to-speech accuracy.

View File

@@ -0,0 +1,15 @@
# Google Gemini-TTS
Google Gemini-TTS provides access to Google's text-to-speech service.
## API Setup
Google Gemini-TTS requires a Google Cloud API key.
See the [Google Cloud API setup](/talemate/user-guide/apis/google/) for instructions on obtaining an API key.
## Configuration
![Google TTS settings](/talemate/img/0.32.0/google-tts-api-settings.png)
**Model:** Select from available Google TTS models

View File

@@ -1,6 +1,26 @@
# Overview
Talemate supports Text-to-Speech (TTS) functionality, allowing users to convert text into spoken audio. This document outlines the steps required to configure TTS for Talemate using different providers, including ElevenLabs and a local TTS API.
In 0.32.0 Talemate's TTS (Text-to-Speech) agent has been completely refactored to provide advanced voice capabilities including per-character voice assignment, speaker separation, and support for multiple local and remote APIs. The voice system now includes a comprehensive voice library for managing and organizing voices across all supported providers.
## Key Features
- **Per-character voice assignment** - Each character can have their own unique voice
- **Speaker separation** - Automatic detection and separation of dialogue from narration
- **Voice library management** - Centralized management of all voices across providers
- **Multiple API support** - Support for both local and remote TTS providers
- **Director integration** - Automatic voice assignment for new characters
## Supported APIs
### Local APIs
- **Kokoro** - Fastest generation with predefined voice models and mixing
- **F5-TTS** - Fast voice cloning with occasional mispronunciations
- **Chatterbox** - High-quality voice cloning (slower generation)
### Remote APIs
- **ElevenLabs** - Professional voice synthesis with voice cloning
- **Google Gemini-TTS** - Google's text-to-speech service
- **OpenAI** - OpenAI's TTS-1 and TTS-1-HD models
## Enable the Voice agent
@@ -12,28 +32,30 @@ If your voice agent is disabled - indicated by the grey dot next to the agent -
![Agent disabled](/talemate/img/0.26.0/agent-disabled.png) ![Agent enabled](/talemate/img/0.26.0/agent-enabled.png)
!!! note "Ctrl click to toggle agent"
You can use Ctrl click to toggle the agent on and off.
!!! abstract "Next: Connect to a TTS api"
Next you need to decide which service / api to use for audio generation and configure the voice agent accordingly.
## Voice Library Management
- [OpenAI](openai.md)
- [ElevenLabs](elevenlabs.md)
- [Local TTS](local_tts.md)
Voices are managed through the Voice Library, accessible from the main application bar. The Voice Library allows you to:
You can also find more information about the various settings [here](settings.md).
- Add and organize voices from all supported providers
- Assign voices to specific characters
- Create mixed voices (Kokoro)
- Manage both global and scene-specific voice libraries
## Select a voice
See the [Voice Library Guide](voice-library.md) for detailed instructions.
![Elevenlaps voice missing](/talemate/img/0.26.0/voice-agent-no-voice-selected.png)
## Character Voice Assignment
Click on the agent to open the agent settings.
![Character voice assignment](/talemate/img/0.32.0/character-voice-assignment.png)
Then click on the `Narrator Voice` dropdown and select a voice.
Characters can have individual voices assigned through the Voice Library. When a character has a voice assigned:
![Elevenlaps voice selected](/talemate/img/0.26.0/voice-agent-select-voice.png)
1. Their dialogue will use their specific voice
2. The narrator voice is used for exposition in their messages (with speaker separation enabled)
3. If their assigned voice's API is not available, it falls back to the narrator voice
The selection is saved automatically, click anywhere outside the agent window to close it.
The Voice agent status will show all assigned character voices and their current status.
The Voice agent should now show that the voice is selected and be ready to use.
![Elevenlabs ready](/talemate/img/0.26.0/elevenlabs-ready.png)
![Voice agent status with characters](/talemate/img/0.32.0/voice-agent-status-characters.png)

View File

@@ -0,0 +1,55 @@
# Kokoro
Kokoro provides predefined voice models and voice mixing capabilities for creating custom voices.
## Using Predefined Voices
Kokoro comes with built-in voice models that are ready to use immediately
Available predefined voices include various male and female voices with different characteristics.
## Creating Mixed Voices
Kokor allows you to mix voices together to create a new voice.
### Voice Mixing Interface
To create a mixed voice:
1. Open the Voice Library
2. Click ":material-plus: New"
3. Select "Kokoro" as the provider
4. Choose ":material-tune:Mixer" option
5. Configure the mixed voice:
![Voice mixing interface](/talemate/img/0.32.0/kokoro-mixer.png)
**Label:** Descriptive name for the mixed voice
**Base Voices:** Select 2-4 existing Kokoro voices to combine
**Weights:** Set the influence of each voice (0.1 to 1.0)
**Tags:** Descriptive tags for organization
### Weight Configuration
Each selected voice can have its weight adjusted:
- Higher weights make that voice more prominent in the mix
- Lower weights make that voice more subtle
- Total weights need to sum to 1.0
- Experiment with different combinations to achieve desired results
### Saving Mixed Voices
Once configured click "Add Voice", mixed voices are saved to your voice library and can be:
- Assigned to characters
- Used as narrator voices
just like any other voice.
Saving a mixed cvoice may take a moment to complete.

View File

@@ -1,53 +0,0 @@
# Local TTS
!!! warning
This has not been tested in a while and may not work as expected. It will likely be replaced with something different in the future. If this approach is currently broken its likely to remain so until it is replaced.
For running a local TTS API, Talemate requires specific dependencies to be installed.
### Windows Installation
Run `install-local-tts.bat` to install the necessary requirements.
### Linux Installation
Execute the following command:
```bash
pip install TTS
```
### Model and Device Configuration
1. Choose a TTS model from the [Coqui TTS model list](https://github.com/coqui-ai/TTS).
2. Decide whether to use `cuda` or `cpu` for the device setting.
3. The first time you run TTS through the local API, it will download the specified model. Please note that this may take some time, and the download progress will be visible in the Talemate backend output.
Example configuration snippet:
```yaml
tts:
device: cuda # or 'cpu'
model: tts_models/multilingual/multi-dataset/xtts_v2
```
### Voice Samples Configuration
Configure voice samples by setting the `value` field to the path of a .wav file voice sample. Official samples can be downloaded from [Coqui XTTS-v2 samples](https://huggingface.co/coqui/XTTS-v2/tree/main/samples).
Example configuration snippet:
```yaml
tts:
voices:
- label: English Male
value: path/to/english_male.wav
- label: English Female
value: path/to/english_female.wav
```
## Saving the Configuration
After configuring the `config.yaml` file, save your changes. Talemate will use the updated settings the next time it starts.
For more detailed information on configuring Talemate, refer to the `config.py` file in the Talemate source code and the `config.example.yaml` file for a barebone configuration example.

View File

@@ -8,16 +8,12 @@ See the [OpenAI API setup](/apis/openai.md) for instructions on how to set up th
## Settings
![Voice agent openai settings](/talemate/img/0.26.0/voice-agent-openai-settings.png)
![Voice agent openai settings](/talemate/img/0.32.0/openai-tts-api-settings.png)
##### Model
Which model to use for generation.
- GPT-4o Mini TTS
- TTS-1
- TTS-1 HD
!!! quote "OpenAI API documentation on quality"
For real-time applications, the standard tts-1 model provides the lowest latency but at a lower quality than the tts-1-hd model. Due to the way the audio is generated, tts-1 is likely to generate content that has more static in certain situations than tts-1-hd. In some cases, the audio may not have noticeable differences depending on your listening device and the individual person.
Generally i have found that HD is fast enough for talemate, so this is the default.
- TTS-1 HD

View File

@@ -1,36 +1,65 @@
# Settings
![Voice agent settings](/talemate/img/0.26.0/voice-agent-settings.png)
![Voice agent settings](/talemate/img/0.32.0/voice-agent-settings.png)
##### API
##### Enabled APIs
The TTS API to use for voice generation.
Select which TTS APIs to enable. You can enable multiple APIs simultaneously:
- OpenAI
- ElevenLabs
- Local TTS
- **Kokoro** - Fastest generation with predefined voice models and mixing
- **F5-TTS** - Fast voice cloning with occasional mispronunciations
- **Chatterbox** - High-quality voice cloning (slower generation)
- **ElevenLabs** - Professional voice synthesis with voice cloning
- **Google Gemini-TTS** - Google's text-to-speech service
- **OpenAI** - OpenAI's TTS-1 and TTS-1-HD models
!!! note "Multi-API Support"
You can enable multiple APIs and assign different voices from different providers to different characters. The system will automatically route voice generation to the appropriate API based on the voice assignment.
##### Narrator Voice
The voice to use for narration. Each API will come with its own set of voices.
The default voice used for narration and as a fallback for characters without assigned voices.
![Narrator voice](/talemate/img/0.26.0/voice-agent-select-voice.png)
The dropdown shows all available voices from all enabled APIs, with the format: "Voice Name (Provider)"
!!! note "Local TTS"
For local TTS, you will have to provide voice samples yourself. See [Local TTS Instructions](local_tts.md) for more information.
!!! info "Voice Management"
Voices are managed through the Voice Library, accessible from the main application bar. Adding, removing, or modifying voices should be done through the Voice Library interface.
##### Generate for player
##### Speaker Separation
Whether to generate voice for the player. If enabled, whenever the player speaks, the voice agent will generate audio for them.
Controls how dialogue is separated from exposition in messages:
##### Generate for NPCs
- **No separation** - Character messages use character voice entirely, narrator messages use narrator voice
- **Simple** - Basic separation of dialogue from exposition using punctuation analysis, with exposition being read by the narrator voice
- **Mixed** - Enables AI assisted separation for narrator messages and simple separation for character messages
- **AI assisted** - AI assisted separation for both narrator and character messages
Whether to generate voice for NPCs. If enabled, whenever a non player character speaks, the voice agent will generate audio for them.
!!! warning "AI Assisted Performance"
AI-assisted speaker separation sends additional prompts to your LLM, which may impact response time and API costs.
##### Generate for narration
##### Auto-generate for player
Whether to generate voice for narration. If enabled, whenever the narrator speaks, the voice agent will generate audio for them.
Generate voice automatically for player messages
##### Split generation
##### Auto-generate for AI characters
If enabled, the voice agent will generate audio in chunks, allowing for faster generation. This does however cause it lose context between chunks, and inflection may not be as good.
Generate voice automatically for NPC/AI character messages
##### Auto-generate for narration
Generate voice automatically for narrator messages
##### Auto-generate for context investigation
Generate voice automatically for context investigation messages
## Advanced Settings
Advanced settings are configured per-API and can be found in the respective API configuration sections:
- **Chunk size** - Maximum text length per generation request
- **Model selection** - Choose specific models for each API
- **Voice parameters** - Provider-specific voice settings
!!! tip "Performance Optimization"
Each API has different optimal chunk sizes and parameters. The system automatically handles chunking and queuing for optimal performance across all enabled APIs.

View File

@@ -0,0 +1,156 @@
# Voice Library
The Voice Library is the central hub for managing all voices across all TTS providers in Talemate. It provides a unified interface for organizing, creating, and assigning voices to characters.
## Accessing the Voice Library
The Voice Library can be accessed from the main application bar at the top of the Talemate interface.
![Voice Library access](/talemate/img/0.32.0/voice-library-access.png)
Click the voice icon to open the Voice Library dialog.
!!! note "Voice agent needs to be enabled"
The Voice agent needs to be enabled for the voice library to be available.
## Voice Library Interface
![Voice Library interface](/talemate/img/0.32.0/voice-library-interface.png)
The Voice Library interface consists of:
### Scope Tabs
- **Global** - Voices available across all scenes
- **Scene** - Voices specific to the current scene (only visible when a scene is loaded)
- **Characters** - Character voice assignments for the current scene (only visible when a scene is loaded)
### API Status
The toolbar shows the status of all TTS APIs:
- **Green** - API is enabled and ready
- **Orange** - API is enabled but not configured
- **Red** - API has configuration issues
- **Gray** - API is disabled
![API status](/talemate/img/0.32.0/voice-library-api-status.png)
## Managing Voices
### Global Voice Library
The global voice library contains voices that are available across all scenes. These include:
- Default voices provided by each TTS provider
- Custom voices you've added
#### Adding New Voices
To add a new voice:
1. Click the "+ New" button
2. Select the TTS provider
3. Configure the voice parameters:
- **Label** - Display name for the voice
- **Provider ID** - Provider-specific identifier
- **Tags** - Free-form descriptive tags you define (gender, age, style, etc.)
- **Parameters** - Provider-specific settings
Check the provider specific documentation for more information on how to configure the voice.
#### Voice Types by Provider
**F5-TTS & Chatterbox:**
- Upload .wav reference files for voice cloning
- Specify reference text for better quality
- Adjust speed and other parameters
**Kokoro:**
- Select from predefined voice models
- Create mixed voices by combining multiple models
- Adjust voice mixing weights
**ElevenLabs:**
- Select from available ElevenLabs voices
- Configure voice settings and stability
- Use custom cloned voices from your ElevenLabs account
**OpenAI:**
- Choose from available OpenAI voice models
- Configure model (GPT-4o Mini TTS, TTS-1, TTS-1-HD)
**Google Gemini-TTS:**
- Select from Google's voice models
- Configure language and gender settings
### Scene Voice Library
Scene-specific voices are only available within the current scene. This is useful for:
- Scene-specific characters
- Temporary voice experiments
- Custom voices for specific scenarios
Scene voices are saved with the scene and will be available when the scene is loaded.
## Character Voice Assignment
### Automatic Assignment
The Director agent can automatically assign voices to new characters based on:
- Character tags and attributes
- Voice tags matching character personality
- Available voices in the voice library
This feature can be enabled in the Director agent settings.
### Manual Assignment
![Character voice assignment](/talemate/img/0.32.0/character-voice-assignment.png)
To manually assign a voice to a character:
1. Go to the "Characters" tab in the Voice Library
2. Find the character in the list
3. Click the voice dropdown for that character
4. Select a voice from the available options
5. The assignment is saved automatically
### Character Voice Status
The character list shows:
- **Character name**
- **Currently assigned voice** (if any)
- **Voice status** - whether the voice's API is available
- **Quick assignment controls**
## Voice Tags and Organization
### Tagging System
Voices can be tagged with any descriptive attributes you choose. Tags are completely free-form and user-defined. Common examples include:
- **Gender**: male, female, neutral
- **Age**: young, mature, elderly
- **Style**: calm, energetic, dramatic, mysterious
- **Quality**: deep, high, raspy, smooth
- **Character types**: narrator, villain, hero, comic relief
- **Custom tags**: You can create any tags that help you organize your voices
### Filtering and Search
Use the search bar to filter voices by:
- Voice label/name
- Provider
- Tags
- Character assignments
This makes it easy to find the right voice for specific characters or situations.

View File

@@ -5,5 +5,6 @@ nav:
- Google Cloud: google.md
- Groq: groq.md
- Mistral.ai: mistral.md
- OpenRouter: openrouter.md
- OpenAI: openai.md
- ...

View File

@@ -0,0 +1,11 @@
# OpenRouter API Setup
Talemate can use any model accessible through OpenRouter.
You need an OpenRouter API key and must set it in the application config. You can create and manage keys in your OpenRouter dashboard at [https://openrouter.ai/keys](https://openrouter.ai/keys).
Once you have generated a key open the Talemate settings, switch to the `APPLICATION` tab and then select the `OPENROUTER API` category. Paste your key in the **API Key** field.
![OpenRouter API settings](/talemate/img/0.31.0/openrouter-settings.png)
Finally click **Save** to store the credentials.

View File

@@ -4,4 +4,5 @@ nav:
- Recommended Local Models: recommended-models.md
- Inference Presets: presets.md
- Client Types: types
- Endpoint Override: endpoint-override.md
- ...

View File

@@ -0,0 +1,24 @@
# Endpoint Override
Starting in version 0.31.0 it is now possible for some of the remote clients to override the endpoint used for the API.
THis is helpful wehn you want to point the client at a proxy gateway to serve the api instead (LiteLLM for example).
!!! warning "Only use trusted endpoints"
Only use endpoints that you trust and NEVER used your actual API key with them, unless you are hosting your endpoint proxy yourself.
If you need to provide an api key there is a separate field for that specifically in the endpoint override settings.
## How to use
Clients that support it will have a tab in their settings that allows you to override the endpoint.
![Endpoint Override](/talemate/img/0.31.0/client-endpoint-override.png)
##### Base URL
The base URL of the endpoint. For example, `http://localhost:4000` if you're running a local LiteLLM gateway,
##### API Key
The API key to use for the endpoint. This is only required if the endpoint requires an API key. This is **NOT** the API key you would use for the official API. For LiteLLM for example this could be the `general_settings.master_key` value.

View File

@@ -0,0 +1,82 @@
# Reasoning Model Support
Talemate supports reasoning models that can perform step-by-step thinking before generating their final response. This feature allows models to work through complex problems internally before providing an answer.
## Enabling Reasoning Support
To enable reasoning support for a client:
1. Open the **Clients** dialog from the main toolbar
2. Select the client you want to configure
3. Navigate to the **Reasoning** tab in the client configuration
![Client reasoning configuration](/talemate/img/0.32.0/client-reasoning-2.png)
4. Check the **Enable Reasoning** checkbox
## Configuring Reasoning Tokens
Once reasoning is enabled, you can configure the **Reasoning Tokens** setting using the slider:
![Reasoning tokens configuration](/talemate/img/0.32.0/client-reasoning.png)
### Recommended Token Amounts
**For local reasoning models:** Use a high token allocation (recommended: 4096 tokens) to give the model sufficient space for complex reasoning.
**For remote APIs:** Start with lower amounts (512-1024 tokens) and adjust based on your needs and token costs.
### Token Allocation Behavior
The behavior of the reasoning tokens setting depends on your API provider:
**For APIs that support direct reasoning token specification:**
- The specified tokens will be allocated specifically for reasoning
- The model will use these tokens for internal thinking before generating the response
**For APIs that do NOT support reasoning token specification:**
- The tokens are added as extra allowance to the response token limit for ALL requests
- This may lead to more verbose responses than usual since Talemate normally uses response token limits to control verbosity
!!! warning "Increased Verbosity"
For providers without direct reasoning token support, enabling reasoning may result in more verbose responses since the extra tokens are added to all requests.
## Response Pattern Configuration
When reasoning is enabled, you may need to configure a **Pattern to strip from the response** to remove the thinking process from the final output.
### Default Patterns
Talemate provides quick-access buttons for common reasoning patterns:
- **Default** - Uses the built-in pattern: `.*?</think>`
- **`.*?◁/think▷`** - For models using arrow-style thinking delimiters
- **`.*?</think>`** - For models using XML-style think tags
### Custom Patterns
You can also specify a custom regular expression pattern that matches your model's reasoning format. This pattern will be used to strip the thinking tokens from the response before displaying it to the user.
## Model Compatibility
Not all models support reasoning. This feature works best with:
- Models specifically trained for chain-of-thought reasoning
- Models that support structured thinking patterns
- APIs that provide reasoning token specification
## Important Notes
- **Coercion Disabled**: When reasoning is enabled, LLM coercion (pre-filling responses) is automatically disabled since reasoning models need to generate their complete thought process
- **Response Time**: Reasoning models may take longer to respond as they work through their thinking process
## Troubleshooting
### Pattern Not Working
If the reasoning pattern isn't properly stripping the thinking process:
1. Check your model's actual reasoning output format
2. Adjust the regular expression pattern to match your model's specific format
3. Test with the default pattern first to see if it works

View File

@@ -8,6 +8,8 @@ nav:
- Mistral.ai: mistral.md
- OpenAI: openai.md
- OpenAI Compatible: openai-compatible.md
- Ollama: ollama.md
- OpenRouter: openrouter.md
- TabbyAPI: tabbyapi.md
- Text-Generation-WebUI: text-generation-webui.md
- ...

View File

@@ -0,0 +1,59 @@
# Ollama Client
If you want to add an Ollama client, change the `Client Type` to `Ollama`.
![Client Ollama](/talemate/img/0.31.0/client-ollama.png)
Click `Save` to add the client.
### Ollama Server
The client should appear in the clients list. Talemate will ping the Ollama server to verify that it is running. If the server is not reachable you will see a warning.
![Client ollama offline](/talemate/img/0.31.0/client-ollama-offline.png)
Make sure that the Ollama server is running (by default at `http://localhost:11434`) and that the model you want to use has been pulled.
It may also show a yellow dot next to it, saying that there is no model loaded.
![Client ollama no model](/talemate/img/0.31.0/client-ollama-no-model.png)
Open the client settings by clicking the :material-cogs: icon, to select a model.
![Ollama settings](/talemate/img/0.31.0/client-ollama-select-model.png)
Click save and the client should have a green dot next to it, indicating that it is ready to go.
![Client ollama ready](/talemate/img/0.31.0/client-ollama-ready.png)
### Settings
##### Client Name
A unique name for the client that makes sense to you.
##### API URL
The base URL where the Ollama HTTP endpoint is running. Defaults to `http://localhost:11434`.
##### Model
Name of the Ollama model to use. Talemate will automatically fetch the list of models that are currently available in your local Ollama instance.
##### API handles prompt template
If enabled, Talemate will send the raw prompt and let Ollama apply its own built-in prompt template. If you are unsure leave this disabled Talemate's own prompt template generally produces better results.
##### Allow thinking
If enabled Talemate will allow models that support "thinking" (`assistant:thinking` messages) to deliberate before forming the final answer. At the moment Talemate has limited support for this feature when talemate is handling the prompt template. Its probably ok to turn it on if you let Ollama handle the prompt template.
!!! tip
You can quickly refresh the list of models by making sure the Ollama server is running and then hitting **Save** again in the client settings.
### Common issues
#### Generations are weird / bad
If letting talemate handle the prompt template, make sure the [correct prompt template is assigned](/talemate/user-guide/clients/prompt-templates/).

View File

@@ -35,4 +35,19 @@ A unique name for the client that makes sense to you.
Which model to use. Currently defaults to `gpt-4o`.
!!! note "Talemate lags behind OpenAI"
When OpenAI adds a new model, it currently requires a Talemate update to add it to the list of available models. We are working on making this more dynamic.
When OpenAI adds a new model, it currently requires a Talemate update to add it to the list of available models. We are working on making this more dynamic.
##### Reasoning models (o1, o3, gpt-5)
!!! important "Enable reasoning and allocate tokens"
The `o1`, `o3`, and `gpt-5` families are reasoning models. They always perform internal thinking before producing the final answer. To use them effectively in Talemate:
- Enable the **Reasoning** option in the client configuration.
- Set **Reasoning Tokens** to a sufficiently high value to make room for the model's thinking process.
A good starting range is 5121024 tokens. Increase if your tasks are complex. Without enabling reasoning and allocating tokens, these models may return minimal or empty visible content because the token budget is consumed by internal reasoning.
See the detailed guide: [Reasoning Model Support](/talemate/user-guide/clients/reasoning/).
!!! tip "Getting empty responses?"
If these models return empty or very short answers, it usually means the reasoning budget was exhausted. Increase **Reasoning Tokens** and try again.

View File

@@ -0,0 +1,48 @@
# OpenRouter Client
If you want to add an OpenRouter client, change the `Client Type` to `OpenRouter`.
![Client OpenRouter](/talemate/img/0.31.0/client-openrouter.png)
Click `Save` to add the client.
### OpenRouter API Key
The client should appear in the clients list. If you haven't set up OpenRouter before, you will see a warning that the API key is missing.
![Client openrouter no api key](/talemate/img/0.31.0/client-openrouter-no-api-key.png)
Click the `SET API KEY` button. This will open the API settings window where you can add your OpenRouter API key.
For additional instructions on obtaining and setting your OpenRouter API key, see [OpenRouter API instructions](/talemate/user-guide/apis/openrouter/).
![OpenRouter settings](/talemate/img/0.31.0/openrouter-settings.png)
Click `Save` and after a moment the client should have a red dot next to it, saying that there is no model loaded.
Click the :material-cogs: icon to open the client settings and select a model.
![OpenRouter select model](/talemate/img/0.31.0/client-openrouter-select-model.png).
Click save and the client should have a green dot next to it, indicating that it is ready to go.
### Ready to use
![Client OpenRouter Ready](/talemate/img/0.31.0/client-openrouter-ready.png)
### Settings
##### Client Name
A unique name for the client that makes sense to you.
##### Model
Choose any model available via your OpenRouter account. Talemate dynamically fetches the list of models associated with your API key so new models will show up automatically.
##### Max token length
Maximum context length (in tokens) that OpenRouter should consider. If you are not sure leave the default value.
!!! note "Available models are fetched automatically"
Talemate fetches the list of available OpenRouter models when you save the configuration (if a valid API key is present). If you add or remove models to your account later, simply click **Save** in the application settings again to refresh the list.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -2,17 +2,6 @@
This tutorial will show you how to use the `Dynamic Storyline` module (added in `0.30`) to randomize the scene introduction for ANY scene.
!!! note "A more streamlined approach is coming soon"
I am aware that some people may not want to touch the node editor at all, so a more streamlined approach is planned.
For now this will lay out the simplest way to set this up while still using the node editor.
!!! learn-more "For those interested..."
There is tutorial on how the `Dynamic Storyline` module was made (or at least the beginnings of it).
If you are interested in the process, you can find it [here](/talemate/user-guide/howto/infinity-quest-dynamic).
## Save a foundation scene copy
This should be a save of your scene that has had NO progress made to it yet. We are generating a new scene introduction after all.
@@ -21,59 +10,52 @@ The introduction is only generated once. So you should maintain a save-file of t
To ensure this foundation scene save isn't overwritten you can go to the scene settings in the world editor and turn on the Locked save file flag:
![Immutable save](./img/0008.png)
![Immutable save](./img/0001.png)
Save the scene.
## Switch to the node editor
## Install the module
In your scene tools find the :material-puzzle-edit: creative menu and click on the **Node Editor** option.
Click the `Mods` tab in the world editor.
![Mods Tab](./img/0002.png)
![Node Editor](./img/0001.png)
Find the `COPY AS EDITABLE MODULE FOR ..` button beneath the node editor.
Find the `Dynamic Storyline` module and click **Install**.
![Copy as editable module](./img/0002.png)
It will say installed (not configured)
Click it.
![Installed (not configured)](./img/0003.png)
In the next window, don't even read any of the stuff, just click **Continue**.
Click **Configure** and set topic to something like `Sci-fi adventure with lovecraftian horror`.
## Find a blank area
![Configure Module](./img/0004.png)
Use the mousewheel to zoom out a bit, then click the canvas and drag it to the side so you're looking at some blank space. Literally anywhere that's grey background is fine.
!!! note "Optional settings"
Double click the empty area to bring up the module searcand type in "Dynamic Story" into th
##### Max intro text length
How many tokens to generate for the intro text.
![Dynamic Story](./img/0003.png)
##### Additional instructions for topic analysis task
If topic analysis is enabled, this will be used to augment the topic analysis task with further instructions
Select the `Dynamic Storyline` node to add it to the scene.
##### Enable topic analysis
This will enable the topic analysis task
![Dynamic Story](./img/0004.png)
**Save** the module configuration.
Click the `topic` input and type in a general genre or thematic guide for the story.
Finally click "Reload Scene" in the left sidebar.
Some examples
![Reload Scene](./img/0007.png)
- `sci-fi with cosmic horror elements`
- `dungeons and dragons campaign ideas`
- `slice of life story ideas`
If everything is configured correctly, the storyline generation will begin immediately.
Whatever you enter will be used to generate a list of story ideas, of which one will be chosen at random to bootstrap a new story, taking the scene context that exists already into account.
![Dynamic Storyline Module Configured](./img/0005.png)
This will NOT create new characters or world context.
!!! note "Switch out of edit mode"
It simply bootstraps a story premise based on the random topic and what's already there.
Once the topic is set, save the changes by clicking the node editor's **Save** button in the upper right corner.
![Save](./img/0005.png)
Exit the node editor through the same menu as before.
![Exit node editor](./img/0006.png)
Once back in the scene, if everythign was done correctly you should see it working on setting the scene introduction.
![Scene introduction](./img/0007.png)
If nothing is happening after configuration and reloading the scene, make sure you are not in edit mode.
You can leave edit mode by clicking the "Exit Node Editor" button in the creative menu.
![Exit Node Editor](./img/0006.png)

View File

@@ -0,0 +1,105 @@
# Installable Packages
It is possible to "package" your node modules so they can be installed into a scene.
This allows for easier controlled set up and makes your node module more sharable as users no longer need to use the node editor to install it.
Installable packages show up in the Mods list once a scene is loaded.
![Mods List](../img/package-0003.png)
## 1. Create a package module
To create a package - click the **:material-plus: Create Module** button in the node editor and select **Package**.
![Create Package Module](../img/package-0001.png)
The package itself is a special kind of node module that will let Talemate know that your node module is installable and how to install it.
## 2. Open the module properties
With the package module open find the module properties in the upper left corner of the node editor.
![Module Properties](../img/package-0002.png)
Fill in the fields:
##### The name of the node module
This is what the module package will be called in the Mods list.
Example:
```
Dynamic Storyline
```
##### The author of the node module
Your name or handle. This is arbitrary and just lets people know who made the package.
##### The description of the node module
A short description of the package. This is displayed in the Mods list.
Example:
```
Generate a random story premise at the beginning of the scene.
```
##### Whether the node module is installable to the scene
A checkbox to indicate if the package is installable to the scene.
Right now this should always be checked, there are no other package types currently.
##### Whether the scene loop should be restarted when the package is installed
If checked, installing this package will restart the scene loop. This is mostly important for modules that require to hook into the scene loop init event.
## 3. Install instructions
Currently there are only two nodes relevant for the node module install process.
1. `Install Node Module` - this node is used to make sure the target node module is added to the scene loop when installing the package. You can have more than one of these nodes in your package.
1. `Promote Config` - this node is used to promote your node module's properties to configurable fields in the mods list. E.g., this dictates what the user can configure when installing the package.
### Install Node Module
![Install Node Module](../img/package-0004.png)
!!! payload "Install Node Module"
| Property | Value |
|----------|-------|
| node_registry | the registry path of the node module to install |
### Promote Config
![Promote Config](../img/package-0005.png)
!!! payload "Promote Config"
| Property | Value |
|----------|-------|
| node_registry | the registry path of the node module |
| property_name | the name of the property to promote (as it is set in the node module) |
| exposed_property_name | expose as this name in the mods list, this can be the same as the property name or a different name - this is important if youre installing multiple node modules with the same property name, so you can differentiate between them |
| required | whether the property is required to be set when installing the package |
| label | a user friendly label for the property |
### Make talemate aware of the package
For talemate to be aware of the package, you need to copy it to the public node module directory, which exists as `templates/modules/`.
Create a new sub directory:
```
./templates/modules/<your-package-name>/
```
Copy the package module and your node module files into the directory.
Restart talemate and the package should now show up in the Mods list.

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,14 +1,63 @@
# History
Will hold the archived history for the scene.
Will hold historical events for the scene.
This historical archive is extended everytime the [Summarizer Agent](/talemate/user-guide/agents/summarizer/) summarizes the scene.
There are three types of historical entries:
Summarization happens when a certain progress treshold is reached (tokens) or when a time passage event occurs.
- **Archived history (static)** - These are entries are manually defined and dated before the starting point of the scene. Things that happened in the past that are **IMPORTANT** for the understanding of the world. For anything that is not **VITAL**, use world entries instead.
- **Archived history (from summary)** - These are historical entries generated from the progress in the scene. Whenever a certain token (length) threshold is reached, the [Summarizer Agent](/talemate/user-guide/agents/summarizer/) will generate a summary of the progression and add it to the history.
- **Layered history (from summary)** - As summary archives are generated, they themselves will be summarized again and added to the history, leading to a natural compression of the history sent with the context while also keeping track of the most important events. (hopefully)
All archived history is a potential candidate to be included in the context sent to the AI based on relevancy. This is handled by the [Memory Agent](/talemate/user-guide/agents/memory/).
![History](/talemate/img/0.31.0/history.png)
You can use the **:material-refresh: Regenerate History** button to force a new summarization of the scene.
## Layers
!!! warning
If there has been lots of progress this will potentially take a long time to complete.
There is always the **BASE** layer, which is where the archived history (both static and from summary) is stored. For all intents and purposes, this is layer 0.
At the beginning of a scene, there won't be any additional layers, as any layer past layer 0 will come from summarization down the line.
Note that layered history is managed by the [Summarizer Agent](/talemate/user-guide/agents/summarizer/) and can be disabled in its settings.
### Managing entries
- **All entries** can be edited by double-clicking the text.
- **Static entries** can be deleted by clicking the **:material-close-box-outline: Delete** button.
- **Summarized entries** can be regenerated by clicking the **:material-refresh: Regenerate** button. This will cause the LLM to re-summarize the entry and update the text.
- **Summarized entries** can be inspected by clicking the **:material-magnify-expand: Inspect** button. This will expand the entry and show the source entries that were used to generate the summary.
### Adding static entries
Static entries can be added by clicking the **:material-plus: Add Entry** button.
!!! note "Static entries must be older than any summary entries"
Static entries must be older than any summary entries. This is to ensure that the history is always chronological.
Trying to add a static entry that is more recent than any summary entry will result in an error.
##### Entry Text
The text of the entry. Should be at most 1 - 2 paragraphs. Less is more. Anything that needs great detail should be a world entry instead.
##### Unit
Defines the duration unit of the entry. So minutes, hours, days, weeks, months or years.
##### Amount
Defines the duration unit amount of the entry.
So if you want to define something that happened 10 months ago (from the current moment in the scene), you would set the unit to months and the amount to 10.
![Add Static Entry](/talemate/img/0.31.0/history-add-entry.png)
## Regenerate everything
It is possible to regenerate the entire history by clicking the **:material-refresh: Regenerate All History** button in the left sidebar. Static entries will remain unchanged.
![Regenerate All History](/talemate/img/0.31.0/history-regenerate-all.png)
!!! warning "This can take a long time"
This will go through the entire scene progress and regenerate all summarized entries.
If you have a lot of progress, be ready to wait for a while.

View File

@@ -1,6 +1,6 @@
import os
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse, FileResponse
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from starlette.exceptions import HTTPException
@@ -14,6 +14,7 @@ app = FastAPI()
# Serve static files, but exclude the root path
app.mount("/", StaticFiles(directory=dist_dir, html=True), name="static")
@app.get("/", response_class=HTMLResponse)
async def serve_root():
index_path = os.path.join(dist_dir, "index.html")
@@ -24,5 +25,6 @@ async def serve_root():
else:
raise HTTPException(status_code=404, detail="index.html not found")
# This is the ASGI application
application = app
application = app

View File

@@ -1,8 +1,23 @@
REM activate the virtual environment
call talemate_env\Scripts\activate
@echo off
REM uninstall torch and torchaudio
python -m pip uninstall torch torchaudio -y
REM Check if .venv exists
IF NOT EXIST ".venv" (
echo [ERROR] .venv directory not found. Please run install.bat first.
goto :eof
)
REM install torch and torchaudio
python -m pip install torch~=2.7.0 torchaudio~=2.7.0 --index-url https://download.pytorch.org/whl/cu128
REM Check if embedded Python exists
IF NOT EXIST "embedded_python\python.exe" (
echo [ERROR] embedded_python not found. Please run install.bat first.
goto :eof
)
REM uninstall torch and torchaudio using embedded Python's uv
embedded_python\python.exe -m uv pip uninstall torch torchaudio --python .venv\Scripts\python.exe
REM install torch and torchaudio with CUDA support using embedded Python's uv
embedded_python\python.exe -m uv pip install torch~=2.7.0 torchaudio~=2.7.0 --index-url https://download.pytorch.org/whl/cu128 --python .venv\Scripts\python.exe
echo.
echo CUDA versions of torch and torchaudio installed!
echo You may need to restart your application for changes to take effect.

View File

@@ -1,10 +1,7 @@
#!/bin/bash
# activate the virtual environment
source talemate_env/bin/activate
# uninstall torch and torchaudio
python -m pip uninstall torch torchaudio -y
uv pip uninstall torch torchaudio
# install torch and torchaudio
python -m pip install torch~=2.7.0 torchaudio~=2.7.0 --index-url https://download.pytorch.org/whl/cu128
# install torch and torchaudio with CUDA support
uv pip install torch~=2.7.1 torchaudio~=2.7.1 --index-url https://download.pytorch.org/whl/cu128

View File

@@ -1,4 +0,0 @@
REM activate the virtual environment
call talemate_env\Scripts\activate
call pip install "TTS>=0.21.1"

28579
install-utils/get-pip.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,65 +1,227 @@
@echo off
REM Check for Python version and use a supported version if available
SET PYTHON=python
python -c "import sys; sys.exit(0 if sys.version_info[:2] in [(3, 10), (3, 11), (3, 12), (3, 13)] else 1)" 2>nul
IF NOT ERRORLEVEL 1 (
echo Selected Python version: %PYTHON%
GOTO EndVersionCheck
)
REM ===============================
REM Talemate project installer
REM ===============================
REM 1. Detect CPU architecture and pick the best-fitting embedded Python build.
REM 2. Download & extract that build into .\embedded_python\
REM 3. Bootstrap pip via install-utils\get-pip.py
REM 4. Install virtualenv and create .\talemate_env\ using the embedded Python.
REM 5. Activate the venv and proceed with Poetry + frontend installation.
REM ---------------------------------------------------------------
SET PYTHON=python
FOR /F "tokens=*" %%i IN ('py --list') DO (
echo %%i | findstr /C:"-V:3.11 " >nul && SET PYTHON=py -3.11 && GOTO EndPythonCheck
echo %%i | findstr /C:"-V:3.10 " >nul && SET PYTHON=py -3.10 && GOTO EndPythonCheck
)
:EndPythonCheck
%PYTHON% -c "import sys; sys.exit(0 if sys.version_info[:2] in [(3, 10), (3, 11), (3, 12), (3, 13)] else 1)" 2>nul
IF ERRORLEVEL 1 (
echo Unsupported Python version. Please install Python 3.10 or 3.11.
exit /b 1
)
IF "%PYTHON%"=="python" (
echo Default Python version is being used: %PYTHON%
) ELSE (
echo Selected Python version: %PYTHON%
)
SETLOCAL ENABLEDELAYEDEXPANSION
:EndVersionCheck
REM Define fatal-error handler
REM Usage: CALL :die "Message explaining what failed"
goto :after_die
IF ERRORLEVEL 1 (
echo Unsupported Python version. Please install Python 3.10 or 3.11.
exit /b 1
)
REM create a virtual environment
%PYTHON% -m venv talemate_env
REM activate the virtual environment
call talemate_env\Scripts\activate
REM upgrade pip and setuptools
python -m pip install --upgrade pip setuptools
REM install poetry
python -m pip install "poetry==1.7.1" "rapidfuzz>=3" -U
REM use poetry to install dependencies
python -m poetry install
REM copy config.example.yaml to config.yaml only if config.yaml doesn't exist
IF NOT EXIST config.yaml copy config.example.yaml config.yaml
REM navigate to the frontend directory
echo Installing frontend dependencies...
cd talemate_frontend
call npm install
echo Building frontend...
call npm run build
REM return to the root directory
cd ..
echo Installation completed successfully.
:die
echo.
echo ============================================================
echo !!! INSTALL FAILED !!!
echo %*
echo ============================================================
pause
exit 1
:after_die
REM ---------[ Check Prerequisites ]---------
ECHO Checking prerequisites...
where tar >nul 2>&1 || CALL :die "tar command not found. Please ensure Windows 10 version 1803+ or install tar manually."
where curl >nul 2>&1
IF %ERRORLEVEL% NEQ 0 (
where bitsadmin >nul 2>&1 || CALL :die "Neither curl nor bitsadmin found. Cannot download files."
)
REM ---------[ Remove legacy Poetry venv if present ]---------
IF EXIST "talemate_env" (
ECHO Detected legacy Poetry virtual environment 'talemate_env'. Removing...
RD /S /Q "talemate_env"
IF ERRORLEVEL 1 (
ECHO [WARNING] Failed to fully remove legacy 'talemate_env' directory. Continuing installation.
)
)
REM ---------[ Clean reinstall check ]---------
SET "NEED_CLEAN=0"
IF EXIST ".venv" SET "NEED_CLEAN=1"
IF EXIST "embedded_python" SET "NEED_CLEAN=1"
IF EXIST "embedded_node" SET "NEED_CLEAN=1"
IF "%NEED_CLEAN%"=="1" (
ECHO.
ECHO Detected existing Talemate environments.
REM Prompt user (empty input defaults to Y)
SET "ANSWER=Y"
SET /P "ANSWER=Perform a clean reinstall of the python and node.js environments? [Y/n] "
IF /I "!ANSWER!"=="N" (
ECHO Installation aborted by user.
GOTO :EOF
)
ECHO Removing previous installation...
IF EXIST ".venv" RD /S /Q ".venv"
IF EXIST "embedded_python" RD /S /Q "embedded_python"
IF EXIST "embedded_node" RD /S /Q "embedded_node"
ECHO Cleanup complete.
)
REM ---------[ Version configuration ]---------
SET "PYTHON_VERSION=3.11.9"
SET "NODE_VERSION=22.16.0"
REM ---------[ Detect architecture & choose download URL ]---------
REM Prefer PROCESSOR_ARCHITEW6432 when the script is run from a 32-bit shell on 64-bit Windows
IF DEFINED PROCESSOR_ARCHITEW6432 (
SET "ARCH=%PROCESSOR_ARCHITEW6432%"
) ELSE (
SET "ARCH=%PROCESSOR_ARCHITECTURE%"
)
REM Map architecture to download URL
IF /I "%ARCH%"=="AMD64" (
SET "PY_URL=https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-amd64.zip"
SET "NODE_URL=https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-win-x64.zip"
) ELSE IF /I "%ARCH%"=="IA64" (
REM Itanium systems are rare, but AMD64 build works with WoW64 layer
SET "PY_URL=https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-amd64.zip"
SET "NODE_URL=https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-win-x64.zip"
) ELSE IF /I "%ARCH%"=="ARM64" (
SET "PY_URL=https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-arm64.zip"
SET "NODE_URL=https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-win-arm64.zip"
) ELSE (
REM Fallback to 64-bit build for x86 / unknown architectures
SET "PY_URL=https://www.python.org/ftp/python/%PYTHON_VERSION%/python-%PYTHON_VERSION%-embed-amd64.zip"
SET "NODE_URL=https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-win-x86.zip"
)
ECHO Detected architecture: %ARCH%
ECHO Downloading embedded Python from: %PY_URL%
REM ---------[ Download ]---------
SET "PY_ZIP=python_embed.zip"
where curl >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
ECHO Using curl to download Python...
curl -L -# -o "%PY_ZIP%" "%PY_URL%" || CALL :die "Failed to download Python embed package with curl."
) ELSE (
ECHO curl not found, falling back to bitsadmin...
bitsadmin /transfer "DownloadPython" /download /priority normal "%PY_URL%" "%CD%\%PY_ZIP%" || CALL :die "Failed to download Python embed package (curl & bitsadmin unavailable)."
)
REM ---------[ Extract ]---------
SET "PY_DIR=embedded_python"
IF EXIST "%PY_DIR%" RD /S /Q "%PY_DIR%"
mkdir "%PY_DIR%" || CALL :die "Could not create directory %PY_DIR%."
where tar >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
ECHO Extracting with tar...
tar -xf "%PY_ZIP%" -C "%PY_DIR%" || CALL :die "Failed to extract Python embed package with tar."
) ELSE (
CALL :die "tar utility not found (required to unpack zip without PowerShell)."
)
DEL /F /Q "%PY_ZIP%"
SET "PYTHON=%PY_DIR%\python.exe"
ECHO Using embedded Python at %PYTHON%
REM ---------[ Enable site-packages in embedded Python ]---------
FOR %%f IN ("%PY_DIR%\python*._pth") DO (
ECHO Adding 'import site' to %%~nxf ...
echo import site>>"%%~ff"
)
REM ---------[ Ensure pip ]---------
ECHO Installing pip...
"%PYTHON%" install-utils\get-pip.py || (
CALL :die "pip installation failed."
)
REM Upgrade pip to latest
"%PYTHON%" -m pip install --no-warn-script-location --upgrade pip || CALL :die "Failed to upgrade pip in embedded Python."
REM ---------[ Install uv ]---------
ECHO Installing uv...
"%PYTHON%" -m pip install uv || (
CALL :die "uv installation failed."
)
REM ---------[ Create virtual environment with uv ]---------
ECHO Creating virtual environment with uv...
"%PYTHON%" -m uv venv || (
CALL :die "Virtual environment creation failed."
)
REM ---------[ Install dependencies using embedded Python's uv ]---------
ECHO Installing backend dependencies with uv...
"%PYTHON%" -m uv sync || CALL :die "Failed to install backend dependencies with uv."
REM Activate the venv for the remainder of the script
CALL .venv\Scripts\activate
REM echo python version
python --version
REM ---------[ Config file ]---------
IF NOT EXIST config.yaml COPY config.example.yaml config.yaml
REM ---------[ Node.js portable runtime ]---------
ECHO.
ECHO Downloading portable Node.js runtime...
REM Node download variables already set earlier based on %ARCH%.
ECHO Downloading Node.js from: %NODE_URL%
SET "NODE_ZIP=node_embed.zip"
where curl >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
ECHO Using curl to download Node.js...
curl -L -# -o "%NODE_ZIP%" "%NODE_URL%" || CALL :die "Failed to download Node.js package with curl."
) ELSE (
ECHO curl not found, falling back to bitsadmin...
bitsadmin /transfer "DownloadNode" /download /priority normal "%NODE_URL%" "%CD%\%NODE_ZIP%" || CALL :die "Failed to download Node.js package (curl & bitsadmin unavailable)."
)
REM ---------[ Extract Node.js ]---------
SET "NODE_DIR=embedded_node"
IF EXIST "%NODE_DIR%" RD /S /Q "%NODE_DIR%"
mkdir "%NODE_DIR%" || CALL :die "Could not create directory %NODE_DIR%."
where tar >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
ECHO Extracting Node.js...
tar -xf "%NODE_ZIP%" -C "%NODE_DIR%" --strip-components 1 || CALL :die "Failed to extract Node.js package with tar."
) ELSE (
CALL :die "tar utility not found (required to unpack zip without PowerShell)."
)
DEL /F /Q "%NODE_ZIP%"
REM Prepend Node.js folder to PATH so npm & node are available
SET "PATH=%CD%\%NODE_DIR%;%PATH%"
ECHO Using portable Node.js at %CD%\%NODE_DIR%\node.exe
ECHO Node.js version:
node -v
REM ---------[ Frontend ]---------
ECHO Installing frontend dependencies...
CD talemate_frontend
CALL npm install || CALL :die "npm install failed."
ECHO Building frontend...
CALL npm run build || CALL :die "Frontend build failed."
REM Return to repo root
CD ..
ECHO.
ECHO ==============================
ECHO Installation completed!
ECHO ==============================
PAUSE
ENDLOCAL

View File

@@ -1,20 +1,16 @@
#!/bin/bash
# create a virtual environment
echo "Creating a virtual environment..."
python3 -m venv talemate_env
# create a virtual environment with uv
echo "Creating a virtual environment with uv..."
uv venv
# activate the virtual environment
echo "Activating the virtual environment..."
source talemate_env/bin/activate
source .venv/bin/activate
# install poetry
echo "Installing poetry..."
pip install poetry
# use poetry to install dependencies
# install dependencies with uv
echo "Installing dependencies..."
poetry install
uv pip install -e ".[dev]"
# copy config.example.yaml to config.yaml only if config.yaml doesn't exist
if [ ! -f config.yaml ]; then

6496
poetry.lock generated

File diff suppressed because it is too large Load Diff

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