/
Soldier327
/
LLM_AI
Обзор
Документация
Войти
/
Soldier327
/
LLM_AI
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
api/chat.py
118 строк
4 KB
Soldier-327
Initial commit
24 май 2026, 17:24
24 май 2026, 17:24
dae6bc3
Код
Авторство
О чём код?
import logging from fastapi import APIRouter, HTTPException, status from pydantic import BaseModel, Field, validator from config.settings import settings from services.chat_service import ChatService logger = logging.getLogger(__name__) router = APIRouter(prefix="/api", tags=["chat"]) # Модели данных class ChatRequest(BaseModel): message: str = Field(..., min_length=1, max_length=settings.api_max_message_length, description="Сообщение пользователя") @validator('message') def validate_message(cls, v): # Дополнительная валидация if not v or not v.strip(): raise ValueError("Сообщение не может быть пустым") if len(v.strip()) > settings.api_max_message_length: raise ValueError(f"Сообщение не может превышать {settings.api_max_message_length} символов") # Проверка на слишком много пробелов if len(v.split()) > 500: raise ValueError("Слишком много слов в сообщении") return v.strip() class ChatResponse(BaseModel): response: str from_cache: bool = False status: str = "success" class ErrorResponse(BaseModel): error: str status: str = "error" # Сервис (синглтон) chat_service = ChatService() @router.post( "/chat", response_model=ChatResponse, responses={ 400: {"model": ErrorResponse, "description": "Bad Request"}, 503: {"model": ErrorResponse, "description": "Service Unavailable"}, 500: {"model": ErrorResponse, "description": "Internal Server Error"} } ) async def chat_endpoint(request: ChatRequest): """ Эндпоинт для общения с LLM ассистентом - **message**: сообщение пользователя (1-1000 символов) Возвращает ответ от ассистента с информацией о статусе и кеше """ logger.info(f"Получен запрос: message={request.message[:100]}...") try: # Вызов бизнес-логики result = await chat_service.process_message(request.message) if result["status"] == "error": # Обработка ошибок бизнес-логики error_msg = result.get("error", "Unknown error") if "таймаут" in error_msg.lower() or "timeout" in error_msg.lower(): raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="Сервис временно недоступен. Попробуйте позже." ) else: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Внутренняя ошибка сервера" ) return ChatResponse( response=result["response"], from_cache=result["from_cache"], status="success" ) except HTTPException: raise except Exception as e: logger.error(f"Необработанная ошибка в API: {str(e)}", exc_info=True) raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Внутренняя ошибка сервера" ) @router.get("/health") async def health_check(): """Health check эндпоинт""" return { "status": "healthy", "cache_stats": chat_service.cache.get_stats() } @router.post("/cache/clear") async def clear_cache(): """Очистка кеша (административный эндпоинт)""" chat_service.cache.clear() logger.info("Кеш очищен по запросу API") return {"status": "cache_cleared"}