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

203 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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
from datetime import datetime, UTC
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()
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:
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}"
)
if env_settings.apiMode != 'bench':
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Environment {environment} is not configured for bench mode"
)
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}"
)
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
)
return QueryResponse(
request_id=request_id,
timestamp=datetime.now(UTC).isoformat().replace('+00:00', 'Z'),
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()
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:
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}"
)
if env_settings.apiMode != 'backend':
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Environment {environment} is not configured for backend mode"
)
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}"
)
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
)
return QueryResponse(
request_id=request_id,
timestamp=datetime.now(UTC).isoformat().replace('+00:00', 'Z'),
environment=environment,
response={"answers": response_data}
)
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()