Skip to content

Latest commit

 

History

History
172 lines (142 loc) · 4.65 KB

File metadata and controls

172 lines (142 loc) · 4.65 KB

Manual Instrumentation (TypeScript)

Add custom spans using convenience wrappers or withSpan for fine-grained tracing control.

Setup

npm install @arizeai/phoenix-otel @arizeai/openinference-core
import { register } from "@arizeai/phoenix-otel";
register({ projectName: "my-app" });

Quick Reference

Span Kind Method Use Case
CHAIN traceChain Workflows, pipelines, orchestration
AGENT traceAgent Multi-step reasoning, planning
TOOL traceTool External APIs, function calls
RETRIEVER withSpan Vector search, document retrieval
LLM withSpan LLM API calls (prefer auto-instrumentation)
EMBEDDING withSpan Embedding generation
RERANKER withSpan Document re-ranking
GUARDRAIL withSpan Safety checks, content moderation
EVALUATOR withSpan LLM evaluation

Convenience Wrappers

import { traceChain, traceAgent, traceTool } from "@arizeai/openinference-core";

// CHAIN - workflows
const pipeline = traceChain(
  async (query: string) => {
    const docs = await retrieve(query);
    return await generate(docs, query);
  },
  { name: "rag-pipeline" }
);

// AGENT - reasoning
const agent = traceAgent(
  async (question: string) => {
    const thought = await llm.generate(`Think: ${question}`);
    return await processThought(thought);
  },
  { name: "my-agent" }
);

// TOOL - function calls
const getWeather = traceTool(
  async (city: string) => fetch(`/api/weather/${city}`).then(r => r.json()),
  { name: "get-weather" }
);

withSpan for Other Kinds

import { withSpan, getInputAttributes, getRetrieverAttributes } from "@arizeai/openinference-core";

// RETRIEVER with custom attributes
const retrieve = withSpan(
  async (query: string) => {
    const results = await vectorDb.search(query, { topK: 5 });
    return results.map(doc => ({ content: doc.text, score: doc.score }));
  },
  {
    kind: "RETRIEVER",
    name: "vector-search",
    processInput: (query) => getInputAttributes(query),
    processOutput: (docs) => getRetrieverAttributes({ documents: docs })
  }
);

Options:

withSpan(fn, {
  kind: "RETRIEVER",              // OpenInference span kind
  name: "span-name",              // Span name (defaults to function name)
  processInput: (args) => {},     // Transform input to attributes
  processOutput: (result) => {},  // Transform output to attributes
  attributes: { key: "value" }    // Static attributes
});

Capturing Input/Output

Always capture I/O for evaluation-ready spans. Use getInputAttributes and getOutputAttributes helpers for automatic MIME type detection:

import {
  getInputAttributes,
  getOutputAttributes,
  withSpan,
} from "@arizeai/openinference-core";

const handleQuery = withSpan(
  async (userInput: string) => {
    const result = await agent.generate({ prompt: userInput });
    return result;
  },
  {
    name: "query.handler",
    kind: "CHAIN",
    // Use helpers - automatic MIME type detection
    processInput: (input) => getInputAttributes(input),
    processOutput: (result) => getOutputAttributes(result.text),
  }
);

await handleQuery("What is 2+2?");

What gets captured:

{
  "input.value": "What is 2+2?",
  "input.mime_type": "text/plain",
  "output.value": "2+2 equals 4.",
  "output.mime_type": "text/plain"
}

Helper behavior:

  • Strings → text/plain
  • Objects/Arrays → application/json (automatically serialized)
  • undefined/null → No attributes set

Why this matters:

  • Phoenix evaluators require input.value and output.value
  • Phoenix UI displays I/O prominently for debugging
  • Enables exporting data for fine-tuning datasets

Custom I/O Processing

Add custom metadata alongside standard I/O attributes:

const processWithMetadata = withSpan(
  async (query: string) => {
    const result = await llm.generate(query);
    return result;
  },
  {
    name: "query.process",
    kind: "CHAIN",
    processInput: (query) => ({
      "input.value": query,
      "input.mime_type": "text/plain",
      "input.length": query.length,  // Custom attribute
    }),
    processOutput: (result) => ({
      "output.value": result.text,
      "output.mime_type": "text/plain",
      "output.tokens": result.usage?.totalTokens,  // Custom attribute
    }),
  }
);

See Also