Skip to content
This repository was archived by the owner on Apr 24, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions voice-to-mermaid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,31 @@ WebSocket /ws/mermaid

---

## Environment Variables
## Configuration

### Backend (`backend/.env`)
### `backend/config.yaml` — non-secret settings

Edit this file to change model names, Whisper settings, prompt path, and model filter.
It is volume-mounted in Docker, so changes take effect on restart without rebuilding.

| Key | Default | Description |
|---|---|---|
| `ollama.default_model` | `qwen3:8b` | Ollama model for diagram generation |
| `ollama.model_filter` | _(list)_ | Model name prefixes shown in the UI picker |
| `openai.model` | `gpt-4o-mini` | OpenAI-compatible model name |
| `whisper.enabled` | `false` | Set `true` after installing `requirements.stt.txt` |
| `whisper.model` | `medium.en` | Whisper model size |
| `whisper.device` | `auto` | `auto` / `cpu` / `cuda` |
| `paths.prompt` | `prompts/mermaid.txt` | Path to LLM prompt template |
| `paths.log_dir` | `data/logs` | Directory for generation logs |

### Backend (`backend/.env`) — secrets only

| Variable | Default | Description |
|---|---|---|
| `OLLAMA_URL` | `http://localhost:11434` | Ollama server URL |
| `OLLAMA_MODEL` | `qwen2.5:14b` | Model for diagram generation |
| `OPENAI_BASE_URL` | _(empty)_ | OpenAI-compatible API base (optional) |
| `OPENAI_API_KEY` | _(empty)_ | API key for OpenAI-compatible API |
| `WHISPER_MODEL` | `medium` | `tiny` / `base` / `small` / `medium` / `large-v3` |
| `WHISPER_DEVICE` | `auto` | `auto` / `cpu` / `cuda` |
| `API_KEY` | _(empty)_ | If set, require `X-Api-Key` header on all requests |
| `PORT` | `7625` | Server port |

Expand Down
20 changes: 4 additions & 16 deletions voice-to-mermaid/backend/.env.example
Original file line number Diff line number Diff line change
@@ -1,31 +1,19 @@
# voice-to-mermaid backend — copy to .env and fill in
#
# Non-secret settings (model names, Whisper config, prompt path, model filter)
# are in config.yaml — edit that file instead of adding them here.

# ── LLM backend (pick one) ────────────────────────────────────────────────
# ── LLM backend URLs (secrets — keep out of config.yaml) ─────────────────

# Option A: Ollama (local, recommended for self-hosting)
OLLAMA_URL=http://localhost:11434
OLLAMA_MODEL=qwen2.5:14b
# Comma-separated model name prefixes shown in the picker (empty = show all)
OLLAMA_MODEL_FILTER=qwen2.5:,qwen3.5:

# Option B: OpenAI-compatible API (vLLM, OpenAI, Together, etc.)
# OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_API_KEY=sk-...
# OPENAI_MODEL=gpt-4o-mini

# ── Whisper (transcription) ───────────────────────────────────────────────
# Model size: tiny | base | small | medium | large-v3
# Device: auto | cpu | cuda
WHISPER_MODEL=medium
WHISPER_DEVICE=auto

# ── Server ────────────────────────────────────────────────────────────────
PORT=7625
# Shared secret — Next.js proxy sends this as X-Api-Key header.
# Leave blank to disable auth (dev only).
API_KEY=

# ── Prompts ───────────────────────────────────────────────────────────────
# Path to mermaid prompt template (relative to this file).
# Edit prompts/mermaid.txt to customise diagram generation behaviour.
MERMAID_PROMPT_PATH=prompts/mermaid.txt
6 changes: 5 additions & 1 deletion voice-to-mermaid/backend/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ openai:
model: "gpt-4o-mini"

whisper:
enabled: false # set true only when requirements.stt.txt deps are installed
# true = attempt to load WhisperLiveKit at startup.
# If import fails (deps not installed), _stt_available stays False and
# /v1/config returns stt_enabled: false — no crash.
# Install requirements.stt.txt (or add it to Dockerfile) before setting true.
enabled: true

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whisper.enabled is set to true by default, but the Docker image (Dockerfile installs only requirements.txt) doesn’t include whisperlivekit/faster-whisper. In the default docker compose up flow this will result in STT being effectively unavailable (and currently can still cause runtime import failures unless additionally guarded). Either ship STT deps in the image (e.g., install requirements.stt.txt behind a build arg/profile) or default whisper.enabled to false and document the steps needed to enable STT locally.

