Initial import NDC_1C

This commit is contained in:
2026-03-26 10:38:25 +03:00
commit a162d77ef7
2943 changed files with 3615871 additions and 0 deletions
+438
View File
@@ -0,0 +1,438 @@
TZ_Assistant_Mode_vNext2.md
Да, даю уже в формате **жёсткой вставки в ТЗ**.
Ниже блок, который логично добавлять как отдельный раздел после текущего `Final Answer Composer / answer policy`, потому что в текущем контуре уже есть правильная базовая архитектура, но composer пока остаётся operational, retrieval — sandbox/stubbed, а пользовательский ответ не обязан доказывать основание отбора и полноту покрытия вопроса. Это прямо следует из текущего vNext ТЗ и архитектурного отчёта.
---
# Дополнение к ТЗ: explainable answer layer и контроль полноты декомпозиции
## 1. Цель дополнения
Закрыть два критических продуктовых дефекта Assistant Mode:
1. ассистент выдаёт формально человекочитаемый, но смыслово пустой ответ без объяснения, почему именно эти объекты, записи или цепочки были отобраны;
2. ассистент теряет части многосоставного пользовательского запроса на этапе decomposition/routing и отвечает только на отдельный фрагмент, создавая ложное ощущение, что задача решена.
Цель этого этапа — сделать так, чтобы Assistant Mode:
* отвечал **по смыслу бухгалтерского вопроса**;
* объяснял **основания отбора и вывода**;
* гарантировал **покрытие всех существенных частей запроса**;
* не подменял пользовательский вопрос ближайшим технически доступным маршрутом.
---
## 2. Что фиксируем как обязательный продуктовый контракт
Считать ответ ассистента корректным можно только тогда, когда одновременно выполнены четыре условия:
1. ответ относится именно к предмету вопроса пользователя, а не к соседнему маршруту;
2. ответ объясняет, **почему** найденные записи/объекты/контрагенты попали в результат;
3. ответ показывает, **на каких признаках и фактах** основан вывод;
4. ответ закрывает **все существенные части** многосоставного запроса либо явно помечает, что часть вопроса не покрыта.
Если хотя бы одно из этих условий не выполнено, ответ считается непригодным даже при технически успешном pipeline.
---
## 3. Новый обязательный слой: Explainable Answer Layer
После `Result Normalization` и до финального `Assistant Reply` должен быть отдельный обязательный слой:
**Explainable Answer Layer**
Новый полный контур:
**User message → Normalizer → Requirement Extraction → Execution Planning → Route-specific Retrieval → Result Normalization → Explainable Answer Layer → Final Answer Composer → Assistant Reply**
Задача этого слоя:
* восстановить пользовательское намерение в нормальной человекочитаемой форме;
* проверить полноту покрытия вопроса;
* проверить предметную релевантность ответа;
* собрать не просто summary, а **объяснимый вывод**.
---
## 4. Новый обязательный контракт декомпозиции
### 4.1. Декомпозиция должна выделять не только fragments, но и requirements
Нужно разделить два уровня:
### A. `requirements`
Смысловые требования пользователя.
Примеры:
* найти поставщиков с хвостами;
* объяснить, почему они считаются проблемными;
* показать, где именно разрыв по цепочке;
* отделить аномалии по риску от аномалий по сумме.
### B. `execution_fragments`
Технические единицы исполнения, которые маршрутизируются по route.
Важно:
один `requirement` может порождать несколько `execution_fragments`;
несколько fragments могут обслуживать один requirement.
Без этого разделения многосоставные вопросы будут и дальше схлопываться в один ближайший route.
---
### 4.2. Для каждого пользовательского сообщения нужен coverage report
После decomposition система обязана формировать объект:
```json
{
"requirements_total": 0,
"requirements_covered": 0,
"requirements_uncovered": [],
"requirements_partially_covered": [],
"clarification_needed_for": [],
"out_of_scope_requirements": []
}
```
Это внутренний контракт pipeline.
Без него нельзя считать, что система поняла вопрос.
---
### 4.3. Запрещён silent loss of intent
Если в исходном сообщении было несколько требований, а в execution plan попала только часть, система не имеет права:
* молча проигнорировать остальные части;
* выдавать ответ так, будто задача полностью выполнена;
* считать вопрос закрытым.
В этом случае допустимы только три режима:
1. **полный ответ** — если покрыто всё;
2. **partial answer** — если покрыта только часть и это явно сказано;
3. **clarification** — если без уточнения нельзя корректно закрыть все требования.
---
## 5. Новый обязательный контракт retrieval result
Текущий unified result schema нужно расширить. Сейчас в нём есть хороший базовый каркас, но для объяснимого ответа его недостаточно.
Каждый route executor должен возвращать не только данные, но и признаки, объясняющие включение объекта в ответ.
### Обязательные поля результата
```json
{
"fragment_id": "F1",
"requirement_ids": ["R1"],
"route": "store_feature_risk",
"status": "ok | empty | partial | error",
"result_type": "list | summary | object | chain | ranking",
"items": [],
"summary": {},
"evidence": [],
"why_included": [],
"selection_reason": [],
"risk_factors": [],
"business_interpretation": [],
"confidence": "high | medium | low",
"limitations": [],
"errors": []
}
```
---
### 5.1. Смысл новых полей
`why_included`
Почему объект вообще попал в выборку.
`selection_reason`
По каким конкретным правилам, фильтрам, признакам или сопоставлениям он был отобран.
`risk_factors`
Какие именно признаки риска, расхождения, аномалии или разрыва цепочки обнаружены.
`business_interpretation`
Как это интерпретируется в бухгалтерском или операционном смысле.
`confidence`
Оценка уверенности результата.
`limitations`
Что система не смогла подтвердить или где данные неполны.
---
## 6. Новый обязательный слой: Answer Grounding Check
Перед выдачей финального ответа должен выполняться `Answer Grounding Check`.
### Его задача:
проверить, что итоговый ответ действительно опирается на retrieval results и не съехал по предметной области.
### Проверяемые условия:
1. ключевые сущности ответа присутствуют в retrieval results;
2. ключевые выводы ответа подтверждены `evidence` и `selection_reason`;
3. предмет ответа совпадает с предметом вопроса;
4. если пользователь спрашивал про ОС, ответ не может быть собран по НДС;
5. если пользователь спрашивал про 97 счёт, ответ не может уйти в общий рейтинг контрагентов без объяснения связи;
6. если пользователь спрашивал про аномалию, ответ обязан назвать признак аномалии.
Если проверка не проходит, ответ не отправляется в user-facing канал и должен перейти в один из fallback-режимов:
* clarification;
* partial with limitation;
* technical error;
* no-grounded-answer.
---
## 7. Новый обязательный стандарт user-facing ответа
Каждый нормальный factual answer должен содержать не просто summary, а следующие смысловые элементы:
### 7.1. Итоговый вывод
Короткий ответ на главный вопрос.
### 7.2. Основание отбора
Почему именно эти объекты попали в ответ.
### 7.3. Подтверждающие признаки
Какие факты, поля, несоответствия, связи или разрывы обнаружены.
### 7.4. Практический смысл
Что это означает для бухгалтера или что именно здесь выглядит проблемным.
### 7.5. Ограничения
Что не удалось проверить полностью, если такое есть.
### 7.6. Следующее действие
Что стоит посмотреть или проверить дальше.
---
### 7.2. Требование к стилю ответа
Ответ должен быть:
* на русском;
* коротким, но содержательным;
* предметным;
* без route names;
* без debug-лексики;
* без пустых формулировок типа “по запросу найдены данные”;
* без перечисления ссылок без пояснения, зачем они показаны.
---
## 8. Обязательные шаблоны смысловой структуры ответа
### 8.1. Для anomaly / risk / suspicious scan
Ответ обязан содержать:
* что именно признано аномалией;
* по каким признакам это признано аномалией;
* чем запись отличается от нормального поведения;
* какие объекты наиболее рискованные;
* в чём риск состоит практически.
### 8.2. Для chain / causal / cross-entity explanation
Ответ обязан содержать:
* какую цепочку система проверяла;
* где именно найден разрыв или конфликт;
* какие сущности участвуют в цепочке;
* почему это считается хвостом, разрывом или зависшей ситуацией.
### 8.3. Для ranking / overview / top
Ответ обязан содержать:
* принцип ранжирования;
* почему верхние позиции оказались наверху;
* какие признаки сильнее всего влияли на приоритет.
### 8.4. Для canonical factual reply
Ответ обязан содержать:
* прямой ответ по объекту;
* источник/основание;
* при необходимости — уточнение статуса, периода, документа, связанной записи.
---
## 9. Новый обязательный формат partial answer
Если закрыта не вся задача, partial reply обязан быть структурирован так:
1. что удалось проверить;
2. что именно не покрыто;
3. почему не покрыто;
4. нужно ли уточнение;
5. можно ли продолжить по оставшейся части.
Недопустимо:
выдать ответ по одному фрагменту без явной маркировки того, что другие части вопроса потеряны.
---
## 10. Новые reply types
К текущему набору reply/fallback типов нужно добавить или закрепить отдельно:
* `factual`
* `factual_with_explanation`
* `partial_coverage`
* `clarification_required`
* `empty_but_valid`
* `no_grounded_answer`
* `route_mismatch_blocked`
* `backend_error`
Это нужно, чтобы различать:
просто технически успешный ответ и
семантически валидный ответ с объяснимым основанием.
---
## 11. Что нужно изменить в логировании
К уже существующим логам надо добавить поля, которые позволят анализировать именно смысловую пригодность ответа, а не только route/fallback. Сейчас логирование уже есть, но его надо расширить для field hardening.
### Добавить в structured log:
* `requirements_extracted`
* `requirements_total`
* `requirements_covered`
* `requirements_uncovered`
* `coverage_status`
* `answer_grounding_status`
* `reply_semantic_type`
* `why_included_summary`
* `selection_reason_summary`
* `route_subject_match`
* `clarification_target`
* `dropped_intent_segments`
---
## 12. Что нужно изменить в UI
Debug drawer остаётся, но в основном ответе надо показывать не только итог, а и короткий explainable summary.
### В bubble ответа ассистента показывать:
* краткий вывод;
* короткий блок “почему это попало в ответ”;
* по необходимости — список объектов;
* по необходимости — блок “что проверить дальше”.
### В debug drawer переносить:
* raw fragments;
* route selection;
* trace id;
* fallback state;
* raw retrieval payloads;
* coverage report;
* grounding check result.
---
## 13. Новые критерии приёмки этапа
Этап считается принятым только если выполнены все условия:
1. ассистент отвечает по предмету вопроса, а не по ближайшему соседнему route;
2. каждый factual answer содержит объяснение, почему объект/запись/контрагент попал в ответ;
3. для каждого многосоставного вопроса система фиксирует coverage report;
4. система не теряет части вопроса молча;
5. если покрыта только часть — это явно отмечено в ответе;
6. если предмет ответа съехал — ответ блокируется как `route_mismatch_blocked` или `no_grounded_answer`;
7. anomaly-ответы объясняют признак аномалии, а не только выводят список сущностей;
8. chain-ответы объясняют разрыв цепочки, а не только перечисляют документы;
9. в основном ответе нет route names, trace, sandbox wording и другого внутреннего мусора;
10. debug остаётся доступен отдельно и не ломает основной UX.
---
## 14. Минимальный MVP этого дополнения
### MVP-1
Внедрить:
* `requirements` + `coverage report`;
* расширенный unified result schema;
* `Answer Grounding Check`;
* explainable answer contract хотя бы для:
* `store_feature_risk`
* `hybrid_store_plus_live`
### MVP-2
Добавить explainable templates для:
* `batch_refresh_then_store`
* `store_canonical`
### MVP-3
Дополировать:
* richer explanation formatting;
* confidence/limitations;
* better partial answer behavior;
* трассировку semantic failures.
---
## 15. Что считать провалом этапа
Этап не считается выполненным, если сохраняется хотя бы один из сценариев:
* пользователь спросил про аномалию, а получил список без признаков аномальности;
* пользователь задал многосоставной вопрос, а ассистент ответил только на один фрагмент без явной маркировки;
* ответ предметно съехал в другой участок учёта;
* ответ содержит ссылки, route names, trace или sandbox-пояснения вместо нормального объяснения;
* ассистент дал формально связный, но необоснованный вывод без основания отбора.
---
## 16. Короткий итог для разработчика
Задача следующего этапа — не просто улучшить текст ответа.
Задача этапа:
* сделать декомпозицию **полной**, а не частичной;
* сделать ответ **объяснимым**, а не декоративно-человекочитаемым;
* заставить ассистента **доказывать**, почему он выбрал именно эти записи;
* запретить выдачу ответа, если система не может подтвердить предметную релевантность и полноту покрытия вопроса.
---
Если хочешь, следующим сообщением я сразу соберу ещё и **сверхкороткую версию для Codex/разработчика на 1 экран**, без пояснений, только требования и acceptance criteria.