diff --git a/README.md b/README.md
index da18256..79d902c 100755
--- a/README.md
+++ b/README.md
@@ -195,6 +195,25 @@ The frontend uses a reverse proxy to route requests, so when running with `--pro
+## Olares Packaging
+
+Olares chart and manifest are under:
+
+- `olares/chatterboxapi`
+
+The Olares package is modeled as a shared app:
+
+- Admin install: deploys the shared GPU-backed Chatterbox API service.
+- User install: deploys a lightweight user-space API proxy.
+- Shared internal endpoint: `http://chatterboxapi.shared.olares.com`
+- User endpoint: `https://chatterboxapi.{OlaresID}.olares.com`
+
+Package manually:
+
+```bash
+helm package olares/chatterboxapi
+```
+
## Screenshots of Frontend (Web UI)
diff --git a/olares/chatterboxapi/Chart.yaml b/olares/chatterboxapi/Chart.yaml
index 5db80c2..dc4042d 100644
--- a/olares/chatterboxapi/Chart.yaml
+++ b/olares/chatterboxapi/Chart.yaml
@@ -3,4 +3,4 @@ name: chatterboxapi
description: Olares app for Chatterbox TTS API
type: application
version: 2.31.0
-appVersion: "2.31.0"
\ No newline at end of file
+appVersion: "2.31.0"
diff --git a/olares/chatterboxapi/OlaresManifest.yaml b/olares/chatterboxapi/OlaresManifest.yaml
index e4c4439..f0b3b31 100644
--- a/olares/chatterboxapi/OlaresManifest.yaml
+++ b/olares/chatterboxapi/OlaresManifest.yaml
@@ -1,5 +1,6 @@
olaresManifest.version: "0.11.0"
olaresManifest.type: app
+apiVersion: "v2"
metadata:
name: chatterboxapi
description: Private text-to-speech API powered by Chatterbox.
@@ -11,6 +12,22 @@ metadata:
- AI
- Utilities
- Developer Tools
+sharedEntrances:
+ - name: chatterboxapi
+ port: 0
+ host: sharedentrances-api
+ title: Chatterbox API
+ icon: https://avatars.githubusercontent.com/u/21249137?s=200&v=4
+ invisible: true
+ authLevel: internal
+entrances:
+ - name: chatterboxapi
+ port: 8080
+ host: chatterboxapi-proxy
+ title: Chatterbox API
+ icon: https://avatars.githubusercontent.com/u/21249137?s=200&v=4
+ authLevel: internal
+ openMethod: window
permission:
appData: true
appCache: true
@@ -36,9 +53,12 @@ spec:
- Multipart speech endpoint with optional uploaded reference audio.
Example request
- - `curl -X POST http://chatterboxapi-svc:4123/v1/audio/speech -H "Content-Type: application/json" -d '{"model":"turbo","input":"Hello from Olares","response_format":"wav"}' --output speech.wav`
+ - Internal shared endpoint: `http://chatterboxapi.shared.olares.com`
+ - User endpoint: `https://chatterboxapi.{OlaresID}.olares.com`
+ - `curl -X POST http://chatterboxapi.shared.olares.com/v1/audio/speech -H "Content-Type: application/json" -d '{"model":"turbo","input":"Hello from Olares","response_format":"wav"}' --output speech.wav`
Notes
+ - This is a shared Olares app. The GPU-backed API service is installed once by the Olares admin, while each user receives a lightweight user-space API entrance.
- This package targets `amd64` Olares nodes with NVIDIA GPU support.
- First request may be slow while model artifacts are downloaded.
- Hugging Face and torch cache paths are persisted under `userspace.appData`.
@@ -52,6 +72,7 @@ spec:
url: https://github.com/resemble-ai/chatterbox/blob/main/LICENSE
locale:
- en-US
+ {{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
requiredMemory: 12Gi
limitedMemory: 12Gi
requiredDisk: 5Gi
@@ -60,14 +81,42 @@ spec:
limitedCpu: 4
requiredGpu: 12Gi
limitedGpu: 16Gi
+ {{- else }}
+ requiredMemory: 64Mi
+ limitedMemory: 256Mi
+ requiredDisk: 1Mi
+ limitedDisk: 100Mi
+ requiredCpu: 10m
+ limitedCpu: 100m
+ {{- end }}
supportArch:
- amd64
+ subCharts:
+ - name: chatterboxapiserver
+ shared: true
+ - name: chatterboxapi
options:
apiTimeout: 0
dependencies:
- name: olares
type: system
- version: ">=1.12.1-0"
+ version: ">=1.12.3-0"
+ {{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
+ {{- else }}
+ - name: chatterboxapi
+ type: application
+ version: ">=2.2.0"
+ mandatory: true
+ {{- end }}
+ appScope:
+ {{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
+ clusterScoped: true
+ appRef:
+ - chatterboxapi
+ {{- else }}
+ clusterScoped: false
+ {{- end }}
+{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
envs:
- envName: OLARES_USER_HUGGINGFACE_TOKEN
required: false
@@ -79,11 +128,4 @@ envs:
applyOnChange: true
valueFrom:
envName: OLARES_USER_HUGGINGFACE_SERVICE
-entrances:
- - name: chatterboxapi
- port: 4123
- host: chatterboxapi-svc
- title: Chatterbox API
- icon: https://avatars.githubusercontent.com/u/21249137?s=200&v=4
- authLevel: internal
- openMethod: window
+{{- end }}
diff --git a/olares/chatterboxapi/README.md b/olares/chatterboxapi/README.md
index e52c4c9..8ad0d31 100644
--- a/olares/chatterboxapi/README.md
+++ b/olares/chatterboxapi/README.md
@@ -1,13 +1,38 @@
# Chatterbox API for Olares
-This package deploys the published image:
+This package deploys Chatterbox API as an Olares shared application.
+
+The Olares admin installs the shared GPU-backed API service once for the
+cluster. Each user installation receives a lightweight user-space API entrance
+that proxies to that shared service.
+
+The shared service uses the published image:
- `ghcr.io/progress44/rpi-system-chatterbox-api:latest`
-The app exposes text-to-speech endpoints at:
+## Olares endpoints
+
+Backend-to-backend clients inside Olares should use the hidden shared entrance:
+
+- `http://chatterboxapi.shared.olares.com`
+
+Browser clients or per-user integrations should use the normal user-space
+entrance:
+
+- `https://chatterboxapi.{OlaresID}.olares.com`
+
+Inside the shared server namespace, the admin-installed service is exposed at:
- `http://chatterboxapi-svc:4123`
+From another namespace, use:
+
+- `http://chatterboxapi-svc.chatterboxapiserver-shared:4123`
+
+User-space installations proxy through:
+
+- `http://chatterboxapi-proxy:8080`
+
## Endpoints
- `GET /`
@@ -26,6 +51,24 @@ curl -X POST http://chatterboxapi-svc:4123/v1/audio/speech \
--output speech.wav
```
+Shared Olares endpoint:
+
+```bash
+curl -X POST http://chatterboxapi.shared.olares.com/v1/audio/speech \
+ -H "Content-Type: application/json" \
+ -d '{"model":"turbo","input":"Hello from Olares","response_format":"wav"}' \
+ --output speech.wav
+```
+
+User-space endpoint:
+
+```bash
+curl -X POST https://chatterboxapi.{OlaresID}.olares.com/v1/audio/speech \
+ -H "Content-Type: application/json" \
+ -d '{"model":"turbo","input":"Hello from Olares","response_format":"wav"}' \
+ --output speech.wav
+```
+
## Notes
- The first synthesis request may be slower while model files are downloaded.
diff --git a/olares/chatterboxapi/chatterboxapi/Chart.yaml b/olares/chatterboxapi/chatterboxapi/Chart.yaml
new file mode 100644
index 0000000..43cf173
--- /dev/null
+++ b/olares/chatterboxapi/chatterboxapi/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: chatterboxapi
+description: User-space proxy for the shared Chatterbox API service
+type: application
+version: 2.2.0
+appVersion: "2.2.0"
diff --git a/olares/chatterboxapi/chatterboxapi/templates/clientproxy.yaml b/olares/chatterboxapi/chatterboxapi/templates/clientproxy.yaml
new file mode 100644
index 0000000..5a18cce
--- /dev/null
+++ b/olares/chatterboxapi/chatterboxapi/templates/clientproxy.yaml
@@ -0,0 +1,126 @@
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: chatterboxapi-proxy-config
+ namespace: {{ .Release.Namespace }}
+data:
+ nginx.conf: |
+ server {
+ listen 8080;
+ access_log /opt/bitnami/openresty/nginx/logs/access.log;
+ error_log /opt/bitnami/openresty/nginx/logs/error.log;
+
+ proxy_connect_timeout 30s;
+ proxy_send_timeout 600s;
+ proxy_read_timeout 600s;
+
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-Host $http_host;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-BFL-USER {{ .Values.bfl.username }};
+ proxy_set_header Authorization $http_authorization;
+ proxy_set_header Cookie $http_cookie;
+
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection "upgrade";
+
+ location / {
+ resolver coredns.kube-system.svc.cluster.local valid=10s;
+ proxy_pass http://chatterboxapi-svc.chatterboxapiserver-shared:4123;
+
+ proxy_hide_header Access-Control-Allow-Origin;
+ proxy_hide_header Access-Control-Allow-Methods;
+ proxy_hide_header Access-Control-Allow-Headers;
+ add_header Access-Control-Allow-Origin *;
+ add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD";
+ add_header Access-Control-Allow-Headers "deviceType,token,authorization,content-type,x-csrftoken";
+
+ if ($request_method = 'OPTIONS') {
+ add_header Access-Control-Allow-Origin *;
+ add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS, HEAD";
+ add_header Access-Control-Allow-Headers "deviceType,token,authorization,content-type,x-csrftoken";
+ return 204;
+ }
+ }
+ }
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ .Release.Name }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ app: chatterboxapi-proxy
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: chatterboxapi-proxy
+ strategy:
+ type: Recreate
+ template:
+ metadata:
+ labels:
+ app: chatterboxapi-proxy
+ spec:
+ volumes:
+ - name: nginx-config
+ configMap:
+ name: chatterboxapi-proxy-config
+ items:
+ - key: nginx.conf
+ path: nginx.conf
+ containers:
+ - name: nginx
+ image: "docker.io/beclab/aboveos-bitnami-openresty:1.25.3-2"
+ ports:
+ - containerPort: 8080
+ protocol: TCP
+ env:
+ - name: OPENRESTY_CONF_FILE
+ value: /etc/nginx/nginx.conf
+ readinessProbe:
+ exec:
+ command:
+ - /bin/sh
+ - -c
+ - |
+ http_code=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health)
+ [ "$http_code" -ge 200 ] && [ "$http_code" -lt 500 ]
+ initialDelaySeconds: 5
+ timeoutSeconds: 5
+ periodSeconds: 5
+ successThreshold: 1
+ failureThreshold: 120
+ resources:
+ requests:
+ cpu: 10m
+ memory: 64Mi
+ limits:
+ cpu: 100m
+ memory: 256Mi
+ volumeMounts:
+ - name: nginx-config
+ mountPath: /etc/nginx/nginx.conf
+ subPath: nginx.conf
+ - name: nginx-config
+ mountPath: /opt/bitnami/openresty/nginx/conf/server_blocks/nginx.conf
+ subPath: nginx.conf
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: chatterboxapi-proxy
+ namespace: {{ .Release.Namespace }}
+spec:
+ type: ClusterIP
+ selector:
+ app: chatterboxapi-proxy
+ ports:
+ - name: http
+ protocol: TCP
+ port: 8080
+ targetPort: 8080
diff --git a/olares/chatterboxapi/chatterboxapi/values.yaml b/olares/chatterboxapi/chatterboxapi/values.yaml
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/olares/chatterboxapi/chatterboxapi/values.yaml
@@ -0,0 +1 @@
+
diff --git a/olares/chatterboxapi/chatterboxapiserver/Chart.yaml b/olares/chatterboxapi/chatterboxapiserver/Chart.yaml
new file mode 100644
index 0000000..5fd1206
--- /dev/null
+++ b/olares/chatterboxapi/chatterboxapiserver/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: chatterboxapiserver
+description: Shared GPU-backed Chatterbox API service
+type: application
+version: 2.2.0
+appVersion: "2.2.0"
diff --git a/olares/chatterboxapi/templates/configmap.yaml b/olares/chatterboxapi/chatterboxapiserver/templates/configmap.yaml
similarity index 92%
rename from olares/chatterboxapi/templates/configmap.yaml
rename to olares/chatterboxapi/chatterboxapiserver/templates/configmap.yaml
index 9ab8139..3d01fc4 100644
--- a/olares/chatterboxapi/templates/configmap.yaml
+++ b/olares/chatterboxapi/chatterboxapiserver/templates/configmap.yaml
@@ -1,3 +1,4 @@
+{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
---
apiVersion: v1
kind: ConfigMap
@@ -26,3 +27,4 @@ data:
TORCH_HOME: /data/torch
NVIDIA_VISIBLE_DEVICES: {{ .Values.tts.nvidiaVisibleDevices | quote }}
NVIDIA_DRIVER_CAPABILITIES: {{ .Values.tts.nvidiaDriverCapabilities | quote }}
+{{- end }}
diff --git a/olares/chatterboxapi/templates/deployment.yaml b/olares/chatterboxapi/chatterboxapiserver/templates/deployment.yaml
similarity index 92%
rename from olares/chatterboxapi/templates/deployment.yaml
rename to olares/chatterboxapi/chatterboxapiserver/templates/deployment.yaml
index 66b716f..1e8b64d 100644
--- a/olares/chatterboxapi/templates/deployment.yaml
+++ b/olares/chatterboxapi/chatterboxapiserver/templates/deployment.yaml
@@ -1,3 +1,4 @@
+{{- if and .Values.admin .Values.bfl.username (eq .Values.admin .Values.bfl.username) }}
---
apiVersion: apps/v1
kind: Deployment
@@ -139,3 +140,19 @@ spec:
protocol: TCP
port: {{ .Values.service.port }}
targetPort: http
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: sharedentrances-api
+ namespace: {{ .Release.Namespace }}
+spec:
+ type: ClusterIP
+ selector:
+ app: chatterboxapi
+ ports:
+ - name: http
+ protocol: TCP
+ port: 80
+ targetPort: http
+{{- end }}
diff --git a/olares/chatterboxapi/chatterboxapiserver/values.yaml b/olares/chatterboxapi/chatterboxapiserver/values.yaml
new file mode 100644
index 0000000..7736f08
--- /dev/null
+++ b/olares/chatterboxapi/chatterboxapiserver/values.yaml
@@ -0,0 +1,18 @@
+image:
+ repository: ghcr.io/progress44/rpi-system-chatterbox-api
+ tag: latest
+ pullPolicy: Always
+
+service:
+ port: 4123
+
+tts:
+ device: cuda
+ maxTotalLength: "4000"
+ maxChunkLength: "280"
+ exaggeration: "0.5"
+ cfgWeight: "0.5"
+ temperature: "0.8"
+ useMultilingualModel: "true"
+ nvidiaVisibleDevices: all
+ nvidiaDriverCapabilities: compute,utility
diff --git a/olares/chatterboxapi/templates/keep b/olares/chatterboxapi/templates/keep
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/olares/chatterboxapi/templates/keep
@@ -0,0 +1 @@
+