ranjithkumar111's picture
Upload 10 files
1bfbac9 verified
Raw
History Blame Contribute Delete
2.75 kB
# File: src/bland_webhook.py
# Purpose: FastAPI webhook endpoint that receives Bland AI call events and runs the pipeline
from fastapi import FastAPI, Request, HTTPException
from pathlib import Path
import json
import sys
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from src.pipeline import run_pipeline
from src.stt import transcribe_from_bland_webhook
app = FastAPI(title="Bland AI Webhook Receiver", version="1.0")
@app.post("/webhook/bland")
async def bland_webhook(request: Request):
"""
Receive a Bland AI call webhook.
Bland AI sends a POST with:
- call_id: unique call identifier
- transcript: full call transcript (if available)
- recording_url: URL of audio recording
- status: call status (e.g., "completed", "in-progress")
This endpoint:
1. Extracts the transcript (from text or audio)
2. Runs the full verification pipeline
3. Returns the verified spoken response to Bland AI
"""
try:
payload = await request.json()
except Exception:
raise HTTPException(status_code=400, detail="Invalid JSON payload")
call_id = payload.get("call_id", "unknown")
status = payload.get("status", "")
print(f"[Webhook] Received call {call_id} with status: {status}")
if status != "completed":
return {"status": "ignored", "reason": "Call not yet completed"}
# Get transcript from Bland AI (try text first, then audio transcription)
transcript = payload.get("transcript", "").strip()
if not transcript:
recording_url = payload.get("recording_url", "")
if recording_url:
print(f"[Webhook] Transcribing from recording_url: {recording_url}")
transcript = transcribe_from_bland_webhook(recording_url)
if not transcript:
return {"status": "error", "reason": "No transcript or audio available"}
# Run the anti-hallucination pipeline
result = run_pipeline(transcript)
# Return the verified response to be spoken back to the patient
return {
"call_id": call_id,
"response": result["response"],
"escalated": result["escalated"],
"appointment_id": (
result["verification"].appointment_id
if result["verification"] and result["verification"].verified
else None
),
}
@app.get("/health")
def health():
return {"status": "ok"}
if __name__ == "__main__":
try:
uvicorn = __import__("uvicorn")
except ImportError:
raise RuntimeError("uvicorn must be installed to run this server") from None
uvicorn.run("src.bland_webhook:app", host="0.0.0.0", port=9000, reload=True)