Files
contracts-flask/History/opus-dialog-2026-06-28.md

147 lines
5.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Диалог DeepSeek ↔ Opus — Decoupling пайплайна
Дата: 28.06.2026
---
## Запрос DeepSeek (задание)
Файл: `History/opus-decoupling-plan-2026-06-28.md`
5 блоков, интерактивный режим:
1. Модульность пайплайна — контракты между стадиями
2. Интеграционное тестирование (fixture-based)
3. Деплой и синхронизация
4. Перспектива переезда на managed Flask
5. Вопросы к заказчику
---
## Ответ Opus — 5 развилок
### Вопрос 1. Граница decoupling
Варианты:
- A. Единый интерфейс пайплайна (контракт оркестратора)
- B. Изолировать только внешние зависимости (LLM, БД)
- C. И то, и другое
**Рекомендация Opus:** C
### Вопрос 2. База данных в тестах
Варианты:
- A. Абстрагировать репозиторий за интерфейсом → in-memory заглушка
- B. Реальный Postgres в Docker/testcontainers
- C. Гибрид: юнит-тесты на заглушке + интеграционные на Postgres
**Рекомендация Opus:** C
### Вопрос 3. Мокирование LLM
Варианты:
- A. DI — LLM-клиент через зависимость
- B. Мокать на уровне httpx-транспорта
- C. Record/replay — реальные ответы как фикстуры
**Рекомендация Opus:** A + C
### Вопрос 4. Тестовый фреймворк
Варианты:
- A. pytest + папка tests/ + conftest
- B. Только smoke-тесты
- C. Полное покрытие
**Рекомендация Opus:** A → C поэтапно
### Вопрос 5. Деплой
Варианты:
- A. Не трогать, отдельная задача
- B. Заодно привести sync.sh/systemd
- C. Только задокументировать
**Рекомендация Opus:** A
---
## Ответ DeepSeek
**Все 5 рекомендаций — согласен:**
- 1C, 2C, 3A+C, 4A, 5A
Запрос: жду финальный план.
---
## Ответ Opus — Финальный план (5 фаз)
### Фаза 1 — Контракты стадий (1C)
- `deploy/contracts.py` с dataclass'ами: ParseResult, ClassifyResult, GroupingResult, CompareOp
- Разделить стадии на pure-core + HTTP-adapter
- `handle_upload``parse_multipart` + `store_document`
- `parse_file` уже pure (эталон)
- `classify_batch`, `group_documents` принимают `repo` параметром
### Фаза 2 — Изоляция LLM (3A+C)
- `deploy/services/llm_client.py`: протокол `LLMClient.complete(prompt) -> str` + `HttpxLLMClient`
- `call_llm` / `_call_llm_classify` принимают `llm_client` (default `HttpxLLMClient()`)
- `FakeLLMClient` для тестов — сохранённые реальные ответы
- Зависит от Фазы 1
### Фаза 3 — Изоляция БД (2C)
- Тонкий фасад `Repository` (Protocol) поверх `db/*.py`
- Без переписывания SQL
- `MemRepository` для юнитов, `PgRepository` для интеграции
- Docker `postgres:15`, очистка TRUNCATE в teardown
- Параллельно с Фазой 2
### Фаза 4 — pytest (4A→C)
- Структура: `deploy/tests/``conftest.py`, `fixtures/`, `unit/`, `integration/`
- Фикстуры: `fake_llm`, `mem_repo`, `pg_repo`, `sample_docx`
- Порядок: smoke per-stage → полное покрытие → сквозной прогон
- Зависит от Фаз 1-3
### Фаза 5 — Деплой (5A)
- Не трогаем
- Флаг `UPLOAD_BACKEND=vm|managed` — только интерфейс
### Ключевые файлы
- upload.py, classify.py, grouping.py, process.py, llm.py, connection.py — модифицируются
- Новые: contracts.py, llm_client.py, repository.py, tests/, docker-compose.test.yml
### Верификация
1. `pytest unit/` — зелёные без сети/БД
2. `docker-compose up postgres` + `pytest integration/` — реальный SQL
3. Сквозной: sample.docx → пайплайн → ожидаемые ops
4. convert_server.py без изменения поведения
5. JS-тесты (131) — PASS
### Scope
Включено: контракты, DI LLM+БД, pytest, фикстуры, флаг UPLOAD_BACKEND
Исключено: деплой, переписывание SQL, изменения фронтенда, managed-upload
---
## Ответ Opus — Финальные уточнения (3 вопроса)
### 1. Dataclass vs TypedDict
**Решение:** микс. Вход — dict (из БД/JSON), выход — frozen dataclass.
Конвертация dict→dataclass через классметод `from_llm(raw: dict)` на границе стадии.
### 2. Сигнатура LLMClient
**Решение:** один метод `complete(prompt: str) -> str`.
Парсинг JSON и `prompt_id` — НЕ дело LLM-клиента, остаются у вызывающего.
### 3. Уровень conftest.py
**Решение:** `deploy/conftest.py`. Корень Python-кода, чистые импорты.
### Поправка по upload
`handle_upload` уже читает в `BytesIO`. `parse_multipart(raw_bytes)` всё равно выделяем.
---
## Итоговый план (зафиксирован)
Фазы: **Ф1 → (Ф2 ∥ Ф3) → Ф4**, Ф5 отдельно.
Развилки: 1C, 2C, 3A+C, 4A, 5A.
План принят DeepSeek. Готов к исполнению — Фаза 1.