1352 lines
54 KiB
Markdown
1352 lines
54 KiB
Markdown
Да — помочь могу. И нет, у тебя не “всё в корне неправильно”. По форме ты уже описал вполне нормальный паттерн: **augmented LLM** с инструментами/MCP, **prompt chaining** по шагам и отдельный проход на проверку качества перед финальным ответом. Это очень похоже на то, что в официальных гайдах описывают как рабочую основу: сначала простые композиционные паттерны, потом только при необходимости — более автономные agent-циклы. И OpenAI, и Anthropic отдельно советуют сначала выжать максимум из **одного агента с инструментами**, а не городить много агентов слишком рано. ([Anthropic][1])
|
||
|
||
Но у тебя, по описанию, смешаны в одну массу **четыре разные роли**:
|
||
|
||
1. разговор с пользователем,
|
||
2. семантическое понимание вопроса,
|
||
3. походы в 1С/MCP,
|
||
4. объяснение результата человеку.
|
||
Когда это всё делает одна и та же “мыслящая каша”, система и становится сухой, тупой и неясной в дебаге. Для таких систем проблема обычно не в том, что “мало LLM”, а в том, что нет **жёстких контрактов состояния** между шагами. Anthropic прямо разделяет **workflow** как предопределённые кодовые этапы и **agent** как динамический loop; для запросов в 1С у тебя, по сути, большая часть работы должна быть именно workflow, а не полностью свободный агент. ([Anthropic][1])
|
||
|
||
Самая важная мысль: **не надо “сильно упрощать” вопрос пользователя и выбрасывать оригинал**. Это одна из типовых ловушек. Нужно не simplification, а **semantic unpacking**: хранить рядом
|
||
|
||
* исходный вопрос,
|
||
* нормализованную формулировку,
|
||
* список неоднозначностей,
|
||
* гипотезы домена,
|
||
* контракт ответа: что именно надо доказать, чтобы считать вопрос отвеченным.
|
||
Иначе ты рано убиваешь нюанс, а потом уже собираешь “правильные” данные не на тот вопрос. Это особенно критично в длинных agent-пайплайнах: актуальная практика сейчас вообще больше про **context engineering**, то есть про управление состоянием контекста, а не про красивый системный промпт. Контекст конечен, и чем больше ты тащишь в модель сырых логов/кусков, тем выше риск потери фокуса. ([Anthropic][2])
|
||
|
||
Я бы собрал тебе архитектуру так:
|
||
|
||
```text
|
||
Пользователь
|
||
↓
|
||
A. Dialogue Interpreter (LLM)
|
||
↓
|
||
B. Query Frame Builder (LLM, strict JSON)
|
||
↓
|
||
C. Planner / Resolver (LLM + код)
|
||
↓
|
||
D. MCP / 1C Executor (только код и инструменты)
|
||
↓
|
||
E. Coverage Critic (LLM + правила)
|
||
↓
|
||
F. Answer Composer (LLM)
|
||
↓
|
||
Пользовательский ответ + инженерный trace
|
||
```
|
||
|
||
Ключевая идея тут в том, что **LLM не должна быть источником истины**. Истина — это 1С/MCP и детерминированные результаты вызовов. LLM делает интерпретацию, план, проверку покрытия и человеческую упаковку ответа. А всё, что связано с фактом “нашлось / не нашлось / есть противоречие / не удалось привязать сущность”, должно жить в машинном объекте состояния, а не в свободном тексте. Такой подход прямо согласуется с current best practices: модели + tools + state/memory + orchestration, с loop-выходами и внятными stop conditions. ([OpenAI Developers][3])
|
||
|
||
### Что должно появиться между шагами
|
||
|
||
Не “много промптов”, а **несколько обязательных артефактов**.
|
||
|
||
**1. QueryFrame** — как система поняла вопрос.
|
||
|
||
```json
|
||
{
|
||
"original_user_question": "...",
|
||
"normalized_question": "...",
|
||
"business_intent": "settlement_tail_check",
|
||
"requested_answer_shape": "list_with_explanation",
|
||
"time_scope": {
|
||
"explicit": null,
|
||
"inferred": "current_as_of_date",
|
||
"ambiguity": true
|
||
},
|
||
"entity_candidates": [
|
||
{"surface": "поставщики", "type": "counterparty_group"},
|
||
{"surface": "хвосты", "type": "informal_term", "needs_domain_resolution": true}
|
||
],
|
||
"ambiguities": [
|
||
"что считать хвостами",
|
||
"на какую дату смотреть",
|
||
"по какому контуру: расчеты, акты, оплаты, закрытие документов"
|
||
],
|
||
"success_criteria": [
|
||
"определено доменное значение 'хвостов'",
|
||
"выбран период/as_of",
|
||
"собран список контрагентов с доказательством"
|
||
]
|
||
}
|
||
```
|
||
|
||
**2. ExecutionPlan** — не просто “сходить в 1С”, а конкретный план доказательства.
|
||
|
||
```json
|
||
{
|
||
"plan_steps": [
|
||
"resolve_domain_term('хвосты')",
|
||
"resolve_counterparty_scope('поставщики')",
|
||
"resolve_as_of_date()",
|
||
"query_open_settlements()",
|
||
"query_unclosed_docs_if_needed()"
|
||
],
|
||
"tool_calls_expected": [...],
|
||
"fallbacks": [...],
|
||
"stop_conditions": [
|
||
"all success criteria covered",
|
||
"hard blocker",
|
||
"ambiguity requires user clarification"
|
||
]
|
||
}
|
||
```
|
||
|
||
**3. EvidenceBundle** — весь ground truth.
|
||
|
||
```json
|
||
{
|
||
"facts": [...],
|
||
"source_refs": [...],
|
||
"tool_runs": [...],
|
||
"entity_bindings": [...],
|
||
"not_found": [...],
|
||
"conflicts": [...],
|
||
"execution_errors": [...]
|
||
}
|
||
```
|
||
|
||
**4. CoverageReport** — самый недостающий у вас слой.
|
||
|
||
```json
|
||
{
|
||
"answerability": "full | partial | insufficient",
|
||
"covered_points": [...],
|
||
"uncovered_points": [...],
|
||
"why_partial": [...],
|
||
"next_best_actions": [...]
|
||
}
|
||
```
|
||
|
||
**5. FinalAnswerPackage** — уже для человека.
|
||
|
||
```json
|
||
{
|
||
"short_answer": "...",
|
||
"detailed_explanation": "...",
|
||
"evidence_summary": "...",
|
||
"limitations": "...",
|
||
"clarifying_question_if_needed": "..."
|
||
}
|
||
```
|
||
|
||
Вот это и даёт тебе одновременно и хороший UX, и инженерную диагностируемость.
|
||
|
||
### Где у вас сейчас, скорее всего, ломается качество
|
||
|
||
Первая ошибка: **слишком ранняя компрессия смысла**.
|
||
Не надо превращать вопрос пользователя в один “упрощённый” вариант и жить с ним дальше. Нужен пакет из: оригинал + нормализация + неоднозначности + критерии ответа.
|
||
|
||
Вторая ошибка: **LLM сама решает, достаточно ли она ответила**.
|
||
Нужен отдельный слой **coverage critic**, который сверяет:
|
||
|
||
* что хотел пользователь,
|
||
* что реально доказано evidence’ом,
|
||
* какие дыры остались.
|
||
Это очень похоже на паттерн **evaluator-optimizer**, который Anthropic отдельно рекомендует для задач, где качество растёт от дополнительной критики и итеративной доработки. ([Anthropic][1])
|
||
|
||
Третья ошибка: **инженерный trace не оформлен как продукт системы**.
|
||
У тебя он, судя по описанию, где-то размазан по логам. А он должен быть первоклассным объектом: чтобы и пользователь, и инженер могли понять, почему ответ полный/частичный/невозможный.
|
||
|
||
### Как сделать ассистента “человечным”, а не сухим
|
||
|
||
Сухость почти никогда не лечится “более креативным промптом”. Она лечится **формой финального ответа**.
|
||
|
||
Финальный ответ у такого ассистента должен всегда иметь 5 смысловых слоёв:
|
||
|
||
1. **Короткий вывод** — прямой ответ на вопрос.
|
||
2. **Что именно проверено** — какие регистры/документы/сущности смотрели.
|
||
3. **Что найдено** — с привязкой к фактам.
|
||
4. **Что не удалось установить** — честно, без стыда.
|
||
5. **Что нужно уточнить или что система сделает следующим лучшим шагом**.
|
||
|
||
То есть не “вот ссылка на документ, иди сам разбирайся”, а:
|
||
“Под хвостами в текущем прогоне система проверила незакрытые расчёты с поставщиками на дату X. Найдены такие-то контрагенты. Для двух контрагентов есть движения без подтверждающего закрывающего документа, поэтому ответ частичный. Чтобы дать окончательный список хвостов, нужно уточнить: считать ли хвостами только просроченные расчёты или любые незакрытые остатки.”
|
||
|
||
Вот это уже и человеку полезно, и инженеру показывает, **какого доменного определения не хватает**.
|
||
|
||
### Практическое правило №1
|
||
|
||
**Не спрашивай LLM: “ответь на вопрос”**.
|
||
Спрашивай по шагам:
|
||
|
||
* “Собери QueryFrame”
|
||
* “Собери ExecutionPlan”
|
||
* “Оцени CoverageReport”
|
||
* “Собери человеческий ответ по пакету evidence + coverage”
|
||
|
||
То есть LLM не пишет свободный роман, а закрывает **конкретный контракт шага**.
|
||
|
||
### Практическое правило №2
|
||
|
||
Для внутренних шагов используй **строгие структурированные выходы**, а не просто JSON “на честном слове”. В официальных гайдах OpenAI это отдельно вынесено как способ добиваться строгого совпадения со схемой при tool calling / structured outputs. Даже если у тебя не OpenAI-стек, сам принцип тот же: каждый шаг должен возвращать объект по схеме, иначе ретрай/repair loop. ([OpenAI][4])
|
||
|
||
### Практическое правило №3
|
||
|
||
**Не пихай в финальную LLM сырые результаты всех MCP-вызовов.**
|
||
Перед финальным проходом делай **evidence compaction**:
|
||
|
||
* только нужные факты,
|
||
* только привязанные сущности,
|
||
* только важные ошибки,
|
||
* только конфликты,
|
||
* только краткие source refs.
|
||
|
||
Иначе у тебя начинается классическая деградация от перегруженного контекста. Это сейчас уже прямо рассматривается как отдельная инженерная дисциплина — context engineering. ([Anthropic][2])
|
||
|
||
### Практическое правило №4
|
||
|
||
Держи **два параллельных выхода** на каждый turn:
|
||
|
||
**Пользовательский**
|
||
|
||
* короткий вывод,
|
||
* объяснение,
|
||
* ограничения,
|
||
* следующий вопрос/шаг.
|
||
|
||
**Инженерный**
|
||
|
||
* QueryFrame,
|
||
* Plan,
|
||
* Tool trace,
|
||
* EvidenceBundle,
|
||
* CoverageReport,
|
||
* reason codes.
|
||
|
||
Например reason codes:
|
||
|
||
* `missing_period`
|
||
* `ambiguous_business_term`
|
||
* `entity_not_resolved`
|
||
* `insufficient_1c_coverage`
|
||
* `conflicting_documents`
|
||
* `tool_execution_error`
|
||
|
||
Это резко упрощает и улучшение доменов, и анализ того, почему “ответ тупой”.
|
||
|
||
### Практическое правило №5
|
||
|
||
Введи **claim-to-evidence binding**.
|
||
Любое содержательное утверждение в финальном ответе должно быть либо:
|
||
|
||
* доказано конкретным evidence id,
|
||
* либо помечено как inference,
|
||
* либо помечено как unknown.
|
||
|
||
Это очень сильно отрезает галлюцинации в бухгалтерских и 1С-задачах.
|
||
|
||
### Что я бы сделал именно в твоём кейсе с 1С
|
||
|
||
Не строил бы “свободного умного агента”, который сам решает, куда идти по 1С. Я бы сделал **manager-style orchestrator** с небольшим числом жёстко описанных инструментов и доменных процедур. OpenAI отдельно отмечает, что чаще проблема не в количестве инструментов, а в том, что они похожи, пересекаются и плохо описаны; если инструменты чёткие, один агент часто справляется лучше и проще в сопровождении. ([OpenAI][5])
|
||
|
||
То есть не 40 мутных MCP-тулов вроде:
|
||
|
||
* `search_docs`
|
||
* `find_data`
|
||
* `get_entries`
|
||
|
||
А доменно:
|
||
|
||
* `resolve_counterparty`
|
||
* `resolve_period_or_asof`
|
||
* `get_open_settlements`
|
||
* `get_unclosed_documents`
|
||
* `get_payments_for_counterparty`
|
||
* `get_document_movements`
|
||
* `explain_domain_term`
|
||
|
||
И каждому — чёткое описание входа, выхода, ограничений и типичных ошибок. И Anthropic, и OpenAI отдельно подчёркивают, что надёжность агента очень сильно зависит от качества инструментов и их документации. ([Anthropic][1])
|
||
|
||
### Про Qwen 2.5 отдельно
|
||
|
||
Если ты сидишь на локальном Qwen 2.5 и у тебя tool calling/MCP местами ведёт себя странно, это может быть не только “модель тупая”, а ещё и проблема **шаблона/парсера tool calls**. В `llama.cpp` прямо указана поддержка native tool call formats для **Qwen 2.5** и generic fallback, причём generic менее эффективен. У текущего `Qwen-Agent` функция tool calling и MCP есть, но сам репозиторий уже ориентирован на Qwen>=3.0; при этом в changelog есть отдельные упоминания адаптаций под Qwen2.5 general models в 2025 году. То есть сам подход рабочий, но стек надо очень внимательно проверять на уровне parser/template/runtime, а не только промпта. ([GitHub][6])
|
||
|
||
Итоговый тезис такой:
|
||
**вам не нужен “ещё более агентный агент”. Вам нужен доказательный диалоговый workflow с отдельным critic-слоем и явными артефактами состояния.**
|
||
Тогда система станет:
|
||
|
||
* человечнее для пользователя,
|
||
* полезнее для инженера,
|
||
* понятнее в дебаге,
|
||
* устойчивее к доменным дырам,
|
||
* и при этом не обязательно сложнее по коду.
|
||
|
||
|
||
|
||
[1]: https://www.anthropic.com/research/building-effective-agents "Building Effective AI Agents \ Anthropic"
|
||
[2]: https://www.anthropic.com/engineering/effective-context-engineering-for-ai-agents "Effective context engineering for AI agents \ Anthropic"
|
||
[3]: https://developers.openai.com/tracks/building-agents "Building agents"
|
||
[4]: https://openai.com/index/introducing-structured-outputs-in-the-api/ "Introducing Structured Outputs in the API | OpenAI"
|
||
[5]: https://openai.com/business/guides-and-resources/a-practical-guide-to-building-ai-agents/ "A practical guide to building agents | OpenAI"
|
||
[6]: https://github.com/ggml-org/llama.cpp/blob/master/docs/function-calling.md "llama.cpp/docs/function-calling.md at master · ggml-org/llama.cpp · GitHub"
|
||
|
||
______
|
||
|
||
Ниже — ТЗ в прикладном виде под **диалогового 1С-ассистента с MCP**, где приоритет — **максимальное качество, объяснимость, удержание контекста и инженерная диагностируемость**, а не скорость.
|
||
|
||
---
|
||
|
||
# ТЗ
|
||
|
||
## Диалоговый LLM-ассистент для 1С через MCP
|
||
|
||
### Версия: Draft v1
|
||
|
||
### Назначение: архитектура качественного, объяснимого и инженерно прозрачного ассистента
|
||
|
||
## 1. Цель
|
||
|
||
Разработать диалоговый ассистент для работы с данными 1С через MCP, который:
|
||
|
||
* корректно понимает пользовательский вопрос в бизнес-терминах;
|
||
* удерживает смысл и контекст вопроса без грубой потери нюансов;
|
||
* умеет декомпозировать вопрос на доменные сущности и проверяемые подзадачи;
|
||
* выполняет доказательный проход по 1С через MCP-инструменты;
|
||
* формирует **человеческий**, а не сухой ответ;
|
||
* явно сообщает, **что найдено, что не найдено, чего не хватает, где неоднозначность**;
|
||
* одновременно помогает **инженерам системы** понимать, почему ответ получился полным, частичным или не получился.
|
||
|
||
---
|
||
|
||
## 2. Проблема текущего состояния
|
||
|
||
Текущее поведение ассистента описывается следующими симптомами:
|
||
|
||
* ответы сухие и мало полезные для пользователя;
|
||
* система рано “сжимает” вопрос и теряет часть смысла;
|
||
* механика маршрутизации, извлечения данных и ответа человеку смешаны в одну логическую массу;
|
||
* отсутствует явный слой, который проверяет: **действительно ли собранные данные покрывают исходный вопрос**;
|
||
* отсутствует прозрачный reason trace для инженеров;
|
||
* при невозможности ответа система не объясняет полезно и предметно, **почему именно** ответ неполный.
|
||
|
||
Следствие: ассистент выглядит тупым не только из-за модели, а в первую очередь из-за **неразделённых ролей и отсутствия промежуточных артефактов состояния**.
|
||
|
||
---
|
||
|
||
## 3. Основной архитектурный принцип
|
||
|
||
Ассистент должен быть построен не как “одна умная LLM, которая делает всё”, а как **жёсткий workflow из нескольких этапов**, где каждый этап производит **структурированный артефакт**, а не свободный текст.
|
||
|
||
### Ключевой принцип
|
||
|
||
Каждый шаг обязан оставлять после себя:
|
||
|
||
* машинно проверяемый результат;
|
||
* объяснимую причину выбранного пути;
|
||
* список неопределённостей и ограничений.
|
||
|
||
### Базовое разделение ролей
|
||
|
||
Нужно развести четыре логики:
|
||
|
||
1. **Диалоговая интерпретация** — что пользователь на самом деле хочет узнать.
|
||
2. **Доменная нормализация и планирование** — какие сущности, периоды, типы объектов и операции нужны.
|
||
3. **Детерминированное извлечение данных** — походы в 1С через MCP.
|
||
4. **Человеческая упаковка ответа** — как сформулировать результат полезно, мягко и честно.
|
||
|
||
---
|
||
|
||
## 4. Границы этапа
|
||
|
||
### Входит в этап
|
||
|
||
* архитектура пайплайна запроса;
|
||
* контракты промежуточных артефактов;
|
||
* правила диалогового ответа;
|
||
* правила неполного ответа;
|
||
* reason codes;
|
||
* логирование и трассировка;
|
||
* требования к памяти контекста;
|
||
* требования к качеству и acceptance.
|
||
|
||
### Не входит в этап
|
||
|
||
* обучение собственной модели;
|
||
* полная реализация семантического поиска по документам вне 1С;
|
||
* универсальный open-ended autonomous agent;
|
||
* полный онтологический слой предприятия;
|
||
* автоматическое исправление данных в 1С.
|
||
|
||
---
|
||
|
||
## 5. Целевой результат
|
||
|
||
После внедрения этапа система должна уметь:
|
||
|
||
* отвечать на вопрос не “как LLM”, а **как доказательный доменный ассистент**;
|
||
* возвращать не только ответ, но и полезное пояснение, почему ответ именно такой;
|
||
* разделять:
|
||
|
||
* уверенно доказанное,
|
||
* вероятностный вывод,
|
||
* пробел данных,
|
||
* пробел доменной формализации,
|
||
* ошибку инструмента;
|
||
* удерживать контекст диалога между репликами;
|
||
* накапливать инженерную телеметрию для улучшения маршрутов и доменов.
|
||
|
||
---
|
||
|
||
# 6. Общая архитектура
|
||
|
||
## 6.1. Логическая схема
|
||
|
||
```text
|
||
Пользователь
|
||
↓
|
||
1. Dialogue Interpreter
|
||
↓
|
||
2. Query Frame Builder
|
||
↓
|
||
3. Domain Resolver / Entity Resolver
|
||
↓
|
||
4. Execution Planner
|
||
↓
|
||
5. MCP / 1C Executor
|
||
↓
|
||
6. Evidence Builder
|
||
↓
|
||
7. Coverage Critic
|
||
↓
|
||
8. Answer Composer
|
||
↓
|
||
Пользовательский ответ + инженерный trace
|
||
```
|
||
|
||
---
|
||
|
||
## 6.2. Назначение блоков
|
||
|
||
### 1. Dialogue Interpreter
|
||
|
||
Задача:
|
||
|
||
* понять намерение пользователя;
|
||
* сохранить исходную формулировку;
|
||
* выявить скрытые неоднозначности;
|
||
* определить ожидаемую форму ответа.
|
||
|
||
Важно:
|
||
**Нельзя заменять исходный вопрос одним “упрощённым” вопросом и жить только с ним.**
|
||
Нужно сохранять:
|
||
|
||
* оригинал;
|
||
* нормализованный вариант;
|
||
* доменные гипотезы;
|
||
* список неоднозначностей.
|
||
|
||
---
|
||
|
||
### 2. Query Frame Builder
|
||
|
||
Формирует структурированный каркас запроса — QueryFrame.
|
||
|
||
В QueryFrame должны быть:
|
||
|
||
* исходный вопрос;
|
||
* нормализованный вопрос;
|
||
* intent;
|
||
* предполагаемый домен;
|
||
* сущности-кандидаты;
|
||
* временной контекст;
|
||
* ожидаемый тип ответа;
|
||
* критерии успешности ответа.
|
||
|
||
---
|
||
|
||
### 3. Domain Resolver / Entity Resolver
|
||
|
||
Задача:
|
||
|
||
* привязать пользовательские слова к доменным сущностям;
|
||
* разрешить разговорные термины;
|
||
* проверить, что именно имеется в виду под неоднозначными словами.
|
||
|
||
Примеры:
|
||
|
||
* “хвосты” → незакрытые остатки / просроченные расчёты / не закрытые документами движения;
|
||
* “поставщики” → контрагенты конкретного типа;
|
||
* “на конец месяца” → требуется точная дата отсечения;
|
||
* “договоры висят” → проверить логику “остаток по расчётам”, “незакрытые акты”, “непроведённые взаиморасчёты” и т.д.
|
||
|
||
На этом этапе нельзя молча принимать одну трактовку, если есть несколько бизнес-валидных.
|
||
|
||
---
|
||
|
||
### 4. Execution Planner
|
||
|
||
Строит **план доказательства**, а не просто список тулов.
|
||
|
||
План должен отвечать на вопросы:
|
||
|
||
* что надо доказать;
|
||
* какие сущности обязательны;
|
||
* какие поля/регистры/документы нужны;
|
||
* какие шаги обязательны;
|
||
* какие шаги fallback;
|
||
* при каких условиях можно завершить ответ;
|
||
* когда нужно остановиться и запросить уточнение.
|
||
|
||
---
|
||
|
||
### 5. MCP / 1C Executor
|
||
|
||
Это детерминированный контур.
|
||
|
||
Требования:
|
||
|
||
* никакой свободной импровизации LLM при исполнении;
|
||
* строго типизированные вызовы;
|
||
* прозрачные ошибки;
|
||
* возвращаемый результат должен быть нормализован;
|
||
* каждый вызов должен иметь идентификатор, статус, параметры, источник, время выполнения.
|
||
|
||
---
|
||
|
||
### 6. Evidence Builder
|
||
|
||
Собирает результат исполнений в единый **EvidenceBundle**:
|
||
|
||
* факты;
|
||
* привязки сущностей;
|
||
* источники;
|
||
* найденные документы;
|
||
* найденные движения;
|
||
* конфликты;
|
||
* пробелы;
|
||
* ошибки исполнения.
|
||
|
||
EvidenceBundle — это основной ground truth для ответа.
|
||
|
||
---
|
||
|
||
### 7. Coverage Critic
|
||
|
||
Самый важный слой.
|
||
|
||
Проверяет:
|
||
|
||
* что хотел пользователь;
|
||
* что действительно найдено;
|
||
* что доказано;
|
||
* что покрыто частично;
|
||
* что не покрыто вообще;
|
||
* какая причина неполноты.
|
||
|
||
Этот блок не должен “додумывать”, он должен **оценивать покрытие**.
|
||
|
||
---
|
||
|
||
### 8. Answer Composer
|
||
|
||
Формирует финальный ответ человеку.
|
||
|
||
Ответ должен быть:
|
||
|
||
* прямым;
|
||
* полезным;
|
||
* объясняющим;
|
||
* честным по ограничениям;
|
||
* пригодным и для пользователя, и для инженера в разборе кейса.
|
||
|
||
---
|
||
|
||
# 7. Контракты данных
|
||
|
||
## 7.1. QueryFrame
|
||
|
||
```json
|
||
{
|
||
"request_id": "uuid",
|
||
"conversation_id": "uuid",
|
||
"turn_id": 12,
|
||
"original_user_question": "По каким поставщикам висят хвосты?",
|
||
"normalized_question": "Определить список поставщиков с незавершенными расчетами или иными незакрытыми остатками на целевую дату.",
|
||
"business_intent": "detect_open_supplier_settlements",
|
||
"expected_answer_shape": "list_with_explanation",
|
||
"domain_candidates": [
|
||
"supplier_settlements",
|
||
"document_closure",
|
||
"mutual_reconciliations"
|
||
],
|
||
"time_scope": {
|
||
"explicit_period": null,
|
||
"as_of_date": null,
|
||
"needs_resolution": true
|
||
},
|
||
"entity_candidates": [
|
||
{
|
||
"surface": "поставщики",
|
||
"type": "counterparty_group",
|
||
"confidence": 0.96
|
||
},
|
||
{
|
||
"surface": "хвосты",
|
||
"type": "informal_business_term",
|
||
"confidence": 0.41,
|
||
"requires_domain_resolution": true
|
||
}
|
||
],
|
||
"ambiguities": [
|
||
"Не определено, что считать 'хвостами'",
|
||
"Не определена дата отсечения",
|
||
"Не определен точный контур проверки"
|
||
],
|
||
"success_criteria": [
|
||
"Определить трактовку термина 'хвосты'",
|
||
"Определить дату/период",
|
||
"Найти подтверждаемые остатки или незакрытые документы",
|
||
"Сформировать список контрагентов с обоснованием"
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7.2. ExecutionPlan
|
||
|
||
```json
|
||
{
|
||
"request_id": "uuid",
|
||
"plan_version": 1,
|
||
"goal": "Подтвердить наличие незакрытых обязательств/остатков по поставщикам",
|
||
"steps": [
|
||
{
|
||
"step_id": "S1",
|
||
"type": "resolve_business_term",
|
||
"input": "хвосты",
|
||
"required": true
|
||
},
|
||
{
|
||
"step_id": "S2",
|
||
"type": "resolve_as_of_date",
|
||
"required": true
|
||
},
|
||
{
|
||
"step_id": "S3",
|
||
"type": "resolve_counterparty_scope",
|
||
"input": "поставщики",
|
||
"required": true
|
||
},
|
||
{
|
||
"step_id": "S4",
|
||
"type": "query_open_settlements",
|
||
"required": true
|
||
},
|
||
{
|
||
"step_id": "S5",
|
||
"type": "query_supporting_documents",
|
||
"required": false
|
||
}
|
||
],
|
||
"fallbacks": [
|
||
"Если термин 'хвосты' не резолвится однозначно — проверить 2-3 допустимые трактовки и явно показать пользователю",
|
||
"Если дата отсутствует — использовать рабочую дату с явной пометкой",
|
||
"Если список поставщиков не выделяется напрямую — применить фильтр по типу контрагента"
|
||
],
|
||
"stop_conditions": [
|
||
"success_criteria_fully_covered",
|
||
"critical_ambiguity_requires_user_input",
|
||
"tooling_failure_no_evidence",
|
||
"max_execution_budget_reached"
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7.3. ToolRun
|
||
|
||
```json
|
||
{
|
||
"tool_run_id": "uuid",
|
||
"tool_name": "get_open_settlements",
|
||
"status": "success",
|
||
"input": {
|
||
"counterparty_type": "supplier",
|
||
"as_of_date": "2026-04-10"
|
||
},
|
||
"started_at": "2026-04-10T12:01:15Z",
|
||
"finished_at": "2026-04-10T12:01:16Z",
|
||
"duration_ms": 842,
|
||
"rows_returned": 17,
|
||
"error_code": null,
|
||
"error_message": null
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7.4. EvidenceBundle
|
||
|
||
```json
|
||
{
|
||
"request_id": "uuid",
|
||
"facts": [
|
||
{
|
||
"fact_id": "F1",
|
||
"type": "open_balance",
|
||
"entity": "ООО Альфа",
|
||
"value": 152340.55,
|
||
"currency": "RUB",
|
||
"as_of_date": "2026-04-10",
|
||
"source_ref": "SRC12"
|
||
}
|
||
],
|
||
"entity_bindings": [
|
||
{
|
||
"surface": "поставщики",
|
||
"resolved_to": "counterparty.role=supplier",
|
||
"confidence": 0.97
|
||
}
|
||
],
|
||
"source_refs": [
|
||
{
|
||
"source_ref": "SRC12",
|
||
"kind": "1C_register_extract",
|
||
"object_type": "settlement_register",
|
||
"object_id": "..."
|
||
}
|
||
],
|
||
"documents": [],
|
||
"conflicts": [],
|
||
"not_found": [],
|
||
"execution_errors": []
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7.5. CoverageReport
|
||
|
||
```json
|
||
{
|
||
"request_id": "uuid",
|
||
"answerability": "partial",
|
||
"covered_points": [
|
||
"Сформирован список поставщиков с открытыми остатками",
|
||
"Определена дата отсечения"
|
||
],
|
||
"uncovered_points": [
|
||
"Не доказано, считать ли все остатки именно 'хвостами' в бизнес-смысле",
|
||
"Не подтверждено закрытие документами по каждому случаю"
|
||
],
|
||
"why_partial": [
|
||
{
|
||
"reason_code": "AMBIGUOUS_BUSINESS_TERM",
|
||
"message": "Термин 'хвосты' не имеет единственной фиксированной трактовки"
|
||
},
|
||
{
|
||
"reason_code": "EVIDENCE_DEPTH_LIMIT",
|
||
"message": "Для части контрагентов есть остатки, но нет дополнительной проверки закрывающих документов"
|
||
}
|
||
],
|
||
"next_best_actions": [
|
||
"Уточнить, считать ли хвостами любые незакрытые остатки или только просроченные/неподтвержденные",
|
||
"Запустить углубленный проход по документам"
|
||
]
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 7.6. FinalAnswerPackage
|
||
|
||
```json
|
||
{
|
||
"short_answer": "На текущую дату выявлены поставщики с незакрытыми остатками.",
|
||
"user_facing_answer": "Проверка выполнена по контуру расчетов с поставщиками...",
|
||
"evidence_summary": [
|
||
"Найдены открытые остатки по 7 контрагентам",
|
||
"Для 2 случаев есть недостающая глубина подтверждения"
|
||
],
|
||
"limitations": [
|
||
"Термин 'хвосты' интерпретирован как незакрытые остатки по расчетам"
|
||
],
|
||
"clarifying_question": "Нужно ли считать хвостами только просроченные случаи, или любые незакрытые остатки?"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
# 8. Пайплайн обработки запроса
|
||
|
||
## 8.1. Этап 1. Приём и первичная интерпретация
|
||
|
||
Вход: пользовательская реплика.
|
||
Выход: QueryFrame draft.
|
||
|
||
Обязательные действия:
|
||
|
||
* сохранить оригинальную формулировку;
|
||
* выделить intent;
|
||
* выделить сущности;
|
||
* выявить разговорные/неформальные термины;
|
||
* определить недостающие обязательные параметры;
|
||
* определить ожидаемый формат ответа.
|
||
|
||
---
|
||
|
||
## 8.2. Этап 2. Разрешение доменной неоднозначности
|
||
|
||
Вход: QueryFrame draft.
|
||
Выход: QueryFrame resolved.
|
||
|
||
Обязательные действия:
|
||
|
||
* резолвить бизнес-термины;
|
||
* резолвить типы сущностей;
|
||
* резолвить временные параметры;
|
||
* не делать скрытых предположений без пометки.
|
||
|
||
Если есть несколько допустимых трактовок:
|
||
|
||
* либо выбрать одну с явным дисклеймером;
|
||
* либо проверить несколько трактовок;
|
||
* либо задать уточнение, если без этого ответ потенциально вводит в заблуждение.
|
||
|
||
---
|
||
|
||
## 8.3. Этап 3. Построение плана
|
||
|
||
Вход: QueryFrame resolved.
|
||
Выход: ExecutionPlan.
|
||
|
||
Требования:
|
||
|
||
* шаги должны быть атомарными;
|
||
* обязательные и необязательные шаги должны быть разделены;
|
||
* должен быть определён критерий остановки;
|
||
* должен быть определён fallback.
|
||
|
||
---
|
||
|
||
## 8.4. Этап 4. Исполнение плана
|
||
|
||
Вход: ExecutionPlan.
|
||
Выход: ToolRun[].
|
||
|
||
Требования:
|
||
|
||
* каждый вызов независим и логируется;
|
||
* ошибка не должна теряться;
|
||
* если инструмент вернул пустой результат, это отдельное состояние, а не “успех без данных”.
|
||
|
||
---
|
||
|
||
## 8.5. Этап 5. Сбор доказательной базы
|
||
|
||
Вход: ToolRun[].
|
||
Выход: EvidenceBundle.
|
||
|
||
Правила:
|
||
|
||
* факты должны быть нормализованы;
|
||
* дубликаты должны быть схлопнуты;
|
||
* противоречия должны быть вынесены отдельно;
|
||
* важна не полнота сырых данных, а качественная сборка доказательной базы.
|
||
|
||
---
|
||
|
||
## 8.6. Этап 6. Проверка покрытия
|
||
|
||
Вход: QueryFrame + EvidenceBundle.
|
||
Выход: CoverageReport.
|
||
|
||
CoverageReport обязателен всегда, даже если ответ “полный”.
|
||
|
||
---
|
||
|
||
## 8.7. Этап 7. Формирование ответа
|
||
|
||
Вход: QueryFrame + EvidenceBundle + CoverageReport.
|
||
Выход: FinalAnswerPackage.
|
||
|
||
---
|
||
|
||
# 9. Правила ответа пользователю
|
||
|
||
## 9.1. Общая форма ответа
|
||
|
||
Каждый ответ должен содержать до пяти смысловых блоков:
|
||
|
||
1. **Прямой ответ**
|
||
2. **Что именно проверено**
|
||
3. **Что найдено**
|
||
4. **Что не удалось установить**
|
||
5. **Что нужно уточнить / какой следующий шаг наиболее полезен**
|
||
|
||
---
|
||
|
||
## 9.2. Требования к стилю ответа
|
||
|
||
Ответ должен:
|
||
|
||
* быть человеческим;
|
||
* не быть “канцелярской выгрузкой”;
|
||
* не быть пустым перечислением ссылок и документов;
|
||
* объяснять связь между вопросом и найденными данными.
|
||
|
||
Плохой ответ:
|
||
|
||
> Найден документ списания с расчетного счета. Ссылка: ...
|
||
|
||
Хороший ответ:
|
||
|
||
> Вопрос интерпретирован как проверка незакрытых расчетов с поставщиками на дату X.
|
||
> По данным 1С найдены такие-то контрагенты с открытыми остатками.
|
||
> Один из найденных документов относится к списанию средств, но сам по себе не доказывает наличие “хвоста”, поэтому использован только как вспомогательный источник, а не как основное основание ответа.
|
||
|
||
---
|
||
|
||
## 9.3. Правила неполного ответа
|
||
|
||
Если ответ частичный, система обязана не просто написать “недостаточно данных”, а объяснить:
|
||
|
||
* чего конкретно не хватает;
|
||
* это проблема данных, маршрута или доменного определения;
|
||
* какой следующий шаг даст наибольшую пользу.
|
||
|
||
Пример:
|
||
|
||
* “Найдены открытые остатки, но для части случаев не выполнена проверка закрывающих документов.”
|
||
* “Термин ‘хвосты’ не имеет фиксированной трактовки в текущем домене.”
|
||
* “Вопрос можно доуточнить по дате отсечения, иначе используется рабочая дата.”
|
||
|
||
---
|
||
|
||
# 10. Reason codes
|
||
|
||
Нужно ввести единый справочник причин неполноты, ошибок и спорных состояний.
|
||
|
||
## 10.1. Минимальный набор reason codes
|
||
|
||
### Домен и интерпретация
|
||
|
||
* `AMBIGUOUS_BUSINESS_TERM`
|
||
* `MISSING_PERIOD`
|
||
* `MISSING_AS_OF_DATE`
|
||
* `MULTIPLE_VALID_INTERPRETATIONS`
|
||
* `ENTITY_NOT_RESOLVED`
|
||
* `LOW_CONFIDENCE_ENTITY_BINDING`
|
||
|
||
### Данные и покрытие
|
||
|
||
* `NO_MATCH_IN_1C`
|
||
* `PARTIAL_MATCH_IN_1C`
|
||
* `INSUFFICIENT_DOCUMENT_DEPTH`
|
||
* `CONFLICTING_EVIDENCE`
|
||
* `MISSING_SUPPORTING_DOCUMENT`
|
||
* `EVIDENCE_DEPTH_LIMIT`
|
||
|
||
### Инструменты и исполнение
|
||
|
||
* `TOOL_EXECUTION_ERROR`
|
||
* `MCP_TIMEOUT`
|
||
* `MCP_SCHEMA_ERROR`
|
||
* `INVALID_TOOL_OUTPUT`
|
||
* `ROUTE_EXECUTION_ABORTED`
|
||
|
||
### Диалог и UX
|
||
|
||
* `QUESTION_UNDER_SPECIFIED`
|
||
* `NEEDS_USER_CONFIRMATION`
|
||
* `ASSUMPTION_APPLIED_EXPLICITLY`
|
||
|
||
---
|
||
|
||
# 11. Память и удержание контекста
|
||
|
||
## 11.1. Требование
|
||
|
||
Ассистент должен работать не как набор независимых реплик, а как **диалоговая система с состоянием**.
|
||
|
||
## 11.2. Что хранить между ходами
|
||
|
||
Нужно хранить ConversationState:
|
||
|
||
```json
|
||
{
|
||
"conversation_id": "uuid",
|
||
"active_domain": "supplier_settlements",
|
||
"active_entities": [
|
||
{"type": "counterparty_group", "value": "suppliers"}
|
||
],
|
||
"active_time_scope": {
|
||
"as_of_date": "2026-04-10"
|
||
},
|
||
"resolved_business_terms": [
|
||
{
|
||
"surface": "хвосты",
|
||
"resolved_to": "open_settlement_balance",
|
||
"confidence": 0.72
|
||
}
|
||
],
|
||
"last_clarifications": [],
|
||
"open_ambiguities": [],
|
||
"last_evidence_refs": ["SRC12", "SRC19"]
|
||
}
|
||
```
|
||
|
||
## 11.3. Правила использования контекста
|
||
|
||
* контекст не должен бесконтрольно разрастаться;
|
||
* в следующий ход передаются только релевантные выжимки;
|
||
* старые гипотезы не должны silently переезжать в “истину”;
|
||
* каждая предпосылка должна иметь пометку:
|
||
|
||
* подтверждена,
|
||
* унаследована,
|
||
* предположена.
|
||
|
||
---
|
||
|
||
# 12. Требования к инструментальному контуру
|
||
|
||
## 12.1. MCP-инструменты должны быть доменно гранулированы
|
||
|
||
Плохо:
|
||
|
||
* `search_data`
|
||
* `find_docs`
|
||
* `query_1c_anything`
|
||
|
||
Хорошо:
|
||
|
||
* `resolve_counterparty`
|
||
* `resolve_period_or_asof`
|
||
* `get_open_supplier_settlements`
|
||
* `get_unclosed_documents_for_counterparty`
|
||
* `get_document_movements`
|
||
* `get_payment_chain`
|
||
* `get_balance_as_of`
|
||
* `get_related_closing_documents`
|
||
|
||
---
|
||
|
||
## 12.2. Каждый инструмент обязан иметь
|
||
|
||
* чёткое описание назначения;
|
||
* входную схему;
|
||
* выходную схему;
|
||
* перечень типовых ошибок;
|
||
* ограничения;
|
||
* политику пустого ответа.
|
||
|
||
---
|
||
|
||
## 12.3. Политика пустого результата
|
||
|
||
Пустой результат не равен успешному ответу пользователю.
|
||
|
||
Нужно различать:
|
||
|
||
* данных нет;
|
||
* данных не найдено по текущему маршруту;
|
||
* сущность не привязана;
|
||
* фильтр слишком узкий;
|
||
* инструмент вернул ноль из-за ошибки/схемы;
|
||
* вопрос некорректно поставлен.
|
||
|
||
---
|
||
|
||
# 13. Требования к LLM-слоям
|
||
|
||
## 13.1. Общий принцип
|
||
|
||
LLM не должна быть единственным источником решения.
|
||
LLM должна выполнять следующие типы задач:
|
||
|
||
* интерпретация вопроса;
|
||
* построение QueryFrame;
|
||
* планирование;
|
||
* оценка покрытия;
|
||
* человекоориентированная сборка ответа.
|
||
|
||
LLM не должна:
|
||
|
||
* выдумывать факты из 1С;
|
||
* подменять инструментальный ответ домыслом;
|
||
* молча трактовать неопределённый бизнес-термин как однозначный.
|
||
|
||
---
|
||
|
||
## 13.2. Формат взаимодействия с LLM
|
||
|
||
Для внутренних шагов использовать только:
|
||
|
||
* строгие схемы JSON;
|
||
* validator;
|
||
* repair/retry loop при нарушении схемы.
|
||
|
||
---
|
||
|
||
## 13.3. Отдельные проходы LLM
|
||
|
||
Нужно разделить как минимум на 4 разных промптовых режима:
|
||
|
||
1. **Interpreter Prompt**
|
||
Понимание вопроса и неоднозначностей.
|
||
|
||
2. **Planner Prompt**
|
||
Построение плана извлечения.
|
||
|
||
3. **Critic Prompt**
|
||
Проверка покрытия и полноты.
|
||
|
||
4. **Answer Prompt**
|
||
Формирование финального ответа человеку.
|
||
|
||
Запрещается использовать один и тот же общий промпт для всех режимов.
|
||
|
||
---
|
||
|
||
# 14. Требования к инженерной диагностике
|
||
|
||
## 14.1. По каждому запросу сохранять
|
||
|
||
* QueryFrame;
|
||
* ExecutionPlan;
|
||
* ToolRun[];
|
||
* EvidenceBundle;
|
||
* CoverageReport;
|
||
* FinalAnswerPackage;
|
||
* latency по этапам;
|
||
* reason codes;
|
||
* summary failure class.
|
||
|
||
---
|
||
|
||
## 14.2. Нужен отдельный debug-вывод
|
||
|
||
Инженерный trace должен быть читаемым.
|
||
|
||
Минимальная структура debug view:
|
||
|
||
* как понят вопрос;
|
||
* какие сущности распознаны;
|
||
* какие сущности не распознаны;
|
||
* какой маршрут выбран;
|
||
* какие тулзы вызваны;
|
||
* что реально найдено;
|
||
* почему ответ полный/частичный/ошибочный.
|
||
|
||
---
|
||
|
||
## 14.3. Классы итогов запроса
|
||
|
||
На верхнем уровне запрос должен классифицироваться как:
|
||
|
||
* `FULLY_ANSWERED`
|
||
* `PARTIALLY_ANSWERED`
|
||
* `BLOCKED_BY_AMBIGUITY`
|
||
* `BLOCKED_BY_MISSING_DATA`
|
||
* `BLOCKED_BY_TOOLING`
|
||
* `MISROUTED`
|
||
* `FAILED_TO_BIND_ENTITIES`
|
||
|
||
---
|
||
|
||
# 15. Acceptance criteria
|
||
|
||
Система считается принятой на этапе, если:
|
||
|
||
## 15.1. По качеству ответа
|
||
|
||
* ответ всегда содержит прямой вывод;
|
||
* ответ не состоит из голого набора ссылок;
|
||
* ответ объясняет, почему найденные данные относятся к вопросу;
|
||
* неполный ответ объясняется предметно.
|
||
|
||
## 15.2. По объяснимости
|
||
|
||
* по каждому кейсу доступен CoverageReport;
|
||
* по каждому кейсу доступны reason codes;
|
||
* можно восстановить, почему выбран маршрут.
|
||
|
||
## 15.3. По устойчивости
|
||
|
||
* сломанный или пустой tool output не приводит к “уверенному бреду”;
|
||
* неоднозначные термины не замалчиваются;
|
||
* система не теряет исходный смысл вопроса после нормализации.
|
||
|
||
## 15.4. По контексту
|
||
|
||
* следующий ход корректно использует ранее разрешённые сущности и периоды;
|
||
* контекст не дрейфует в соседний домен без причины;
|
||
* предыдущие предположения не становятся “фактами” без подтверждения.
|
||
|
||
---
|
||
|
||
# 16. План внедрения
|
||
|
||
## Этап 1. QueryFrame и разделение ролей
|
||
|
||
Сделать:
|
||
|
||
* отдельный Interpreter;
|
||
* отдельный Planner;
|
||
* отдельный Critic;
|
||
* отдельный Answer Composer.
|
||
|
||
Результат:
|
||
|
||
* система перестаёт быть “одной кашей”.
|
||
|
||
---
|
||
|
||
## Этап 2. Ввести структурированные артефакты
|
||
|
||
Сделать:
|
||
|
||
* QueryFrame;
|
||
* ExecutionPlan;
|
||
* ToolRun;
|
||
* EvidenceBundle;
|
||
* CoverageReport.
|
||
|
||
Результат:
|
||
|
||
* появляется прозрачная трассировка.
|
||
|
||
---
|
||
|
||
## Этап 3. Ввести reason codes
|
||
|
||
Сделать:
|
||
|
||
* единый справочник;
|
||
* обязательную простановку причин неполноты.
|
||
|
||
Результат:
|
||
|
||
* становится видно, где проблема: домен, данные, маршрут или инструмент.
|
||
|
||
---
|
||
|
||
## Этап 4. Переделать финальный ответ
|
||
|
||
Сделать:
|
||
|
||
* новый шаблон ответа;
|
||
* вывод “что найдено / что не доказано / что уточнить”.
|
||
|
||
Результат:
|
||
|
||
* ответы становятся полезными и человеческими.
|
||
|
||
---
|
||
|
||
## Этап 5. Контекст и диалог
|
||
|
||
Сделать:
|
||
|
||
* ConversationState;
|
||
* наследование разрешённых сущностей и периода;
|
||
* учёт открытых неоднозначностей.
|
||
|
||
Результат:
|
||
|
||
* появляется реальный диалог, а не серия разрозненных вызовов.
|
||
|
||
---
|
||
|
||
## Этап 6. Оценка качества
|
||
|
||
Сделать:
|
||
|
||
* набор сценариев;
|
||
* ручную разметку;
|
||
* сравнение old vs new;
|
||
* сбор статистики по reason codes.
|
||
|
||
Результат:
|
||
|
||
* становится видно, что реально улучшилось.
|
||
|
||
---
|
||
|
||
# 17. Основные риски
|
||
|
||
## Риск 1. Ранняя потеря смысла
|
||
|
||
Причина: слишком сильная “нормализация”.
|
||
Снижение риска: всегда хранить original question + normalized question + ambiguities.
|
||
|
||
## Риск 2. Скрытые предположения
|
||
|
||
Причина: LLM молча выбирает трактовку.
|
||
Снижение риска: reason code + явная пометка assumption.
|
||
|
||
## Риск 3. Сырой контекст перегружает модель
|
||
|
||
Причина: в финальный шаг передаётся весь мусор.
|
||
Снижение риска: отдельный EvidenceBuilder и evidence compaction.
|
||
|
||
## Риск 4. Пустой output трактуется как ответ
|
||
|
||
Причина: тул вернул ноль, а система делает вывод.
|
||
Снижение риска: разделить no-data / no-match / tool-failure.
|
||
|
||
## Риск 5. Ответ красивый, но недоказательный
|
||
|
||
Причина: хороший prose без claim binding.
|
||
Снижение риска: каждое содержательное утверждение должно опираться на evidence.
|
||
|
||
---
|
||
|
||
# 18. Итоговое архитектурное решение
|
||
|
||
Для данной задачи рекомендуется не fully autonomous agent, а **жёсткий доказательный workflow с LLM-слоями**.
|
||
|
||
## Итоговая формула
|
||
|
||
Ассистент =
|
||
|
||
* LLM для понимания вопроса,
|
||
* LLM для планирования,
|
||
* код и MCP для извлечения фактов,
|
||
* LLM для проверки покрытия,
|
||
* LLM для человеческого ответа,
|
||
* обязательные промежуточные артефакты,
|
||
* обязательные reason codes,
|
||
* обязательный инженерный trace.
|
||
|
||
---
|
||
|
||
# 19. Коротко: что именно надо сделать в первую очередь
|
||
|
||
Если совсем приземлённо, то первыми задачами должны стать вот эти:
|
||
|
||
1. Вынести отдельный `QueryFrame`.
|
||
2. Вынести отдельный `CoverageReport`.
|
||
3. Запретить финальному ответу формироваться без CoverageReport.
|
||
4. Ввести reason codes.
|
||
5. Сделать новый шаблон финального ответа.
|
||
6. Ввести `ConversationState`.
|
||
7. Перестать считать “упрощённый вопрос” заменой исходного вопроса.
|
||
|
||
---
|
||
|
||
# 20. Ожидаемый эффект после внедрения
|
||
|
||
После внедрения ассистент должен перестать выглядеть как:
|
||
|
||
* сухая LLM-выгрузка;
|
||
* случайный маршрутизатор по 1С;
|
||
* генератор ссылок без объяснения.
|
||
|
||
И должен начать выглядеть как:
|
||
|
||
* осмысленный доменный ассистент;
|
||
* понятный и честный собеседник;
|
||
* диагностируемая инженерная система;
|
||
* инструмент, который одновременно помогает пользователю и вскрывает пробелы домена/маршрутов.
|
||
|
||
---
|
||
|
||
|