voice-rag / app.py
MrNK2107
fix(deploy): force SentenceTransformer to CPU mode for ZeroGPU compatibility
50b6e87
Raw
History Blame Contribute Delete
4.02 kB
import os
os.environ["CUDA_VISIBLE_DEVICES"] = ""
os.environ["FORCE_CUDA"] = "0"
import subprocess
import sqlite3
import sys
import threading
import traceback
from pathlib import Path
from datetime import datetime
sys.path.insert(0, str(Path(__file__).resolve().parent))
from fastapi import File, UploadFile, HTTPException
from fastapi.responses import FileResponse
from gradio import Server
import spaces
from app.config import settings
from app.harness import VoiceRAGHarness
from app.schemas import RagResponse, TextRequest
app = Server()
harness = None
_log_entries = []
def _log(msg):
ts = datetime.now().strftime("%H:%M:%S")
entry = f"[{ts}] {msg}"
_log_entries.append(entry)
print(entry, flush=True)
@spaces.GPU
def _gpu_placeholder():
pass
def _init_app():
_log(f"QDRANT_PATH={settings.qdrant_path}")
_log(f"SQLITE_FTS_PATH={settings.sqlite_fts_path}")
_log(f"HF_TOKEN={'set' if os.environ.get('HF_TOKEN') else 'NOT SET'}")
Path(settings.sqlite_fts_path).parent.mkdir(parents=True, exist_ok=True)
Path(settings.qdrant_path).mkdir(parents=True, exist_ok=True)
has_data = False
if os.path.exists(settings.sqlite_fts_path):
try:
conn = sqlite3.connect(settings.sqlite_fts_path)
count = conn.execute("SELECT COUNT(*) FROM chunks_meta").fetchone()[0]
conn.close()
has_data = count > 0
_log(f"SQLite has {count} chunks")
except Exception as e:
_log(f"SQLite check: {e}")
if not has_data:
_log("No index. Building in background...")
threading.Thread(target=_build_and_init, daemon=True).start()
else:
_log("Index exists. Initializing harness...")
_init_harness()
def _build_and_init():
try:
_log("Running build_index.py...")
result = subprocess.run(
[sys.executable, "-u", "scripts/build_index.py", "--languages", "hin", "--max-rows", "500"],
capture_output=True, text=True, timeout=1200,
)
_log(f"build_index exit code: {result.returncode}")
if result.stdout:
for line in result.stdout.strip().split("\n")[-15:]:
_log(f" {line}")
if result.returncode != 0 and result.stderr:
for line in result.stderr.strip().split("\n")[-10:]:
_log(f"ERR: {line}")
except Exception as e:
_log(f"build_index EXCEPTION: {e}")
_init_harness()
def _init_harness():
global harness
_log("Creating VoiceRAGHarness...")
try:
harness = VoiceRAGHarness()
_log("Harness READY!")
except Exception as e:
_log(f"Harness FAILED: {e}")
traceback.print_exc()
@app.get("/health")
def health_check():
return {"status": "ok", "harness_loaded": harness is not None}
@app.get("/status")
def status():
sqlite_exists = os.path.exists(settings.sqlite_fts_path)
sqlite_size = os.path.getsize(settings.sqlite_fts_path) if sqlite_exists else 0
return {
"harness_loaded": harness is not None,
"sqlite_exists": sqlite_exists,
"sqlite_size_bytes": sqlite_size,
"log": _log_entries[-50:],
}
@app.post("/api/ask-text", response_model=RagResponse)
def ask_text(req: TextRequest):
if not harness:
raise HTTPException(status_code=503, detail="Harness loading.")
return harness.ask_text(req.query)
@app.post("/api/ask-audio", response_model=RagResponse)
async def ask_audio(file: UploadFile = File(...)):
if not harness:
raise HTTPException(status_code=503, detail="Harness loading.")
audio_bytes = await file.read()
return harness.ask_audio(
audio_bytes=audio_bytes,
filename=file.filename or "audio.webm",
content_type=file.content_type or "audio/webm",
)
@app.get("/")
def serve_ui():
if Path("web/index.html").exists():
return FileResponse("web/index.html")
return {"message": "Voice RAG API is running."}
_init_app()
app.launch()