Перейти к содержанию

Трейсинг

Eval AI Library содержит легковесную подсистему трейсинга для продакшн-мониторинга LLM-вызовов и работы агентов. Она собирает span-данные (время, токены, стоимость, вход/выход, вызовы инструментов, шаги рассуждений) и асинхронно отправляет их в коллектор. Десять фреймворк-интеграций подключаются к трейсеру без клеевого кода.

Легковесная установка

Для трейсинга в продакшне без полного фреймворка оценки:

pip install "eval-ai-library[lite]"

Lite-экстра тянет только pydantic и aiohttp, без ML-зависимостей.

Конфигурация

TracingConfig читает три env-переменные для базовой установки и несколько опциональных для тонкой настройки:

Env-переменная По умолчанию Описание
TRACING_ENABLED false Главный переключатель. Установите true для включения трейсинга
TRACING_URL "" HTTP-эндпоинт вашего trace-receiver-а
TRACING_PROJECT default ID проекта для разделения трейсов на receiver-е
TRACING_API_KEY Опциональный Bearer-токен для receiver-а
TRACING_SINK http Дефолтный sink -- http, memory или file
TRACING_SINK_PATH traces.jsonl Путь при TRACING_SINK=file
TRACING_STRICT false При true ошибки отправки бросают исключение вместо лога (для CI)
TRACING_STREAM false При true каждый end_span() сразу флашит span как partial_span -- долгие сессии выживают падение
from eval_lib.tracing import TracingConfig

TracingConfig.is_enabled()  # bool
TracingConfig.get_url()     # str
TracingConfig.get_project() # str

Все методы TracingConfig статические -- просто читают окружение. Никакого конструктора вызывать не нужно.

Типы спанов

SpanType Значение
LLM_CALL Вызов LLM API (сообщения, ответ, токены, стоимость)
TOOL_CALL Вызов инструмента / функции
AGENT_STEP Шаг рассуждений / планирования агента
REASONING Шаг chain-of-thought
RETRIEVAL Поиск документов / векторов
EVALUATION Запуск метрики оценки
CUSTOM Всё остальное

Основной трейсер

Синглтон tracer собирает спаны и рассылает их через sink:

from eval_lib.tracing import tracer, SpanType

# Явный жизненный цикл спана
trace_id = tracer.start_trace("my-pipeline")
span = tracer.start_span("generate-answer", SpanType.LLM_CALL, input_data={"prompt": "..."})
# ... ваш LLM-вызов ...
tracer.end_span(span, output="Ответ: 42")
tracer.end_trace()

# Или через контекст-менеджер
with tracer.trace("retrieval", SpanType.RETRIEVAL) as span:
    results = retrieve_documents(query)

Спаны вкладываются автоматически через context-variables -- ручного проброса parent_span_id не требуется.

Декораторы

Автоматическая инструментация функций для написанных вручную пайплайнов:

from eval_lib.tracing import trace_llm, trace_tool, trace_step

@trace_llm()
async def call_openai(prompt: str) -> str:
    # Записывает вход, выход, длительность, стоимость как LLM_CALL span
    ...

@trace_tool()
async def search_database(query: str) -> list:
    # Записывает как TOOL_CALL span
    ...

@trace_step()
async def process_request(request):
    # Записывает как AGENT_STEP span
    ...

Фреймворк-интеграции

Все callback-и lazy-loaded -- импорт из eval_lib.tracing требует SDK соответствующего фреймворка только тогда, когда вы реально им пользуетесь. Установите нужную экстра рядом с eval-ai-library[lite].

LangChain

from eval_lib.tracing import EvalLibCallbackHandler, callback_handler
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(callbacks=[callback_handler])  # глобальный экземпляр
# или: llm = ChatOpenAI(callbacks=[EvalLibCallbackHandler()])

LlamaIndex

from eval_lib.tracing import install_llamaindex_tracing

install_llamaindex_tracing()  # патчит Settings.callback_manager глобально

Низкоуровневые классы: EvalLibEventHandler, EvalLibSpanHandler.

CrewAI

from eval_lib.tracing import CrewAITraceCollector

collector = CrewAITraceCollector()
crew.step_callback = collector

AutoGen

from eval_lib.tracing import AutoGenTraceHandler

handler = AutoGenTraceHandler()
# подключить согласно runtime-API AutoGen

Haystack

from eval_lib.tracing import install_haystack_tracing

install_haystack_tracing()

Низкоуровневый класс: EvalLibHaystackTracer.

Semantic Kernel

from eval_lib.tracing import install_sk_tracing

install_sk_tracing(kernel)

Claude Agent SDK

from eval_lib.tracing import ClaudeAgentTraceCollector

collector = ClaudeAgentTraceCollector()
# передайте collector.on_event в message-stream SDK

smolagents

from eval_lib.tracing import smolagents_step_callback

agent = CodeAgent(..., step_callbacks=[smolagents_step_callback])

phidata

from eval_lib.tracing import PhidataTraceCollector

collector = PhidataTraceCollector()

OpenAI Assistants

from eval_lib.tracing import OpenAIAssistantsTraceCollector

collector = OpenAIAssistantsTraceCollector()
# передайте run-events ассистента

OpenTelemetry

Отправляйте спаны eval-lib через OTel (Jaeger, Tempo, DataDog, любой OTel-совместимый бэкенд):

from eval_lib.tracing import EvalLibSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(EvalLibSpanExporter()))

Sinks

TraceSender принимает любую реализацию Sink. Встроено три:

HTTPSink -- дефолтный

Отправляет батчи трейсов на TRACING_URL по HTTP (Bearer-auth через TRACING_API_KEY).

from eval_lib.tracing import TraceSender, HTTPSink

sender = TraceSender(sink=HTTPSink(url="https://collector.example.com", api_key="..."))

FileSink -- JSONL append

Удобен для локальной отладки или air-gapped развёртываний.

from eval_lib.tracing import FileSink, TraceSender

sender = TraceSender(sink=FileSink(path="traces.jsonl"))

Или через env: TRACING_SINK=file TRACING_SINK_PATH=./out/traces.jsonl.

InMemorySink -- для тестов

Буферизует всё в памяти; удобно в unit-тестах.

from eval_lib.tracing import InMemorySink, TraceSender

sink = InMemorySink()
sender = TraceSender(sink=sink)
# ... запуск пайплайна ...
assert len(sink.spans) == 3

Receiver-сторона

Приёмная сторона живёт в eval_lib.connector -- trace_routes (FastAPI-роуты) и trace_receiver (storage + runtime-eval loop). Монтируйте их за собственной аутентификацией / БД. См. tracing-hardening-tz.md в репозитории для контракта pluggable-storage.

Модель данных

Спаны -- это dataclass-ы в eval_lib.tracing.types:

from eval_lib.tracing import TraceSpan, SpanType

TraceSpan содержит: span_id, trace_id, parent_span_id, span_type, name, start_time, end_time, input_data, output_data, metadata, status, плюс LLM-специфичные поля (tokens, cost, model). Все поля чисто сериализуются в JSON.