# Сверка договоров — описание сервиса ## Что делает Сервис автоматически сравнивает договоры и дополнительные документы облачного провайдера (colocation, ЦОД). Юрист загружает файлы (.docx/.doc/.pdf), система извлекает спецификации услуг и при помощи LLM находит изменения: что добавилось, изменилось, удалилось. ## Как устроен пайплайн ``` Загрузка → Парсинг → Порядок → LLM-сравнение → Результаты ``` 1. **Загрузка** — файлы принимаются через веб-интерфейс. Поддерживаются .docx, .doc (старый Word), .pdf, а также .zip с несколькими файлами. 2. **Парсинг** — каждый файл автоматически разбирается на ВМ: извлекаются таблицы и текст. Используется pdfplumber для PDF (с сохранением структуры таблиц) и python-docx для Word. Результат — структурированный JSON (elements_json) и текстовое представление. 3. **Порядок** — файлы можно переставить стрелками ↕. Первый в списке считается базовым договором, остальные — дополнительные документы к нему. 4. **LLM-сравнение** — каждый дополнительный документ последовательно сравнивается с текущей спецификацией. Модель (gpt-oss-120b) получает промпт с текущим списком услуг, текстом дополнительного документа и возвращает операции: - **ADD** — новая услуга - **UPDATE** — изменение цены, количества, названия - **DELETE** — услуга исключена - **UNRESOLVED** — не удалось однозначно сопоставить 5. **Результаты** — накапливаются по цепочке дополнительных документов (Event Sourcing). Каждый следующий дополнительный документ учитывает изменения из предыдущих. Итоговая спецификация — сумма всех применённых операций. ## Архитектура ``` Браузер (index.cfm + JS) │ ├── загрузка файлов ──→ VM (Python, convert_server.py) │ │ │ ├── /upload ──→ parse.py (pdfplumber + python-docx) │ ├── /llm-ops ──→ LLM (api.aillm.ru, gpt-oss-120b) │ └── /process-v2 ──→ Lucee (apply_events.cfm) │ └── API ──→ Lucee (CFML на k8s) │ └── PostgreSQL 15 (документы, спецификации, события, промпты) ``` | Компонент | Где | Технология | |-----------|-----|------------| | Веб-интерфейс | Lucee 6.0 (k8s) | CFML + JavaScript | | База данных | Внутренний PostgreSQL 15 | JSONB, UUID, advisory locks | | Парсинг документов | ВМ (5.172.178.213) | pdfplumber (PDF) + python-docx (DOCX) | | LLM-анализ | ВМ (5.172.178.213) | Python 3, httpx, SSE-стриминг | | Модель | api.aillm.ru | gpt-oss-120b (бесплатно, 8000 токенов) | ## Event Sourcing Изменения не перезаписывают спецификацию — каждая операция сохраняется как событие в `spec_events`. Текущее состояние (`spec_current`) — материализованное представление всех событий. Это даёт: - **Аудит** — кто/when/откуда каждая строка - **Откат** — можно пересобрать состояние на любой момент - **Provenance** — ссылка на документ-источник, версию промпта, полный ответ LLM ## Промпты Промпты для LLM хранятся в БД и версионируются. Есть два: для первого документа (извлечение) и для сравнения дополнительных документов. Встроенный редактор с историей версий позволяет улучшать промпты без правки кода: сохранил новую версию → она сразу используется LLM. Старые версии остаются в истории, можно откатиться. ## Стек - **Backend**: Lucee 6.0 (CFML) на Kubernetes - **База**: PostgreSQL 15 (JSONB, UUID, window functions) - **Парсинг**: pdfplumber (PDF) + python-docx (DOCX) на ВМ - **LLM-прокси**: Python 3 + httpx + threading (SSE) - **Модель**: gpt-oss-120b (OpenAI-совместимый API) - **Фронтенд**: ванильный JS + Lucide иконки