530 lines
18 KiB
Markdown
530 lines
18 KiB
Markdown
Да, так двигаться **можно**, но не в виде «сейчас добьём все сложные вопросы, а потом когда-нибудь займёмся длинным диалогом».
|
||
Правильнее так:
|
||
|
||
**сейчас добивать сложные вычислительные вопросы — да,
|
||
но уже сейчас заложить минимальный каркас длинного диалога, чтобы потом не пришлось ломать всё заново.**
|
||
|
||
То есть ответ не «сначала одно, потом другое», а:
|
||
|
||
**основной фокус — на сложных доказуемых вопросах,
|
||
но с обязательной тонкой прослойкой 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**.
|
||
|
||
Прям обязательно:
|
||
|
||
* 30–50 простых сценариев;
|
||
* 10–20 средних;
|
||
* 5–10 сложных.
|
||
|
||
И для каждого:
|
||
|
||
* 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. Сделать 2–3 эталонные длинные цепочки, а не весь “длинный диалог”
|
||
|
||
Вот это важный баланс.
|
||
|
||
Не надо сейчас пытаться закрыть **все** длинные диалоги.
|
||
Нужно взять 2–3 ключевые цепочки и довести их как вертикальные срезы.
|
||
|
||
Например:
|
||
|
||
### Цепочка 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. Выбрать 5–7 самых важных сложных управленческих вопросов.
|
||
3. Для каждого сделать exact business route.
|
||
4. Одновременно заложить минимальный result/state/navigation layer.
|
||
5. Прогнать 2–3 длинные эталонные цепочки.
|
||
|
||
### Не сейчас
|
||
|
||
* не пытаться закрыть весь длинный диалог целиком;
|
||
* не делать глобальную магическую “универсальную” оркестрацию;
|
||
* не лечить сложные кейсы только prompt engineering’ом.
|
||
|
||
---
|
||
|
||
## Короткий ответ на твой главный вопрос
|
||
|
||
**Да, фокус на сложных вопросах сейчас — правильный.**
|
||
Но **полностью откладывать длинные цепочки нельзя**. Их нужно не “доделывать потом”, а **заложить сейчас в виде минимальной объектной модели состояния и 2–3 эталонных навигационных сценариев**.
|
||
|
||
То есть:
|
||
|
||
**сначала не “сложные вопросы vs длинные диалоги”,
|
||
а “exact routes first, state skeleton in parallel, rich dialog later”.**
|
||
|
||
Это, на мой взгляд, для вас сейчас самый здоровый путь.
|
||
|
||
Могу дальше сразу разложить это в виде **конкретного roadmap-а по спринтам / этапам**, чтобы это можно было отдать в работу.
|