brief-rags-bench/app/api/v1/query.py

203 lines
6.5 KiB
Python
Raw Normal View History

2025-12-17 15:37:32 +01:00
"""
Query API endpoints.
Отправка запросов к RAG backends в двух режимах:
1. Bench mode - batch запросы
2. Backend mode - последовательные запросы
"""
from fastapi import APIRouter, Depends, HTTPException, status
from typing import Dict, Any
from app.models.query import BenchQueryRequest, BackendQueryRequest, QueryResponse
from app.interfaces.db_api_client import DBApiClient
from app.services.rag_service import RagService
from app.dependencies import get_db_client, get_current_user
import httpx
import logging
2025-12-25 07:52:08 +01:00
from datetime import datetime, UTC
2025-12-17 15:37:32 +01:00
import uuid
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/query", tags=["query"])
def get_rag_service() -> RagService:
"""Dependency для получения RAG service."""
return RagService()
@router.post("/bench", response_model=QueryResponse)
async def bench_query(
request: BenchQueryRequest,
current_user: dict = Depends(get_current_user),
db_client: DBApiClient = Depends(get_db_client),
rag_service: RagService = Depends(get_rag_service)
):
"""
Отправить batch запрос к RAG backend (bench mode).
Отправляет все вопросы одним запросом.
Args:
request: Запрос с окружением и списком вопросов
Returns:
QueryResponse: Ответ от RAG backend с metadata
"""
user_id = current_user["user_id"]
environment = request.environment.lower()
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
if environment not in ['ift', 'psi', 'prod']:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid environment. Must be one of: ift, psi, prod"
)
try:
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
user_settings_response = await db_client.get_user_settings(user_id)
env_settings = user_settings_response.settings.get(environment)
if not env_settings:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Settings not found for environment: {environment}"
)
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
if env_settings.apiMode != 'bench':
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Environment {environment} is not configured for bench mode"
)
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
request_id = str(uuid.uuid4())
logger.info(
f"User {user_id} sending bench query to {environment}: "
f"{len(request.questions)} questions, request_id={request_id}"
)
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
env_settings_dict = env_settings.model_dump()
response_data = await rag_service.send_bench_query(
environment=environment,
questions=request.questions,
user_settings=env_settings_dict,
request_id=request_id
)
2025-12-25 07:52:08 +01:00
2025-12-17 15:37:32 +01:00
return QueryResponse(
request_id=request_id,
2025-12-25 07:52:08 +01:00
timestamp=datetime.now(UTC).isoformat().replace('+00:00', 'Z'),
2025-12-17 15:37:32 +01:00
environment=environment,
response=response_data
)
except httpx.HTTPStatusError as e:
logger.error(f"RAG backend error for bench query: {e}")
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail=f"RAG backend returned error: {e.response.status_code}"
)
except Exception as e:
logger.error(f"Unexpected error in bench query: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal server error"
)
finally:
await rag_service.close()
@router.post("/backend", response_model=QueryResponse)
async def backend_query(
request: BackendQueryRequest,
current_user: dict = Depends(get_current_user),
db_client: DBApiClient = Depends(get_db_client),
rag_service: RagService = Depends(get_rag_service)
):
"""
Отправить запросы к RAG backend (backend mode).
Отправляет вопросы по одному с возможностью сброса сессии.
Args:
request: Запрос с окружением, вопросами и флагом reset_session
Returns:
QueryResponse: Список ответов от RAG backend с metadata
"""
user_id = current_user["user_id"]
environment = request.environment.lower()
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
if environment not in ['ift', 'psi', 'prod']:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid environment. Must be one of: ift, psi, prod"
)
try:
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
user_settings_response = await db_client.get_user_settings(user_id)
env_settings = user_settings_response.settings.get(environment)
if not env_settings:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Settings not found for environment: {environment}"
)
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
if env_settings.apiMode != 'backend':
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Environment {environment} is not configured for backend mode"
)
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
request_id = str(uuid.uuid4())
logger.info(
f"User {user_id} sending backend query to {environment}: "
f"{len(request.questions)} questions, request_id={request_id}, "
f"reset_session={request.reset_session}"
)
2025-12-18 09:36:24 +01:00
2025-12-17 15:37:32 +01:00
env_settings_dict = env_settings.model_dump()
response_data = await rag_service.send_backend_query(
environment=environment,
questions=request.questions,
user_settings=env_settings_dict,
reset_session=request.reset_session
)
2025-12-25 07:52:08 +01:00
2025-12-17 15:37:32 +01:00
return QueryResponse(
request_id=request_id,
2025-12-25 07:52:08 +01:00
timestamp=datetime.now(UTC).isoformat().replace('+00:00', 'Z'),
2025-12-17 15:37:32 +01:00
environment=environment,
2025-12-25 07:52:08 +01:00
response={"answers": response_data}
2025-12-17 15:37:32 +01:00
)
except httpx.HTTPStatusError as e:
logger.error(f"RAG backend error for backend query: {e}")
raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail=f"RAG backend returned error: {e.response.status_code}"
)
except Exception as e:
logger.error(f"Unexpected error in backend query: {e}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Internal server error"
)
finally:
await rag_service.close()