157 lines
11 KiB
Markdown
157 lines
11 KiB
Markdown
# Контракт-чек
|
||
|
||
LLM-сервис скрининга рисков в договорах (PDF/DOCX) по ГК РФ / ГК РБ.
|
||
Telegram-бот MVP + B2B API сейчас; веб + подписки — позже.
|
||
|
||
Pipeline: `PDF/DOCX → текст (pymupdf/tesseract OCR) → чанки → Ollama Cloud (LLM, json-schema + repair-loop) → markdown-отчёт` с цитатами, ссылкой на пункт и дисклеймером «не заменяет юриста».
|
||
|
||
## Документы
|
||
|
||
- [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — **единственный источник истины** для production-рефакторинга. Hexagonal-архитектура, RabbitMQ-конвейер, схемы БД, очередь/ретраи/DLQ, конфиг, deploy, observability.
|
||
- [`docs/DEPLOY.md`](docs/DEPLOY.md) — руководство по развёртыванию: локально, Docker Compose, VPS, seed-token, backup, troubleshooting.
|
||
- [`docs/BUSINESS_IDEA.md`](docs/BUSINESS_IDEA.md) — идея и бизнес-модель.
|
||
- [`docs/IMPLEMENTATION_PLAN.md`](docs/IMPLEMENTATION_PLAN.md) — исходный «ленивый» план. Этап 0 (прототип) актуален; этапы 1+ superseded в `docs/ARCHITECTURE.md`.
|
||
- [`docs/TICKETS.md`](docs/TICKETS.md) — тикеты реализации со статусами.
|
||
|
||
## Архитектура (одна строка)
|
||
|
||
Hexagonal (ports & adapters). Ядро `contract_check.core` владеет всем состоянием
|
||
(Postgres/MinIO/RabbitMQ/LLM/кредиты). Четыре сервиса собираются из него:
|
||
|
||
```
|
||
Telegram ──► bot (aiogram, HTTP-only) ──HTTP──► api (FastAPI) ──publish──► RabbitMQ
|
||
владеет: PG, MinIO, │
|
||
Redis, кредитами ▼
|
||
extract.q ──► worker-extract
|
||
(pymupdf+tesseract, CPU) │
|
||
▼ publish
|
||
analyze.q ──► worker-analyze
|
||
(LLM, I/O) → Report
|
||
```
|
||
|
||
- **api** — единственный писатель для пользовательских мутаций (upload → reserve credit → MinIO → publish `DocumentUploaded`).
|
||
- **worker-extract** — CPU: достаёт текст (PDF/DOCX), при необходимости OCR, грузит `.txt` в MinIO, публикует `DocumentExtracted`.
|
||
- **worker-analyze** — I/O: LLM-анализ по чек-листу, валидация/repair, сохраняет `Report`, `status=done`.
|
||
- **bot** — адаптер: HTTP-клиент к api, **не импортирует** core.db/s3/llm/mq (граница проверяется тестом `tests/unit/test_bot_boundary.py`).
|
||
|
||
## Структура репозитория
|
||
|
||
```
|
||
src/contract_check/
|
||
__main__.py # указывает на prototype (stage-0 CLI сохранён)
|
||
core/ # общий домен (импортируется каждым сервисом)
|
||
config.py logging.py telemetry.py sentry.py metrics.py
|
||
credits.py tokens.py api_keys.py rate_limit.py redis_client.py
|
||
db/ models.py session.py enums.py
|
||
mq/ topology.py publisher.py consumer.py messages.py
|
||
s3/ port.py minio_storage.py
|
||
llm/ port.py ollama_cloud.py factory.py
|
||
analysis/ extractor.py chunker.py checklist.py report_schema.py ocr.py analyzer.py
|
||
api/ # FastAPI-образ
|
||
app.py deps.py middleware.py services.py __main__.py
|
||
admin/ # серверный UI по /admin (users; позже — подписки)
|
||
routes/ health.py documents.py reports.py me.py metrics.py b2b.py
|
||
worker_extract/ # CPU-образ (pymupdf + tesseract)
|
||
consumer.py handler.py extract_document.py __main__.py
|
||
worker_analyze/ # I/O-образ (LLM provider)
|
||
consumer.py handler.py __main__.py
|
||
bot/ # aiogram-адаптер (самый «тощий» образ: только core.logging)
|
||
client.py config.py handlers.py __main__.py
|
||
prototype/ # stage-0 standalone CLI (бенчмарк go/no-go)
|
||
docs/ # документация проекта (README остаётся в корне)
|
||
ARCHITECTURE.md # архитектура, схемы БД, конфиг
|
||
DEPLOY.md # руководство по развёртыванию
|
||
TICKETS.md # статусы тикетов
|
||
IMPLEMENTATION_PLAN.md # исходный план (superseded для этапов 1+)
|
||
BUSINESS_IDEA.md # продукт / бизнес-модель
|
||
srv/ # Dockerfile-ы (один на сервис, deps заточены)
|
||
api/Dockerfile worker-extract/Dockerfile worker-analyze/Dockerfile
|
||
bot/Dockerfile prototype/Dockerfile
|
||
migrations/ # alembic (async): 0001_initial, 0002_api_keys
|
||
tests/
|
||
conftest.py
|
||
unit/ chunker, extractor, llm_ollama_cloud, credits, messages,
|
||
rate_limit, checklist_report, bot_client, bot_boundary
|
||
integration/ upload_pipeline, extract_worker, analyze_worker, b2b_api, credits_db
|
||
docker-compose.yml # default = инфра; --profile services = стек
|
||
pyproject.toml # hatchling + PEP 735 dependency-groups (db/mq/s3/obs/api/extract/analyze/bot/prototype/dev)
|
||
.env.example # полный список env (см. docs/ARCHITECTURE.md §11)
|
||
```
|
||
|
||
## Быстрый старт
|
||
|
||
### Локально (разработка)
|
||
|
||
```bash
|
||
uv sync --group dev # все группы для локальной разработки
|
||
cp .env.example .env # впишите OLLAMA_HOST / OLLAMA_API_KEY
|
||
docker compose up -d # только инфра (postgres/redis/rabbitmq/minio)
|
||
uv run alembic upgrade head # миграции
|
||
uv run python -m contract_check.api # api на :8000
|
||
uv run python -m contract_check.worker_extract # воркер экстракции
|
||
uv run python -m contract_check.worker_analyze # воркер анализа
|
||
uv run python -m contract_check.bot # Telegram-бот
|
||
```
|
||
|
||
### Через Docker Compose
|
||
|
||
```bash
|
||
cp .env.example .env # заполнить секреты (DB, Rabbit, MinIO, Ollama, BOT_TOKEN, ...)
|
||
docker compose up -d # только инфра с healthchecks
|
||
docker compose --profile services up -d --build # + api, worker-extract, worker-analyze, bot
|
||
```
|
||
|
||
Профиль `services` собирает 4 образа из `srv/<service>/Dockerfile` и поднимает их
|
||
с `depends_on: condition: service_healthy`. Edge-прокси (Nginx + certbot) доступен
|
||
профилем `edge` (`deploy/nginx/`, `docs/DEPLOY.md §13`). Observability (Prometheus/Grafana/Tempo/OTel)
|
||
— за будущим профилем `obs`.
|
||
|
||
Порты на хосте (смещены, чтобы не конфликтовать): Postgres `15432`, Redis `17379`,
|
||
RabbitMQ AMQP `5672` / UI `15672`, MinIO `9000` / console `9001`, api `8000` / metrics `9100`,
|
||
worker metrics `9101`/`9102`, edge `80`/`443`.
|
||
|
||
### Stage-0 прототип (бенчмарк)
|
||
|
||
```bash
|
||
uv sync --group prototype
|
||
uv run python -m contract_check prototype contract.pdf # отчёт в stdout
|
||
uv run contract-check contract.pdf -o report.md # или консольная команда
|
||
uv run python -m contract_check prototype contract.pdf --json metrics.json # + метрики go/no-go
|
||
```
|
||
|
||
## API (кратко)
|
||
|
||
JSON-роуты под `/api/v1`; серверный admin UI — по `/admin/*` (FastAPI + Jinja2 + HTMX). Auth зависит от роута:
|
||
|
||
- **Пользовательские роуты** (bot / web / Mini App) — `Authorization: Bearer <user_jwt>`. JWT выдаётся через `/api/v1/auth/telegram/*` после проверки identity от Telegram.
|
||
- **Адаптер-level** (только `/api/v1/auth/telegram/bot`) — `Authorization: Bearer <service_token>`.
|
||
- **B2B** — `X-API-Key`. Управление B2B-ключами требует пользовательский JWT.
|
||
- **Health/metrics** — без auth.
|
||
- **/admin** — HttpOnly cookie с user JWT + `users.role = admin` (или `ADMIN_REQUIRED_ROLE`).
|
||
|
||
| Метод | Путь | Auth | Назначение |
|
||
|---|---|---|---|
|
||
| GET | `/healthz`, `/readyz`, `/metrics` | — | liveness / readiness / Prometheus |
|
||
| POST | `/api/v1/auth/telegram/bot` | service token | бот меняет verified `telegram_id` на JWT |
|
||
| POST | `/api/v1/auth/telegram/web` | — | Telegram Login Widget → JWT |
|
||
| POST | `/api/v1/auth/telegram/miniapp` | — | Mini App `initData` → JWT |
|
||
| POST | `/api/v1/auth/register` | — | регистрация email/password |
|
||
| POST | `/api/v1/auth/login` | — | вход email/password → JWT-пара |
|
||
| GET | `/api/v1/auth/me` | user JWT | introspect JWT |
|
||
| POST | `/api/v1/documents` | user JWT | multipart upload → reserve credit → MinIO → publish → `202 {document_id, correlation_id}` |
|
||
| GET | `/api/v1/documents/{id}` | user JWT | статус + stage (для поллинга) |
|
||
| GET | `/api/v1/reports/{document_id}` | user JWT | `202 {status, stage}` или `200 {markdown, findings, ...}` |
|
||
| GET | `/api/v1/me` | user JWT | `{telegram_id, credits_left}` |
|
||
| POST | `/api/v1/analyze` | `X-API-Key` | B2B: анализ документа |
|
||
| GET | `/api/v1/b2b/reports/{id}`, `/api/v1/b2b/usage` | `X-API-Key` | B2B: отчёт / usage |
|
||
| POST/GET | `/api/v1/b2b/keys`, `/api/v1/b2b/keys/{id}/revoke`, `.../usage` | user JWT | управление B2B-ключами |
|
||
| GET/POST | `/admin/users*` | admin cookie | управление пользователями (list, create, edit, ban, role, credits) |
|
||
|
||
Полная спецификация — `docs/ARCHITECTURE.md §15` (актуализируется).
|
||
|
||
## Проверки (DoD)
|
||
|
||
```bash
|
||
uv run ruff check . && uv run mypy src && uv run pytest -q # unit, быстро
|
||
uv run pytest -m integration -q # интеграционные (нужны контейнеры)
|
||
```
|