diff --git a/.gitignore b/.gitignore index 5b5355f..c6c59b9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,11 +26,15 @@ __pycache__/ /memory/chroma_db/ # Ignore the directory for generated audio files. -/audio_out/ +/audio/ # Ignore locally generated SSL certificates. /ssl/ +# Ignore build artifacts from setuptools. +/src/vdm_server.egg-info +/build + # Ignore local diagnostic files. local_digest.txt @@ -48,9 +52,11 @@ local_digest.txt *.db *.bat *.ps1 +*.lock # macOS .DS_Store # Windows Thumbs.db +uv diff --git a/pyproject.toml b/pyproject.toml index cfbf135..b0cb058 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,43 +1,50 @@ # =================================================================== # VDM - Project Configuration File # =================================================================== -# This file defines the project, its metadata, and its dependencies -# for modern Python packaging tools like uv and pip. - [build-system] requires = ["setuptools"] build-backend = "setuptools.build_meta" [project] name = "vdm-server" -version = "0.1.0" +version = "0.0.1" description = "A multiplayer, AI-driven storytelling game server." requires-python = ">=3.11" -# These are the core dependencies, equivalent to the old requirements.txt -# They will install the CPU-only version of PyTorch by default. dependencies = [ + # Server & API Framework "fastapi", - "uvicorn", - "pydantic-settings", "orjson", + "pydantic-settings", + "uvicorn", + + # Networking "httpx", - "chromadb", - "sentence-transformers", + + # User Management + "passlib[bcrypt]", + + # AI & Machine Learning "chonkie[st]", + "chromadb", + "hf_xet", "kokoro", + "misaki", + "sentence-transformers", + "soundfile", "torch", "torchaudio", - "passlib[bcrypt]", + + # Utilities "PyYAML", "rich", ] -# This section defines optional features that can be installed. [project.optional-dependencies] -# The 'gpu' extra will install the CUDA-enabled version of PyTorch for -# significantly better performance on NVIDIA GPUs. gpu = [ "torch", "torchaudio", -] \ No newline at end of file +] + +[tool.setuptools.packages.find] +where = ["src"] \ No newline at end of file diff --git a/readme.md b/readme.md index 75ec474..1ee0f1b 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ The project is built with a focus on stability and cutting-edge features, levera * **AI-Powered Game Master:** A sophisticated LLM acts as the storyteller, reacting to player actions, describing the world, and narrating events. * **Real-Time Multiplayer:** Join a room with friends from anywhere. The game state is synchronized in real-time for a seamless collaborative experience. * **Turn-Based System:** A structured turn system allows players to declare their actions, which are then submitted to the GM as a single turn for resolution. -* **Session Persistence:** Save your game with the `/save` command. The server automatically reloads your session when you rejoin the room. +* **Permanent Room Ownership**: The first player to create a room becomes its permanent owner, ensuring they always have host controls when they rejoin. ### Advanced AI Memory * **State-of-the-Art RAG Pipeline:** The AI has a true long-term memory, powered by Google's **EmbeddingGemma** model for top-tier embeddings and the **Chonkie** library for intelligent semantic chunking. @@ -24,18 +24,19 @@ The project is built with a focus on stability and cutting-edge features, levera ### Immersive Experience * **High-Quality Voice Narration:** The GM's responses are brought to life with server-side Text-to-Speech using the `kokoro` library. * **Speech-to-Text Input:** A "Hold to Talk" microphone button allows players to speak their actions instead of typing. -* **Markdown Rendering:** GM and player messages are rendered with Markdown for better formatting and readability (e.g., *italics* and **bold**). +* **Markdown Rendering:** Chat messages are rendered with Markdown for rich text formatting (*italics*, **bold**). ### Modern UI/UX * **Clean & Responsive Interface:** A modern single-page application that works on any device. * **Light/Dark Modes:** A persistent theme toggle for user comfort. -* **Modular Frontend:** The JavaScript is broken down into small, maintainable modules for features like auth, commands, and avatars. +* **Modular Frontend:** The JavaScript is broken down into small, maintainable modules. * **Visual Turn Indicator:** See at a glance which players have submitted their action for the current turn. ### Robust Backend -* **Pluggable AI Backends:** Easily switch between different LLM providers, including local options like **LM Studio** and **Ollama**, or cloud services like **OpenRouter**. +* **Modern Python Packaging**: Uses a `pyproject.toml` file and a `src` layout, following the latest Python standards. +* **Pluggable AI Backends:** Easily switch between different LLM providers (LM Studio, Ollama, OpenRouter). * **Secure User Accounts:** Player accounts are stored with hashed passwords in a dedicated SQLite database. -* **Persistent Sessions:** User logins survive server restarts, allowing for a seamless reconnection experience. +* **Persistent Sessions:** User logins survive server restarts for a seamless reconnection experience. --- @@ -45,55 +46,70 @@ Follow these steps to get your VDM server up and running. ### Prerequisites -* **Python 3.11+** -* **`uv`**: A fast Python package installer. If you don't have it, run: - ```bash - pip install uv - ``` -* **(Optional) NVIDIA GPU**: For the best performance with local LLMs and TTS. +* **Python 3.11 or higher** installed on your system. +* **`uv`**: A fast Python package manager. If you don't have it, run: + ```bash + pip install uv + ``` -### 1. Project Setup +--- -First, clone or download the project repository. +### 1. Setup and Environment Activation -### 2. Create and Activate the Virtual Environment - -Open your terminal in the project's root directory and run: +Open your terminal and run the following commands from the directory where you want to store the project. ```bash -# Create the virtual environment -uv venv +# 1. Clone the project repository +git clone https://github.com/Nighthawk42/VDM.git +cd VDM -# Activate the environment +# 2. Create a seeded virtual environment with Python 3.11 (required step) +uv venv --seed --python 3.11 + +# 3. Activate the new environment # On Windows: .venv\Scripts\activate # On macOS / Linux: # source .venv/bin/activate ``` -### 3. Install Dependencies +--- -Install all required Python packages. **Note:** This step will download large AI models for embeddings and TTS, which may take some time. +### 2. Install Dependencies + +This project can be run on a CPU, but an NVIDIA GPU is highly recommended for the best performance. Choose one of the following installation options. + +**For NVIDIA GPU Systems (Recommended):** +```bash +uv pip install ".[gpu]" --extra-index-url https://download.pytorch.org/whl/cu121 +``` + +**For CPU-Only Systems:** +```bash +uv pip install . +``` + +> **Note:** This step will download large AI models for embeddings and TTS, which may take some time. + +--- + +### 3. Configure the VDM + +* **Environment Variables**: Copy `.env.example` to `.env` and fill in any necessary API keys or change the default URLs for your local LLM providers. +* **Main Configuration**: Open `settings.yml` to configure the core behavior, especially the `llm` and `memory` sections. +* **Prompts (Optional)**: Edit `prompts.yml` to change the GM's personality. + +--- + +### 4. Launch the Server! + +Simply run the launch script. ```bash -uv pip install -r requirements.txt +uv run uvicorn vdm_server.main:app --reload --reload-dir ./src/vdm_server --reload-dir ./web --host 127.0.0.1 --port 8000 ``` -### 4. Configure the VDM - - * **Environment Variables**: Copy `.env.example` to `.env` and fill in any necessary API keys or change the default URLs for your local LLM providers. - * **Main Configuration**: Open `settings.yml` to configure the core behavior, especially the `llm` and `memory` sections to select your AI backend and chunking strategy. - * **Prompts & Voices (Optional)**: Edit `prompts.yml` to change the GM's personality or `voices.yml` for dynamic voice casting. - -### 5. Launch the Server! - -Simply run the launch script. It will activate the environment and start the Uvicorn server. - -```cmd -uvicorn server.main:app --reload --reload-dir ./server --reload-dir ./web --host 127.0.0.1 --port 8000 -``` - -The server will be running at `http://127.0.0.1:8000`. You and your friends can now connect and play! +The server will be running at `http://127.0.0.1:8000`. --- @@ -111,8 +127,8 @@ The server will be running at `http://127.0.0.1:8000`. You and your friends can ## ⌨️ Slash Commands -* `/roll [dice]`: Rolls dice (e.g., `/roll 2d6+3`). Defaults to `1d20`. -* `/ooc [message]`: Sends an out-of-character message to other players. -* `/remember [fact]`: Saves a critical fact to the GM's long-term memory. -* `/save`: Saves the current game session. -* `/next`: Submits the current turn's actions to the GM. +* `/roll [dice]`: Rolls dice (e.g., `/roll 2d6+3`). Defaults to `1d20`. +* `/ooc [message]`: Sends an out-of-character message to other players. +* `/remember [fact]`: Saves a critical fact to the GM's long-term memory. +* `/save`: Saves the current game session. +* `/next`: Submits the current turn's actions to the GM. diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b2d331f..0000000 --- a/requirements.txt +++ /dev/null @@ -1,355 +0,0 @@ -# A good many of these are likely not needed. But exist due to ongoing testing and development. - -# You MUST use a .venv for this project. uv or conda is HIGHLY recommended. - -# Not using one will likely break your system-wide Python library. - -# ========================= -# Server / API framework -# ========================= -fastapi==0.116.1 -starlette==0.47.3 -uvicorn==0.35.0 -httptools==0.6.4 -orjson==3.11.3 -watchfiles==1.1.0 - -# ========================= -# HTTP / Networking / Async -# ========================= -aiohappyeyeballs==2.6.1 -aiohttp==3.12.15 -aiolimiter==1.2.1 -aiosignal==1.4.0 -anyio==4.10.0 -h11==0.16.0 -h2==4.3.0 -httpcore==1.0.9 -httpx==0.28.1 -httpx-sse==0.4.0 -hyperframe==6.1.0 -multidict==6.6.4 -rfc3986==1.5.0 -sniffio==1.3.1 -websocket-client==1.8.0 -websockets==15.0.1 -yarl==1.20.1 - -# ========================= -# Auth / Security -# ========================= -authlib==1.6.3 -bcrypt==3.2.0 -cryptography==45.0.6 -google-auth==2.40.3 -oauthlib==3.3.1 -pyasn1==0.6.1 -pyasn1-modules==0.4.2 -pyjwt==2.10.1 -requests-oauthlib==2.0.0 -rsa==4.9.1 - -# ========================= -# Cloud SDKs / Telemetry / Infra -# ========================= -azure-core==1.35.0 -azure-identity==1.24.0 -googleapis-common-protos==1.70.0 -grpcio==1.74.0 -kubernetes==33.1.0 -opentelemetry-api==1.36.0 -opentelemetry-exporter-otlp-proto-common==1.36.0 -opentelemetry-exporter-otlp-proto-grpc==1.36.0 -opentelemetry-proto==1.36.0 -opentelemetry-sdk==1.36.0 -opentelemetry-semantic-conventions==0.57b0 -posthog==5.4.0 - -# ========================= -# Data / Serialization / Validation -# ========================= -annotated-types==0.7.0 -jsonpatch==1.33 -jsonpointer==3.0.0 -jsonschema==4.25.1 -jsonschema-specifications==2025.4.1 -pydantic==2.11.7 -pydantic-core==2.33.2 -pydantic-settings==2.10.1 -protobuf==6.32.0 -python-dateutil==2.9.0.post0 -python-dotenv==1.1.1 -pyyaml==6.0.2 -referencing==0.36.2 -rpds-py==0.27.1 -uritemplate==4.2.0 - -# ========================= -# Core ML / Math / Utils -# ========================= -llvmlite==0.43.0 -numba==0.60.0 -numpy==2.0.0 -scipy==1.16.1 -scikit-learn==1.7.1 -threadpoolctl==3.6.0 -sympy==1.14.0 -tqdm==4.67.1 - -# ========================= -# PyTorch stack -# ========================= -torch==2.8.0+cu126 -torchvision==0.23.0+cu126 -torchaudio==2.8.0 -tensorboardx==2.6.4 -torchcrepe==0.0.20 - -# ========================= -# NLP / LLM tooling -# ========================= -accelerate==1.10.1 -huggingface-hub==0.34.4 -sentence-transformers==5.1.0 -tokenizers==0.22.0 -transformers==4.56.0 -tiktoken==0.11.0 -sacrebleu==2.5.1 -regex==2025.8.29 -openai==1.102.0 -cohere==5.17.0 -google-genai==1.32.0 -voyageai==0.3.4 -langchain-core==0.3.75 -langchain-text-splitters==0.3.11 -langsmith==0.4.21 - -# ========================= -# spaCy + curated transformers -# ========================= -spacy==3.8.7 -en-core-web-sm==3.8.0 -thinc==8.3.4 -catalogue==2.0.10 -confection==0.1.5 -cymem==2.0.11 -murmurhash==1.0.13 -preshed==3.0.10 -srsly==2.5.1 -spacy-legacy==3.0.12 -spacy-loggers==1.0.5 -langcodes==3.5.0 -language-data==1.3.0 -marisa-trie==1.3.1 -wasabi==1.1.3 -spacy-curated-transformers==0.3.1 -curated-tokenizers==0.0.9 -curated-transformers==0.1.1 -misaki==0.9.4 - -# ========================= -# Vectors / Datastores / Retrieval -# ========================= -chromadb==1.0.20 -faiss-cpu==1.10.0 -qdrant-client==1.15.1 -pinecone==7.3.0 -pinecone-plugin-assistant==1.8.0 -pinecone-plugin-interface==0.0.7 -weaviate-client==4.16.9 -turbopuffer==1.0.0 -propcache==0.3.2 -smart-open==7.3.0.post1 - -# ========================= -# Audio / Speech / Media -# ========================= -audioread==3.0.1 -av==15.1.0 -edge-tts==7.2.3 -einops==0.8.1 -espeakng-loader==0.2.4 -ffmpeg-python==0.2.0 -kokoro==0.9.4 -librosa==0.11.0 -praat-parselmouth==0.4.6 -pyworld==0.3.5 -resampy==0.4.3 -soundfile==0.13.1 -soxr==0.5.0.post1 -tts-with-rvc==0.1.9.1 - -# ========================= -# Imaging / Files / Parsing -# ========================= -pillow==11.0.0 -lxml==6.0.1 -rdflib==7.1.4 -csvw==3.5.1 -isodate==0.7.2 -language-tags==1.2.0 -markdown-it-py==4.0.0 -mdurl==0.1.2 -tabulate==0.9.0 -validators==0.35.0 - -# ========================= -# ONNX / Inference backends -# ========================= -onnxruntime==1.22.1 -onnxruntime-gpu==1.22.0 - -# ========================= -# DB / Storage / Locking -# ========================= -pymongo==4.14.1 -portalocker==3.2.0 - -# ========================= -# CLI / Logging / Dev ergonomics -# ========================= -backoff==2.2.1 -click==8.2.1 -colorama==0.4.6 -coloredlogs==15.0.1 -colorlog==6.9.0 -humanfriendly==10.0 -loguru==0.7.3 -pygments==2.19.2 -rich==14.1.0 -tenacity==9.1.2 -typer==0.17.3 -shellingham==1.5.4 - -# ========================= -# Tree-sitter / code tooling -# ========================= -tree-sitter==0.25.1 -tree-sitter-c-sharp==0.23.1 -tree-sitter-embedded-template==0.25.0 -tree-sitter-language-pack==0.9.0 -tree-sitter-yaml==0.7.1 - -# ========================= -# Azure / MSAL helpers -# ========================= -msal==1.33.0 -msal-extensions==1.3.1 - -# ========================= -# Fairseq & friends -# ========================= -fairseq-built==0.12.3 - -# ========================= -# Misc libraries (as installed) -# ========================= -accelerate==1.10.1 -addict==2.4.0 -antlr4-python3-runtime==4.9.3 -attrs==25.3.0 -autotiktokenizer==0.2.2 -babel==2.17.0 -bitarray==3.7.1 -blis==1.2.1 -build==1.3.0 -cachetools==5.5.2 -certifi==2025.8.3 -cffi==1.17.1 -charset-normalizer==3.4.3 -chonkie==1.2.1 -chromadb==1.0.20 -cloudflared==1.0.0.2 -cloudpathlib==0.22.0 -cohere==5.17.0 -confection==0.1.5 -csvw==3.5.1 -cython==3.1.3 -decorator==5.2.1 -deprecation==2.1.0 -distro==1.9.0 -dlinfo==2.0.0 -dnspython==2.7.0 -docopt==0.6.2 -durationpy==0.10 -fastavro==1.12.0 -filelock==3.19.1 -flatbuffers==25.2.10 -frozenlist==1.7.0 -fsspec==2025.7.0 -future==1.0.0 -hpack==4.1.0 -hydra-core==1.3.2 -hyper-connections==0.2.1 -idna==3.10 -importlib-metadata==8.7.0 -importlib-resources==6.5.2 -isodate==0.7.2 -jinja2==3.1.6 -jiter==0.10.0 -joblib==1.5.2 -kokoro==0.9.4 -langcodes==3.5.0 -language-data==1.3.0 -lazy-loader==0.4 -librosa==0.11.0 -local-attention==1.11.2 -lxml==6.0.1 -magika==0.6.2 -marisa-trie==1.3.1 -markupsafe==3.0.2 -mdurl==0.1.2 -misaki==0.9.4 -mmh3==5.2.0 -model2vec==0.6.0 -mpmath==1.3.0 -msgpack==1.1.1 -nest-asyncio==1.6.0 -networkx==3.5 -num2words==0.5.14 -omegaconf==2.3.0 -overrides==7.7.0 -packaging==25.0 -passlib==1.7.4 -phonemizer-fork==3.3.2 -pinecone-plugin-assistant==1.8.0 -pinecone-plugin-interface==0.0.7 -pip==25.2 -platformdirs==4.4.0 -pooch==1.8.2 -portalocker==3.2.0 -praat-parselmouth==0.4.6 -pybase64==1.4.2 -pycparser==2.22 -pyparsing==3.2.3 -pypika==0.48.9 -pyproject-hooks==1.2.0 -pyreadline3==3.5.4 -pywin32==311 -qdrant-client==1.15.1 -rdflib==7.1.4 -requests==2.32.5 -requests-toolbelt==1.0.0 -rich==14.1.0 -safetensors==0.6.2 -segments==2.3.0 -setuptools==80.9.0 -setuptools-scm==9.2.0 -six==1.17.0 -smart-open==7.3.0.post1 -soundfile==0.13.1 -thinc==8.3.4 -tree-sitter==0.25.1 -types-requests==2.32.4.20250809 -typing-extensions==4.15.0 -typing-inspection==0.4.1 -urllib3==2.5.0 -validators==0.35.0 -wasabi==1.1.3 -weasel==0.4.1 -weaviate-client==4.16.9 -wheel==0.45.1 -win32-setctime==1.2.0 -wrapt==1.17.3 -zipp==3.23.0 -zstandard==0.24.0 diff --git a/settings.yml b/settings.yml index 65dbcf4..184b4c2 100644 --- a/settings.yml +++ b/settings.yml @@ -67,7 +67,6 @@ memory: # The SentenceTransformer model used to create embeddings for the AI's embedding_model: "google/embeddinggemma-300m" - # UPDATED: Split database paths for better organization. # The database for saving game room/session states. sessions_db_file: "./database/vdm_sessions.db" # The database for saving user accounts and profiles. @@ -89,4 +88,4 @@ paths: memory_dir: "./memory" # Directory where generated TTS audio files are saved. - audio_out_dir: "./audio_out" \ No newline at end of file + audio_out_dir: "./audio" \ No newline at end of file diff --git a/server/audio_manager.py b/src/vdm_server/audio_manager.py similarity index 100% rename from server/audio_manager.py rename to src/vdm_server/audio_manager.py diff --git a/server/config.py b/src/vdm_server/config.py similarity index 100% rename from server/config.py rename to src/vdm_server/config.py diff --git a/server/database_manager.py b/src/vdm_server/database_manager.py similarity index 100% rename from server/database_manager.py rename to src/vdm_server/database_manager.py diff --git a/server/game_manager.py b/src/vdm_server/game_manager.py similarity index 100% rename from server/game_manager.py rename to src/vdm_server/game_manager.py diff --git a/server/llm_providers.py b/src/vdm_server/llm_providers.py similarity index 100% rename from server/llm_providers.py rename to src/vdm_server/llm_providers.py diff --git a/server/logger.py b/src/vdm_server/logger.py similarity index 100% rename from server/logger.py rename to src/vdm_server/logger.py diff --git a/server/main.py b/src/vdm_server/main.py similarity index 96% rename from server/main.py rename to src/vdm_server/main.py index adac5b0..393deaf 100644 --- a/server/main.py +++ b/src/vdm_server/main.py @@ -1,4 +1,4 @@ -# server/main.py +# src/vdm_server/main.py import base64 import asyncio from pathlib import Path @@ -10,9 +10,9 @@ from fastapi.responses import JSONResponse, FileResponse from fastapi.staticfiles import StaticFiles from starlette.websockets import WebSocketState -from .config import settings -from .database_manager import DatabaseManager -from .models import ( +from vdm_server.config import settings +from vdm_server.database_manager import DatabaseManager +from vdm_server.models import ( Room, WSIncomingMessage, WSOutgoingMessage, @@ -20,19 +20,20 @@ from .models import ( Player, LoginRequest, ) -from .persistence_manager import PersistenceManager -from .room_manager import RoomManager -from .story_manager import StoryManager -from .audio_manager import AudioManager -from .game_manager import DiceRoller -from .logger import logger -from .user_manager import UserManager +from vdm_server.persistence_manager import PersistenceManager +from vdm_server.room_manager import RoomManager +from vdm_server.story_manager import StoryManager +from vdm_server.audio_manager import AudioManager +from vdm_server.game_manager import DiceRoller +from vdm_server.logger import logger +from vdm_server.user_manager import UserManager # =================================================================== # Application Setup # =================================================================== -BASE_DIR = Path(__file__).resolve().parent.parent +BASE_DIR = Path(__file__).resolve().parent.parent.parent app = FastAPI(title="VDM - Virtual Dungeon Master") + app.add_middleware( CORSMiddleware, allow_origins=["*"], @@ -40,9 +41,9 @@ app.add_middleware( allow_methods=["*"], allow_headers=["*"], ) +# These paths now correctly resolve from the project root app.mount("/static", StaticFiles(directory=BASE_DIR / "web"), name="static") -app.mount("/audio", StaticFiles(directory=Path(settings.paths.audio_out_dir)), name="audio") - +app.mount("/audio", StaticFiles(directory=BASE_DIR / settings.paths.audio_out_dir), name="audio") class ConnectionManager: """Manages active WebSocket connections for each room.""" diff --git a/server/memory_manager.py b/src/vdm_server/memory_manager.py similarity index 100% rename from server/memory_manager.py rename to src/vdm_server/memory_manager.py diff --git a/server/models.py b/src/vdm_server/models.py similarity index 100% rename from server/models.py rename to src/vdm_server/models.py diff --git a/server/persistence_manager.py b/src/vdm_server/persistence_manager.py similarity index 100% rename from server/persistence_manager.py rename to src/vdm_server/persistence_manager.py diff --git a/server/room_manager.py b/src/vdm_server/room_manager.py similarity index 100% rename from server/room_manager.py rename to src/vdm_server/room_manager.py diff --git a/server/story_manager.py b/src/vdm_server/story_manager.py similarity index 100% rename from server/story_manager.py rename to src/vdm_server/story_manager.py diff --git a/server/user_manager.py b/src/vdm_server/user_manager.py similarity index 100% rename from server/user_manager.py rename to src/vdm_server/user_manager.py