Что такое LLM observability: трассы и метрики — это сигналы для разбора работы приложения вместе с логами. Они помогают восстановить операции и проверить гипотезу о месте ошибки. Документация Langfuse определяет наблюдаемость как широкую возможность разбирать работу системы, а трассировку называет её частью. Трасса хранит путь запроса, метрики дают сводку, логи фиксируют отдельные события. Один лог отвечает на вопрос «что записано», наблюдаемость отвечает на вопрос «почему получился такой ответ».
Наблюдаемость и один лог: где граница
Один лог — это запись события. Для разбора сигналы связывают идентификаторами запроса, временными метками и отношениями вложенности. Такая связь помогает диагностике, но сама по себе не доказывает причинность. В документации Langfuse сказано, что генеративные системы недетерминированы, и отладка без инструментов наблюдаемости превращается в догадки. Там же наблюдаемость описана как более широкая способность, которая охватывает трассировку, метрики и логирование.
Практическая разница видна на вопросе читателя. Лог сообщает: «запрос завершён, код 200». В подробной трассе можно увидеть выход поиска, отсутствие вызова инструмента и вход генерации. Запись одного кода завершения для такого разбора недостаточна; журнал с нужными полями тоже может быть частью решения.
В блоге OpenTelemetry 2024 года перечислены сигналы для LLM-приложений: метаданные запроса, имя и версия модели, детали промпта, метаданные ответа, токены, стоимость. Там же отмечено, что рабочая группа рекомендует записывать крупные детали в события, поскольку бэкенды испытывают трудности с большими payload в атрибутах span. Это техническое ограничение формата хранения, и оно влияет на схему телеметрии.
Для читателя вывод простой: лог остаётся одним из сигналов. Диагноз появляется, когда сигналы связаны общим идентификатором запроса и порядком операций.
Request, trace, span и связь стадий
Request — один входящий запрос пользователя. Trace — полная запись его жизненного цикла. Span — отдельная операция внутри трассы со своим временем, входом, выходом и метаданными. Документация Langfuse описывает трассу как структурированный лог запроса, который сохраняет точный промпт, ответ модели, расход токенов, задержку и промежуточные шаги поиска и вызова инструментов.
Документация Arize Phoenix добавляет: трасса захватывает вызовы модели, поиск, использование инструментов и собственную логику приложения. Это позволяет разбирать поведение и понимать, куда уходит время.
Связь стадий выстраивается по вложенности. Корневой span — весь request. Внутри него лежат дочерние span: поиск, вызов инструмента, обращение к модели. Родительские связи задают вложенность. Порядок и возможный параллелизм проверяют по времени и зависимостям операций; из одной вложенности нельзя вывести строгую последовательность.
| Сущность | Что описывает | Что хранит |
|---|---|---|
| Request | Один входящий запрос | Идентификатор, время, пользовательский ввод |
| Trace | Полный жизненный цикл запроса | Все операции, их порядок и связи |
| Span | Одну операцию | Вход, выход, время, метаданные, статус |
Таблица показывает уровни детализации. Идентификатор request связывает трассу с обращением, вложенность описывает структуру, а времена и зависимости помогают восстановить порядок стадий.
Полный условный пример: вход и выход каждой стадии
Ниже учебный пример. Числа и тексты условны и не являются замером платформы. Вопрос пользователя: «Сколько дней даётся на возврат товара?». Ручной эталон по документу POLICY-R: «Для возврата даётся 14 календарных дней». Срок 14 дней — условие вымышленной POLICY-R, это учебная величина.
Трасса A: request=A, prompt_version=v1. Поиск по запросу «возврат» вернул документ DOC-S «Доставка 3 дня». Вызовов инструментов нет. Вход генерации — DOC-S. Выход генерации — «Возврат 3 дня». Длительность 800 мс, входных токенов 120, выходных 12. Диагноз: нужного основания нет уже после поиска, затем генерация подменила предмет.
Трасса B: request=B, prompt_version=v1. Поиск вернул POLICY-R. Инструмент get_order_status с order=X-1 завершился таймаутом. Вход генерации — POLICY-R и сообщение о таймауте. Выход — «Возврат 14 дней, заказ доставлен». Длительность 1600 мс, входных токенов 140, выходных 18. Диагноз: 14 дней подтверждены, статус доставки неизвестен. Здесь два разных события: сбой инструмента и выдуманный статус.
Трасса C: request=C, prompt_version=v2. Поиск вернул POLICY-R. Вызовов инструментов нет. Вход генерации — POLICY-R. Выход — «Возврат 30 дней». Длительность 700 мс, входных токенов 100, выходных 10. Диагноз: основание верное, искажение возникло при генерации.
| Трасса | Поиск | Инструмент | Выход | Первая ошибка |
|---|---|---|---|---|
| A | DOC-S «Доставка 3 дня» | нет | «Возврат 3 дня» | Поиск |
| B | POLICY-R | timeout | «Возврат 14 дней, заказ доставлен» | Инструмент |
| C | POLICY-R | нет | «Возврат 30 дней» | Генерация |
Таблица сводит три случая в одну картину. В каждой трассе первая ошибочная стадия разная, и правка требуется в разных местах.
Поиск, инструмент, генерация и несколько ошибок сразу
Различение стадий строится на чтении входов и выходов. Если поиск вернул нерелевантный документ, ошибка возникла на стадии поиска. Если инструмент вернул таймаут, ошибка относится к вызову инструмента. Если вход генерации корректен, а выход искажён, ошибка в генерации.
В трассе B видны два события одновременно. Таймаут инструмента — технический сбой. Выдуманный статус доставки — ошибка генерации, которая получила сообщение о таймауте и заполнила пробел. Разделение этих событий меняет план действий: одно требует проверки доступности инструмента, другое — правки промпта или правил обработки неизвестного состояния.
Документация Arize Phoenix описывает трассировку как способ увидеть, что произошло за один запуск приложения, шаг за шагом. Там же сказано, что эксперименты помогают сравнивать версии приложения на одних и тех же входах. Это подходит для проверки гипотезы о причине ошибки.
Порядок разбора:
- Открыть трассу по идентификатору request.
- Прочитать выход поиска и сверить с ожидаемым основанием.
- Проверить статус каждого вызова инструмента.
- Сравнить вход и выход генерации.
- Зафиксировать первую ошибочную стадию.
- Отдельно перечислить неизвестные данные.
Шестой шаг важен. В трассе B статус доставки остаётся неизвестным; это существенное ограничение вывода.
Токены и latency: что они показывают
Токены и задержка описывают расход и скорость. Они не измеряют фактическую верность ответа. В блоге OpenTelemetry 2024 года токены и стоимость отнесены к метрикам управления бюджетом, а длительность запроса — к показателям производительности и надёжности сервиса. Там же сказано, что отслеживание объёма запросов помогает замечать аномалии использования.
Отсюда практическое следствие. Трасса A заняла 800 мс, трасса C — 700 мс, трасса B — 1600 мс. Быстрая трасса A дала неверный ответ, а медленная трасса B содержала верную часть про 14 дней. Задержка не отделяет правильный ответ от ошибочного.
Верность проверяется отдельным эталоном. В учебном примере эталон — ручной ответ по POLICY-R. Сравнение выхода генерации с эталоном даёт оценку качества. Документация Arize Phoenix описывает оценки как способ измерять качество выхода: оценки на основе LLM, проверки кодом и человеческие метки. Документация Langfuse относит оценки к отдельному слою поверх трасс.
| Показатель | Что измеряет | Чего не показывает |
|---|---|---|
| Токены | Расход и длину | Верность ответа |
| Длительность | Скорость обработки | Правильность стадии |
| Объём запросов | Нагрузку и аномалии | Причину ошибки |
| Оценка по эталону | Совпадение с ожиданием | Место возникновения ошибки |
Две последние строки дополняют друг друга. Оценка говорит, что ответ неверен. Трасса говорит, где именно возникло расхождение.
Версии перед сравнением
Для сравнения фиксируют версии и остальные условия. Различие номера версии само по себе не доказывает, что именно правка промпта вызвала изменение ответа. В учебном примере трассы A и B используют prompt_version=v1, трасса C — prompt_version=v2. Эта метка позволяет различить варианты. ТрассыA/B/C не являются контролируемым экспериментом: у них различаются найденные документы и события инструментов, поэтому причинный эффект v2 по ним не вычисляется.
Документация Arize Phoenix описывает управление промптами: версионирование, хранение и развёртывание, а также площадку для экспериментов с промптами и моделями. Там же сказано, что эксперименты сравнивают разные версии приложения на одних входах, а датасеты собирают трассы для повторного прогона.
Порядок фиксации:
- Записать идентификатор request.
- Записать версию промпта.
- Записать версию модели и её параметры.
- Записать версию кода приложения.
- Сохранить ожидаемый ответ эталона.
- Повторить тот же эталонный вопрос после правки.
Шестой шаг повторяет вопрос с тем же источником. Документация Langfuse относит управление промптами к функциям, специфичным для AI-инженерии, наряду с оценкой через LLM и датасетами. Версия промпта становится частью карточки разбора.
Карточка разбора содержит идентификатор request, версии, ожидаемый ответ, первую ошибочную стадию, неизвестное и следующую проверку. Такой набор полей делает сравнение воспроизводимым.
Чувствительные данные и пределы диагноза
Трассы содержат промпты, ответы и промежуточные данные. Перед передачей трассы во внешнюю систему определите, какие поля допустимо отправлять. Лишние личные сведения удалите или обезличьте; для сопоставления событий сохраните технический ID запроса. Пользовательский текст и номер заказа проверяйте по правилам своего контура данных.
Документация Langfuse описывает самостоятельный хостинг как вариант развёртывания. Выбор места хранения влияет на то, какие данные покидают контур приложения.
Ограничения диагноза стоит держать рядом с выводами. Трасса показывает, что произошло в одном запуске. Она не доказывает, что правка улучшила систему в целом. Документация Arize Phoenix описывает эксперименты как способ подтвердить, что изменение действительно улучшило результат, через повторный прогон на тех же входах.
После предполагаемой правки повторяют тот же эталонный вопрос с тем же источником и отдельно проверяют остальные случаи. Уменьшение задержки само по себе не доказывает улучшение качества. В трассеB есть таймаут и общая длительность1600 мс, но времени отдельных стадий не задано. Долю таймаута в задержке мы не знаем. Устранение технического сбоя также не заменяет проверку выдуманного статуса доставки.
Промпт для разбора одной трассы:
Ты помогаешь разобрать одну трассу LLM-приложения.
Входные данные:
- вопрос пользователя: [ваш вопрос]
- ожидаемый ответ по эталону: [ваш эталон]
- версия промпта: [версия]
- выход поиска: [документы]
- вызовы инструментов и их статусы: [список]
- вход генерации: [текст]
- выход генерации: [текст]
- длительность и токены: [значения]
Верни:
1. Первую стадию, где результат разошёлся с эталоном.
2. Данные, которых не хватает для полного диагноза.
3. Отдельно перечисли технические сбои и ошибки генерации.
4. Следующую проверку, которая подтвердит или опровергнет гипотезу.
Не делай вывода о качестве всей системы по одной трассе.
В промпте меняют поля входа под свою схему телеметрии. Варианты той же задачи: разбор трассы с несколькими ошибками сразу, сравнение двух версий промпта на одном вопросе, проверка обработки таймаута инструмента, сборка карточки разбора для повторяющихся случаев.
Частые вопросы
Чем LLM observability отличается от обычного логирования?
Наблюдаемость объединяет трассировку, метрики и логи для разбора работы системы. В примере одного сообщения о коде завершения недостаточно: нужны выход поиска, статус инструмента и данные генерации.
Что такое trace и span простыми словами?
Trace связывает операции одного запроса. Span описывает отдельную операцию. Вложенность показывает структуру; время и зависимости нужны для проверки последовательности, включая параллельные вызовы.
Как понять, на каком шаге появился неверный ответ?
Нужно прочитать выход каждой стадии и сравнить с ожидаемым основанием. Если поиск вернул нерелевантный документ, ошибка на стадии поиска. Если инструмент вернул таймаут, ошибка относится к вызову инструмента. Если вход генерации корректен, а выход искажён, ошибка в генерации. Первая ошибочная стадия записывается в карточку разбора.
Можно ли судить о качестве ответа по latency и токенам?
Токены и задержка описывают расход и скорость. В блоге OpenTelemetry 2024 года они отнесены к управлению бюджетом и производительности сервиса. Верность ответа проверяется отдельным эталоном. В учебном примере быстрая трасса дала неверный ответ, а медленная содержала верную часть.
Какие данные удаляют перед передачей трассы?
Перед отправкой удалите или обезличьте лишние личные сведения и проверьте допустимость остальных полей. Сохраните техническую связность событий. Самостоятельный хостинг и настройки экспорта рассматривайте отдельно.
