Add deployment scripts and RunPod guide

- deploy/runpod/README.md - Full RunPod deployment guide
- scripts/generate_master_key.py - Generate secure admin keys
- scripts/download_models.py - Pre-download Whisper models

Deployment options documented:
- RunPod GPU (/bin/zsh.44/hr for RTX 4090)
- Docker Compose (local GPU/CPU)
- Cost optimization tips
This commit is contained in:
gianni-dalerta
2026-01-30 13:44:16 -05:00
parent ca620b4a83
commit c965f22f03
3 changed files with 211 additions and 0 deletions
+97
View File
@@ -0,0 +1,97 @@
# Deploy OpenClaw Voice on RunPod
Deploy OpenClaw Voice on RunPod for GPU-accelerated voice inference.
## Quick Deploy
### 1. Create a RunPod Account
Sign up at [runpod.io](https://runpod.io)
### 2. Deploy from Template
Use our pre-built template:
```
Template ID: openclaw-voice
Docker Image: ghcr.io/purple-horizons/openclaw-voice:latest
```
Or deploy manually:
### 3. Manual Deployment
**Create a new Pod:**
- GPU: RTX 4090 recommended ($0.44/hr)
- Docker Image: `ghcr.io/purple-horizons/openclaw-voice:latest`
- Expose Port: 8765
- Volume: 20GB (for model cache)
**Environment Variables:**
```
OPENCLAW_STT_MODEL=large-v3-turbo
OPENCLAW_STT_DEVICE=cuda
OPENCLAW_REQUIRE_AUTH=true
OPENCLAW_MASTER_KEY=<generate-a-secure-key>
OPENAI_API_KEY=<your-openai-key>
```
### 4. Connect
Once deployed, get your Pod's public URL:
```
wss://<pod-id>-8765.proxy.runpod.net/ws?api_key=<your-key>
```
## Cost Optimization
### On-Demand (Pay per hour)
- RTX 4090: ~$0.44/hr
- RTX 3090: ~$0.30/hr
- A10: ~$0.50/hr
### Spot Instances (Up to 80% cheaper)
- Use spot instances for non-critical workloads
- May be interrupted with 30s notice
### Reserved (Best for production)
- Reserve a GPU for consistent pricing
- No interruptions
## Scaling
### Single Pod
- Handles ~10-20 concurrent voice sessions
- Good for testing and small deployments
### Multiple Pods with Load Balancer
1. Deploy 2+ pods
2. Use RunPod's serverless endpoints
3. Or put behind Cloudflare Load Balancer
## Monitoring
### Health Check
```bash
curl https://<pod-url>/
```
### Check Logs
```bash
runpodctl logs <pod-id>
```
## Troubleshooting
### GPU Not Detected
- Ensure NVIDIA drivers are loaded
- Check `nvidia-smi` in pod terminal
### Out of Memory
- Reduce batch size
- Use smaller Whisper model (base vs large)
- Upgrade to GPU with more VRAM
### High Latency
- Use larger GPU
- Enable streaming responses
- Check network latency to RunPod region
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""
Download Whisper models for offline use.
Usage:
python scripts/download_models.py [model_name]
Models:
tiny - 39M params, ~1GB VRAM (fastest)
base - 74M params, ~1GB VRAM
small - 244M params, ~2GB VRAM
medium - 769M params, ~5GB VRAM
large-v3-turbo - 809M params, ~6GB VRAM (best quality/speed)
"""
import sys
import os
def download_model(model_name: str = "base"):
"""Download a Whisper model."""
print(f"Downloading Whisper model: {model_name}")
print("This may take a few minutes...")
try:
from faster_whisper import WhisperModel
# This will download the model if not cached
model = WhisperModel(model_name, device="cpu", compute_type="int8")
print(f"✅ Model '{model_name}' downloaded successfully!")
print(f" Cached at: ~/.cache/huggingface/")
# Test the model
import numpy as np
audio = np.zeros(16000, dtype=np.float32)
segments, info = model.transcribe(audio)
list(segments) # Consume generator
print(f"✅ Model tested successfully!")
except ImportError:
print("❌ faster-whisper not installed. Run:")
print(" pip install faster-whisper")
sys.exit(1)
except Exception as e:
print(f"❌ Error: {e}")
sys.exit(1)
def list_models():
"""List available models."""
models = {
"tiny": "39M params, ~1GB VRAM, fastest",
"base": "74M params, ~1GB VRAM, good balance",
"small": "244M params, ~2GB VRAM",
"medium": "769M params, ~5GB VRAM",
"large-v3": "1.5B params, ~10GB VRAM, best quality",
"large-v3-turbo": "809M params, ~6GB VRAM, best quality/speed ratio",
}
print("Available Whisper models:")
print()
for name, desc in models.items():
print(f" {name:20} - {desc}")
print()
print("Recommended: large-v3-turbo (GPU) or base (CPU)")
if __name__ == "__main__":
if len(sys.argv) < 2:
list_models()
print()
model = input("Enter model name to download (or 'q' to quit): ").strip()
if model.lower() == 'q':
sys.exit(0)
else:
model = sys.argv[1]
if model in ["-h", "--help", "help"]:
list_models()
sys.exit(0)
download_model(model)
+30
View File
@@ -0,0 +1,30 @@
#!/usr/bin/env python3
"""
Generate a secure master API key for OpenClaw Voice.
Usage:
python scripts/generate_master_key.py
Add the output to your .env file or deployment environment.
"""
import secrets
def generate_master_key() -> str:
"""Generate a secure master key."""
return f"ocv_master_{secrets.token_urlsafe(32)}"
if __name__ == "__main__":
key = generate_master_key()
print("=" * 60)
print("OpenClaw Voice Master Key")
print("=" * 60)
print()
print(f"OPENCLAW_MASTER_KEY={key}")
print()
print("Add this to your .env file or deployment environment.")
print("Keep this key SECRET - it has full admin access.")
print("=" * 60)