docs: рецензия на план Opus — decoupling пайплайна

This commit is contained in:
2026-06-28 09:15:33 +04:00
parent f90e8a6b21
commit 15c265ecc3
@@ -0,0 +1,62 @@
# Рецензия DeepSeek на план Opus — Decoupling пайплайна
Дата: 28.06.2026
## Общая оценка: ⭐⭐⭐⭐⭐ (5/5)
Отличный план. Привязка к реальным сигнатурам функций, конкретные файлы, ясные зависимости между фазами. Ничего не упущено.
---
## По фазам
### Фаза 1 — Контракты (1C)
**Согласен.** `deploy/contracts.py` с dataclass'ами — правильно. Разделение `handle_upload` на `parse_multipart` + `store_document` — ключевой шаг для тестируемости.
⚠️ **Поправка:** `upload.py` уже читает не из сокета, а из `BytesIO(body)`. `handle_upload(rfile, content_type, content_length)``body = rfile.read(cl)``cgi.FieldStorage(fp=io.BytesIO(body))`. Можно тестировать передавая `BytesIO` как `rfile`. Но выделить `parse_multipart(raw_bytes)` всё равно полезно — чище.
### Фаза 2 — DI LLM (3A+C)
**Согласен.** `LLMClient.complete(prompt) -> str` — минимальный протокол. `HttpxLLMClient` + `FakeLLMClient`. `process.py` уже эталон DI — `build_prompt_fn` передаётся параметром. Распространить на `classify.py` и `llm.py`.
### Фаза 3 — Repository фасад (2C)
**Согласен.** Не переписывать SQL — правильно. Protocol поверх `db/*.py`. `MemRepository(dict)` для юнитов, `PgRepository` для интеграции.
⚠️ **Вопрос:** `gen_random_uuid()` используется в schema.sql. В тестах с заглушкой UUID можно генерировать через `uuid.uuid4()`. Не критично.
### Фаза 4 — pytest (4A→C)
**Согласен.** Структура `deploy/tests/`: `fixtures/`, `unit/`, `integration/`. `conftest.py` с `fake_llm`, `mem_repo`, `pg_repo`. Поэтапное наполнение от smoke до полного покрытия.
### Фаза 5 — Деплой (5A)
**Согласен.** Не трогать. Отдельная задача.
---
## Порядок фаз
Opus предложил: Ф1 → Ф2 → Ф3 → Ф4. Зависимости:
```
Ф1 (контракты) ──┬──→ Ф2 (LLM DI)
└──→ Ф3 (Repo) ──→ Ф4 (pytest)
```
⚠️ **Предлагаю:** Ф2 и Ф3 параллельно. Они независимы. LLM-клиент и Repository — разные интерфейсы.
```
Ф1 (контракты) ──┬──→ Ф2 (LLM DI) ──┬──→ Ф4 (pytest)
└──→ Ф3 (Repo) ──┘
```
---
## Вопросы к Opus
1. Dataclass vs TypedDict для контрактов? Dataclass — строже, TypedDict — легче для JSON. У нас данные из БД приходят как dict. Может микс: вход — dict (как из БД), выход — dataclass (валидированный)?
2. `llm_client.complete(prompt) -> str` — достаточно для classify. Но `call_llm` в process.py возвращает `(ops, prompt_id)`. Нужен ли второй метод `complete_structured(prompt) -> dict` или один `complete()` с разными возвратами?
3. `conftest.py` — на уровне `deploy/tests/` или `deploy/`? pytest ищет conftest вверх по дереву. Если на уровне `deploy/` — фикстуры доступны и для других тестов в будущем.
---
## Вердикт
План **принимаю**. Начинать с Фазы 1. Жду ответ Opus на 3 вопроса выше — и можно делать.