发布

  • [NA] [SDK] feat: enrich opik-vercel exporter for AI SDK v7 / Vercel eve (#7177)

    frostbyte_neo 发布于 2026-06-22 12:27:56 +00:00

    • [NA] [SDK] feat: enrich opik-vercel exporter for AI SDK v7 / Vercel eve

    The opik-vercel OpenTelemetry exporter only understood AI SDK v4/v5/v6
    (ai.* scope) and produced nearly-empty traces for AI SDK v7 / Vercel eve,
    which emit the OpenTelemetry GenAI gen_ai.* scope (plus eve's eve.*
    context) and no parent-child links.

    Exporter changes:

    • Ingest gen_ai and eve scopes in addition to ai.
    • Capture prompts, answers, tool args/results, token usage (incl. cache
      tokens), thread id (from eve session id) and eve.* metadata.
    • Classify span types: chat -> llm, execute_tool -> tool, agent/step/turn ->
      general.
    • Reconstruct the hierarchy by time containment (eve emits no parent links)
      and set trace timestamps to span the whole turn.
    • Normalize messages to OpenAI chat shape (messages/choices/tool_calls) so the
      Opik UI pretty-renders the conversation.
    • Emit create-only (upsert) operations from stable ids; never update()/end().
    • Extract all attribute parsing into attributes.ts, split by convention
      (aiSdk vs genAi), leaving the exporter to do OTel orchestration only.

    Tests & CI:

    • gen-ai.test.ts: deterministic tests over captured v7/eve spans (input,
      output, usage, error info, span types, containment nesting, create-only).
    • real-llm.test.ts: gated live Anthropic test (generateText, streamText,
      error) asserting input present / some output / usage / error info.
    • Add TypeScript SDK Library Integration Tests workflow that runs these on
      TS SDK PRs with the ANTHROPIC_API_KEY secret.

    No regressions to the AI SDK v4/v5/v6 path (existing ai-sdk/otel tests pass).

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • fix(opik-vercel): attach token usage only to LLM spans

    eve repeats each model call's gen_ai.usage on the parent invoke_agent/step
    spans as well as the chat span. Logging usage on those non-LLM wrapper spans
    double-counts tokens once the trace total is aggregated across spans (a real
    turn showed prompt_tokens 20842 instead of 10421). Emit usage only on llm-typed
    spans. Verified against a local Opik backend via the Opik MCP.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • fix(opik-vercel): record token usage only on LLM spans, not traces

    Token usage is now emitted exclusively on llm-typed spans. It is no longer set
    on the trace (the backend aggregates the trace total from the LLM spans) nor on
    tool/general spans. Update the v5/v6, gen_ai and real-LLM tests to assert usage
    lives on the LLM span and is absent from the trace.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • test(opik-vercel): mirror real invoke_agent usage in double-count fixture

    The invoke_agent wrapper span carries the model call's full gen_ai.usage in real
    eve telemetry (input/output + cache tokens), not just input/output. Match that
    in the fixture so the test proves the exporter drops the complete usage payload
    from non-LLM spans.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • perf(opik-vercel): bound exporter memory with TTL pruning of stale traces

    The exporter accumulates a trace's spans and stable id mappings across export
    batches and never released them, so a long-running process (e.g. an eve server)
    retained every trace for its lifetime. Add TTL pruning: track each trace's
    last-seen time and, on each export, drop the accumulated spans / trace id /
    span ids for traces idle longer than traceTtlMs (default 10 min). The window is
    generous so in-flight turns are never dropped; eager 'delete after flush' would
    break cross-batch coalescing and the create-only upsert. Configurable via the
    new traceTtlMs option.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

    • fix(opik-vercel): set model & provider on LLM spans so cost is computed

    The backend estimates span cost from the dedicated top-level model + provider +
    usage fields, but the exporter only put model/provider in metadata, so no cost
    was computed (trace providers was empty). Set model (gen_ai.response/request.model)
    and provider (gen_ai.system / gen_ai.provider.name) on LLM spans only. Verified
    via the Opik MCP: a real eve turn now reports per-span and aggregated trace cost.

    Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com


    Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com

    下载附件