Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce4c302d73 | ||
|
|
685ca994f9 | ||
|
|
285b0699ab | ||
|
|
7825489cfc | ||
|
|
fb2fa31f13 | ||
|
|
9eb4c48d79 | ||
|
|
e4d465ba42 | ||
|
|
61d01984ba | ||
|
|
113553c306 | ||
|
|
736e6702f5 | ||
|
|
80256012ad | ||
|
|
bb1cf6941b | ||
|
|
2c8b4b8186 |
53
.github/workflows/ci.yml
vendored
@@ -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
|
||||
32
.github/workflows/test-container-build.yml
vendored
Normal 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 }}
|
||||
62
.github/workflows/test.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Python Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, 'prep-*' ]
|
||||
pull_request:
|
||||
branches: [ main, 'prep-*' ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ['3.10', '3.11', '3.12', '3.13']
|
||||
fail-fast: false
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
cache: 'pip'
|
||||
|
||||
- name: Install uv
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install uv
|
||||
|
||||
- name: Cache uv dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/uv
|
||||
key: ${{ runner.os }}-uv-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-uv-${{ matrix.python-version }}-
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
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: |
|
||||
cp config.example.yaml config.yaml
|
||||
|
||||
- name: Download NLTK data
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
python -c "import nltk; nltk.download('punkt_tab')"
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
pytest tests/ -p no:warnings
|
||||
16
.gitignore
vendored
@@ -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/
|
||||
@@ -17,4 +29,6 @@ scenes/
|
||||
!scenes/infinity-quest-dynamic-scenario/infinity-quest.json
|
||||
!scenes/infinity-quest/assets/
|
||||
!scenes/infinity-quest/infinity-quest.json
|
||||
tts_voice_samples/*.wav
|
||||
tts_voice_samples/*.wav
|
||||
third-party-docs/
|
||||
legacy-state-reinforcements.yaml
|
||||
16
.pre-commit-config.yaml
Normal 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
@@ -0,0 +1 @@
|
||||
3.11
|
||||
64
CONTRIBUTING.md
Normal 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.
|
||||
79
Dockerfile
Normal file
@@ -0,0 +1,79 @@
|
||||
# Stage 1: Frontend build
|
||||
FROM node:21-slim AS frontend-build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copy frontend package files
|
||||
COPY talemate_frontend/package*.json ./
|
||||
|
||||
# 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
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Install system dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
bash \
|
||||
gcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install uv
|
||||
RUN pip install uv
|
||||
|
||||
# Copy installation files
|
||||
COPY pyproject.toml uv.lock /app/
|
||||
|
||||
# Copy the Python source code (needed for editable install)
|
||||
COPY ./src /app/src
|
||||
|
||||
# Create virtual environment and install dependencies (includes CUDA support via pyproject.toml)
|
||||
RUN uv sync
|
||||
|
||||
# Stage 3: Final image
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
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/.venv /app/.venv
|
||||
|
||||
# Copy Python source code
|
||||
COPY --from=backend-build /app/src /app/src
|
||||
|
||||
# Copy Node.js build artifacts from frontend-build stage
|
||||
COPY --from=frontend-build /app/dist /app/talemate_frontend/dist
|
||||
|
||||
# Copy the frontend WSGI file if it exists
|
||||
COPY frontend_wsgi.py /app/frontend_wsgi.py
|
||||
|
||||
# Copy base config
|
||||
COPY config.example.yaml /app/config.yaml
|
||||
|
||||
# Copy essentials
|
||||
COPY scenes templates chroma* /app/
|
||||
|
||||
# Set PYTHONPATH to include the src directory
|
||||
ENV PYTHONPATH=/app/src:$PYTHONPATH
|
||||
|
||||
# Make ports available to the world outside this container
|
||||
EXPOSE 5050
|
||||
EXPOSE 8080
|
||||
|
||||
# Use bash as the shell, activate the virtual environment, and run backend server
|
||||
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"]
|
||||
@@ -1,25 +0,0 @@
|
||||
# Use an official Python runtime as a parent image
|
||||
FROM python:3.11-slim
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the current directory contents into the container at /app
|
||||
COPY ./src /app/src
|
||||
|
||||
# Copy poetry files
|
||||
COPY pyproject.toml /app/
|
||||
# If there's a poetry lock file, include the following line
|
||||
COPY poetry.lock /app/
|
||||
|
||||
# Install poetry
|
||||
RUN pip install poetry
|
||||
|
||||
# Install dependencies
|
||||
RUN poetry install --no-dev
|
||||
|
||||
# Make port 5050 available to the world outside this container
|
||||
EXPOSE 5050
|
||||
|
||||
# Run backend server
|
||||
CMD ["poetry", "run", "python", "src/talemate/server/run.py", "runserver", "--host", "0.0.0.0", "--port", "5050"]
|
||||
@@ -1,23 +0,0 @@
|
||||
# Use an official node runtime as a parent image
|
||||
FROM node:20
|
||||
|
||||
# Make sure we are in a development environment (this isn't a production ready Dockerfile)
|
||||
ENV NODE_ENV=development
|
||||
|
||||
# Echo that this isn't a production ready Dockerfile
|
||||
RUN echo "This Dockerfile is not production ready. It is intended for development purposes only."
|
||||
|
||||
# Set the working directory in the container
|
||||
WORKDIR /app
|
||||
|
||||
# Copy the frontend directory contents into the container at /app
|
||||
COPY ./talemate_frontend /app
|
||||
|
||||
# Install all dependencies
|
||||
RUN npm install
|
||||
|
||||
# Make port 8080 available to the world outside this container
|
||||
EXPOSE 8080
|
||||
|
||||
# Run frontend server
|
||||
CMD ["npm", "run", "serve"]
|
||||
55
README.md
@@ -2,29 +2,13 @@
|
||||
|
||||
Roleplay with AI with a focus on strong narration and consistent world and game state tracking.
|
||||
|
||||
|||
|
||||
<div align="center">
|
||||
|
||||
|<img src="docs/img/ss-1.png" width="400" height="250" alt="Screenshot 1">|<img src="docs/img/ss-2.png" width="400" height="250" alt="Screenshot 2">|
|
||||
|------------------------------------------|------------------------------------------|
|
||||
|||
|
||||
|||
|
||||
|<img src="docs/img/ss-3.png" width="400" height="250" alt="Screenshot 3">|<img src="docs/img/ss-4.png" width="400" height="250" alt="Screenshot 4">|
|
||||
|
||||
Supported APIs:
|
||||
- [OpenAI](https://platform.openai.com/overview)
|
||||
- [Anthropic](https://www.anthropic.com/)
|
||||
- [mistral.ai](https://mistral.ai/)
|
||||
- [Cohere](https://www.cohere.com/)
|
||||
- [Groq](https://www.groq.com/)
|
||||
- [Google Gemini](https://console.cloud.google.com/)
|
||||
|
||||
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/)
|
||||
|
||||
Generic OpenAI api implementations (tested and confirmed working):
|
||||
- [DeepInfra](https://deepinfra.com/)
|
||||
- [llamacpp](https://github.com/ggerganov/llama.cpp) with the `api_like_OAI.py` wrapper
|
||||
- let me know if you have tested any other implementations and they failed / worked or landed somewhere in between
|
||||
</div>
|
||||
|
||||
## Core Features
|
||||
|
||||
@@ -33,6 +17,7 @@ Generic OpenAI api implementations (tested and confirmed working):
|
||||
- Long-term memory and passage of time tracking
|
||||
- Narrative world state management to reinforce character and world truths
|
||||
- Creative tools for managing NPCs, AI-assisted character, and scenario creation with template support
|
||||
- Node editor for creating complex scenarios and re-usable modules
|
||||
- Context management for character details, world information, past events, and pinned information
|
||||
- Customizable templates for all prompts using Jinja2
|
||||
- Modern, responsive UI
|
||||
@@ -40,4 +25,30 @@ Generic OpenAI api implementations (tested and confirmed working):
|
||||
## Documentation
|
||||
|
||||
- [Installation and Getting started](https://vegu-ai.github.io/talemate/)
|
||||
- [User Guide](https://vegu-ai.github.io/talemate/user-guide/interacting/)
|
||||
- [User Guide](https://vegu-ai.github.io/talemate/user-guide/interacting/)
|
||||
|
||||
## Discord Community
|
||||
|
||||
Need help? Join the new [Discord community](https://discord.gg/8bGNRmFxMj)
|
||||
|
||||
## Supported APIs
|
||||
|
||||
- [OpenAI](https://platform.openai.com/overview)
|
||||
- [Anthropic](https://www.anthropic.com/)
|
||||
- [mistral.ai](https://mistral.ai/)
|
||||
- [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/)
|
||||
- [llamacpp](https://github.com/ggerganov/llama.cpp) with the `api_like_OAI.py` wrapper
|
||||
- let me know if you have tested any other implementations and they failed / worked or landed somewhere in between
|
||||
|
||||
20
docker-compose.manual.yml
Normal 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"]
|
||||
@@ -1,27 +1,18 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
talemate-backend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.backend
|
||||
talemate:
|
||||
image: ghcr.io/vegu-ai/talemate:latest
|
||||
ports:
|
||||
- "5050:5050"
|
||||
- "${FRONTEND_PORT:-8080}:8080"
|
||||
- "${BACKEND_PORT:-5050}:5050"
|
||||
volumes:
|
||||
# can uncomment for dev purposes
|
||||
#- ./src/talemate:/app/src/talemate
|
||||
- ./config.yaml:/app/config.yaml
|
||||
- ./scenes:/app/scenes
|
||||
- ./templates:/app/templates
|
||||
- ./chroma:/app/chroma
|
||||
- ./tts:/app/tts
|
||||
environment:
|
||||
- PYTHONUNBUFFERED=1
|
||||
|
||||
talemate-frontend:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.frontend
|
||||
ports:
|
||||
- "8080:8080"
|
||||
#volumes:
|
||||
# - ./talemate_frontend:/app
|
||||
- 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"]
|
||||
185
docs/cleanup.py
Normal file
@@ -0,0 +1,185 @@
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
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:
|
||||
content = f.read()
|
||||
|
||||
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 :]
|
||||
# Only keep references to versioned images
|
||||
parts = os.path.normpath(path).split(os.sep)
|
||||
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"):
|
||||
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 == ".":
|
||||
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():
|
||||
continue
|
||||
|
||||
for file in files:
|
||||
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.
|
||||
Returns True if any reference is found, False otherwise.
|
||||
"""
|
||||
try:
|
||||
# Split the image path to get version and filename
|
||||
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],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if result.stdout.strip():
|
||||
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"
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Convert paths to absolute paths
|
||||
docs_dir = os.path.abspath(args.docs_dir)
|
||||
img_dir = os.path.abspath(args.img_dir)
|
||||
|
||||
print(f"Scanning markdown files in: {docs_dir}")
|
||||
print(f"Looking for versioned images in: {img_dir}")
|
||||
|
||||
# Get all markdown files
|
||||
md_files = scan_markdown_files(docs_dir)
|
||||
print(f"Found {len(md_files)} markdown files")
|
||||
|
||||
# Collect all image references
|
||||
used_images = set()
|
||||
for md_file in md_files:
|
||||
refs = find_image_references(md_file)
|
||||
used_images.update(refs)
|
||||
|
||||
# Get all actual images (only from version directories)
|
||||
all_images = set(find_all_images(img_dir))
|
||||
|
||||
if args.verbose:
|
||||
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}")
|
||||
|
||||
# Find potentially unused images
|
||||
unused_images = all_images - used_images
|
||||
|
||||
# Additional grep validation if not skipped
|
||||
if not args.skip_grep and unused_images:
|
||||
print("\nPerforming additional grep validation...")
|
||||
actually_unused = set()
|
||||
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!"
|
||||
)
|
||||
unused_images = actually_unused
|
||||
|
||||
# Report findings
|
||||
print("\nResults:")
|
||||
print(f"Total versioned images found: {len(all_images)}")
|
||||
print(f"Versioned images referenced in markdown: {len(used_images)}")
|
||||
print(f"Unused versioned images: {len(unused_images)}")
|
||||
|
||||
if unused_images:
|
||||
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:
|
||||
full_path = os.path.join(img_dir, img)
|
||||
try:
|
||||
os.remove(full_path)
|
||||
print(f"Deleted: {img}")
|
||||
except Exception as e:
|
||||
print(f"Error deleting {img}: {e}")
|
||||
print("\nDeletion complete")
|
||||
else:
|
||||
print("\nNo unused versioned images found!")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -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.",
|
||||
)
|
||||
|
||||
@@ -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(
|
||||
@@ -126,5 +131,4 @@ class RunPodVLLMClient(ClientBase):
|
||||
self.model_name = kwargs["model"]
|
||||
if "runpod_id" in kwargs:
|
||||
self.api_auth = kwargs["runpod_id"]
|
||||
log.warning("reconfigure", kwargs=kwargs)
|
||||
self.set_client(**kwargs)
|
||||
|
||||
@@ -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):
|
||||
|
||||
166
docs/dev/howto/add-a-worldstate-template-type.md
Normal 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'},
|
||||
]
|
||||
```
|
||||
@@ -1,3 +1,3 @@
|
||||
# Coning soon
|
||||
# Coming soon
|
||||
|
||||
Developer documentation is coming soon. Stay tuned!
|
||||
14
docs/dev/third-party-reference.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## Third Party API docs
|
||||
|
||||
### Chat completions
|
||||
|
||||
- [Anthropic](https://docs.anthropic.com/en/api/messages)
|
||||
- [Cohere](https://docs.cohere.com/reference/chat)
|
||||
- [Google AI](https://ai.google.dev/api/generate-content#v1beta.GenerationConfig)
|
||||
- [Groq](https://console.groq.com/docs/api-reference#chat-create)
|
||||
- [KoboldCpp](https://lite.koboldai.net/koboldcpp_api#/api/v1)
|
||||
- [LMStudio](https://lmstudio.ai/docs/api/rest-api)
|
||||
- [Mistral AI](https://docs.mistral.ai/api/)
|
||||
- [OpenAI](https://platform.openai.com/docs/api-reference/completions)
|
||||
- [TabbyAPI](https://theroyallab.github.io/tabbyAPI/#operation/chat_completion_request_v1_chat_completions_post)
|
||||
- [Text-Generation-WebUI](https://github.com/oobabooga/text-generation-webui/blob/main/extensions/openai/typing.py)
|
||||
3
docs/getting-started/advanced/.pages
Normal file
@@ -0,0 +1,3 @@
|
||||
nav:
|
||||
- change-host-and-port.md
|
||||
- ...
|
||||
99
docs/getting-started/advanced/change-host-and-port.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Changing host and port
|
||||
|
||||
## Backend
|
||||
|
||||
By default, the backend listens on `localhost:5050`.
|
||||
|
||||
To run the server on a different host and port, you need to change the values passed to the `--host` and `--port` parameters during startup and also make sure the frontend knows the new values.
|
||||
|
||||
### Changing the host and port for the backend
|
||||
|
||||
#### :material-linux: Linux
|
||||
|
||||
Copy `start.sh` to `start_custom.sh` and edit the `--host` and `--port` parameters.
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
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.
|
||||
|
||||
```batch
|
||||
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 `VITE_TALEMATE_BACKEND_WEBSOCKET_URL`.
|
||||
|
||||
```env
|
||||
VITE_TALEMATE_BACKEND_WEBSOCKET_URL=ws://localhost:1234
|
||||
```
|
||||
|
||||
Next rebuild the frontend.
|
||||
|
||||
```bash
|
||||
cd talemate_frontend
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Start the backend and frontend
|
||||
|
||||
Start the backend and frontend as usual.
|
||||
|
||||
#### :material-linux: Linux
|
||||
|
||||
```bash
|
||||
./start_custom.sh
|
||||
```
|
||||
|
||||
#### :material-microsoft-windows: Windows
|
||||
|
||||
```batch
|
||||
start_custom.bat
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
By default, the frontend listens on `localhost:8080`.
|
||||
|
||||
To change the frontend host and port, you need to change the values passed to the `--frontend-host` and `--frontend-port` parameters during startup.
|
||||
|
||||
### Changing the host and port for the frontend
|
||||
|
||||
#### :material-linux: Linux
|
||||
|
||||
Copy `start.sh` to `start_custom.sh` and edit the `--frontend-host` and `--frontend-port` parameters.
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
uv run src/talemate/server/run.py runserver --host 0.0.0.0 --port 5055 \
|
||||
--frontend-host localhost --frontend-port 8082
|
||||
```
|
||||
|
||||
#### :material-microsoft-windows: Windows
|
||||
|
||||
Copy `start.bat` to `start_custom.bat` and edit the `--frontend-host` and `--frontend-port` parameters.
|
||||
|
||||
```batch
|
||||
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
|
||||
|
||||
Start the backend and frontend as usual.
|
||||
|
||||
#### :material-linux: Linux
|
||||
|
||||
```bash
|
||||
./start_custom.sh
|
||||
```
|
||||
|
||||
#### :material-microsoft-windows: Windows
|
||||
|
||||
```batch
|
||||
start_custom.bat
|
||||
```
|
||||
@@ -19,7 +19,7 @@ On the right hand side click the **:material-plus-box: ADD CLIENT** button.
|
||||
|
||||
The client configuration window will appear. Here you can choose the type of client you want to add.
|
||||
|
||||

|
||||

|
||||
|
||||
## Choose an API / Client Type
|
||||
|
||||
@@ -55,7 +55,7 @@ Select the API you want to use and click through to follow the instructions to c
|
||||
|
||||
Whenever you add your first client, Talemate will automatically assign it to all agents. Once the client is configured and assigned, all agents should have a green dot next to them. (Or grey if the agent is currently disabled)
|
||||
|
||||

|
||||

|
||||
|
||||
You can tell the client is assigned to the agent by checking the tag beneath the agent name, which will contain the client name if it is assigned.
|
||||
|
||||
|
||||
@@ -1,17 +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. 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.
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
|
||||
## Quick install instructions
|
||||
|
||||
!!! warning
|
||||
python 3.12 and node.js v21 are currently not supported.
|
||||
### Dependencies
|
||||
|
||||
--8<-- "docs/snippets/common.md:python-versions"
|
||||
|
||||
1. node.js and npm - see instructions [here](https://nodejs.org/en/download/package-manager/)
|
||||
1. python- see instructions [here](https://www.python.org/downloads/)
|
||||
1. uv - see instructions [here](https://github.com/astral-sh/uv#installation)
|
||||
|
||||
### Installation
|
||||
|
||||
1. `git clone https://github.com/vegu-ai/talemate.git`
|
||||
1. `cd talemate`
|
||||
1. `source install.sh`
|
||||
1. Start the backend: `python src/talemate/server/run.py runserver --host 0.0.0.0 --port 5050`.
|
||||
1. Open a new terminal, navigate to the `talemate_frontend` directory, and start the frontend server by running `npm run serve`.
|
||||
- When asked if you want to install pytorch with CUDA support choose `y` if you have
|
||||
a CUDA compatible Nvidia GPU and have installed the necessary drivers.
|
||||
1. `source start.sh`
|
||||
|
||||
If everything went well, you can proceed to [connect a client](../../connect-a-client).
|
||||
|
||||
@@ -18,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
|
||||
|
||||
@@ -38,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.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1,42 +1,32 @@
|
||||
## Quick install instructions
|
||||
|
||||
!!! warning
|
||||
python 3.12 and node.js v21 are currently not supported.
|
||||
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**.
|
||||
|
||||
1. Download and install Python 3.10 or Python 3.11 from the [official Python website](https://www.python.org/downloads/windows/).
|
||||
1. Download and install Node.js v20 from the [official Node.js website](https://nodejs.org/en/download/). 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. Once the installation is complete, you can start the backend and frontend servers by running `start.bat`.
|
||||
1. Navigate your browser to http://localhost:8080
|
||||
!!! 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 3.10 or 3.11
|
||||
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`**.
|
||||
|
||||
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. Click on the link for the Latest Python 3 Release - Python 3.10.x.
|
||||
3. Scroll to the bottom and select either Windows x86-64 executable installer for 64-bit or Windows x86 executable installer for 32-bit.
|
||||
4. Run the installer file and follow the setup instructions. Make sure to check the box that says Add Python 3.10 to PATH before you click Install Now.
|
||||
## Maintenance & advanced usage
|
||||
|
||||
### How to Install npm
|
||||
| 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. |
|
||||
|
||||
1. Download Node.js from the official site [https://nodejs.org/en/download/](https://nodejs.org/en/download/).
|
||||
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`.
|
||||
|
||||
#### 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.
|
||||
@@ -6,6 +6,9 @@ To load the introductory `Infinity Quest` scenario, simply click on its entry in
|
||||
|
||||

|
||||
|
||||
!!! info "First time may take a moment"
|
||||
When you load the a scenario for the first time, Talemate will need to initialize the long term memory model. Which likely means a download. Just be patient and it will be ready soon.
|
||||
|
||||
## Interacting with the scenario
|
||||
|
||||
After a moment of loading, you will see the scenario's introductory message and be able to send a text interaction.
|
||||
|
||||
|
Before Width: | Height: | Size: 449 KiB |
|
Before Width: | Height: | Size: 449 KiB |
|
Before Width: | Height: | Size: 396 KiB |
|
Before Width: | Height: | Size: 468 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 5.1 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 418 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 50 KiB |
BIN
docs/img/0.27.0/automatic1111-settings.png
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
docs/img/0.27.0/cancel-generation.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
docs/img/0.27.0/embedding-settings-edit.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
docs/img/0.27.0/embedding-settings-new-1.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
docs/img/0.27.0/memory-agent-settings.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
docs/img/0.27.0/open-debug-tools.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
docs/img/0.27.0/testing-memory-1.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
docs/img/0.27.0/testing-memory-2.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
docs/img/0.27.0/visual-agent-settings.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/img/0.28.0/quick-action-generated-text.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
docs/img/0.28.0/quick-action.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/img/0.29.0/agent-long-term-memory-settings.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/img/0.29.0/app-settings-appearance-scene.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
docs/img/0.29.0/app-settings-application.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
docs/img/0.29.0/app-settings-game-default-character.png
Normal file
|
After Width: | Height: | Size: 40 KiB |
BIN
docs/img/0.29.0/app-settings-game-general.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
docs/img/0.29.0/app-settings-presets-embeddings.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
BIN
docs/img/0.29.0/app-settings-presets-inference.png
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
docs/img/0.29.0/app-settings-presets-system-prompts.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs/img/0.29.0/conversation-generation-settings.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
docs/img/0.29.0/director-dynamic-actions-settings.png
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
docs/img/0.29.0/director-general-settings.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
docs/img/0.29.0/director-guide-scene-settings.png
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
docs/img/0.29.0/editor-agent-settings.png
Normal file
|
After Width: | Height: | Size: 58 KiB |