5.8 KiB
5.8 KiB
Архитектура Contracts App
Обзор
Сервис Сверка договоров — автоматизированная обработка договоров и допников (docx/pdf) с извлечением структурированных данных, отслеживанием изменений и восстановлением истории договора во времени.
Принципы
- НЕ МОНОЛИТ — каждый слой независим, отдельный файл, своя зона ответственности
- Данные не покидают облако — всё в PostgreSQL внутри кластера
- Ничего не терять — парсер отдаёт полный слепок документа, LLM решает что важно
- Исключения — не фантазировать — нерешаемые подзадачи отмечать явно
Слои приложения
┌─────────────────────────────────────────────┐
│ app.py │
│ ContractsApp (сборка) │
├──────────┬──────────┬──────────┬────────────┤
│ db.py │ parser.py│ test_ │ (будущие) │
│ (БД) │ (парсинг)│ routes.py │ llm.py │
│ │ │ (/test) │ upload.py│
└──────────┴──────────┴──────────┴────────────┘
| Слой | Файл | Что делает | Статус |
|---|---|---|---|
| Ядро | app.py |
Flask-приложение, инициализация, регистрация Blueprint | ✅ |
| БД | db.py |
connect(), query(), _pg_connect() |
✅ |
| Тесты | test_routes.py |
Blueprint /test — мост к БД извне |
✅ |
| Парсер | parser.py |
parse(bytes, mime) → elements для docx/pdf/doc/zip |
✅ |
| LLM | llm.py |
Нормализация строк через aillm.ru (120B) | ⬜ |
| Загрузка | upload.py |
Приём файлов, сохранение в БД | ⬜ |
Поток обработки документа
Пользователь
│
▼
POST /upload (файл .docx/.pdf/.doc/.zip)
│
▼
upload.py: сохранить в contract_docs (original_bytes)
│
▼
parser.py: parse(bytes, mime) → elements JSON
│
▼
db.py: сохранить parsed_json в contract_docs
│
▼
llm.py: отправить elements → LLM → нормализованные spec_rows
│
▼
db.py: сохранить в spec_rows, сравнить с предыдущими → spec_history
│
▼
GET /contract/{id}/history → полная история изменений
Схема БД (план)
contract_docs — исходные файлы + сырой парсинг
id UUID PK
contract_id → contracts.id
filename TEXT
mime_type TEXT
original_bytes BYTEA ← сам файл
parsed_json JSONB ← выдача parser.py
created_at TIMESTAMPTZ
contracts — договоры
id UUID PK
number TEXT ← номер договора
client TEXT ← клиент
date DATE
status TEXT
supplements — допники
id UUID PK
contract_id → contracts.id
number TEXT
date DATE
type TEXT ← новый / изменение / расторжение
doc_id → contract_docs.id
spec_rows — строки спецификаций
id UUID PK
supplement_id → supplements.id
row_num INT
name TEXT ← наименование услуги
price NUMERIC
qty NUMERIC
sum NUMERIC
date_start DATE
date_end DATE
spec_history — история изменений
id UUID PK
spec_row_id → spec_rows.id
supplement_id → supplements.id
change_type TEXT ← added / changed / deleted / unchanged
old_values JSONB
new_values JSONB
API эндпоинты
| Метод | Путь | Слой | Что |
|---|---|---|---|
| GET | / |
app.py | Главная (HTML) |
| GET | /health |
app.py | Health check → "OK" |
| GET | /test |
test_routes | Статус БД + список команд |
| POST | /test {"action":"status"} |
test_routes | Статус БД |
| POST | /test {"action":"createdb"} |
test_routes | Создать БД contracts |
| POST | /test {"action":"tables"} |
test_routes | Список таблиц |
| POST | /test {"action":"sql","sql":"..."} |
test_routes | Произвольный SQL |
Технологии
| Компонент | Выбор |
|---|---|
| Язык | Python 3.12 |
| Фреймворк | Flask |
| БД | PostgreSQL (внутрикластерный) |
| Парсинг docx | python-docx |
| Парсинг .doc | LibreOffice (headless) |
| Парсинг PDF | pdfplumber |
| LLM | aillm.ru API (120B модель) |
| Деплой | pythonk8s.services.ngcloud.ru |
| Репозиторий | gitea.services.ngcloud.ru/Nail/contracts-app.git |
Конфигурация (переменные окружения)
| Переменная | Назначение |
|---|---|
DB_HOST |
Хост PostgreSQL |
DB_PORT |
Порт (5432) |
DB_NAME |
Имя БД (contracts) |
DB_USER |
Пользователь |
DB_PASS |
Пароль |
DB_SSLMODE |
SSL mode (disable) |
LLM_API_KEY |
Ключ aillm.ru (будет) |
LLM_API_URL |
URL LLM API (будет) |