OpenInference

Расширение OpenTelemetry, которое учит стандартную трассировку говорить на языке LLM-приложений. Обычный OTel знает про HTTP-вызовы и обращения к базе, но не знает, что такое промпт, вызов инструмента и извлечённый документ. OpenInference добавляет эти понятия как типизированные спаны.

Суть

Наблюдаемость агента упирается в вопрос словаря. Можно писать трейсы вручную, придумывая свои поля, — тогда каждый инструмент визуализации придётся учить их читать. OpenInference задаёт общие семантические конвенции: как называется атрибут с промптом, как — с ответом, как считать токены, какого типа бывают спаны.

Выигрыш в том, что это надстройка над OpenTelemetry, а не отдельный мир. Один протокол собирает и классический APM (латентность, коды ответов, инфраструктура), и специфичную для ИИ телеметрию.

Как работает

Вызов агента представляется деревом спанов:

Trace (Root)
└── LLM Span
    ├── Tool Span
    └── Retriever Span

Тип спана хранится в openinference.span.kind — по нему отличают обращение к модели от вызова инструмента и от поиска в индексе. Ключевые атрибуты: input.value, output.value, llm.token_count.prompt.

Это атрибуты OpenInference, а не OTel GenAI И на слайде вебинара, и в первой версии этой заметки они были подписаны как конвенция OTel GenAI. Это неверно: input.value, output.value, llm.token_count.prompt и ключ openinference.span.kind принадлежат словарю OpenInference. У официального OTel-стандарта префикс другой — gen_ai.*.

Словарей в 2026 году сосуществует три: gen_ai.* (официальный OTel), openinference.* (Arize) и traceloop.*. Ни один не вытеснил остальные — и LangSmith, и Langfuse маппят все три. Официальный OTel GenAI в мае 2026 вынесен в отдельный репозиторий semantic-conventions-genai, но всё ещё в статусе Development.

Подключение автоматическое: библиотека сама перехватывает вызовы клиента модели, руками спаны расставлять не нужно.

from opentelemetry import trace
from openinference.instrumentation.openai import OpenAIInstrumentor

# Автоматический перехват вызовов по спецификации OTLP
OpenAIInstrumentor().instrument()
tracer = trace.get_tracer(__name__)

Что это даёт на практике

Типизация спанов превращает часть отладки в запрос к телеметрии, а не в чтение логов:

  • Рост числа спанов с openinference.span.kind == TOOL внутри одного трейса — сигнатура зацикливания: агент долбит один и тот же инструмент без условия выхода.
  • Retriever-спан с пустым результатом, за которым идёт уверенный ответ модели, — сигнатура голодания RAG, то есть генерации на выдуманном основании.
  • Токены на конкретном спане позволяют считать себестоимость не всего запроса целиком, а отдельного шага.

В вебинаре отдельно подчёркнута связка трёх практик: семантический трейсинг, версионирование промптов и семантический кэш. Когда промпт хранится и версионируется на стороне системы трейсов, его нельзя вытащить из кода — потому что в коде его нет.

Из инструментов, которые понимают эту телеметрию: Arize Phoenix (эталонная реализация от авторов спецификации), LangSmith, Langfuse.

Связано с

  • W3C Trace Context — как трейс переживает границы сервисов; OpenInference отвечает за содержимое спанов
  • Agent Observability — общий разбор, зачем агенту трейсинг шагов
  • LangSmith vs Langfuse — инструменты-приёмники этой телеметрии
  • Agent Failure Modes — режимы отказа, которые ловятся именно по типам спанов
  • Agent CostControl — атрибуция стоимости строится на токенах из спанов

Открытые вопросы

  • насколько полно Langfuse поддерживает конвенции OpenInference по сравнению с Phoenix
  • что делать с промптами в трейсах, когда в них попадают персональные данные — маскировать до отправки или полагаться на политику хранения