diff --git a/.gitignore b/.gitignore index 4ed861f..59381cf 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,6 @@ dogovora/ testgen/out/ testgen/out_100files/ contracts-flask/hz/ +contractor-legacy/ llm.key loadtest/ diff --git a/DOC/architecture-contracts-flask.md b/DOC/architecture-contracts-flask.md new file mode 100644 index 0000000..f2d0843 --- /dev/null +++ b/DOC/architecture-contracts-flask.md @@ -0,0 +1,91 @@ +# Архитектура contracts-flask (актуально на v2.0.16) + +Сервис сверки договоров. Flask + vanilla JS (без frontend-фреймворков). +Managed на Nubes (Штурвал), redeploy через панель (не kubectl). + +## Компоненты + +``` +Браузер (vanilla JS: files.js, compare.js, app.js) + │ + ├─ PUT файла → ВМ-буфер (WebDAV /contracts-upload/) + │ Браузер кладёт файл на ВМ, т.к. managed-gateway рвёт тело >64 КБ. + │ ВМ: 5.172.178.213, домен contracts.kube5s.ru. + │ + ├─ /, /static/*, /templates/* → Managed Flask + │ Отдаёт HTML + JS. + │ + └─ API (SQLite, WAL) → LLM (api.aillm.ru, gpt-oss-120b) + /api/upload_refs — бэк сам тянет файл с ВМ (egress не лимитирован) + /process-v2 (SSE) — конвейер сравнения + /api/classify-* — классификация + /chat — чат по спецификации +``` + +## БД + +- **SQLite**, WAL-режим, `/tmp/contracts.db`. +- Thread-local соединения (`db/connection.py`), API совместим с PostgreSQL + через `_pg_to_sqlite()`. +- Таблицы: `documents`, `supplements`, `spec_current`, `spec_events`, + `prompts`, `upload_chunks`. + +## Event sourcing (спецификация) + +- `spec_events` — append-only журнал операций (история). +- `spec_current` — материализованное текущее состояние (для рендера/сравнения). +- `_hash(name, date_start)` = sha256(name.strip().lower() + "|" + normalize_date)[:16] — ключ строки. +- `apply_ops()` обрабатывает ADD / UPDATE / DELETE / UNRESOLVED. + +## Загрузка файлов + +1. `uploadFile()` (files.js) — браузер PUT файла в ВМ-буфер (WebDAV). +2. `POST /api/upload_refs {files:[{name,size,url}]}` — бэк тянет файл с ВМ + по `url` (egress без лимита), конвертирует `.doc` → `.docx` + (`contracts_upload_sink`), парсит и кладёт в БД. +3. Парсинг: pdfplumber / python-docx → `elements_json`. + +## ZIP (важно: клиентское раскрытие) + +⚠️ ZIP раскрывается **на клиенте**, НЕ серверным `/unzip-upload` (тот — legacy). + +- `expandZipClient(f)` (files.js) — рекурсивно раскрывает архив через + `window.listZipFiles` (endpoint drhider, подтянут в браузере). +- Каждый вложенный файл получает `zip_source = имя архива` для группировки + в таблице. +- Fallback: если раскрыть не удалось — архив кладётся как есть. +- Фильтр вложений: `.pdf`, `.doc`, `.docx`. + +## Сравнение (`/process-v2`, SSE) + +1. `run_pipeline()` шлёт SSE-события браузеру. +2. Текущая спецификация → текст → LLM → `{mode, ops[]}`. +3. **Трансляция `target_id` → `target_hash`**: LLM возвращает `target_id: "r1"` + (индекс строки), а `apply_ops()` читает `target_hash`. Без трансляции + UPDATE/DELETE уходили бы в UNRESOLVED. +4. `apply_ops()` пишет `spec_events` + обновляет `spec_current`. + +### Режимы LLM + +- `partial` — точечные ADD/UPDATE/DELETE (UPDATE/DELETE по `target_hash`). +- `full_replace` — LLM возвращает полную новую редакцию (все ADD). + ⚠️ Перед применением очищается **только** `spec_current` (`clear_current()`), + чтобы ADD-строки новой редакции не дублировали старые. История + `spec_events` сохраняется. + +## Классификация + +- `api.aillm.ru`, модель `gpt-oss-120b` (конфиденциальные данные — только своя модель). +- `ThreadPoolExecutor(max_workers=4)`. +- Поля: `doc_type`, `own_number`, `parent_number`, `counterparty`, `doc_date`. + +## Конфигурация + +`site/config.py`: VERSION, LLM_URL/KEY/MODEL, CONVERT_SERVICE_URL, +VM_UPLOAD_URL/VM_UPLOAD_PREFIX/VM_UPLOAD_MAX_BYTES (50 МБ), PULL_RETRIES (3). + +## Модуль `upload/` + +Переиспользован из drhider (слои 1–2). Плаг-ин через `sink`: +`create_upload_refs_blueprint(cfg, sink=contracts_upload_sink)`. +Слои 3–4 (in-memory session) — НЕ используются в contracts. diff --git a/contractor b/contractor deleted file mode 160000 index c56b980..0000000 --- a/contractor +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c56b9805019cbb72d6c35f3d53e33c11ae220c3d diff --git a/contracts-flask b/contracts-flask index ebdab73..87524c5 160000 --- a/contracts-flask +++ b/contracts-flask @@ -1 +1 @@ -Subproject commit ebdab731ff601320076d18fa68ff1f46faeacd8c +Subproject commit 87524c54a4b4334973cf1260c6d1bad5cdf54e0a