Source code for app.api.chat_routes

"""
This module defines the API routes for the chat functionality of the chatbot.
"""

# app/api/chat_routes.py
from fastapi import APIRouter, Depends, HTTPException, status, Response, Query
from pydantic import BaseModel, Field
from typing import List, Tuple, Dict, Optional
from app.services.chat_service import ChatService
from app.models.chat_models import ChatRequest, ChatResponse
from app.services.llm_service import LLMService
from app.utils.context_manager import ContextManager

router = APIRouter()

llm_service = LLMService()
context_manager = ContextManager()
chat_service = ChatService(llm_service, context_manager)

[docs] class ErrorResponse(BaseModel): """ Model for error responses. :param detail: A string describing the error. """ detail: str
# class ConversationHistory(BaseModel): # history: List[Tuple[str, str]]
[docs] class ConversationHistory(BaseModel): """ Model for conversation history with context information. :param history: A list of tuples containing the conversation history. :param context_info: A dictionary with information about the conversation context. """ history: List[Tuple[str, str]] context_info: Optional[Dict[str, int]] = None
[docs] class ChatRequest(BaseModel): """ Model for chat request. :param message: The user's input message, with length constraints. """ message: str = Field(..., min_length=1, max_length=1000)
[docs] def get_chat_service(): """ Dependency injection function to get the ChatService instance. :return: An instance of ChatService. """ return chat_service
[docs] @router.post("/chat", response_model=ChatResponse, responses={422: {"model": ErrorResponse}, 500: {"model": ErrorResponse}}) async def chat(request: ChatRequest, chat_service: ChatService = Depends(get_chat_service)): """ Endpoint for processing a chat message. :param request: The ChatRequest containing the user's message. :param chat_service: An instance of ChatService, injected as a dependency. :return: A ChatResponse containing the AI's response. :raises HTTPException: If the message is empty or an error occurs during processing. """ stripped_message = request.message.strip() if not stripped_message: raise HTTPException(status_code=422, detail="Message cannot be empty or just whitespace") try: return await chat_service.process_message(stripped_message) except Exception as e: raise HTTPException(status_code=500, detail=str(e))
[docs] @router.get("/conversation", response_model=ConversationHistory, responses={500: {"model": ErrorResponse}}) async def get_conversation( include_context: Optional[bool] = Query(None, description="Include context information"), chat_service: ChatService = Depends(get_chat_service) ): """ Endpoint for retrieving the conversation history and optionally context information. :param include_context: If True, includes context information in the response. :param chat_service: An instance of ChatService, injected as a dependency. :return: A dictionary containing the conversation history and optionally context info. :raises HTTPException: If an error occurs while retrieving the conversation history. """ try: history = await chat_service.get_conversation_history() response = {"history": history} if include_context: context_info = chat_service.get_context_info() response["context_info"] = context_info return response except Exception as e: raise HTTPException(status_code=500, detail=str(e))
[docs] @router.post("/clear", status_code=status.HTTP_204_NO_CONTENT) def clear_conversation(chat_service: ChatService = Depends(get_chat_service)): """ Endpoint for clearing the conversation history. :param chat_service: An instance of ChatService, injected as a dependency. :return: A Response with a 204 No Content status code on success. :raises HTTPException: If an error occurs while clearing the conversation. """ try: chat_service.clear_conversation() return Response(status_code=status.HTTP_204_NO_CONTENT) except Exception as e: raise HTTPException(status_code=500, detail=str(e))