Robo Pest: 24/7 hosting on CT144 nginx + auth token on both APIs (X-Auth-Token). App served at robopest-app.thetempleofdoom.com
This commit is contained in:
Binary file not shown.
@@ -2,22 +2,34 @@
|
|||||||
"""Robo Pest STT relay — faster-whisper on nightmare's RTX 4080 SUPER.
|
"""Robo Pest STT relay — faster-whisper on nightmare's RTX 4080 SUPER.
|
||||||
|
|
||||||
POST /transcribe (body: raw PCM 16kHz s16le mono bytes) -> {"text": "..."}
|
POST /transcribe (body: raw PCM 16kHz s16le mono bytes) -> {"text": "..."}
|
||||||
GET /health -> {"status": "ok", "model": ...}
|
GET /health -> {"status": "ok", ...}
|
||||||
|
|
||||||
|
Auth: X-Auth-Token header required (set via STT_AUTH_TOKEN env var).
|
||||||
|
Health endpoint is open (no secrets).
|
||||||
"""
|
"""
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request, HTTPException
|
||||||
from faster_whisper import WhisperModel
|
from faster_whisper import WhisperModel
|
||||||
|
|
||||||
MODEL_NAME = os.environ.get("STT_MODEL", "small.en")
|
MODEL_NAME = os.environ.get("STT_MODEL", "small.en")
|
||||||
DEVICE = os.environ.get("STT_DEVICE", "cuda")
|
DEVICE = os.environ.get("STT_DEVICE", "cuda")
|
||||||
|
AUTH_TOKEN = os.environ.get("STT_AUTH_TOKEN", "")
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
model = WhisperModel(MODEL_NAME, device=DEVICE, compute_type="float16")
|
model = WhisperModel(MODEL_NAME, device=DEVICE, compute_type="float16")
|
||||||
|
|
||||||
|
|
||||||
|
def check_auth(request: Request):
|
||||||
|
if not AUTH_TOKEN:
|
||||||
|
return
|
||||||
|
token = request.headers.get("X-Auth-Token", "")
|
||||||
|
if token != AUTH_TOKEN:
|
||||||
|
raise HTTPException(status_code=401, detail="bad token")
|
||||||
|
|
||||||
|
|
||||||
def pcm16_to_float32(data: bytes) -> np.ndarray:
|
def pcm16_to_float32(data: bytes) -> np.ndarray:
|
||||||
n = len(data) // 2
|
n = len(data) // 2
|
||||||
ints = struct.unpack(f"<{n}h", data[: n * 2])
|
ints = struct.unpack(f"<{n}h", data[: n * 2])
|
||||||
@@ -31,6 +43,7 @@ def health():
|
|||||||
|
|
||||||
@app.post("/transcribe")
|
@app.post("/transcribe")
|
||||||
async def transcribe(request: Request):
|
async def transcribe(request: Request):
|
||||||
|
check_auth(request)
|
||||||
body = await request.body()
|
body = await request.body()
|
||||||
if not body:
|
if not body:
|
||||||
return {"text": ""}
|
return {"text": ""}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { TextContainerProperty, CreateStartUpPageContainer } from '@evenrealitie
|
|||||||
// Endpoints — public via Cloudflare fleet tunnel (work anywhere); LAN fallbacks in comments
|
// Endpoints — public via Cloudflare fleet tunnel (work anywhere); LAN fallbacks in comments
|
||||||
const STT_URL = 'https://robopest.thetempleofdoom.com/transcribe'
|
const STT_URL = 'https://robopest.thetempleofdoom.com/transcribe'
|
||||||
const WORKBRAIN_URL = 'https://pestcontroller.thetempleofdoom.com/api/chat'
|
const WORKBRAIN_URL = 'https://pestcontroller.thetempleofdoom.com/api/chat'
|
||||||
|
const AUTH_TOKEN = 'rp-EiluwonVC5JiqfNtec1253LPPvNvxLXV'
|
||||||
// LAN: STT http://10.30.20.5:8765/transcribe | WorkBrain http://10.30.20.249/api/chat
|
// LAN: STT http://10.30.20.5:8765/transcribe | WorkBrain http://10.30.20.249/api/chat
|
||||||
|
|
||||||
interface AskResult {
|
interface AskResult {
|
||||||
@@ -20,7 +21,7 @@ interface AskResult {
|
|||||||
async function askWorkbrain(query: string, convId: string): Promise<AskResult> {
|
async function askWorkbrain(query: string, convId: string): Promise<AskResult> {
|
||||||
const res = await fetch(WORKBRAIN_URL, {
|
const res = await fetch(WORKBRAIN_URL, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json', 'X-Auth-Token': AUTH_TOKEN },
|
||||||
body: JSON.stringify({ query, conv_id: convId }),
|
body: JSON.stringify({ query, conv_id: convId }),
|
||||||
})
|
})
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
@@ -36,7 +37,7 @@ async function askWorkbrain(query: string, convId: string): Promise<AskResult> {
|
|||||||
async function transcribe(pcm: ArrayBuffer): Promise<string> {
|
async function transcribe(pcm: ArrayBuffer): Promise<string> {
|
||||||
const res = await fetch(STT_URL, {
|
const res = await fetch(STT_URL, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/octet-stream' },
|
headers: { 'Content-Type': 'application/octet-stream', 'X-Auth-Token': AUTH_TOKEN },
|
||||||
body: pcm,
|
body: pcm,
|
||||||
})
|
})
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
|
|||||||
Reference in New Issue
Block a user