Suggested change
enabled: true
enabled: false # Enable only when whisperlivekit/faster-whisper dependencies are installed in the environment/image.

Copilot uses AI. Check for mistakes.
model: "medium.en"
language: "en"
device: "auto" # "auto", "cuda", "cpu" — maps to WhisperLiveKitConfig backend
Expand Down
45 changes: 33 additions & 12 deletions voice-to-mermaid/backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,21 +71,41 @@ def _load_config() -> dict:

_cfg = _load_config()



def _config_section(name: str) -> dict:
section = _cfg.get(name, {})
if isinstance(section, dict):
return section
log.warning("config.%s is not a mapping — using defaults for that section", name)
return {}


_ollama_cfg = _config_section("ollama")
_openai_cfg = _config_section("openai")
_whisper_cfg = _config_section("whisper")
_paths_cfg = _config_section("paths")


# Secrets — env only
OLLAMA_URL = os.environ.get("OLLAMA_URL", "http://localhost:11434").rstrip("/")
OPENAI_URL = os.environ.get("OPENAI_BASE_URL", "").rstrip("/")
OPENAI_KEY = os.environ.get("OPENAI_API_KEY", "")

# Settings — config.yaml only; edit config.yaml to change these
OLLAMA_MODEL = _cfg.get("ollama", {}).get("default_model", "qwen3:8b")
OPENAI_MODEL = _cfg.get("openai", {}).get("model", "gpt-4o-mini")
WHISPER_ENABLED = _cfg.get("whisper", {}).get("enabled", False)
WHISPER_MODEL = _cfg.get("whisper", {}).get("model", "medium.en")
WHISPER_LANG = _cfg.get("whisper", {}).get("language", "en")
WHISPER_DEVICE = _cfg.get("whisper", {}).get("device", "auto")
PROMPT_PATH = Path(_cfg.get("paths", {}).get("prompt", "prompts/mermaid.txt"))
LOG_DIR = Path(_cfg.get("paths", {}).get("log_dir", "data/logs"))
_MODEL_FILTER: list[str] = [str(p) for p in (_cfg.get("ollama", {}).get("model_filter") or [])]
OLLAMA_MODEL = _ollama_cfg.get("default_model", "qwen3:8b")
OPENAI_MODEL = _openai_cfg.get("model", "gpt-4o-mini")
WHISPER_ENABLED = _whisper_cfg.get("enabled", False)
WHISPER_MODEL = _whisper_cfg.get("model", "medium.en")
WHISPER_LANG = _whisper_cfg.get("language", "en")
WHISPER_DEVICE = _whisper_cfg.get("device", "auto")
PROMPT_PATH = Path(_paths_cfg.get("prompt", "prompts/mermaid.txt"))
LOG_DIR = Path(_paths_cfg.get("log_dir", "data/logs"))
_MODEL_FILTER: list[str] = [str(p) for p in (_ollama_cfg.get("model_filter") or [])]

# Set True only after WhisperLiveKit loads successfully at startup.
# WHISPER_ENABLED=True but import fails → _stt_available stays False.
_stt_available: bool = False

_ollama_models_cache: list[dict] | None = None

Expand Down Expand Up @@ -253,7 +273,7 @@ async def _to_mermaid(

@asynccontextmanager
async def _lifespan(app: FastAPI):
global _transcription_engine
global _transcription_engine, _stt_available
_init_log_file()
if WHISPER_ENABLED:
try:
Expand All @@ -279,6 +299,7 @@ async def _lifespan(app: FastAPI):
pcm_input=False,
)
)
_stt_available = True
log.info("WhisperLiveKit ready")
else:
log.info("STT disabled (whisper.enabled=false) — audio transcription unavailable")
Expand Down Expand Up @@ -319,8 +340,8 @@ async def config():
"ollama_model": OLLAMA_MODEL,
"ollama_models": _ollama_models_cache,
"openai_model": OPENAI_MODEL,
"stt_enabled": WHISPER_ENABLED,
"whisper_model": WHISPER_MODEL if WHISPER_ENABLED else None,
"stt_enabled": _stt_available,
"whisper_model": WHISPER_MODEL if _stt_available else None,
}


Expand Down
Loading