Голосовые системы

Гибкий диалог chat-agent: причины отказов и следующая доработка

Дата: 06.10.2026. Источники: код переработки на e4bfe285306fc225c3d445ade16296021bd934f3 и read-only проверка открытой пользовательской сессии. Основной checkout содержит более старую версию; ссылки ниже закреплены на SHA переработки.

Статус: требование показа причин отказов зафиксировано. Целевая схема ниже — предложение для обсуждения; изменения приложений и deployment не выполнялись.

Зафиксированное требование: конкретная причина отказа

Показывать причину рядом с ответом, а не только общую фразу "Не удалось сформировать ответ". Указывать этап, понятное объяснение и машинный код; пояснять доступное действие, если оно действительно помогает. Подробности связывать с соответствующим request_id.

  • Для context_budget_exceeded: "Не удалось подготовить запрос: данные карты переполнили контекст модели". Технические подробности должны сохранять исходный код ошибки.
  • Ошибка генерации ответа и ошибка передачи микрофона — разные события. Нельзя представлять сбой WSS как причину отказа LLM без подтверждённой связи.
  • Различать запрос, который не выполнен, и ответ, который сформирован частично. Не показывать "Незавершённый ответ" как единственное объяснение любого отказа.
  • При частично выполненной задаче показывать подтверждённые результаты шагов и причину остановки.
  • Проверка приёмки: ошибки контекста, инструмента, очереди и аудиотранспорта отображаются со своей причиной и принадлежат своей сессии/запросу; диагностические подробности не содержат credentials и полного содержимого разговора.

Что помешало гибкости

Отказ от жёстких сценариев остаётся целью. Возврат генеративного router перед каждым запросом не требуется. Новый общий цикл уже умеет выбирать и сочетать инструменты; сохранённые графы обслуживают явно активный workflow.

  1. Память блокирует следующие ходы. Dialog отправляет артефакты в context.entities и повторно внутри context.state.artifact_memory. Engine сохраняет геометрию маршрута, а TokenBudget сокращает только сообщения истории. В проверенной сессии после маршрута следующие запросы получили context_budget_exceeded. Причина отказов подтверждена history; механизм переполнения подтверждён кодом. Новый точный подсчёт токенов каждого prompt в этой проверке не выполнялся.
  2. Модель не получает автоматически всё, что показано на карте. init_map публикует аэропорты и позицию в UI, но не записывает эти исходные факты в память Agent. Новый диалог должен сам вызвать get_current_position; подсказка не устанавливает явного правила сначала получить доступную позицию при запросе "ближайший ко мне". Уточнение города может заменить это действие.
  3. Каталог действий узкий. Доступны пять конкретных инструментов. search_airports_nearby принимает город и радиус, возвращает расстояния по возрастанию. Полный каталог и поиск по имени существуют в HTTP API, но не объявлены модели как инструменты. Параметров сортировки, координатного центра и лимита в текущем NATS-инструменте нет. Модель может выбрать максимальное расстояние среди полученных строк, но не гарантировать самый удалённый аэропорт за пределами этой выборки.
  4. Приёмка не покрыла продолжение после маршрута. Контрольный corpus содержит короткий разговор, поиск аэропортов и уточнения рейса. Цепочки "маршрут → следующий запрос", полнота полезного результата и исходное состояние карты должны иметь отдельные проверки. DONE сам по себе не доказывает выполнение пользовательской цели.

Текущие авиационные данные демонстрационные: четыре московских аэропорта, фиксированная позиция в Москве, синтетическая погода и маршрут-дуга. Самый удалённый объект нужно искать в явно обозначенной области данных; результат такого каталога нельзя выдавать за глобальный поиск.

Как работает сейчас: новый запрос

