NODEDC_1C/docs/TECH/PLAN_FIX.md

530 lines
18 KiB
Markdown
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.

Да, так двигаться **можно**, но не в виде «сейчас добьём все сложные вопросы, а потом когда-нибудь займёмся длинным диалогом».
Правильнее так:
**сейчас добивать сложные вычислительные вопросы — да,
но уже сейчас заложить минимальный каркас длинного диалога, чтобы потом не пришлось ломать всё заново.**
То есть ответ не «сначала одно, потом другое», а:
**основной фокус — на сложных доказуемых вопросах,
но с обязательной тонкой прослойкой state/navigation уже сейчас.**
---
## Почему так
У тебя сейчас по сути есть **три разных задачи**, и их нельзя смешивать:
### 1. Доказательный вычислительный контур
Это вопросы типа:
* кому должны;
* кто должен нам;
* остатки;
* задолженность;
* обязательства на дату;
* НДС;
* обороты;
* сверки;
* причины расхождения.
Тут нужен не “умный ассистент”, а **строгий финансовый движок ответа**.
LLM тут только:
* понимает запрос,
* канонизирует,
* упаковывает ответ.
### 2. Диалоговая навигация по результатам
Это уже история:
* покажи должников;
* открой первого;
* покажи документы по нему;
* открой вот этот документ;
* вернись к списку;
* теперь покажи только крупных;
* а теперь снова общий список.
Это вообще другая задача. Это не про бухгалтерский расчёт, а про **сессионное состояние, ссылки на объекты и навигацию**.
### 3. Разговорный слой
Это:
* как красиво формулируется ответ;
* как держится контекст;
* как не врёт;
* как не теряет тему;
* как уточняет.
Если не разделить эти три задачи, начнётся каша:
* вычислительные баги будете лечить промптом;
* диалоговые провалы — данными;
* архитектурные проблемы — текстом ответа.
---
## Что у вас уже сделано правильно
Судя по описанию, вы уже сделали важную правильную вещь:
вы ушли от «говно-MVP на if-ах» к более нормальной оркестрации и явным контрактам.
Это правильно.
Потому что без этого дальше было бы бессмысленно развивать сложные вопросы.
---
## Где сейчас опасность
Опасность у вас не в том, что вы пошли в сложные вопросы.
Опасность в другом:
**вы можете начать чинить сложные кейсы так, что они размоют рабочие простые кейсы.**
Это самая частая проблема.
То есть:
* новый route ради сложного кейса начинает перехватывать старые запросы;
* новая нормализация ломает короткие вопросы;
* новый orchestration layer делает хуже там, где раньше всё было стабильно;
* deep/fallback начинает срабатывать там, где раньше был простой exact answer.
Поэтому тебе сейчас нельзя работать по принципу:
> “ну сейчас доделаем тяжёлые вопросы, а там посмотрим”
Нужен другой режим:
> **сложные кейсы добавляются как отдельный слой, не ломая работающий baseline.**
---
## Самый правильный способ двигаться сейчас
### Главный принцип:
**не делать “общую умность”, а делать “изолированные доказательные capability-маршруты”.**
То есть не надо пытаться “в целом сделать ассистент умнее”.
Надо делать конкретные capability-блоки:
* confirmed_payables_as_of_date
* confirmed_receivables_as_of_date
* vat_obligation_breakdown
* account_balance_as_of_date
* document_chain_explainer
* debtor_detail_drilldown
* settlement_reconciliation_trace
И каждый из них:
* имеет входной контракт,
* имеет data-route,
* имеет свой evidence model,
* имеет свои acceptance tests.
Это намного стабильнее, чем пытаться “допилить общий интеллект”.
---
## Можно ли сейчас фокусироваться на сложных вопросах, а длинные цепочки делать потом
**Да, но только частично.**
Правильный ответ такой:
### Что можно отложить
Можно отложить:
* полноценную богатую conversational UX-историю;
* красивые возвращения по веткам;
* умные эллипсисы типа “тот же документ, что мы обсуждали раньше”;
* сложные нелинейные прыжки по истории.
### Что нельзя откладывать
Нельзя откладывать:
* **модель состояния результата**;
* **идентификаторы result setов**;
* **идентификаторы выбранных объектов**;
* **контекст фокуса**;
* **операции drilldown / back / reopen / refine**.
Потому что если этого не заложить сейчас, потом всё придётся перепахивать.
---
## Очень важная мысль
Длинный диалог в вашем кейсе — это **не “LLM держит контекст”**.
Это вообще не об этом.
Это должно быть не:
* “модель помнит, о чём говорили”,
а:
* “система хранит конкретный объектный state разговора”.
Например:
### После запроса “покажи должников”
создаётся объект:
* `result_set_id = debtors_2020_05_v1`
* тип: `receivables_list`
* дата среза
* фильтры
* сортировка
* список entity_id
### Потом “открой второго”
создаётся:
* `focus_object = counterparty:gamma_mebel`
* `parent_result_set = debtors_2020_05_v1`
### Потом “покажи документы по нему”
создаётся:
* `result_set_id = docs_for_gamma_mebel_2020_05_v1`
* тип: `document_list`
* parent focus: `counterparty:gamma_mebel`
### Потом “вернись к списку должников”
это не магия модели, а явное:
* restore `result_set_id = debtors_2020_05_v1`
Вот тогда это работает как система.
А не как “LLM вроде бы держит мысль”.
---
## Поэтому правильная стратегия у вас должна быть двухконтурной
## Контур А — основной: сложные доказательные вопросы
Это ваш главный приоритет прямо сейчас.
Потому что если ассистент не умеет честно отвечать на:
* кому должны,
* кто должен нам,
* сколько НДС,
* какие обязательства открыты,
* почему расхождение,
то всё остальное рано или поздно бессмысленно.
Здесь надо добивать **exact analytical routes**.
## Контур Б — минимальный state/navigation framework
Не весь длинный диалог целиком, а минимальный каркас.
То есть прямо сейчас нужно ввести хотя бы:
* `conversation_state`
* `current_focus`
* `result_sets`
* `drilldown_history`
* `resolvable references`
типа “этот контрагент”, “первый”, “тот документ”, “верни прошлый список”
Без этого потом многоуровневые кейсы будут собираться заново криво.
---
## Как бы я выстроил разработку по этапам
## Этап 1. Заморозить baseline
Перед любыми тяжёлыми доработками нужно зафиксировать текущий рабочий контур:
* список простых запросов, которые уже работают;
* их эталонные ответы;
* их route expectations;
* их допустимые форматы;
* их accuracy baseline.
Иначе вы не заметите, как сложные доработки сожрут простые кейсы.
То есть нужен **golden baseline suite**.
Прям обязательно:
* 3050 простых сценариев;
* 1020 средних;
* 510 сложных.
И для каждого:
* intent;
* expected route;
* required evidence;
* must_not_happen;
* acceptance criteria.
---
## Этап 2. Выделить отдельный слой exact analytical capabilities
Не один “универсальный роут”, а capability registry.
Например:
* `confirmed_payables_as_of_date`
* `confirmed_receivables_as_of_date`
* `account_balance_as_of_date`
* `tax_obligation_snapshot`
* `document_trace_chain`
* `counterparty_reconciliation_detail`
И каждый capability должен быть:
* изолирован,
* версионирован,
* под rollout flag,
* с собственным eval suite.
Это защитит простые кейсы.
---
## Этап 3. Для сложных вопросов делать не prompt-tuning, а data-route design
Вот тут очень важно.
На текущем этапе вам не нужно “допилить LLM, чтобы она лучше поняла вопрос”.
Вам нужно:
* описать доказательный объект ответа;
* понять, какие сущности для него нужны;
* понять, где эти поля лежат;
* понять, как строится формула;
* понять, как выглядит traceability.
То есть сложный вопрос нужно разбирать не как “сложный prompt”, а как:
**какой exact business computation за ним стоит?**
Например, вопрос:
> кому должны на май 2020
разбирается как:
* дата среза,
* открытые обязательства,
* группировка по контрагенту,
* классификация обязательств,
* исключение закрытых,
* доказательная цепочка.
Вот это правильный уровень.
---
## Этап 4. Уже сейчас ввести минимальный state model для диалога
Не надо пока делать “идеальный длинный разговор”.
Но нужно завести базовые сущности:
### `session_context`
* active_result_set_id
* active_focus_object
* last_confirmed_route
* date_scope
* organization_scope
### `result_set`
* id
* type
* route_id
* filters
* sort
* entity_refs[]
* source_refs[]
* created_from_turn
### `focus_object`
* object_type
* object_id
* label
* provenance_result_set_id
### `navigation_event`
* action: open / refine / back / compare / reset
* source_result_set_id
* target_object_id
* derived_result_set_id
Тогда потом длинный диалог нарастает нормально.
---
## Этап 5. Сделать 23 эталонные длинные цепочки, а не весь “длинный диалог”
Вот это важный баланс.
Не надо сейчас пытаться закрыть **все** длинные диалоги.
Нужно взять 23 ключевые цепочки и довести их как вертикальные срезы.
Например:
### Цепочка 1
* покажи должников на дату
* открой крупнейшего
* покажи документы по нему
* открой документ
* покажи, чем закрывался
* вернись к списку
### Цепочка 2
* кому должны на дату
* оставь только поставщиков
* покажи по конкретному контрагенту
* покажи основание долга
* покажи связанные оплаты
* верни сводку
### Цепочка 3
* покажи НДС за период
* объясни расхождение
* открой документы-источники
* покажи корректировки
* вернись к агрегату
Этого уже хватит, чтобы не строить всё вслепую.
---
## На что я бы не тратил время сейчас
Сейчас я бы **не** делал ставку на:
* “сделаем модель ещё умнее, и она сама вытянет”;
* бесконечную шлифовку prose-ответов;
* тонкую косметику fallback-логики;
* попытку одной общей оркестрацией покрыть всё;
* богатую свободную болталку.
Это всё вторично по сравнению с:
* exact routes,
* state model,
* regression harness,
* evidence model.
---
## Как не сломать простые кейсы
Вот тут прям практический совет.
### 1. Все новые маршруты — только за флагами
Новый exact-route не должен сразу заменять старый baseline.
Сначала:
* old route remains default
* new route runs in shadow mode
* сравниваете ответы
* смотрите deltas
* только потом переводите на prod path
### 2. Для каждого кейса фиксируйте expected route
Например:
* “остаток по счету” не должен внезапно уйти в deep-analysis;
* “кому должны” должен идти только в confirmed payables route;
* “покажи документы по этому контрагенту” — только в drilldown route.
### 3. Отдельно меряйте регрессии
Не только answer correctness, но и:
* route correctness;
* evidence completeness;
* fallback frequency;
* overconfident wrong answers;
* broken referential follow-ups.
---
## Самый правильный способ мыслить про ваш продукт сейчас
Не как про “LLM-ассистента по бухгалтерии”, а как про:
**доказательный финансовый query engine + conversational navigator поверх него**
Вот это, по-моему, самая точная рамка.
Потому что если мыслить “ассистентом”, вас всё время будет тянуть лечить вычислительные проблемы через LLM.
А если мыслить “доказательным query engine”, тогда всё встаёт на место:
* LLM — вход и объяснение;
* engine — расчёт;
* state layer — навигация;
* evidence layer — доверие.
---
## Мой прямой совет по порядку работ
Я бы делал так:
### Сейчас
1. Зафиксировать baseline простых рабочих кейсов.
2. Выбрать 57 самых важных сложных управленческих вопросов.
3. Для каждого сделать exact business route.
4. Одновременно заложить минимальный result/state/navigation layer.
5. Прогнать 23 длинные эталонные цепочки.
### Не сейчас
* не пытаться закрыть весь длинный диалог целиком;
* не делать глобальную магическую “универсальную” оркестрацию;
* не лечить сложные кейсы только prompt engineeringом.
---
## Короткий ответ на твой главный вопрос
**Да, фокус на сложных вопросах сейчас — правильный.**
Но **полностью откладывать длинные цепочки нельзя**. Их нужно не “доделывать потом”, а **заложить сейчас в виде минимальной объектной модели состояния и 23 эталонных навигационных сценариев**.
То есть:
**сначала не “сложные вопросы vs длинные диалоги”,
а “exact routes first, state skeleton in parallel, rich dialog later”.**
Это, на мой взгляд, для вас сейчас самый здоровый путь.
Могу дальше сразу разложить это в виде **конкретного roadmap-а по спринтам / этапам**, чтобы это можно было отдать в работу.