462 lines
16 KiB
Markdown
462 lines
16 KiB
Markdown
# Brief Bench FastAPI - Текущий статус проекта
|
||
|
||
**Дата:** 17 декабря 2025
|
||
**Статус:** Базовая структура реализована, готова к продолжению
|
||
|
||
---
|
||
|
||
## Что реализовано
|
||
|
||
### 1. Структура проекта
|
||
|
||
```
|
||
brief-bench-fastapi/
|
||
├── app/
|
||
│ ├── api/
|
||
│ │ └── v1/
|
||
│ │ ├── __init__.py
|
||
│ │ └── auth.py POST /api/v1/auth/login
|
||
│ ├── models/
|
||
│ │ ├── __init__.py
|
||
│ │ ├── auth.py LoginRequest, LoginResponse, UserResponse
|
||
│ │ ├── settings.py EnvironmentSettings, UserSettings
|
||
│ │ ├── analysis.py SessionCreate, SessionResponse, SessionList
|
||
│ │ └── query.py BenchQueryRequest, BackendQueryRequest
|
||
│ ├── services/
|
||
│ │ ├── __init__.py
|
||
│ │ └── auth_service.py AuthService (login logic)
|
||
│ ├── interfaces/
|
||
│ │ ├── __init__.py
|
||
│ │ ├── base.py TgBackendInterface (ЗАГЛУШКА - нужна реализация)
|
||
│ │ └── db_api_client.py DBApiClient (методы для DB API)
|
||
│ ├── middleware/
|
||
│ │ └── __init__.py
|
||
│ ├── utils/
|
||
│ │ ├── __init__.py
|
||
│ │ └── security.py JWT encode/decode
|
||
│ ├── __init__.py
|
||
│ ├── config.py Settings из .env
|
||
│ ├── dependencies.py DI: get_db_client, get_current_user
|
||
│ └── main.py FastAPI app с CORS
|
||
├── static/ Пусто (нужно скопировать из rag-bench)
|
||
├── tests/ Полный набор тестов (unit/integration/e2e)
|
||
├── certs/ Не создана (для mTLS)
|
||
├── .env.example
|
||
├── .gitignore
|
||
├── requirements.txt
|
||
├── Dockerfile
|
||
├── docker-compose.yml
|
||
├── DB_API_CONTRACT.md Полный контракт для DB API
|
||
├── README.md
|
||
└── PROJECT_STATUS.md Этот файл
|
||
```
|
||
|
||
---
|
||
|
||
## Реализованные компоненты
|
||
|
||
### 1. Configuration (app/config.py)
|
||
- Загрузка из .env через pydantic-settings
|
||
- Настройки для 3 окружений RAG (IFT, PSI, PROD)
|
||
- JWT конфигурация
|
||
- DB API URL
|
||
|
||
### 2. Pydantic Models (app/models/)
|
||
|
||
**auth.py:**
|
||
- `LoginRequest` - login (8 цифр) + client_ip
|
||
- `UserResponse` - user_id, login, last_login_at, created_at
|
||
- `LoginResponse` - access_token + user
|
||
- `TokenPayload` - user_id, login, exp
|
||
|
||
**settings.py:**
|
||
- `EnvironmentSettings` - настройки для одного окружения (apiMode, bearerToken, platformUserId, etc.)
|
||
- `UserSettings` - настройки пользователя для всех 3 окружений
|
||
- `UserSettingsUpdate` - обновление настроек
|
||
|
||
**analysis.py:**
|
||
- `SessionCreate` - создание сессии анализа
|
||
- `SessionResponse` - полная сессия
|
||
- `SessionListItem` - элемент списка сессий
|
||
- `SessionList` - список с total
|
||
|
||
**query.py:**
|
||
- `QuestionRequest` - body + with_docs
|
||
- `BenchQueryRequest` - environment + questions[]
|
||
- `BackendQueryRequest` - environment + questions[] + reset_session
|
||
- `QueryResponse` - request_id, timestamp, environment, response
|
||
|
||
### 3. Interfaces (app/interfaces/)
|
||
|
||
**base.py (ЗАГЛУШКА!):**
|
||
```python
|
||
class TgBackendInterface:
|
||
def __init__(self, api_prefix: str, **kwargs)
|
||
async def get(path, params, response_model)
|
||
async def post(path, body, response_model)
|
||
async def put(path, body, response_model)
|
||
async def delete(path)
|
||
```
|
||
**Требует реализации пользователем!** Должна включать:
|
||
- httpx.AsyncClient для HTTP запросов
|
||
- Автоматическую сериализацию/десериализацию Pydantic моделей
|
||
- Error handling и retry logic
|
||
- Логирование
|
||
|
||
**db_api_client.py:**
|
||
Наследуется от TgBackendInterface, методы:
|
||
- `login_user(LoginRequest) -> UserResponse`
|
||
- `get_user_settings(user_id) -> UserSettings`
|
||
- `update_user_settings(user_id, settings) -> UserSettings`
|
||
- `save_session(user_id, session_data) -> SessionResponse`
|
||
- `get_sessions(user_id, environment, limit, offset) -> SessionList`
|
||
- `get_session(user_id, session_id) -> SessionResponse`
|
||
- `delete_session(user_id, session_id) -> dict`
|
||
|
||
### 4. Services (app/services/)
|
||
|
||
**auth_service.py:**
|
||
- `AuthService.login(login, client_ip)` - авторизация через DB API + генерация JWT
|
||
|
||
### 5. Security & Auth (app/utils/security.py)
|
||
- `create_access_token(data, expires_delta)` - создание JWT
|
||
- `decode_access_token(token)` - валидация JWT
|
||
|
||
### 6. Dependencies (app/dependencies.py)
|
||
- `get_db_client()` - DI для DBApiClient
|
||
- `get_current_user(credentials)` - middleware для auth
|
||
|
||
### 7. API Endpoints (app/api/v1/)
|
||
|
||
**auth.py:**
|
||
- `POST /api/v1/auth/login?login=12345678` - авторизация
|
||
- Возвращает JWT token + user info
|
||
- Фиксирует IP клиента
|
||
|
||
### 8. Main App (app/main.py)
|
||
- FastAPI app с CORS
|
||
- Include router для auth
|
||
- Health endpoint: GET /health
|
||
- Root endpoint: GET /
|
||
|
||
### 9. Docker (Dockerfile, docker-compose.yml)
|
||
- Multi-stage build
|
||
- Порт 8000
|
||
- Volumes: certs/ (ro), static/
|
||
- Network: brief-bench-network
|
||
|
||
### 10. Documentation
|
||
- **DB_API_CONTRACT.md** - полный контракт для DB API сервиса
|
||
- **README.md** - инструкции по запуску и разработке
|
||
- **.env.example** - пример конфигурации
|
||
|
||
---
|
||
|
||
## Что НЕ реализовано (TODO)
|
||
|
||
### 1. TgBackendInterface реализация (КРИТИЧНО!)
|
||
Файл: `app/interfaces/base.py`
|
||
|
||
Нужно реализовать:
|
||
```python
|
||
class TgBackendInterface:
|
||
def __init__(self, api_prefix: str, **kwargs):
|
||
self.api_prefix = api_prefix
|
||
self.client = httpx.AsyncClient(
|
||
timeout=kwargs.get('timeout', 30),
|
||
# ... другие настройки
|
||
)
|
||
|
||
async def get(self, path, params=None, response_model=None, **kwargs):
|
||
url = f"{self.api_prefix}{path}"
|
||
response = await self.client.get(url, params=params)
|
||
response.raise_for_status()
|
||
data = response.json()
|
||
if response_model:
|
||
return response_model(**data)
|
||
return data
|
||
|
||
# аналогично post, put, delete
|
||
```
|
||
|
||
### 2. API Endpoints для Settings
|
||
Файл: `app/api/v1/settings.py` (создать!)
|
||
|
||
```python
|
||
@router.get("/settings")
|
||
async def get_settings(user: dict = Depends(get_current_user)):
|
||
# Получить настройки пользователя из DB API
|
||
|
||
@router.put("/settings")
|
||
async def update_settings(settings: UserSettingsUpdate, user: dict = Depends(get_current_user)):
|
||
# Обновить настройки через DB API
|
||
```
|
||
|
||
### 3. API Endpoints для Query
|
||
Файл: `app/api/v1/query.py` (создать!)
|
||
|
||
```python
|
||
@router.post("/query/bench")
|
||
async def bench_query(request: BenchQueryRequest, user: dict = Depends(get_current_user)):
|
||
# Отправить batch запрос к RAG backend через RagService
|
||
|
||
@router.post("/query/backend")
|
||
async def backend_query(request: BackendQueryRequest, user: dict = Depends(get_current_user)):
|
||
# Отправить вопросы по одному через RagService
|
||
```
|
||
|
||
### 4. API Endpoints для Analysis Sessions
|
||
Файл: `app/api/v1/analysis.py` (создать!)
|
||
|
||
```python
|
||
@router.post("/analysis/sessions")
|
||
async def create_session(session: SessionCreate, user: dict = Depends(get_current_user)):
|
||
# Сохранить сессию через DB API
|
||
|
||
@router.get("/analysis/sessions")
|
||
async def get_sessions(environment: str = None, user: dict = Depends(get_current_user)):
|
||
# Получить список сессий
|
||
|
||
@router.get("/analysis/sessions/{session_id}")
|
||
async def get_session(session_id: str, user: dict = Depends(get_current_user)):
|
||
# Получить конкретную сессию
|
||
|
||
@router.delete("/analysis/sessions/{session_id}")
|
||
async def delete_session(session_id: str, user: dict = Depends(get_current_user)):
|
||
# Удалить сессию
|
||
```
|
||
|
||
### 5. RAG Service
|
||
Файл: `app/services/rag_service.py` (создать!)
|
||
|
||
```python
|
||
class RagService:
|
||
def __init__(self):
|
||
# Создать 3 httpx.AsyncClient для IFT, PSI, PROD
|
||
# Настроить mTLS из config
|
||
|
||
async def send_bench_query(self, environment: str, questions: list, user_settings: dict):
|
||
# Отправить batch запрос к RAG backend
|
||
# Headers: Request-Id, System-Id, Bearer token (из user_settings)
|
||
|
||
async def send_backend_query(self, environment: str, questions: list, user_settings: dict):
|
||
# Отправить вопросы по одному
|
||
# После каждого вопроса: reset session если resetSessionMode=true
|
||
```
|
||
|
||
### 6. Services для Settings и Analysis
|
||
Файлы:
|
||
- `app/services/settings_service.py` (создать!)
|
||
- `app/services/analysis_service.py` (создать!)
|
||
|
||
### 7. Frontend Integration
|
||
- Скопировать `index.html`, `app.js`, `styles.css` из rag-bench в `static/`
|
||
- Создать `static/api-client.js` для работы с FastAPI API
|
||
- Добавить login screen в index.html
|
||
- Обновить app.js для использования api-client.js
|
||
|
||
### 8. Middleware (опционально)
|
||
- `app/middleware/logging.py` - логирование запросов
|
||
- `app/middleware/error_handler.py` - глобальная обработка ошибок
|
||
|
||
### 9. Tests COMPLETED
|
||
- **Unit Tests** (119 tests, 99% coverage) - `tests/unit/`
|
||
- All services, models, utilities tested in isolation
|
||
- All external dependencies mocked
|
||
- Run: `.\run_unit_tests.bat`
|
||
- **Integration Tests** (DB API integration) - `tests/integration/`
|
||
- FastAPI endpoints with real DB API
|
||
- Requires DB API service running
|
||
- Run: `.\run_integration_tests.bat`
|
||
- **End-to-End Tests** (Full stack) - `tests/e2e/`
|
||
- Complete workflows: auth → query → save → retrieve
|
||
- Requires all services (FastAPI + DB API + RAG backends)
|
||
- Real network calls to RAG backends
|
||
- Run: `.\run_e2e_tests.bat`
|
||
- **Test Documentation** - `TESTING.md`
|
||
- Comprehensive testing guide
|
||
- Setup instructions for each test level
|
||
- Troubleshooting and best practices
|
||
|
||
---
|
||
|
||
## Важные детали для продолжения
|
||
|
||
### Архитектура авторизации
|
||
1. Пользователь отправляет POST /api/v1/auth/login?login=12345678
|
||
2. FastAPI вызывает DB API: POST /users/login
|
||
3. DB API возвращает UserResponse (user_id, login, ...)
|
||
4. FastAPI генерирует JWT token с {user_id, login, exp}
|
||
5. Возвращает {access_token, user}
|
||
6. Клиент сохраняет token в localStorage
|
||
7. Все последующие запросы: Authorization: Bearer {token}
|
||
8. Middleware get_current_user проверяет token
|
||
|
||
### Настройки пользователя
|
||
- **В .env** (не редактируются из UI): хосты RAG, порты, endpoint'ы, пути к сертификатам
|
||
- **В БД** (индивидуальны для каждого пользователя): bearerToken, systemPlatform, platformUserId, withClassify, resetSessionMode
|
||
- Каждый пользователь имеет свои настройки для 3 окружений (IFT, PSI, PROD)
|
||
|
||
### RAG Backend Integration
|
||
**Bench mode:**
|
||
```python
|
||
POST https://{IFT_RAG_HOST}:{IFT_RAG_PORT}/{IFT_RAG_ENDPOINT}
|
||
Headers:
|
||
Content-Type: application/json
|
||
Request-Id: {uuid}
|
||
System-Id: brief-bench-ift
|
||
Authorization: Bearer {user_settings.bearerToken} # если задан
|
||
System-Platform: {user_settings.systemPlatform} # если задан
|
||
Body: [
|
||
{"body": "вопрос", "with_docs": true},
|
||
...
|
||
]
|
||
```
|
||
|
||
**Backend mode:**
|
||
```python
|
||
# Для каждого вопроса:
|
||
POST https://{host}:{port}/{backendAskEndpoint}
|
||
Headers:
|
||
Platform-User-Id: {user_settings.platformUserId}
|
||
Platform-Id: {user_settings.platformId}
|
||
Authorization: Bearer {user_settings.bearerToken} # если задан
|
||
Body: {
|
||
"question": "вопрос",
|
||
"user_message_id": 1,
|
||
"user_message_datetime": "2025-12-17T12:00:00Z",
|
||
"with_classify": false
|
||
}
|
||
|
||
# Если resetSessionMode=true:
|
||
POST https://{host}:{port}/{backendResetEndpoint}
|
||
Body: {
|
||
"user_message_datetime": "2025-12-17T12:00:00Z"
|
||
}
|
||
```
|
||
|
||
### DB API Endpoints (см. DB_API_CONTRACT.md)
|
||
- POST /users/login
|
||
- GET /users/{user_id}/settings
|
||
- PUT /users/{user_id}/settings
|
||
- POST /users/{user_id}/sessions
|
||
- GET /users/{user_id}/sessions
|
||
- GET /users/{user_id}/sessions/{session_id}
|
||
- DELETE /users/{user_id}/sessions/{session_id}
|
||
|
||
---
|
||
|
||
## План дальнейшей работы
|
||
|
||
### Этап 1: Реализовать TgBackendInterface
|
||
**Приоритет:** ВЫСОКИЙ
|
||
**Файл:** app/interfaces/base.py
|
||
|
||
Без этого DB API клиент не будет работать.
|
||
|
||
### Этап 2: Добавить недостающие API endpoints
|
||
**Приоритет:** ВЫСОКИЙ
|
||
**Файлы:**
|
||
- app/api/v1/settings.py
|
||
- app/api/v1/query.py
|
||
- app/api/v1/analysis.py
|
||
|
||
Зарегистрировать в app/main.py:
|
||
```python
|
||
from app.api.v1 import auth, settings, query, analysis
|
||
|
||
app.include_router(settings.router, prefix="/api/v1")
|
||
app.include_router(query.router, prefix="/api/v1")
|
||
app.include_router(analysis.router, prefix="/api/v1")
|
||
```
|
||
|
||
### Этап 3: Реализовать RAG Service
|
||
**Приоритет:** ВЫСОКИЙ
|
||
**Файл:** app/services/rag_service.py
|
||
|
||
Нужно для query endpoints.
|
||
|
||
### Этап 4: Реализовать Settings & Analysis Services
|
||
**Приоритет:** СРЕДНИЙ
|
||
**Файлы:**
|
||
- app/services/settings_service.py
|
||
- app/services/analysis_service.py
|
||
|
||
### Этап 5: Frontend Integration
|
||
**Приоритет:** СРЕДНИЙ
|
||
- Скопировать static/ файлы из rag-bench
|
||
- Создать api-client.js
|
||
- Добавить login screen
|
||
- Обновить app.js
|
||
|
||
### Этап 6: Testing & Deployment
|
||
**Приоритет:** НИЗКИЙ
|
||
- Создать .env из .env.example
|
||
- Добавить mTLS сертификаты в certs/
|
||
- docker-compose up
|
||
- Тестирование
|
||
|
||
---
|
||
|
||
## Dependencies (requirements.txt)
|
||
|
||
```
|
||
fastapi==0.104.1
|
||
uvicorn[standard]==0.24.0
|
||
python-multipart==0.0.6
|
||
httpx==0.25.2
|
||
pydantic==2.5.0
|
||
pydantic-settings==2.1.0
|
||
python-jose[cryptography]==3.3.0
|
||
passlib[bcrypt]==1.7.4
|
||
anyio==4.1.0
|
||
python-dotenv==1.0.0
|
||
fastapi-cors==0.0.6
|
||
```
|
||
|
||
---
|
||
|
||
## Команды для разработки
|
||
|
||
```bash
|
||
# Установить зависимости
|
||
pip install -r requirements.txt
|
||
|
||
# Запустить локально
|
||
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
|
||
|
||
# Docker
|
||
docker-compose up -d
|
||
docker-compose logs -f fastapi
|
||
docker-compose down
|
||
|
||
# Проверить здоровье
|
||
curl http://localhost:8000/health
|
||
```
|
||
|
||
---
|
||
|
||
## Примечания
|
||
|
||
1. **TgBackendInterface** - это ваша реализация, которая будет использоваться во всех клиентах (DBApiClient, возможно RagClient в будущем)
|
||
|
||
2. **api_prefix** - каждый клиент инициализируется с базовым URL (например, http://db-api:8080/api/v1)
|
||
|
||
3. **Pydantic схемы** - используются везде для type-safety и валидации
|
||
|
||
4. **JWT токены** - 30-дневная экспирация, содержат user_id и login
|
||
|
||
5. **mTLS** - настраивается в .env, пути к сертификатам для каждого окружения
|
||
|
||
6. **CORS** - сейчас allow_origins=["*"], нужно настроить для production
|
||
|
||
7. **Ошибки** - возвращаются в формате FastAPI HTTPException с detail
|
||
|
||
---
|
||
|
||
## Готово к продолжению!
|
||
|
||
Вся базовая структура создана. Следующий шаг - реализация TgBackendInterface и остальных endpoints.
|
||
|
||
**Следующий чат:** начните с реализации TgBackendInterface или создания недостающих API endpoints.
|