NODEDC_1C/IN/TZ_Assistant_Mode_retrieval...

773 lines
29 KiB
Markdown
Raw 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.

TZ_Assistant_Mode_retrievalLAYER.md
Да. Ниже даю **расширенный набор правил для retrieval/execution layer** именно под бухгалтерский контекст, чтобы `executeHybrid` и соседние executors не жили на одном `GUID` и одном `account_hint`, а реально тащили **избыточный набор ограничений и признаков**. Это прямо ложится на ваш текущий контур `route-specific retrieval` и `unified result schema`, который уже зафиксирован в vNext ТЗ.
Это не замена normalizer, а **расширение retrieval contract**: LLM/normalizer должен отдавать не только route, но и плотный набор бухгалтерских ограничителей, а retrieval обязан их исполнять.
---
# Расширение правил retrieval-слоя под бухгалтерский контекст
## 1. Главный принцип
Для бухгалтерского ассистента **нельзя** строить retrieval только по:
* `guid`
* `account_hint`
* общему route
* одной сущности верхнего уровня
Retrieval должен работать по **многослойному бухгалтерскому профилю запроса**.
Минимальный обязательный набор слоёв:
1. **счета / субсчета**
2. **тип участка учёта**
3. **тип документов**
4. **тип движения**
5. **тип связи между сущностями**
6. **тип аномалии / конфликта**
7. **период**
8. **контрагент / договор / объект / номенклатура / ОС / статья / подразделение**
9. **стадия жизненного цикла**
10. **исключающие условия**
11. **приоритет ранжирования**
12. **ожидаемый тип объяснения**
---
## 2. Новый обязательный retrieval contract
Каждый routed fragment должен передаваться в executor не в виде “route + hints”, а в виде расширенного `semantic_retrieval_profile`.
Примерно так:
```json
{
"fragment_id": "F1",
"route": "hybrid_store_plus_live",
"query_subject": "bank_settlement_mismatch",
"account_scope": ["51", "60"],
"subaccount_scope": [],
"domain_scope": ["bank", "settlements", "supplier_payments"],
"document_types": ["bank_statement", "payment_order", "receipt", "settlement_document"],
"entity_types": ["counterparty", "contract", "document", "posting"],
"period_scope": {
"from": null,
"to": null,
"granularity": "month"
},
"relation_patterns": [
"document_to_posting",
"payment_to_settlement",
"statement_to_document"
],
"lifecycle_stage_filters": [
"created",
"posted",
"closed",
"reconciled"
],
"anomaly_patterns": [
"missing_link",
"wrong_document_type",
"broken_closure",
"posting_mismatch"
],
"ranking_basis": [
"financial_impact",
"repeatability",
"closure_risk"
],
"excluded_interpretations": [
"simple_payment_delay",
"amount_only_anomaly"
],
"explanation_focus": [
"why_selected",
"where_chain_breaks",
"what_business_risk"
]
}
```
---
## 3. Общие правила для всех retrieval executorов
## 3.1. Поиск всегда строится не по одному измерению, а по пересечению признаков
Использовать одновременно:
* счёт
* тип документа
* статус документа
* связанную проводку
* период
* предметную область
* relation pattern
* anomaly pattern
Недопустимо:
если нет `guid`, снимать ограничения и лить в ответ весь массив.
Если `guid` нет, retrieval должен переходить на **semantic narrowing**, а не на `full scan without accounting discrimination`.
---
## 3.2. Любой account hint должен разворачиваться в бухгалтерский контекст
Если в вопросе или normalizer output есть `51`, этого недостаточно.
Нужно автоматически достраивать:
* bank domain
* возможные документы: выписка, платежное поручение, списание с р/с, поступление на р/с
* возможные связи: банк → документ → проводка → расчётный контур
* возможные конфликты: документ есть / нет, проводка есть / нет, не тот тип документа, неверный контур закрытия
То есть `51` — это не фильтр, а **семантический вход в набор поисковых правил**.
---
## 3.3. Если вопрос про аномалию, нельзя ранжировать только по сумме
Если пользователь не просил explicitly “самые большие суммы”, то anomaly retrieval обязан учитывать не только money magnitude, но и:
* отсутствие связанной записи;
* рассогласование между документом и проводкой;
* нарушение жизненного цикла;
* повторяемость отклонения;
* влияние на закрытие периода;
* несоответствие карточки и движения;
* конфликт между участками учёта.
---
## 3.4. Если вопрос про цепочку, retrieval должен искать разрыв, а не просто соседние документы
Для `hybrid_store_plus_live` поиск обязан различать:
* наличие документов в цепочке;
* корректность связей между ними;
* полноту прохождения этапов;
* расхождение статусов;
* конфликт проводки и первички;
* отсутствие ожидаемого продолжения;
* наличие “ложного закрытия” не тем документом.
Это соответствует самой идее `hybrid_store_plus_live` в вашем vNext ТЗ: causal / cross-entity / chain queries должны возвращать связи, документы, оплаты, проводки и признаки разрыва цепочки.
---
# 4. Расширенные бухгалтерские измерения для retrieval
## 4.1. Слой счетов
Нужно учитывать не только основной счёт, но и:
* корреспондирующие счета;
* типовой соседний контур;
* признак “счёт упомянут явно” vs “счёт выведен косвенно”;
* приоритет основного счёта;
* исключённые счета.
### Примеры:
* `51` → банк, движения ДС, документы банка, платежи, выписки
* `60` → поставщики, расчёты, закрытие обязательств
* `62` → покупатели, выручка, оплаты, задолженность
* `76` → прочие расчёты, подвешенные взаимосвязи, нестандартные хвосты
* `97` → расходы будущих периодов, сроки списания, график, корректность продолжения жизненного цикла
* `01/02/08`ОС, ввод в эксплуатацию, амортизация, капитальные вложения, карточка объекта
* `19/68` → НДС, принятие к вычету, книга покупок/продаж, закрытие налогового контура
* `10/41/43` → ТМЦ, товар, выпуск, остатки, движение запасов
* `20/23/25/26/44` → затраты, распределение, закрытие, себестоимость
---
## 4.2. Слой участков учёта
Для каждого запроса нужно фиксировать `domain_scope`:
* банк
* поставщики
* покупатели
* склад / запасы
* ОС
* НМА
* РБП
* НДС
* зарплата
* затраты
* закрытие периода
* прочие расчёты
* договорной контур
* авансы
* налоги
* денежные документы
* касса
* производство
Это нужно, чтобы один и тот же счёт не тянул нерелевантный участок.
---
## 4.3. Слой документов
Retrieval обязан учитывать тип документа как first-class filter.
Категории:
* банковская выписка
* платежное поручение
* поступление товаров/услуг
* реализация
* счет-фактура
* корректировка
* акт сверки
* авансовый отчет
* кассовый ордер
* ввод в эксплуатацию ОС
* принятие к учету ОС
* начисление амортизации
* списание РБП
* закрытие месяца
* регламентная операция
* ручная операция
* корректировка долга
* перемещение / списание / оприходование ТМЦ
Если пользователь спрашивает про “не тем документом закрыто”, retrieval обязан искать **ошибочный тип документа в ожидаемой цепочке**, а не просто все связанные документы.
---
## 4.4. Слой сущностей
Поддерживать entity filters:
* контрагент
* договор
* организация
* документ
* проводка
* номенклатура
* склад
* подразделение
* сотрудник
* объект ОС
* статья затрат
* проект
* заказ
* налоговая запись
* регистр/движение
* период закрытия
Если вопрос multi-entity, retrieval обязан различать **главную сущность** и **подтверждающие сущности**.
---
## 4.5. Слой жизненного цикла
Очень важный слой.
Почти все хорошие бухгалтерские аномалии — это не “не та сумма”, а **сломанный lifecycle**.
Для каждой сущности retrieval должен пытаться определить стадию:
* создан
* проведён
* не проведён
* частично связан
* закрыт
* не закрыт
* сторнирован
* отменён
* завис
* повторён
* перенесён
* закрыт не тем документом
* есть продолжение / нет продолжения
* цепочка оборвана
* финальный статус противоречит промежуточным движениям
Это особенно критично для:
* 97
* ОС
* поставщики/авансы
* НДС
* закрытие периода
* расчёты по 60/62/76
---
# 5. Набор anomaly patterns, которые надо заложить в retrieval
Ниже даю именно как **словарь аномалий**, который можно использовать в `semantic_retrieval_profile.anomaly_patterns`.
## 5.1. Missing link
Ожидаемая связь между сущностями отсутствует.
Примеры:
* документ есть, проводки нет;
* платёж есть, закрывающего документа нет;
* ОС есть, начисления есть/нет, но карточка не бьётся;
* запись в одном контуре есть, в смежном нет.
## 5.2. Wrong document type
Закрытие, отражение или продолжение прошло не тем типом документа.
## 5.3. Broken lifecycle
Объект застрял между стадиями.
## 5.4. Posting mismatch
Проводка не соответствует документу, счёту, участку или ожидаемому направлению движения.
## 5.5. Cross-domain inconsistency
Один участок говорит одно, другой — другое.
Примеры:
* банк подтверждает движение, расчётный контур не закрылся;
* документ прихода есть, складское движение не совпадает;
* ОС в карточке в одном статусе, амортизационный контур в другом.
## 5.6. Closure risk
Запись влияет на корректность закрытия периода.
## 5.7. Repeated anomaly
Одна и та же проблема повторяется серийно.
## 5.8. Silent orphan
Запись выглядит спокойной по сумме, но сиротская по связям и жизненному циклу.
## 5.9. Amount-independent risk
Риск не по величине суммы, а по структуре нарушения.
## 5.10. Manual intervention suspicion
Есть признаки ручной коррекции, нестандартной операции или обходного закрытия.
---
# 6. Правила дифференциации по ключевым бухгалтерским зонам
## 6.1. Банк / 51
Если запрос касается 51, retrieval должен автоматически учитывать:
* банковские документы;
* платежные поручения;
* выписки;
* приход/расход ДС;
* связанный расчётный контур;
* закрытие обязательства;
* аванс / оплата / зачет;
* корреспондирующие счета;
* совпадение назначения платежа и учетного отражения;
* факт отражения в выписке;
* факт проведения документа;
* разрыв между движением денег и закрытием расчета.
### Специальные паттерны:
* оплата есть, закрытия обязательства нет;
* выписка есть, документ-основание не найден;
* движение пошло не в тот договор / не в того контрагента;
* банк закрылся, а расчеты зависли;
* проблема не в платеже, а в документе, который интерпретировал платёж.
---
## 6.2. Поставщики / 60
Учитывать:
* контрагент;
* договор;
* документ поступления;
* оплата;
* зачет аванса;
* закрытие обязательства;
* просроченный хвост;
* расхождение по актам/счётам/поступлению/оплате;
* зависшие незакрытые позиции;
* повторяемость по контрагенту;
* влияние на закрытие периода.
### Специальные паттерны:
* хвост без движения после оплаты;
* поступление есть, расчёт не закрылся;
* аванс есть, поставка не бьётся;
* несколько документов спорят за одну оплату;
* один контрагент серийно создаёт одинаковый дефект.
---
## 6.3. Покупатели / 62
Учитывать:
* реализация;
* оплата;
* аванс;
* зачет;
* дебиторка;
* договор;
* закрытие выручки;
* документ основания;
* банковое подтверждение;
* НДС-связка.
### Паттерны:
* оплата есть, реализация не закрылась;
* аванс завис;
* дебиторка выглядит искусственно живой;
* проводка есть, но цепочка первички неполна.
---
## 6.4. Прочие расчёты / 76
Зона повышенного риска.
Retrieval должен относиться к 76 как к зоне, где часто лежат:
* нестандартные хвосты;
* временные костыли;
* переходные записи;
* плохо закрытые взаимосвязи.
Нужны более жёсткие правила на:
* давность;
* отсутствие продолжения;
* слабую связанность;
* нетипичный тип документа;
* ручные операции;
* странные корреспонденции.
---
## 6.5. РБП / 97
Если запрос про 97, retrieval обязан смотреть не только остаток и сумму, но и:
* дату возникновения;
* срок списания;
* график списания;
* факт начала списания;
* факт завершения списания;
* разрыв между сроком и поведением записи;
* документ-источник;
* связанный объект/основание;
* продолжение жизненного цикла.
### Паттерны:
* запись давно живёт, но логика списания не выполняется;
* срок наступил, движения нет;
* объект уже должен был перейти в другой статус;
* карточка/основание есть, но дальше жизни нет;
* запись выглядит закрытой формально, но по связанным движениям не завершена.
---
## 6.6. ОС / 01 / 02 / 08
Retrieval обязан учитывать:
* карточку ОС;
* документ принятия к учету;
* ввод в эксплуатацию;
* инвентарный объект;
* амортизацию;
* счет 08 как источник;
* корректность перехода 08 → 01;
* статус эксплуатации;
* списание/выбытие;
* соответствие карточки и начислений.
### Паттерны:
* объект заведен, но lifecycle не доведён;
* амортизация идет/не идет в противоречии со статусом;
* карточка есть, движений недостаточно;
* ввод в эксплуатацию и отражение по счетам не совпадают;
* объект сиротский по связям.
---
## 6.7. НДС / 19 / 68
Учитывать:
* счёт-фактура;
* поступление/реализация;
* принятие к вычету;
* книга покупок/продаж;
* период вычета;
* отражение в налоговом контуре;
* связь с первичкой;
* расхождение между бухгалтерским и налоговым отражением.
### Паттерны:
* НДС висит без нормального продолжения;
* документ есть, вычет не бьётся;
* вычет попал не в тот период;
* запись живёт без подтверждающей цепочки;
* топ по НДС не должен подменять вопросы про ОС или банк.
---
## 6.8. Закрытие периода
Если пользователь спрашивает о проблемах, “ломающих период”, retrieval должен повышать вес признаков:
* незакрытый хвост;
* конфликт между участками;
* документ/движение в граничных датах;
* сиротские остатки;
* серия однотипных нарушений;
* объекты, затрагивающие регламентные операции;
* следы ручных коррекций;
* зависшие авансы/расчёты/РБП/ОС.
---
# 7. Правила relation patterns для hybrid / chain retrieval
Для `executeHybrid` нужны предопределённые relation patterns.
## 7.1. payment_to_settlement
Платёж ↔ расчёт ↔ закрытие обязательства
## 7.2. document_to_posting
Документ ↔ проводка
## 7.3. statement_to_document
Банковская выписка ↔ внутренний документ
## 7.4. asset_card_to_depreciation
Карточка ОС ↔ начисление амортизации
## 7.5. deferred_expense_to_writeoff
РБП ↔ график/списание
## 7.6. invoice_to_vat
Первичка ↔ счёт-фактура ↔ НДС
## 7.7. receipt_to_stock_movement
Поступление ↔ складское движение
## 7.8. contract_to_documents
Договор ↔ серия документов / хвостов / закрытий
Если route chain-based, executor должен явно понимать, **какой relation pattern проверяет**, а не просто тянуть “всё около темы”.
---
# 8. Правила ранжирования
Нужен не один ranking score, а составной.
## 8.1. Базовые факторы ранжирования
* финансовое влияние
* давность
* повторяемость
* степень незавершённости lifecycle
* количество сломанных связей
* влияние на закрытие периода
* пересечение с несколькими участками учёта
* типовая/нетиповая проводка
* ручное вмешательство
* наличие противоречащих документов
* отсутствие ожидаемого продолжения
## 8.2. Важное правило
Если пользователь спрашивает “не по сумме, а по риску”, то фактор суммы не должен быть доминирующим.
---
# 9. Excluded interpretations — обязательный блок
Очень полезный слой.
Чтобы retrieval не ехал в ближайшую похожую тему, надо явно передавать, **что нельзя считать ответом**.
Примеры:
* не считать любую большую сумму аномалией;
* не сводить вопрос про ОС к НДС;
* не сводить вопрос про 51 к рейтингу контрагентов вообще;
* не считать любой незакрытый документ доказательством хвоста без проверки связи;
* не отвечать на вопрос про lifecycle просто списком документов;
* не подменять “не тем документом закрыто” на “есть документы по контрагенту”.
---
# 10. Что добавить в executeHybrid прямо практически
Ниже уже почти как техзадание на реализацию.
## 10.1. Если GUID нет, не брать весь набор данных
Вместо этого строить фильтрацию по пересечению:
* `account_scope`
* `domain_scope`
* `document_types`
* `entity_types`
* `relation_patterns`
* `anomaly_patterns`
* `period_scope`
* `excluded_interpretations`
## 10.2. Ввести `query_subject`
Категории верхнего уровня, например:
* `bank_settlement_mismatch`
* `supplier_tail_analysis`
* `customer_closure_gap`
* `deferred_expense_lifecycle_anomaly`
* `fixed_asset_card_mismatch`
* `vat_chain_conflict`
* `period_closure_risk`
* `cross_entity_breakage`
* `document_posting_conflict`
## 10.3. Ввести `explanation_focus`
Чтобы retrieval сразу собирал evidence под тип ответа:
* `why_selected`
* `where_chain_breaks`
* `why_risky`
* `why_not_closed`
* `why_ranked_high`
* `what_conflicts_with_what`
## 10.4. Ввести `evidence pack`
На каждый top item возвращать не только сущность, но и:
* ключевой счёт
* документ
* статус
* связанная проводка
* отсутствующая связь
* lifecycle gap
* period impact
* selection_reason
* business_interpretation
---
# 11. Что добавить в result schema
Расширить unified result schema, чтобы answer composer мог собирать нормальный ответ по сути, а не по name/count/id. Это согласуется с вашим целевым слоем `Result normalization` и `Final Answer Composer`.
```json
{
"fragment_id": "F1",
"route": "hybrid_store_plus_live",
"status": "ok",
"result_type": "chain",
"items": [
{
"entity_type": "counterparty",
"entity_id": "....",
"label": "ООО ...",
"account_context": ["51", "60"],
"document_context": ["bank_statement", "payment_order"],
"selection_reason": [
"оплата отражена",
"закрывающий документ не подтвержден",
"цепочка расчета оборвана"
],
"risk_factors": [
"broken_lifecycle",
"missing_link",
"closure_risk"
],
"business_interpretation": "деньги прошли, но обязательство не закрылось корректно",
"evidence": [],
"confidence": "medium"
}
],
"summary": {
"ranking_basis": ["closure_risk", "repeatability", "financial_impact"]
},
"errors": []
}
```
---
# 12. Минимальный набор бухгалтерских правил, который я бы считал must-have
Если прямо урезать до ядра, то retrieval должен обязательно учитывать:
1. `account_scope`
2. `domain_scope`
3. `document_types`
4. `entity_types`
5. `relation_patterns`
6. `anomaly_patterns`
7. `lifecycle_stage_filters`
8. `period_scope`
9. `excluded_interpretations`
10. `ranking_basis`
11. `explanation_focus`
Без этого вы снова получите:
нормализатор понял вопрос,
route выбрали правильно,
а retrieval принёс один и тот же массив “вокруг темы”.
---
# 13. Короткая формулировка для команды
Если тебе нужен короткий месседж в работу, то вот он:
**Нужно расширить executeHybrid и соседние retrieval executors от модели “GUID-or-full-scan” к модели “semantic retrieval profile”.
Фильтрация должна строиться не только по счету, но и по участку учёта, типам документов, типам сущностей, relation patterns, lifecycle stage, anomaly patterns, excluded interpretations и ranking basis.
Если GUID отсутствует, executor не имеет права брать весь датасет; он обязан делать semantic narrowing по бухгалтерскому профилю запроса.**
---
# 14. Что я бы добавил ещё сверх этого
Отдельно заложить в retrieval слой:
* транслит-нормализацию бухгалтерских терминов до исполнения;
* словарь синонимов по участкам учёта;
* бухгалтерские alias-паттерны: “хвост”, “зависло”, “не бьётся”, “не тем закрылось”, “жизни не случилось”, “сломало период”, “сирота”, “висит”, “криво пошло”;
* map “бытовой язык → retrieval constraints”.
Это уже не про answer composer, а про то, чтобы retrieval получал нормальный предметный профиль даже из кривого человеческого запроса.