textmachine/backend/configs/pipeline-c1.yaml

185 lines
19 KiB
YAML
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.

# Ядро C1: draft → editor (Р2). Обязательное приложение Фазы 0 — фиксирует
# границу «конфиг vs код раннера»:
# КОНФИГ: состав/порядок стадий, роль→модель, версии промптов, сэмплинг,
# пороги гейтов, режим инъекции глоссария, токен-бюджеты сборки контекста,
# именованные эскалационные цепочки, fan-out N, cache TTL.
# РАННЕР (код): циклы по главам/чанкам, ветвление по гейтам, механика
# эскалации/ретраев, правило «эскалация → re-gate → флаг», резолв
# content-label → модель/хоп + инвариант «лейбл ⊆ accepts_labels» (пак-17,
# D39.25/D39.26 — сменил ненаписанный «channel-aware фильтр цепочек»;
# Anthropic из стека убран вовсе), resume по чекпоинтам.
core: C1
version: 1
defaults:
# max_tokens ≈ ratio × входные токены; калибровка полигона (эксп. 01):
# русский выход zh→ru ≈1.9× входа в токенах — 2.2 с запасом на ja/en.
max_output_ratio: 2.2
min_max_tokens: 2048
context:
# Р5: обе схемы инъекции глоссария обязаны поддерживаться конфигом.
# selective — ключи/алиасы/леммы в волатильном хвосте (~100800 ток.);
# full_prefix — весь глоссарий в стабильном префиксе (выгодно при cache-hit
# DeepSeek $0.0028/M — решается расчётом на прототипе).
glossary_injection: selective
glossary_token_budget: 800
cache_ttl: "5m"
# STMDepth/OverlapTokens сняты (WS2 §2а): carryover/overlap НЕ строится (D39.7/8 — метрики
# под полом когезии 0.126); мёртвые кнобы в снапшоте приглашали тихий «re-activate».
retries:
# Содержательные регенерации после провала гейта ДО эскалации (транспортные
# ретраи — отдельно, в timeouts models.yaml).
regenerate_before_escalate: 1
# ЭХО-регенерация ДО эскалации, ВКЛЮЧЕНА (пак «деньги и честность выдачи», 31.08).
# Почему не ноль: посылка, ради которой ручка была opt-in, ОПРОВЕРГНУТА для боевого черновика —
# эхо у deepseek-v4-flash 0731 СТОХАСТИЧНО ПО ВЫЗОВУ (D39.61: побайтно идентичные запросы дали
# cjk_share 0.000 и 0.831), значит ре-ген на той же модели восстанавливает чанк, а не воспроизводит
# отказ.
# ⚠ ЧТО ИМЕННО ОНА ДАЁТ — ЗАВИСИТ ОТ escalation.budget_usd НИЖЕ, и режима ДВА:
# • budget_usd > 0 (книга, готовая к боевому прогону — этого шаблон ТРЕБУЕТ явно, см. коммент у
# самого ключа): ре-ген ЗАМЕНЯЕТ хоп. Замер холодного прогона 31.08, пере-снятый с его леджера
# (`coldrun-v16`, книжный конфиг с budget_usd: 0.08): хоп на deepseek-v4-pro — в среднем
# $0.02066090 (5 хопов, $0.10330452), удачный черновой вызов flash — $0.00382851 (15 вызовов),
# то есть хоп дороже в 5.40 раза;
# • budget_usd = 0 (дефолт ЭТОГО файла — он держит CI зелёным без чужих ключей): эскалации нет
# вовсе, эхо просто ФЛАГАЕТСЯ и чанк уезжает дырой в --partial. Ре-ген там ничего не экономит —
# он ВЫКУПАЕТ дыру за один дешёвый вызов flash. Тоже выгодно, но это другая сделка, и называть
# надо обе.
# ⚠ Выгода не безусловна: если ре-ген эхнет ПОВТОРНО, платится и он, и хоп. Направление держится,
# пока вероятность восстановления выше цена_регенаена_хопа ≈ 18.5%; замеренная частота эха
# прогона — 5 из 20 свежих черновых вызовов.
# ⚠ Число «1» — бюджет НА ОСИ ПОПЫТОК, общей с regenerate_before_escalate выше: чанк, уже
# регенерированный по length, приходит к эхо-проверке на attempt=1 и второго шанса не получает.
# ⚠ Гейт эха НЕ ослаблен (порог и детектор те же, D19.2) — меняется только ОТВЕТ на эхо, и только
# на эхо: TestEchoRegenFiresONLYForEcho держит, что отказ/фильтр ре-геном не покупаются (D2.2).
# ⚠ Ручка НЕ фолдится в снапшот — предъявлено машинно на ДВУХ конфигах, TestEchoRegenBudgetMovesNoSnapshot.
regenerate_echo_before_escalate: 1
stages:
- name: draft
role: translator
model: deepseek-v4-flash # интерим — переводчик по exp13 (draft качеством не мерен, D30.6); флип при развязке бейк-оффа
# Слой 2 (D39) + пак-15: промпт резолвится КОНВЕНЦИЕЙ prompts/<пара>/<роль>.md по паре книги
# (Book.LangPair()) и роли стадии — здесь prompts/zh-ru/translator.md. Пути в конфиге больше нет:
# добавить пару = положить каталог. Книга на паре без пакета промптов падает ГРОМКО на загрузке,
# называя ожидаемый путь (закрывает латентный баг «ja едет через китайский паратаксис»).
# Осознанный вариант роли (напр. editor-mono) — через prompt_override на стадии.
# D30.2 reflow: из translator.md убрано «Сохраняй разбивку на абзацы» (построчная
# вёрстка исходника деструктивна для ru — корень нечитаемости exp12 §2.5-S). Bump
# v0-draft→v1-reflow: сменил SHA промпта, осознанный --resnapshot.
prompt_version: v1-reflow
temperature: 0.3
# D39.92 / row 112: "off" here is an ABSENT key (deepseek-v4-flash is ReasoningNone), so the call rode
# the vendor default `high` (quirks 00 §3а) and thinking ate max_tokens: content="", finish=length.
# "low" sends the effort explicitly and thinking stays ON. NOT a free win: quirks 00 §4 measured
# that low RE-ARMS the echo mine (1 raw-Chinese output in 16) — protection degrades continuously
# with effort rather than switching off, and the echo gate is what catches the tail. The hop
# inherits it —
# v4-pro maps low→high, effective effort unchanged. In the snapshot ⇒ --resnapshot, sanctioned.
reasoning: "low"
# single-hop echo-эскалация (D18: deepseek-эхо 25% на 蛊真人 → фолбэк выстрелит). deepseek-v4-pro —
# хоп 1 цепочки A (D3); стреляет ТОЛЬКО при escalation.budget_usd>0 (см. ниже). Escalate_to разрешён
# лишь на translator-роли (editor pinned — D12); результат ре-гейтится.
escalate_to: deepseek-v4-pro
- name: edit
role: editor
# Дефолт-редактор — deepseek-v4-pro БИЛИНГВ, ИНТЕРИМ (D39.22): пере-прогон rerun2 не короновал
# glm-vs-dspro (зазор ~шум), но dspro = судья №1 (0.679), лучшая проза+глоссарий, дефекты чинибельного
# класса (заголовки/CJK-strip → пак-13) и ×2 дешевле glm → интерим-выбор владельца. glm-5 — резервный
# арм (configs/pipeline-arm-glm.yaml); mistral исключён (D39.20 — критические смысловые аварии).
# Флип glm-5→deepseek-v4-pro отменяем одним арм-конфигом. gemini-3.1-pro — премиум-эскалация редактора
# ТОЛЬКО за санитайзером (утечка преамбул 6/6); editor pinned (не эскалирует по цепочке — D12).
# ЭХО-МИНА (несущая): deepseek резолвится в ReasoningNone (нет reasoning-capability) → reasoning:off =
# NO-OP, thinking остаётся ON (эхо-мина НЕ вооружается); floor min_max_tokens 8000 (D24.3) — из
# models.yaml, НЕ переопределять. ⚠️ ПОПРАВКА пака-17: «вход редактора — русский черновик» УСТАРЕЛО
# против D30.1 — редактор БИЛИНГВ и видит плотный CJK-исходник (prompts/zh-ru/editor.md, {{text}}).
# Здесь безопасно не тем, что CJK нет, а тем, что thinking остаётся ON. Модель-редактор, чей провод
# ГАСИТ thinking (control effort/extra_body_disable при reasoning:off), попадает в эхо-зону D19.1 п.2 —
# загрузка это ГРОМКО предупреждает (runner.sourceEchoExposure), гейт эха ловит дальше (D19.2).
model: deepseek-v4-pro
# Промпт — по конвенции prompts/zh-ru/editor.md (см. draft-стадию).
# Bump v2-bilingual-reflow→v3-discourse-reflow: в editor.md вшито валидированное P1a-ядро
# ДИСКУРС-ПЕРЕВЁРСТКИ + few-shot (exp14/D37 §2а — претензия-1 «рубленые абзацы» = рычаг ПРОМПТА,
# не модель; P1a реверстает дефект у всех семей). Меняет SHA промпта → осознанный --resnapshot.
# Билингв-каркас (D30.1) и omission-осторожность (D34.3) сохранены. Моно-вариант — prompts/zh-ru/editor-mono.md.
prompt_version: v3-discourse-reflow
temperature: 0.4
reasoning: "off" # NO-OP на deepseek-v4-pro (ReasoningNone) → thinking ON; НЕ вооружает эхо-мину
few_shot: false # deepseek-thinking CoT сбивается ручными примерами (exp14 §2а) — как в ратифицированном dspro-арме
gates:
coverage:
# Фаза 1. Пороги полигона (эксп. 02, символы БЕЗ пробелов): нижняя граница
# — подозрение на вырезание, верхняя — аномалия/галлюцинация.
enabled: false
sent_cov_min: 0.75
min_chunk_chars: 500 # калибровка порогов — на фрагментах 5002500 симв.
sanitizer:
# Output-санитайзер (D30.3): детерминированный вердикт-гейт «мгновенной
# нечитаемости» на ФИНАЛЬНОМ выходе — ведущие служебные преамбулы («Вот
# отредактированный перевод…»), хвостовые блоки заметок/правок, markdown-###,
# латиница-врезки в ru-выходе (порог), битые словоформы («Первок предок»). Ни
# один существующий гейт этот класс не ловит (exp12/флагманы §5). Дисциплина D2
# (flag+skip): дефект → чанк flagged, мусор не течёт в TM/экспорт. precision>recall.
# ВКЛЮЧЁН для пере-прогона 25 глав (gemini течёт преамбулой 6/6 — премиум-редактор
# за санитайзером). Версия — вердикт-ось (переедет в verdictSnapshotID с D15.2).
enabled: true
regression_guard:
# Пост-reflow регресс-гард (D38-инфра, research/18 §C#5): два детерминированных
# флаггера НАБЛЮДАЕМОСТИ над переходом ЧЕРНОВИК→ФИНАЛ — обвал длины (>40% непробельных
# символов) и числовой дрейф (многозначное число исчезло/появилось). НИКОГДА не вердикт:
# reflow-редактор законно перестраивает и сливает предложения, поэтому hard-skip ложно
# флагнул бы хорошую правку — попадание пишется в наблюдаемость (retrieval_state
# n_style_flags + detail) и всплывает в отчёте.
# ВКЛЮЧЁН 25.07 — исполнение обязательства D38.4 п.5 («оркестратор при сборке единого
# resnapshot ОБЯЗАН включить»), не исполненного к rerun2 (D39.34 находка №1: ключа не
# было НИ В ОДНОМ шиппинг-конфиге ⇒ гейт был тёмным весь пере-прогон).
# ⚠️ Флип НЕ двигает снапшот (пороги — код-консты, версия уже в CheapGateVersion; проверено
# исполнением: снапшоты обеих волн байт-равны с гейтом и без) ⇒ пере-оплаты нет.
enabled: true
escalation:
chains:
# D3-цепочка ЗАВЕДЕНА (пакет №3; все слаги live-фактчекнуты 2026-07-10 — /models + пробный вызов):
# канал A: deepseek-v4-pro → glm-5.1 → gemini-3.1-pro-preview (кросс-семейно; апекс — mandatory-thinking Gemini).
# продуктовый «канал B» = ЛЕЙБЛ контента (пак-17): цепочка лейбла даёт ОДИН хоп = chain[0]
# (len>1 — громкая ошибка «мульти-хоп не построен», D39.26 п.3); переводчик под лейблом задаётся
# `label_models` на стадии, а не стадийным «каналом» (`channel:` отставлен).
# ⚠️ Раннер исполняет SINGLE-HOP: без лейблов — через stage.escalate_to (draft → deepseek-v4-pro выше),
# под лейблом — через chain[0] цепочки, названной в content_policy. Слаг ИМЕННО gemini-3.1-pro-preview
# (gemini-3.1-pro → HTTP 404, live 2026-07-10). Цепочка `adult` осталась ДАННЫМИ: ни один шиппинг-конфиг
# её не выбирает (реестр content_policy пуст) — заготовка под ответ владельца по вокабуляру.
default: [deepseek-v4-pro, glm-5.1, gemini-3.1-pro-preview]
adult: [grok-4.3]
# Адресный премиум-бюджет книги, $. Формула «≤2×» из Р5 неоднозначна — [НУЖНО РЕШЕНИЕ] п.1.
# ⚠️ budget_usd=0 ⇒ эскалация НЕ исполняется (НИ chains, НИ stage.escalate_to — escalationBudgetRemains=false;
# CheckKeys не требует её ключей). Приёмочная сессия 蛊真人 ОБЯЗАНА выставить budget_usd>0, иначе echo-эскалация
# черновика (D18) не выстрелит. Дефолт 0 держит CI/Ф0 зелёными без gemini/mistral-ключей.
budget_usd: 0
# СОДЕРЖАТЕЛЬНЫЕ ЛЕЙБЛЫ (пак-17, D39.25/D39.26) — ПУСТО СОЗНАТЕЛЬНО: этот конфиг обслуживает книги
# БЕЗ лейблов, и его путь байт-идентичен до-паковому. Реестр — УПОРЯДОЧЕННЫЙ список (первая политика,
# претендующая на стадию, выигрывает; map-порядок в Go не хранится). Форма (значение здесь СИНТЕТИЧЕСКОЕ —
# движок не знает ни одного значения, а вокабуляр 18+ ждёт решения владельца, D39.26 добор A):
#
# content_policy:
# - { label: <лейбл-1>, action: allow } # только АССЕРТ: маршрут не меняется
# - { label: <лейбл-2>, action: route, chain: <имя-цепочки> } # маршрут: label_models + один хоп
# # action: terminal — книга вообще не обрабатывается (отказ ВХОДА по объявленным данным; это НЕ скрин
# # контента: ратифицированный пер-чанковый L3-скрин D22.7 остаётся отдельным предусловием прода).
# stages:
# - name: draft
# label_models: { <лейбл-2>: <модель-с-accepts_labels> } # только для route-лейбла
#
# ВСЕ ТРИ действия несут ОДИН инвариант: каждая достижимая модель обязана принимать все лейблы книги
# (иначе загрузка translate падает, называя модель, провайдера и недостающий лейбл; read-only проекции
# остаются доступны). Различаются они остальным:
# • allow — эндпойнты уже верные, ничего не двигаем; chain/label_models/бюджет НЕ нужны и ЗАПРЕЩЕНЫ;
# • route — цепочка существует и содержит РОВНО один член · escalation.budget_usd > 0 ·
# хотя бы одна стадия объявляет label_models для этого лейбла;
# • terminal — ни одного вызова.
# Пара «один лейбл ассертит, второй пере-маршрутизирует» выражается ДАННЫМИ — Go не трогается.
fanout:
candidates: 1 # C1: один черновик