Spaces:
Sleeping
Sleeping
| import os | |
| os.environ["POSTHOG_DISABLED"] = "true" # Disable PostHog telemetry | |
| import requests | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from pydantic import BaseModel | |
| from dotenv import load_dotenv | |
| #from kb_embed import search_knowledge_base | |
| from services.kb_creation import collection, ingest_documents, search_knowledge_base | |
| from contextlib import asynccontextmanager | |
| import google.generativeai as genai | |
| # --- 1. Initialize FastAPI --- | |
| #app = FastAPI() | |
| async def lifespan(app: FastAPI): | |
| try: | |
| folder_path = os.path.join(os.getcwd(), "documents") | |
| if collection.count() == 0: | |
| print("🔍 KB empty. Running ingestion...") | |
| ingest_documents(folder_path) | |
| else: | |
| print(f"✅ KB already populated with {collection.count()} entries. Skipping ingestion.") | |
| except Exception as e: | |
| print(f"⚠️ KB ingestion failed: {e}") | |
| yield | |
| app = FastAPI(lifespan=lifespan) | |
| # --- Configure CORS --- | |
| origins = [ | |
| "https://nova-chatbot-chatbot-frontend.hf.space", | |
| ] | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=origins, | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # --- 3. Define the Request Data Structure --- | |
| class ChatInput(BaseModel): | |
| user_message: str | |
| # --- 4. Gemini API Setup --- | |
| GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") | |
| GEMINI_URL = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-lite:generateContent?key={GEMINI_API_KEY}" | |
| # --- 5. Endpoints --- | |
| async def health_check(): | |
| return {"status": "ok"} | |
| async def chat_with_ai(input_data: ChatInput): | |
| """Handle chat interactions using Google Generative AI via requests.""" | |
| try: | |
| # Retrieve relevant documents from knowledge base | |
| kb_results = search_knowledge_base(input_data.user_message, top_k=10) | |
| #print(f"kb_results are: {kb_results}") | |
| # Extract relevant context from search results | |
| context = "" | |
| relevant_docs=[] | |
| if kb_results and kb_results.get('documents'): | |
| # Limit context to avoid token limits - take top 2 most relevant | |
| relevant_docs = kb_results['documents'][0][:2] | |
| context = "\n\n".join(relevant_docs) | |
| # Construct enhanced prompt with context | |
| if context: | |
| enhanced_prompt = f"""Use the following knowledge base context to answer the user's question accurately. | |
| If the context contains relevant information, base your answer on it. | |
| If the context doesn't help, say you're raising a ticket and provide a ticket number. | |
| Knowledge Base Context: | |
| {context} | |
| User Question: {input_data.user_message} | |
| Answer:""" | |
| else: | |
| enhanced_prompt = f"User Question: {input_data.user_message}\n\nAnswer:" | |
| headers = {"Content-Type": "application/json"} | |
| payload = { | |
| "contents": [ | |
| { | |
| "parts": [{"text": enhanced_prompt}] | |
| } | |
| ] | |
| } | |
| response = requests.post(GEMINI_URL, headers=headers, json=payload, verify=False) # SSL disabled for testing | |
| print("Gemini status:", response.status_code) | |
| print("Gemini resp snippet:", response.text[:500]) | |
| result = response.json() | |
| #print("result",result) | |
| # Extract Gemini's response | |
| bot_response = result["candidates"][0]["content"]["parts"][0]["text"] | |
| # Include debug info in response | |
| debug_info = f"Context found: {'Yes' if context else 'No'}" | |
| if context: | |
| debug_info += f" (Top {len(relevant_docs)} documents used)" | |
| return {"bot_response": bot_response, "debug": debug_info} | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=str(e)) |