Initial import NDC_1C
This commit is contained in:
@@ -0,0 +1,467 @@
|
||||
TZ_LLM_Normalizer_v2.0.2.md
|
||||
|
||||
Ниже даю **ТЗ на новый вариант — `Normalizer v2.0.2`**.
|
||||
Это уже не про “ещё лучше понять бухгалтерию”, а про **доводку устойчивости исполнения** после последнего жирного прогона.
|
||||
|
||||
---
|
||||
|
||||
# ТЗ: `Normalizer v2.0.2`
|
||||
|
||||
## Stability / No-Route / Schema Hardening
|
||||
|
||||
---
|
||||
|
||||
## 1. Контекст этапа
|
||||
|
||||
После перехода на `v2.0.1` система показала правильный вектор:
|
||||
|
||||
* `schema_validation_pass_rate = 96.15`
|
||||
* `scope_in_scope_rate = 92.31`
|
||||
* `clarification_required_rate = 15.38`
|
||||
* `out_of_scope` отрабатывается
|
||||
* нормальные in-scope вопросы в большинстве случаев проходят без лишнего clarification
|
||||
|
||||
Комментарий:
|
||||
Это уже лучше, чем бесконечный prompt-tuning `v1.x`, потому что новая схема стала:
|
||||
|
||||
* устойчивее к новым формулировкам;
|
||||
* лучше разделять допустимый/недопустимый контур;
|
||||
* меньше душить нормальные вопросы уточнениями.
|
||||
|
||||
Но после жирного прогона видны три конкретные проблемы:
|
||||
|
||||
1. `schema_validation_pass_rate` упала с 100 до 96.15
|
||||
2. `no_route_fragment_rate = 20.69` — слишком много
|
||||
3. часть внутренних состояний (`fallback_type`, `execution_readiness`, `soft_assumptions`) согласованы неидеально
|
||||
|
||||
---
|
||||
|
||||
## 2. Цель этапа
|
||||
|
||||
Довести `v2.0.1` до более устойчивой рабочей версии `v2.0.2`, не меняя базовую архитектуру.
|
||||
|
||||
Цели:
|
||||
|
||||
* вернуть `schema_validation_pass_rate` к `100`
|
||||
* разобраться с природой `no_route`
|
||||
* сделать внутреннюю policy-логику согласованной
|
||||
* не сломать уже хорошие свойства:
|
||||
|
||||
* scope gating
|
||||
* out-of-scope filtering
|
||||
* умеренный clarification rate
|
||||
* decomposition-first подход
|
||||
|
||||
---
|
||||
|
||||
## 3. Главный принцип этапа
|
||||
|
||||
На этом этапе **не надо**:
|
||||
|
||||
* снова тюнить под конкретные 26 вопросов;
|
||||
* переписывать всю prompt-логику;
|
||||
* возвращаться к `v1.x`;
|
||||
* пытаться “угадать всё лучше через ещё один prompt”.
|
||||
|
||||
Нужно:
|
||||
|
||||
* сделать систему **строже и честнее на уровне исполнения**;
|
||||
* понять, где `no_route` правильный, а где это недонастроенный mapping;
|
||||
* сделать output pipeline согласованным и стабильным.
|
||||
|
||||
Комментарий:
|
||||
Это уже этап **операционной жёсткости**, а не “семантической магии”.
|
||||
|
||||
---
|
||||
|
||||
# 4. Что именно надо чинить
|
||||
|
||||
---
|
||||
|
||||
## 4.1. Проблема A: schema validation не 100
|
||||
|
||||
### Симптом
|
||||
|
||||
В последнем прогоне:
|
||||
|
||||
* `schema_validation_pass_rate = 96.15`
|
||||
* кейс `BQ-001` не прошёл валидацию
|
||||
* был retry (`request_count_for_case = 2`)
|
||||
|
||||
### Требование
|
||||
|
||||
Нужно вернуть:
|
||||
|
||||
* `schema_validation_pass_rate = 100`
|
||||
|
||||
### Что сделать
|
||||
|
||||
1. Разобрать `BQ-001` целиком:
|
||||
|
||||
* raw question
|
||||
* raw model output
|
||||
* parsed object
|
||||
* validation error
|
||||
* retry output
|
||||
2. Выявить точную причину:
|
||||
|
||||
* field missing
|
||||
* wrong enum
|
||||
* wrong nested type
|
||||
* prompt overflow / malformed json
|
||||
* parser inconsistency
|
||||
3. Исправить причину на системном уровне, а не точечно под кейс.
|
||||
|
||||
### Ожидаемый артефакт
|
||||
|
||||
Файл:
|
||||
`docs/v2_0_2_schema_forensic.md`
|
||||
|
||||
Комментарий:
|
||||
Schema loss даже в одном кейсе — это нельзя игнорировать.
|
||||
Это технический риск уровня “сломается в проде в неожиданный момент”.
|
||||
|
||||
---
|
||||
|
||||
## 4.2. Проблема B: слишком много `no_route`
|
||||
|
||||
### Симптом
|
||||
|
||||
* `no_route_fragment_rate = 20.69`
|
||||
* `route_distribution.no_route = 6`
|
||||
|
||||
### Требование
|
||||
|
||||
Разделить все `no_route` случаи на две категории:
|
||||
|
||||
### A. Legit no-route
|
||||
|
||||
Когда реально нельзя безопасно отправить дальше:
|
||||
|
||||
* fragment out-of-scope;
|
||||
* fragment слишком неопределённый;
|
||||
* fragment требует clarification;
|
||||
* fragment семантически распознан, но не относится к исполняемому бухгалтерскому действию.
|
||||
|
||||
### B. Missing route mapping
|
||||
|
||||
Когда fragment уже in-scope и достаточно понятен, но код не умеет подобрать маршрут.
|
||||
|
||||
### Что сделать
|
||||
|
||||
1. Выгрузить все fragments с `no_route`
|
||||
2. Для каждого сделать ручную классификацию:
|
||||
|
||||
* `legit_no_route`
|
||||
* `missing_mapping`
|
||||
3. Если это `missing_mapping`, добавить deterministic mapping rule
|
||||
4. Если это `legit_no_route`, зафиксировать policy явно
|
||||
|
||||
### Ожидаемый артефакт
|
||||
|
||||
Файл:
|
||||
`docs/v2_0_2_no_route_audit.md`
|
||||
|
||||
Комментарий:
|
||||
Сейчас `no_route` — это ещё слишком “чёрный ящик”.
|
||||
Нужно сделать так, чтобы каждый такой случай был объясним.
|
||||
|
||||
---
|
||||
|
||||
## 4.3. Проблема C: несогласованность execution state
|
||||
|
||||
### Симптом
|
||||
|
||||
Есть кейсы, где:
|
||||
|
||||
* `fallback_type = none`
|
||||
* `predicted_clarification_required = false`
|
||||
* но `executable_with_soft_assumptions_fragments = 0`
|
||||
|
||||
Например:
|
||||
|
||||
* `BQ-007`
|
||||
* `BQ-024`
|
||||
|
||||
### Что это значит
|
||||
|
||||
Внутренняя state machine не полностью согласована.
|
||||
|
||||
### Требование
|
||||
|
||||
Согласовать следующие статусы между собой:
|
||||
|
||||
* `domain_relevance`
|
||||
* `execution_readiness`
|
||||
* `predicted_clarification_required`
|
||||
* `fallback_type`
|
||||
* `route_decision`
|
||||
* `soft_assumption_used`
|
||||
|
||||
### Целевая логика
|
||||
|
||||
Если fragment:
|
||||
|
||||
* in-scope
|
||||
* не clarification
|
||||
* не out-of-scope
|
||||
* и route выбран
|
||||
|
||||
то должно быть явно видно:
|
||||
|
||||
* либо `execution_readiness = executable`
|
||||
* либо `execution_readiness = executable_with_soft_assumptions`
|
||||
|
||||
Не должно быть “исполняем, но readiness не поднят”.
|
||||
|
||||
### Ожидаемый артефакт
|
||||
|
||||
Файл:
|
||||
`docs/v2_0_2_execution_state_machine.md`
|
||||
|
||||
---
|
||||
|
||||
# 5. Что изменить в схеме
|
||||
|
||||
## 5.1. Явно ввести `execution_readiness`
|
||||
|
||||
Если ещё не введено как обязательное поле — сделать обязательным.
|
||||
|
||||
```json id="mgbtkn"
|
||||
{
|
||||
"execution_readiness": "executable | executable_with_soft_assumptions | needs_clarification | no_route"
|
||||
}
|
||||
```
|
||||
|
||||
## 5.2. Явно ввести `route_status`
|
||||
|
||||
```json id="6sdd3j"
|
||||
{
|
||||
"route_status": "routed | no_route"
|
||||
}
|
||||
```
|
||||
|
||||
## 5.3. Явно ввести `no_route_reason`
|
||||
|
||||
Если `route_status = no_route`, обязателен reason:
|
||||
|
||||
```json id="y0eqbg"
|
||||
{
|
||||
"no_route_reason": "out_of_scope | insufficient_specificity | missing_mapping | unsupported_fragment_type"
|
||||
}
|
||||
```
|
||||
|
||||
Комментарий:
|
||||
Это очень важно.
|
||||
Без этого вы будете бесконечно смотреть на `no_route` как на аморфную массу.
|
||||
|
||||
---
|
||||
|
||||
# 6. Что изменить в коде
|
||||
|
||||
---
|
||||
|
||||
## 6.1. Добавить post-normalization state resolver
|
||||
|
||||
Сделать отдельный кодовый слой после ответа LLM:
|
||||
|
||||
```text id="kcynfd"
|
||||
resolve_fragment_execution_state(fragment, session_context) -> resolved_fragment
|
||||
```
|
||||
|
||||
Он должен:
|
||||
|
||||
1. нормализовать readiness;
|
||||
2. нормализовать route_status;
|
||||
3. ставить `no_route_reason`;
|
||||
4. приводить `fallback_type` в согласованное состояние.
|
||||
|
||||
---
|
||||
|
||||
## 6.2. Ввести deterministic `no_route` policy
|
||||
|
||||
Если fragment:
|
||||
|
||||
* in-scope
|
||||
* и не clarification
|
||||
* и есть достаточно route-critical flags
|
||||
|
||||
то `no_route` запрещён.
|
||||
В таком случае должен выбираться маршрут.
|
||||
|
||||
`no_route` разрешён только если:
|
||||
|
||||
* fragment реально вне контура;
|
||||
* fragment реально недостаточно определён;
|
||||
* fragment unsupported by current route map.
|
||||
|
||||
---
|
||||
|
||||
## 6.3. Добавить trace completeness check
|
||||
|
||||
Сейчас у вас раньше был кейс с пустым trace view.
|
||||
|
||||
Нужно проверить, что для каждого run сохраняется:
|
||||
|
||||
* raw input
|
||||
* raw model output
|
||||
* parsed fragments
|
||||
* resolved execution state
|
||||
* final route per fragment
|
||||
|
||||
Если trace неполный — логировать это как системную ошибку.
|
||||
|
||||
---
|
||||
|
||||
# 7. Что изменить в prompt’ах
|
||||
|
||||
На этом этапе prompt менять минимально.
|
||||
|
||||
Нужно только:
|
||||
|
||||
* добавить требование, чтобы fragment-level output был полным и непротиворечивым;
|
||||
* не трогать общий semantic слой без нужды.
|
||||
|
||||
### Добавить в developer prompt
|
||||
|
||||
```text id="xlg5ut"
|
||||
Every in-scope fragment must produce a consistent execution state.
|
||||
If a fragment is routable, mark it as executable or executable_with_soft_assumptions.
|
||||
Do not leave routable fragments in an unresolved execution state.
|
||||
If a fragment cannot be routed, provide an explicit no_route_reason.
|
||||
```
|
||||
|
||||
Комментарий:
|
||||
Это не semantic tuning, а дисциплина output’а.
|
||||
|
||||
---
|
||||
|
||||
# 8. Новый eval для `v2.0.2`
|
||||
|
||||
Нужен уже не просто набор “сложных вопросов”, а **размеченный eval по policy**.
|
||||
|
||||
## 8.1. Состав eval
|
||||
|
||||
Собрать 20 кейсов:
|
||||
|
||||
### Блок A — routable in-scope
|
||||
|
||||
8 кейсов
|
||||
Ожидание:
|
||||
|
||||
* in-scope
|
||||
* no clarification
|
||||
* route selected
|
||||
* no `no_route`
|
||||
|
||||
### Блок B — legit clarification
|
||||
|
||||
4 кейса
|
||||
Ожидание:
|
||||
|
||||
* in-scope
|
||||
* clarification needed
|
||||
|
||||
### Блок C — out-of-scope
|
||||
|
||||
4 кейса
|
||||
Ожидание:
|
||||
|
||||
* out-of-scope
|
||||
* no route
|
||||
* fallback out_of_scope
|
||||
|
||||
### Блок D — borderline / soft assumptions
|
||||
|
||||
4 кейса
|
||||
Ожидание:
|
||||
|
||||
* in-scope
|
||||
* executable_with_soft_assumptions
|
||||
* route selected
|
||||
|
||||
---
|
||||
|
||||
## 8.2. Новые метрики
|
||||
|
||||
Обязательно считать:
|
||||
|
||||
* `schema_validation_pass_rate`
|
||||
* `scope_detection_accuracy`
|
||||
* `route_resolution_accuracy`
|
||||
* `no_route_precision`
|
||||
* `false_no_route_rate`
|
||||
* `execution_state_consistency_rate`
|
||||
* `clarification_precision`
|
||||
* `clarification_recall`
|
||||
|
||||
---
|
||||
|
||||
# 9. Целевые показатели
|
||||
|
||||
Минимально приемлемо:
|
||||
|
||||
* `schema_validation_pass_rate = 100`
|
||||
* `execution_state_consistency_rate >= 95`
|
||||
* `false_no_route_rate <= 10`
|
||||
* `route_resolution_accuracy` заметно выше текущего
|
||||
* `clarification_required_rate` не выше текущего на in-scope одноходовых кейсах
|
||||
|
||||
Хорошо:
|
||||
|
||||
* `false_no_route_rate <= 5`
|
||||
* `execution_state_consistency_rate = 100`
|
||||
|
||||
---
|
||||
|
||||
# 10. Что нельзя делать
|
||||
|
||||
Codex запрещено:
|
||||
|
||||
1. снова возвращать один главный `intent_class` как основу всего;
|
||||
2. снова лечить всё через few-shot под эти 26 вопросов;
|
||||
3. занижать `no_route` искусственно, просто проставляя маршрут куда угодно;
|
||||
4. выключать fallback/out-of-scope;
|
||||
5. игнорировать единичный schema fail как “неважный”.
|
||||
|
||||
---
|
||||
|
||||
# 11. Артефакты
|
||||
|
||||
Codex должен выдать:
|
||||
|
||||
1. `docs/v2_0_2_schema_forensic.md`
|
||||
2. `docs/v2_0_2_no_route_audit.md`
|
||||
3. `docs/v2_0_2_execution_state_machine.md`
|
||||
4. `schemas/normalized_query_v2_0_2.json`
|
||||
5. `prompts/developer/normalizer_v2_0_2.txt`
|
||||
6. `reports/v2_0_2_eval_plan.md`
|
||||
|
||||
---
|
||||
|
||||
# 12. Короткий смысл этапа
|
||||
|
||||
`v2.0.2` — это версия не про “лучше понимать язык”, а про:
|
||||
|
||||
* **не ломать схему**
|
||||
* **не терять route без объяснения**
|
||||
* **сделать внутренние состояния честными и жёсткими**
|
||||
* **перестать иметь серые зоны между clarification / no-route / executable**
|
||||
|
||||
---
|
||||
|
||||
# 13. Практический итог
|
||||
|
||||
После `v2.0.2` вы должны получить систему, где для каждого fragment всегда понятно:
|
||||
|
||||
* он в контуре или нет;
|
||||
* он исполним или нет;
|
||||
* если не исполним — почему;
|
||||
* если исполним — с какими допущениями;
|
||||
* какой route выбран;
|
||||
* если route не выбран — по какой строго указанной причине.
|
||||
|
||||
Это уже будет нормальный инженерный фундамент, а не “LLM что-то там решила”.
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user