voicebot / app.py
Durga-7780's picture
Create app.py
ba6afbb verified
Raw
History Blame Contribute Delete
4.85 kB
import os
import time
import asyncio
import shutil
from fastapi import FastAPI, UploadFile, File, HTTPException, Form
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
import whisper
from gtts import gTTS
from dotenv import load_dotenv
from openai import OpenAI
# =====================================================
# ENV & OPENAI CLIENT
# =====================================================
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
client = OpenAI(api_key=OPENAI_API_KEY) if OPENAI_API_KEY else None
if client:
print("βœ… OpenAI client initialized")
else:
print("❌ OPENAI_API_KEY not found")
# =====================================================
# FASTAPI APP
# =====================================================
app = FastAPI(title="HF VoiceBot – Whisper + LLM + gTTS")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# =====================================================
# TEMP DIRECTORY (HF SAFE)
# =====================================================
TEMP_DIR = "temp"
os.makedirs(TEMP_DIR, exist_ok=True)
app.mount("/api/audio", StaticFiles(directory=TEMP_DIR), name="audio")
# =====================================================
# WHISPER (LAZY LOAD – IMPORTANT FOR HF)
# =====================================================
_whisper_model = None
def get_whisper_model():
global _whisper_model
if _whisper_model is None:
print("⏳ Loading Whisper tiny model (CPU)...")
_whisper_model = whisper.load_model("tiny")
print("βœ… Whisper model loaded")
return _whisper_model
# =====================================================
# LANGUAGE MAP (FOR LLM PROMPT)
# =====================================================
LANG_NAMES = {
"en": "English",
"hi": "Hindi",
"te": "Telugu",
"es": "Spanish",
"fr": "French",
}
# =====================================================
# MAIN API
# =====================================================
@app.post("/api/process-audio")
async def process_audio(
audio: UploadFile = File(...),
input_language: str = Form("en"),
output_language: str = Form("en"),
):
if not audio:
raise HTTPException(status_code=400, detail="No audio uploaded")
timestamp = int(time.time())
input_path = f"{TEMP_DIR}/input_{timestamp}.wav"
output_path = f"{TEMP_DIR}/output_{timestamp}.mp3"
try:
# -----------------------------
# SAVE AUDIO
# -----------------------------
with open(input_path, "wb") as f:
shutil.copyfileobj(audio.file, f)
# -----------------------------
# STT (WHISPER)
# -----------------------------
model = get_whisper_model()
loop = asyncio.get_running_loop()
result = await loop.run_in_executor(
None,
lambda: model.transcribe(
input_path,
language=input_language,
fp16=False
)
)
user_text = result.get("text", "").strip()
print("🎀 USER SAID >>>", user_text)
# -----------------------------
# LLM (MANDATORY)
# -----------------------------
if not user_text:
final_response = "Sorry, I could not hear anything."
elif not client:
final_response = "LLM is not configured."
else:
target_lang = LANG_NAMES.get(output_language, "English")
response = client.responses.create(
model="gpt-4o-mini",
input=f"""
You are a helpful and friendly voice assistant.
Reply ONLY in {target_lang}.
Keep responses short and natural for voice.
User: {user_text}
"""
)
final_response = response.output_text.strip()
print("πŸ€– FINAL RESPONSE >>>", final_response)
# -----------------------------
# TTS (gTTS – HF SUPPORTED)
# -----------------------------
tts = gTTS(text=final_response, lang=output_language)
tts.save(output_path)
return JSONResponse({
"user_text": user_text,
"bot_text": final_response,
"audio_url": f"/api/audio/{os.path.basename(output_path)}"
})
except Exception as e:
print("❌ ERROR >>>", e)
return JSONResponse(status_code=500, content={"error": str(e)})
finally:
if os.path.exists(input_path):
os.remove(input_path)
# =====================================================
# HF REQUIRED ENTRYPOINT
# =====================================================
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)