# Задание Opus 4.8: План decoupling пайплайна contracts-flask Дата: 28.06.2026 | Режим: **plan (интерактивный)** --- ## ⛔ ЧЕГО НЕ ДЕЛАТЬ - **НЕ пиши код.** Анализ и план. Исполнитель — DeepSeek V4 Pro. - **НЕ рисуй mermaid.** Только текст. - **НЕ предлагай «переписать всё с нуля».** ## 📋 КОНТЕКСТ Проект **contracts-flask** — сверка договоров облачного провайдера (colocation, ЦОД) через LLM. ### Текущая архитектура: ``` Браузер │ ▼ check.kube5s.ru (nginx) │ ├── Страницы/статика → Managed Flask (contractor.pythonk8s...) └── API → ВМ :8777 (convert_server.py) │ ├── services/parse.py — PDF (pdfplumber) / DOCX (python-docx) ├── services/upload.py — multipart-загрузка → БД ├── services/classify.py — LLM-классификация (тип/номер/дата/контрагент) ├── services/grouping.py — группировка по контрактам ├── services/process.py — сравнение (LLM + event sourcing) ├── services/llm.py — вызов LLM API ├── services/metrics.py — арифметика + JSON-фиксы ├── db/ — PostgreSQL CRUD └── llm_prompt.py — промпты (из БД, не Lucee) ``` ### Пайплайн (последовательно): ``` 1. Upload → parse.py → elements_json 2. Classify → classify.py → doc_type, own_number, parent_number, counterparty, doc_date 3. Grouping → grouping.py → группы по contract_number 4. Compare → process.py → SSE: ops (ADD/UPDATE/DELETE/UNRESOLVED) 5. Chat → Flask /chat → контекст из spec_current → LLM → ответ ``` ### Фронтенд: Managed Flask (Python 3.12, Dockerfile): - `site/app.py` — роуты: `/`, `/chat`, `/api/prompts/*`, `/health` - `site/templates/index.html` — Jinja2 UI - `site/static/*.js` — 6 JS-файлов, оркестрируют пайплайн - JS вызывает ВМ напрямую: `VM_API = 'https://check.kube5s.ru'` ### БД: PostgreSQL `contracts_check` Таблицы: documents, contracts, supplements, spec_current, spec_events, prompts, upload_chunks. ### LLM: gpt-oss-120b (api.aillm.ru, БЕСПЛАТНО) --- ## 📂 ЧТО ИЗУЧИТЬ ### Основное (contracts-flask/): ``` deploy/convert_server.py — HTTP-роутер, точка входа deploy/services/parse.py — PDF/DOCX парсинг deploy/services/upload.py — multipart-загрузка deploy/services/classify.py — LLM-классификация + фильтр мусора deploy/services/grouping.py — группировка deploy/services/process.py — сравнение (SSE) deploy/services/llm.py — LLM API deploy/services/metrics.py — арифметика + JSON-фиксы deploy/db/*.py — PostgreSQL CRUD (7 файлов) deploy/llm_prompt.py — промпты deploy/classify_worker.py — фоновый процесс site/app.py — Flask-фронтенд site/static/app.js — JS-оркестратор site/static/files.js — загрузка/рендер файлов site/static/groups.js — карточки групп site/static/compare.js — SSE-сравнение site/static/state.js — центральное состояние site/templates/index.html — UI History/architecture.md — архитектура Flask-стека History/session-01-init-2026-06-27.md — история создания ``` ### Контекст из родительского проекта (contracts/History/): ``` History/topics/customer-qa-2026-06-26.md — требования заказчика History/llm-analysis/decoupling-final-plan.md — план размоноличивания JS History/architecture-research-v2-2026-06-27.md — анализ DeepSeek History/opus-architecture-research-2026-06-27.md — опросник Opus History/opus-architecture-research-2026-06-27-review.md — рецензия ``` ВНИМАНИЕ: эти файлы в основном описывают Lucee-морду (contractor/), которая сейчас заморожена. --- ## 🎯 ЗАДАЧА Разработать **подробный план decoupling пайплайна**: ### 1. Модульность пайплайна Каждый шаг — независимый модуль с чёткими входом/выходом. Сейчас `services/` уже так устроены, но: - Модули вызываются напрямую из `convert_server.py` - Нет формального контракта (интерфейса) - Нельзя протестировать изолированно **Вопрос:** как оформить контракты? Dataclass? TypedDict? Proto-буферы? Просто документированные словари? ### 2. Интеграционное тестирование (fixture-based) ``` Тест upload: .docx → upload.py → elements_json (fixture) Тест classify: fixture_elements → classify.py → doc_type/number (fixture) Тест grouping: fixture_classify → grouping.py → группы (fixture) Тест compare: fixture_groups → process.py → ops ``` **Вопросы:** - Где хранить fixtures? `deploy/tests/fixtures/`? - Как мокать LLM? Monkey-patch `_call_llm_classify` / `call_llm`? - БД: отдельная `contracts_test` или in-memory SQLite? - Как очищать БД между тестами? ### 3. Деплой и синхронизация Сейчас: локально правим → git push → вручную копируем на ВМ → рестарт. **Вопрос:** как улучшить? `rsync` из CI? `git pull` на ВМ? systemd + watchdog? ### 4. Перспектива переезда на managed Flask Сейчас managed Flask не может принимать файлы (ограничение платформы). Когда починят — вся загрузка переедет с ВМ на managed. **Вопрос:** что уже сейчас сделать в коде, чтобы переезд был безболезненным? Абстракция над upload? Флаги `UPLOAD_BACKEND=vm|managed`? ### 5. Вопросы к заказчику (блокируют развитие) Без ответов нельзя двигаться дальше: - Формат CRM-данных для сверки? - Есть ли примеры реальных расхождений? - Приоритет: точность vs скорость? - Готов ли дать 30-50 реальных документов для золотого набора? **Вопрос к Opus:** какие ещё вопросы НЕОБХОДИМО задать заказчику прямо сейчас? --- ## 🔄 ИНТЕРАКТИВНЫЙ РЕЖИМ Ты в режиме **plan**. Если тебе нужны уточнения по коду, архитектуре, или ты хочешь предложить альтернативный подход который требует моего мнения — **задай вопрос**. Я (DeepSeek) отвечу. Не пиши финальный план пока не закроем все неясности. --- ## ⚠️ ОГРАНИЧЕНИЯ - Managed Flask: Python 3.12, Dockerfile, `site/` — обязательная структура - ВМ: 5.172.178.213, Ubuntu, порт 8777 - БД: PostgreSQL 15, `contracts_check` - LLM: gpt-oss-120b, 8000 токенов, бесплатно, ~5-30s/вызов - JS-фронтенд: 131 тест (puppeteer-моки), все PASS