Как работает сейчас: новый запрос
Как работает сейчас: новый запрос · Открыть в полном размере
Исходный Mermaid
flowchart TD
    U["Реплика пользователя"] --> A["Core → Agent → Ruby"]
    A --> C["Контекст и каталог пяти инструментов"]
    P["Память: полная геометрия маршрута"] -->|"дважды в следующем prompt"| C
    C --> B{"Вход помещается в 6144 токена?"}
    B -->|"нет"| E["Общий текст отказа в интерфейсе"]
    B -->|"да"| M["Модель: ответ или tool calls"]
    M -->|"tool calls"| V["Проверка имени и аргументов"]
    V --> T["Выполнение инструмента"]
    T -->|"полный JSON результата"| C
    M -->|"итоговый ответ"| F["Ответ и накопленные команды карты"]
    F -->|"сохранить артефакты"| P

Модель выбирает действия динамически. Полные результаты инструментов остаются в текущем диалоге; результаты карты сохраняются для следующих ходов. Переполнение обязательного контекста останавливает запрос, даже если убрать всю старую историю. Команды карты общего цикла публикуются после его завершения.

Как должно работать: предложение

Как должно работать: предложение
Как должно работать: предложение · Открыть в полном размере
Исходный Mermaid
flowchart TD
    U["Реплика пользователя"] --> C["Цель и компактные факты:<br/>позиция, история, выбранные объекты"]
    P["Краткая память и ссылки на артефакты"] --> C
    C --> M["Модель выбирает следующий шаг"]
    M -->|"tool call"| V["Общий исполнитель:<br/>схема, права, deadline, бюджет"]
    V --> T["Разрешённый инструмент"]
    T --> R["Результат или конкретная ошибка"]
    R -->|"компактные данные"| M
    R -->|"тяжёлые артефакты"| S["Хранилище → карта"]
    R -->|"подтверждённые факты и ссылки"| P
    M -->|"кандидат итогового ответа"| K["Проверка фактов и выполненных действий"]
    K -->|"результат подтверждён"| F["Ответ пользователю"]
    K -->|"осталось действие"| M
    V -->|"продолжение невозможно"| E["Конкретная причина остановки"]
    K -->|"данных недостаточно"| E

Модель определяет последовательность, общий исполнитель проверяет и выполняет разрешённые действия. Полные геометрии и большие выборки передаются карте и хранятся отдельно; модель получает координаты концов, расстояние, идентификаторы, краткое описание и ссылку на артефакт. Доступные факты имеют источник и обозначенную область данных. Ошибка шага возвращается модели, когда корректировка допустима; терминальный отказ объясняется пользователю. Для уточнения задаётся вопрос только о действительно недоступных данных.

Для поиска аэропортов предлагается расширить общий инструмент параметрами центра, фильтров, сортировки по расстоянию и лимита. Это операции над данными, а не отдельные сценарии "ближайший", "самый удалённый" или "маршрут". Точный API и состав разрешённого каталога ещё нужно согласовать.

Сохраняются ограничение 10 инструментальных действий, общий deadline 120 секунд и серверная проверка прав/аргументов. Обычный разговор должен по-прежнему обходиться одной генерацией.

Проверяемый результат следующего этапа

  • После построения маршрута минимум 20 следующих ходов проходят без context_budget_exceeded; размер обязательного контекста ограничен и измерен.
  • Поиск ближайшего к доступной позиции сначала получает эту позицию; при её отсутствии задаёт точное уточнение. Демонстрационная позиция явно обозначается.
  • Ближайший/самый удалённый/по имени/по фильтру выполняются над обозначенной выборкой; координаты и расстояния подтверждены инструментами.
  • Новое сочетание "найти объект → узнать погоду → построить маршрут" не требует нового workflow ID или сценарного графа.
  • Итоговое "маршрут построен" связано с успешным инструментальным результатом и артефактом карты; частичный результат и ошибка различимы.
  • Приёмка учитывает полезный результат, количество генераций, размер prompt, длительности и точные коды ошибок, а не только DONE.

Ссылки на реализацию проверенного снимка

  • Новый диалог и передача контекста.
  • Выбор нового диалога и совместимость активных графов.
  • Сохранение геометрии в памяти.
  • Токеновый бюджет.
  • Каталог разрешённых инструментов.
  • Ограничения поиска и демонстрационные данные.
  • Исходные данные карты отправляются в UI.
  • Контрольный corpus.

Исходник

Скачать Markdown · К материалам исследования