Skip to content
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
24 changes: 24 additions & 0 deletions pmoves/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3209,6 +3209,30 @@ vibevoice-smoke: ## Check VibeVoice realtime /config (requires VibeVoice running
echo "✔ VibeVoice /config 200"; \
curl -sS "http://localhost:$$port/config" | jq .

# ────────────────────────────────────────────────────────────────────────────
# OMNIVOICE (k2-fsa/OmniVoice production voice server — managed fleet deploy unit)
# ────────────────────────────────────────────────────────────────────────────
# Service-local compose at services/creator-operator/docker-compose.omnivoice.yml
# (opt-in via the `voice` profile). torch/torchaudio are the per-node CUDA build,
# installed in the image via ARG-driven index URL. SPARK (arm64 + CUDA GB10) needs
# the arm64/sbsa wheel — see services/creator-operator/SPARK_DEPLOY.md (TODO-confirm-on-node).
OMNIVOICE_COMPOSE ?= services/creator-operator/docker-compose.omnivoice.yml

.PHONY: omnivoice-build omnivoice-up omnivoice-down
omnivoice-build: ## Build the OmniVoice voice-server image (amd64 default; pass OMNIVOICE_PLATFORM=linux/arm64 for SPARK)
@test -f "$(OMNIVOICE_COMPOSE)" || (echo "✖ $(OMNIVOICE_COMPOSE) missing — operator must install it from SPARK_DEPLOY.md (compose Known Road)" && exit 1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Commit the compose file used by the targets

In a clean checkout these new omnivoice-build/omnivoice-up targets fail before doing any work because $(OMNIVOICE_COMPOSE) points at services/creator-operator/docker-compose.omnivoice.yml, but that file is not tracked or generated here (I checked git ls-files '*docker-compose.omnivoice.yml'/fd; only references are in this Makefile and the deploy doc). That makes the advertised Make entry points unusable unless every operator manually creates an untracked file first, so the deploy unit is incomplete in the repo.

Useful? React with 👍 / 👎.

@docker compose -f "$(OMNIVOICE_COMPOSE)" --profile voice build omnivoice-server
@echo "✔ OmniVoice image built (image=$${OMNIVOICE_IMAGE:-pmoves-omnivoice:latest})"

omnivoice-up: ## Start the OmniVoice voice server (voice profile; GPU via nvidia runtime)
@test -f "$(OMNIVOICE_COMPOSE)" || (echo "✖ $(OMNIVOICE_COMPOSE) missing — operator must install it from SPARK_DEPLOY.md (compose Known Road)" && exit 1)
@docker compose -f "$(OMNIVOICE_COMPOSE)" --profile voice up -d omnivoice-server
@echo "✔ OmniVoice up at http://$${OMNIVOICE_BIND:-127.0.0.1}:$${OMNIVOICE_HOST_PORT:-8002}/healthz"

omnivoice-down: ## Stop the OmniVoice voice server (keeps the HF model-cache volume)
@docker compose -f "$(OMNIVOICE_COMPOSE)" --profile voice down
@echo "✔ OmniVoice down (omnivoice-hf-cache volume preserved)"

# ────────────────────────────────────────────────────────────────────────────
# VOICEBOX (Pinokio-managed voice production service)
# ────────────────────────────────────────────────────────────────────────────
Expand Down
89 changes: 89 additions & 0 deletions pmoves/services/creator-operator/Dockerfile.omnivoice
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Dockerfile.omnivoice — OmniVoice production voice server deploy unit.
#
# Multi-arch aware (linux/amd64 + linux/arm64). The arm64 variant is the SPARK
# hook: SPARK is an NVIDIA DGX Spark (GB10 Grace-Blackwell, ARM64 + CUDA, 128GB
# unified). GPU support is provided by the NVIDIA container runtime at deploy
# time (`--gpus` / a compose `deploy.resources.reservations.devices` block), NOT
# baked into the base image — mirrors services/agent-zero/Dockerfile.multiarch.
#
# Build context: the creator-operator service directory. omnivoice_server.py does
# NOT import services.common, so the narrow service-dir context is sufficient and
# keeps the build fast.
#
# docker build -f services/creator-operator/Dockerfile.omnivoice \
# -t pmoves-omnivoice:latest services/creator-operator
#
# or multi-arch via buildx (see pmoves/Makefile: omnivoice-build):
# docker buildx build --platform linux/amd64,linux/arm64 \
# -f services/creator-operator/Dockerfile.omnivoice \
# -t pmoves-omnivoice:latest services/creator-operator
#
# ─────────────────────────────────────────────────────────────────────────────
# Torch/torchaudio are NOT in requirements-prod.txt — they are the per-node CUDA
# build, installed here via an ARG-driven index URL (TORCH_INDEX_URL).
#
# amd64 NVIDIA (4090/5090/z890): default cu128 wheel index works as-is.
# arm64 SPARK (GB10 Blackwell): needs the arm64/sbsa CUDA wheel (CUDA 12.8+).
# The exact wheel tag / sbsa index URL is
# TODO-confirm-on-node — do NOT hardcode a guess.
# Override at build time, e.g.:
# --build-arg TORCH_INDEX_URL=<sbsa-cu12x-index>
# --build-arg TORCH_SPEC="torch torchaudio"
# See services/creator-operator/SPARK_DEPLOY.md
# (§ "arm64/sbsa CUDA torch wheel swap").
# ─────────────────────────────────────────────────────────────────────────────

# Base CUDA image. The runtime-ubuntu22.04 family publishes both amd64 and
# arm64/sbsa variants, so buildx selects the right arch per --platform.
# Pinned via ARG so SPARK can swap to the exact CUDA minor confirmed on-node.
ARG CUDA_BASE_TAG=12.8.1-runtime-ubuntu22.04
FROM nvidia/cuda:${CUDA_BASE_TAG}

# Torch wheel controls (see header). Default = cu128 amd64; SPARK overrides.
ARG TORCH_INDEX_URL=https://download.pytorch.org/whl/cu128
# Pin nothing by default so the index's current cu128 build is selected; callers
# may pass e.g. TORCH_SPEC="torch==2.8.0 torchaudio==2.8.0" to pin exactly.
ARG TORCH_SPEC="torch torchaudio"

ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
DEBIAN_FRONTEND=noninteractive \
OMNIVOICE_DEVICE=cuda:0 \
OMNIVOICE_HOST=0.0.0.0 \
OMNIVOICE_PORT=8002 \
HF_HOME=/cache/huggingface

# System deps: python, libsndfile for soundfile, curl for the healthcheck.
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 python3-pip python3-venv \
libsndfile1 ffmpeg curl ca-certificates \
&& rm -rf /var/lib/apt/lists/* \
&& ln -sf /usr/bin/python3 /usr/local/bin/python

WORKDIR /app

# 1) Torch/torchaudio first (largest layer, changes least) via the ARG index.
RUN python -m pip install --no-cache-dir --upgrade pip \
&& python -m pip install --no-cache-dir ${TORCH_SPEC} --index-url ${TORCH_INDEX_URL}

# 2) The rest of the production deps (omnivoice, soundfile, fastapi, uvicorn,
# prometheus_client). torch/torchaudio are intentionally absent from this file.
COPY requirements-prod.txt ./requirements-prod.txt
RUN python -m pip install --no-cache-dir -r requirements-prod.txt

# 3) The server itself. No secrets are baked — OMNIVOICE_TOKEN et al. are passed
# at runtime via compose env passthrough.
COPY omnivoice_server.py ./omnivoice_server.py

# HF model cache lives on a mounted volume (see docker-compose.creator.yml) so the
# ~several-GB k2-fsa/OmniVoice download persists across restarts.
RUN mkdir -p /cache/huggingface

EXPOSE 8002

# Bind 0.0.0.0 so the service is reachable in-compose / over the tailnet. The
# server honors OMNIVOICE_HOST / OMNIVOICE_PORT (see omnivoice_server.py __main__).
HEALTHCHECK --interval=30s --timeout=5s --start-period=120s --retries=5 \
CMD curl -fsS http://localhost:8002/healthz || exit 1

CMD ["python", "omnivoice_server.py"]
Loading
Loading