Spaces:
Sleeping
Sleeping
File size: 4,837 Bytes
6aa1546 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | """
Vercel Serverless Function - Main API endpoint
Handles: POST /api
"""
from http.server import BaseHTTPRequestHandler
import json
import sys
import os
# Add parent directory to path
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.rag import RAGSystem
from src.escalation import EscalationEngine
from src.llm_client import LLMClient
from src.config import Settings
# Global components (cached across invocations)
_settings = None
_rag_system = None
_llm_client = None
_escalation_engine = None
def get_components():
"""Initialize and return components (cached)."""
global _settings, _rag_system, _llm_client, _escalation_engine
if _rag_system is None:
_settings = Settings()
articles_dir = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))),
"data",
"articles"
)
_rag_system = RAGSystem(articles_dir=articles_dir)
_llm_client = LLMClient(api_key=_settings.google_api_key, model=_settings.llm_model)
_escalation_engine = EscalationEngine(
llm_client=_llm_client,
relevance_threshold=_settings.relevance_threshold
)
return _settings, _rag_system, _llm_client, _escalation_engine
class handler(BaseHTTPRequestHandler):
"""Vercel serverless function handler."""
def do_POST(self):
"""Handle POST requests."""
try:
settings, rag_system, llm_client, escalation_engine = get_components()
# Read request body
content_length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_length).decode('utf-8')
# Parse JSON
try:
data = json.loads(body)
question = data.get('question', '').strip()
except json.JSONDecodeError:
self.send_error_response(400, "Invalid JSON")
return
# Validate question
if not question:
self.send_error_response(400, "Question cannot be empty")
return
# Retrieve relevant chunks
chunks = rag_system.retrieve(question, top_k=settings.top_k_chunks)
# Decide whether to answer or escalate
decision = escalation_engine.process_question(question, chunks)
# Send success response
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
self.end_headers()
response = {
"response_type": decision.action,
"message": decision.message,
"confidence_explanation": decision.confidence_explanation,
"sources": decision.sources
}
self.wfile.write(json.dumps(response).encode('utf-8'))
except Exception as e:
print(f"Error processing question: {str(e)}")
import traceback
traceback.print_exc()
self.send_error_response(500, "Internal server error")
def do_OPTIONS(self):
"""Handle OPTIONS requests for CORS."""
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
self.end_headers()
def do_GET(self):
"""Handle GET requests (health check)."""
self.send_response(200)
self.send_header('Content-Type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
response = {
"status": "healthy",
"message": "Smart Escalation API is running",
"vector_store_loaded": _rag_system is not None
}
self.wfile.write(json.dumps(response).encode('utf-8'))
def send_error_response(self, status_code, message):
"""Send error response."""
self.send_response(status_code)
self.send_header('Content-Type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
response = {
"response_type": "error",
"message": message,
"confidence_explanation": "Request error",
"sources": None
}
self.wfile.write(json.dumps(response).encode('utf-8'))
|