CoolFace
Apppublic

ruby2210/rag-chatbot

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
chat_endpoints.py202 linesDownload Raw Back to api
1"""2Chat endpoints for the RAG Chatbot application.3Implements the API endpoints for chat functionality.4"""5from fastapi import APIRouter, HTTPException, Depends, Query6from pydantic import BaseModel, Field7from typing import Optional, List, Dict, Any8from uuid import uuid49from sqlalchemy.orm import Session10from ..services.rag_service import rag_service11from ..services.agent_service import agent_service12from ..utils.database import get_db13from ..utils.config import settings14from ..utils.logging import get_logger15from ..models.chat_history import ChatHistory16from datetime import datetime17 18 19logger = get_logger(__name__)20router = APIRouter()21 22 23class ChatRequest(BaseModel):24    """25    Request model for chat endpoint.26    """27    message: str = Field(..., description="The user's message/query")28    session_id: Optional[str] = Field(None, description="Session identifier; if not provided, a new session is created")29    context_type: str = Field("full_book", description="Type of context to use: 'full_book' or 'selected_text_only'")30 31 32class ChatResponse(BaseModel):33    """34    Response model for chat endpoint.35    """36    response: str = Field(..., description="The chatbot's response to the user's query")37    session_id: str = Field(..., description="The session identifier")38    context_type: str = Field(..., description="The type of context used")39    retrieved_sources: List[Dict[str, Any]] = Field(default=[], description="List of sources used to generate the response")40 41 42class SelectedTextChatRequest(BaseModel):43    """44    Request model for selected-text chat endpoint.45    """46    message: str = Field(..., description="The user's message/query")47    selected_text: str = Field(..., description="The text selected by the user that will be the only context")48    session_id: Optional[str] = Field(None, description="Session identifier; if not provided, a new session is created")49    context_type: str = Field("selected_text_only", description="Must be 'selected_text_only' for this endpoint")50 51 52class HistoryMessage(BaseModel):53    """54    Model for individual messages in chat history.55    """56    message_id: str = Field(..., description="Unique identifier for the message")57    role: str = Field(..., description="Either 'user' or 'assistant'")58    content: str = Field(..., description="The actual message content")59    timestamp: str = Field(..., description="ISO format timestamp")60    context_type: str = Field(..., description="The type of context used for this message")61 62 63class ChatHistoryResponse(BaseModel):64    """65    Response model for chat history endpoint.66    """67    session_id: str = Field(..., description="The session identifier")68    history: List[HistoryMessage] = Field(..., description="List of messages in chronological order")69 70 71class ClearChatRequest(BaseModel):72    """73    Request model for clear chat endpoint.74    """75    session_id: str = Field(..., description="The session identifier to clear")76 77 78class ClearChatResponse(BaseModel):79    """80    Response model for clear chat endpoint.81    """82    session_id: str = Field(..., description="The session identifier that was cleared")83    status: str = Field(..., description="Confirmation status")84    message: str = Field(..., description="Human-readable confirmation message")85 86 87@router.post("/chat", response_model=ChatResponse)88async def chat_endpoint(request: ChatRequest):89    """90    Chat endpoint that handles both full-book and selected-text queries.91    """92    try:93        # Validate context type94        if request.context_type not in ["full_book", "selected_text_only"]:95            raise HTTPException(status_code=400, detail="context_type must be 'full_book' or 'selected_text_only'")96 97        # Create or use provided session ID98        session_id = request.session_id or agent_service.create_session()99 100        # Process the query based on context type101        if request.context_type == "full_book":102            result = rag_service.full_book_query(session_id, request.message)103        else:104            # For selected_text_only, we expect this to be handled by the dedicated endpoint105            # but we'll support it here for flexibility106            result = {107                "response": "Selected text queries should use the /chat/selected-text endpoint",108                "session_id": session_id,109                "context_type": request.context_type,110                "retrieved_sources": []111            }112 113        return ChatResponse(**result)114 115    except Exception as e:116        logger.error(f"Error in chat endpoint: {e}")117        raise HTTPException(status_code=500, detail=f"Error processing chat request: {str(e)}")118 119 120@router.post("/chat/selected-text", response_model=ChatResponse)121async def selected_text_chat_endpoint(request: SelectedTextChatRequest):122    """123    Chat endpoint specifically for selected-text-only queries.124    Enforces strict context isolation to only the provided selected text.125    """126    try:127        # Validate that selected_text is provided128        if not request.selected_text or not request.selected_text.strip():129            raise HTTPException(status_code=400, detail="selected_text is required and cannot be empty")130 131        # Create or use provided session ID132        session_id = request.session_id or agent_service.create_session()133 134        # Process the selected-text query135        result = rag_service.selected_text_query(session_id, request.message, request.selected_text)136 137        return ChatResponse(**result)138 139    except Exception as e:140        logger.error(f"Error in selected-text chat endpoint: {e}")141        raise HTTPException(status_code=500, detail=f"Error processing selected-text chat request: {str(e)}")142 143 144@router.get("/chat/history", response_model=ChatHistoryResponse)145async def get_chat_history(session_id: str = Query(..., description="The session identifier")):146    """147    Retrieve the chat history for a specific session.148    """149    try:150        from sqlalchemy.orm import Session151        from ..utils.database import SessionLocal152        from ..models.chat_history import ChatHistory as ChatHistoryModel153 154        db = SessionLocal()155        try:156            # Query the database for chat history for this session with all details157            history_records = db.query(ChatHistoryModel).filter(158                ChatHistoryModel.session_id == session_id159            ).order_by(ChatHistoryModel.timestamp).all()160 161            # Format the history for the response162            history_messages = []163            for record in history_records:164                history_messages.append(HistoryMessage(165                    message_id=record.message_id,166                    role=record.role,167                    content=record.content,168                    timestamp=record.timestamp.isoformat() if record.timestamp else datetime.utcnow().isoformat(),169                    context_type=record.query_context_type170                ))171 172            return ChatHistoryResponse(173                session_id=session_id,174                history=history_messages175            )176        finally:177            db.close()178 179    except Exception as e:180        logger.error(f"Error in get chat history endpoint: {e}")181        raise HTTPException(status_code=500, detail=f"Error retrieving chat history: {str(e)}")182 183 184@router.post("/chat/clear", response_model=ClearChatResponse)185async def clear_chat_endpoint(request: ClearChatRequest):186    """187    Endpoint to clear chat history for a specific session and reset the session state.188    """189    try:190        # Clear the session191        agent_service.clear_session(request.session_id)192 193        # Return confirmation194        return ClearChatResponse(195            session_id=request.session_id,196            status="cleared",197            message="Chat history has been cleared and session reset"198        )199 200    except Exception as e:201        logger.error(f"Error in clear chat endpoint: {e}")202        raise HTTPException(status_code=500, detail=f"Error clearing chat: {str(e)}")