Spaces:
Sleeping
Sleeping
| """FastAPI application β consultant chatbot microservice. | |
| Endpoints: | |
| POST /chat β Main chat endpoint | |
| GET /sessions β List all sessions | |
| POST /sessions/new β Create a new session | |
| GET /sessions/{session_id} β Get session details + history | |
| DELETE /sessions/{session_id} β Delete a session | |
| GET /health β Health check | |
| The frontend is served as static files from ../frontend/. | |
| """ | |
| from __future__ import annotations | |
| import os | |
| import uuid | |
| from contextlib import asynccontextmanager | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.middleware.cors import CORSMiddleware | |
| from fastapi.responses import FileResponse | |
| from fastapi.staticfiles import StaticFiles | |
| from models import ( | |
| ChatRequest, | |
| ChatResponse, | |
| Message, | |
| NewSessionResponse, | |
| Phase, | |
| SessionInfo, | |
| SessionState, | |
| ) | |
| from storage import delete_session, init_db, list_sessions, load_session, save_session | |
| from graph import run_consultation | |
| # --------------------------------------------------------------------------- | |
| # Greeting message β shown at the start of every new session | |
| # --------------------------------------------------------------------------- | |
| GREETING_MESSAGE = ( | |
| "**Welcome to Stacklogix.** I'm your consultant for this session. π\n\n" | |
| "Whether you have a **clear request** (e.g. build a product or fix an issue) or a **problem** " | |
| "(e.g. something isn't working as you'd like), I'll ask a few questions to understand your needs. " | |
| "Our team will then follow up with you.\n\n" | |
| "**What would you like to achieve or what do you need help with?**" | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # App lifecycle | |
| # --------------------------------------------------------------------------- | |
| async def lifespan(app: FastAPI): | |
| await init_db() | |
| yield | |
| app = FastAPI( | |
| title="Stacklogix Consultant Chatbot API", | |
| description="Stacklogix requirement-collection chatbot β gathers client requirements and explains how Stacklogix will address them. LangGraph + Groq.", | |
| version="1.0.0", | |
| lifespan=lifespan, | |
| ) | |
| # CORS β allow all origins for microservice usage | |
| app.add_middleware( | |
| CORSMiddleware, | |
| allow_origins=["*"], | |
| allow_credentials=True, | |
| allow_methods=["*"], | |
| allow_headers=["*"], | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # Chat endpoint | |
| # --------------------------------------------------------------------------- | |
| async def chat(req: ChatRequest): | |
| """Process a user message and return the consultant's response.""" | |
| # Load or create session | |
| session = await load_session(req.session_id) | |
| if session is None: | |
| session = SessionState(session_id=req.session_id) | |
| # Run consultation graph | |
| result = await run_consultation(session, req.message) | |
| # Persist updated state | |
| await save_session(req.session_id, result["session_state"]) | |
| return ChatResponse( | |
| reply=result["assistant_reply"], | |
| phase=result["new_phase"], | |
| confidence=result["new_confidence"], | |
| understanding=result["new_understanding"], | |
| ) | |
| # --------------------------------------------------------------------------- | |
| # Session management endpoints | |
| # --------------------------------------------------------------------------- | |
| async def get_sessions(): | |
| """List all active sessions.""" | |
| sessions = await list_sessions() | |
| return {"sessions": sessions} | |
| async def create_session(): | |
| """Create a new session with an opening greeting message.""" | |
| session_id = str(uuid.uuid4()) | |
| state = SessionState( | |
| session_id=session_id, | |
| messages=[Message(role="assistant", content=GREETING_MESSAGE)], | |
| ) | |
| await save_session(session_id, state) | |
| return { | |
| "session_id": session_id, | |
| "greeting": GREETING_MESSAGE, | |
| } | |
| async def get_session(session_id: str): | |
| """Get full session details including conversation history.""" | |
| session = await load_session(session_id) | |
| if session is None: | |
| raise HTTPException(status_code=404, detail="Session not found") | |
| return session.model_dump() | |
| async def remove_session(session_id: str): | |
| """Delete a session.""" | |
| deleted = await delete_session(session_id) | |
| if not deleted: | |
| raise HTTPException(status_code=404, detail="Session not found") | |
| return {"status": "deleted", "session_id": session_id} | |
| # --------------------------------------------------------------------------- | |
| # Health check | |
| # --------------------------------------------------------------------------- | |
| async def health(): | |
| return {"status": "healthy", "service": "stacklogix-chatbot"} | |
| # --------------------------------------------------------------------------- | |
| # Serve frontend static files | |
| # --------------------------------------------------------------------------- | |
| FRONTEND_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "frontend") | |
| if os.path.isdir(FRONTEND_DIR): | |
| async def serve_index(): | |
| return FileResponse(os.path.join(FRONTEND_DIR, "index.html")) | |
| app.mount("/static", StaticFiles(directory=FRONTEND_DIR), name="static") | |