本文档介绍了一种较旧的 AI SDK 运行追踪方法。如需一种更简单、更通用且无需 OTEL 设置的方法,请参阅新指南。
你可以使用 LangSmith 通过 OpenTelemetry (OTEL) 追踪来自 Vercel AI SDK 的运行。本指南将逐步介绍一个示例。
0. 安装
安装 Vercel AI SDK 和所需的 OTEL 包。下面的代码片段使用了它们的 OpenAI 集成,但你也可以使用任何其他选项。
npm install ai @ai-sdk/openai zod
npm install @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-proto @opentelemetry/context-async-hooks
1. 配置环境
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<你的 API 密钥>
export LANGSMITH_OTEL_ENABLED=true
# 此示例使用 OpenAI,但你可以选择任何 LLM 提供程序
export OPENAI_API_KEY=<你的 OpenAI API 密钥>
2. 记录追踪
Node.js
要开始追踪,你需要在代码开头导入并调用 initializeOTEL 方法:
import { initializeOTEL } from "langsmith/experimental/otel/setup";
const { DEFAULT_LANGSMITH_SPAN_PROCESSOR } = initializeOTEL();
之后,在你想要追踪的 AI SDK 调用中添加 experimental_telemetry 参数。
请勿忘记在应用程序关闭前调用 await DEFAULT_LANGSMITH_SPAN_PROCESSOR.shutdown();,以便将剩余的追踪数据刷新到 LangSmith。
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
let result;
try {
result = await generateText({
model: openai("gpt-4.1-nano"),
prompt: "为 4 个人写一份素食千层面食谱。",
experimental_telemetry: {
isEnabled: true,
},
});
} finally {
await DEFAULT_LANGSMITH_SPAN_PROCESSOR.shutdown();
}
你应该能在 LangSmith 仪表板中看到类似此示例的追踪记录。
你也可以追踪包含工具调用的运行:
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
await generateText({
model: openai("gpt-4.1-nano"),
messages: [
{
role: "user",
content: "我的订单有哪些,它们在哪里?我的用户 ID 是 123",
},
],
tools: {
listOrders: tool({
description: "列出所有订单",
parameters: z.object({ userId: z.string() }),
execute: async ({ userId }) =>
`用户 ${userId} 有以下订单:1`,
}),
viewTrackingInformation: tool({
description: "查看特定订单的物流信息",
parameters: z.object({ orderId: z.string() }),
execute: async ({ orderId }) =>
`这是订单 ${orderId} 的物流信息`,
}),
},
experimental_telemetry: {
isEnabled: true,
},
maxSteps: 10,
});
这将生成类似此示例的追踪记录。
使用 traceable
你可以在 AI SDK 工具调用的周围或内部包装 traceable 调用。如果这样做,我们建议你初始化一个 LangSmith client 实例,并将其传递给每个 traceable,然后调用 client.awaitPendingTraceBatches(); 以确保所有追踪数据都被刷新。如果采用此方法,你无需手动调用 DEFAULT_LANGSMITH_SPAN_PROCESSOR 的 shutdown() 或 forceFlush()。示例如下:
import { initializeOTEL } from "langsmith/experimental/otel/setup";
initializeOTEL();
import { Client } from "langsmith";
import { traceable } from "langsmith/traceable";
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
const client = new Client();
const wrappedText = traceable(
async (content: string) => {
const { text } = await generateText({
model: openai("gpt-4.1-nano"),
messages: [{ role: "user", content }],
tools: {
listOrders: tool({
description: "列出所有订单",
parameters: z.object({ userId: z.string() }),
execute: async ({ userId }) => {
const getOrderNumber = traceable(
async () => {
return "1234";
},
{ name: "getOrderNumber" }
);
const orderNumber = await getOrderNumber();
return `用户 ${userId} 有以下订单:${orderNumber}`;
},
}),
},
experimental_telemetry: {
isEnabled: true,
},
maxSteps: 10,
});
return { text };
},
{ name: "parentTraceable", client }
);
let result;
try {
result = await wrappedText("我的订单有哪些?");
} finally {
await client.awaitPendingTraceBatches();
}
生成的追踪记录将类似于此。
Next.js
首先,安装 @vercel/otel 包:
然后,在你的根目录中设置一个 instrumentation.ts 文件。
调用 initializeOTEL,并将生成的 DEFAULT_LANGSMITH_SPAN_PROCESSOR 传递到 registerOTEL(...) 调用的 spanProcessors 字段中。
代码应类似如下:
import { registerOTel } from "@vercel/otel";
import { initializeOTEL } from "langsmith/experimental/otel/setup";
const { DEFAULT_LANGSMITH_SPAN_PROCESSOR } = initializeOTEL({});
export function register() {
registerOTel({
serviceName: "你的项目名称",
spanProcessors: [DEFAULT_LANGSMITH_SPAN_PROCESSOR],
});
}
最后,在你的 API 路由中,同样调用 initializeOTEL,并在 AI SDK 调用中添加 experimental_telemetry 字段:
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { initializeOTEL } from "langsmith/experimental/otel/setup";
initializeOTEL();
export async function GET() {
const { text } = await generateText({
model: openai("gpt-4.1-nano"),
messages: [{ role: "user", content: "天空为什么是蓝色的?" }],
experimental_telemetry: {
isEnabled: true,
},
});
return new Response(text);
}
你也可以将部分代码包装在 traceable 中,以实现更细粒度的追踪。
Sentry
如果你使用 Sentry,可以按照以下示例所示,将 LangSmith 追踪导出器附加到 Sentry 的默认 OpenTelemetry 检测中。
截至撰写本文时,Sentry 仅支持 OTEL v1 包。LangSmith 同时支持 v1 和 v2,但你必须确保安装 OTEL v1 包才能使检测正常工作。npm install @opentelemetry/sdk-trace-base@1.30.1 @opentelemetry/exporter-trace-otlp-proto@0.57.2 @opentelemetry/context-async-hooks@1.30.1
import { initializeOTEL } from "langsmith/experimental/otel/setup";
import { LangSmithOTLPTraceExporter } from "langsmith/experimental/otel/exporter";
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { traceable } from "langsmith/traceable";
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
import * as Sentry from "@sentry/node";
import { Client } from "langsmith";
const exporter = new LangSmithOTLPTraceExporter();
const spanProcessor = new BatchSpanProcessor(exporter);
const sentry = Sentry.init({
dsn: "...",
tracesSampleRate: 1.0,
openTelemetrySpanProcessors: [spanProcessor],
});
initializeOTEL({
globalTracerProvider: sentry?.traceProvider,
});
const wrappedText = traceable(
async (content: string) => {
const { text } = await generateText({
model: openai("gpt-4.1-nano"),
messages: [{ role: "user", content }],
experimental_telemetry: {
isEnabled: true,
},
maxSteps: 10,
});
return { text };
},
{ name: "parentTraceable" }
);
let result;
try {
result = await wrappedText("天空是什么颜色的?");
} finally {
await sentry?.traceProvider?.shutdown();
}
添加其他元数据
你可以向追踪记录中添加其他元数据,以帮助在 LangSmith UI 中组织和筛选它们:
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
await generateText({
model: openai("gpt-4.1-nano"),
prompt: "为 4 个人写一份素食千层面食谱。",
experimental_telemetry: {
isEnabled: true,
metadata: { userId: "123", language: "english" },
},
});
元数据将在你的 LangSmith 仪表板中可见,并可用于筛选和搜索特定的追踪记录。
请注意,AI SDK 会在内部的子跨度中传播元数据。
自定义运行名称
你可以通过将名为 ls_run_name 的元数据键传递到 experimental_telemetry 中来自定义运行名称。
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
await generateText({
model: openai("gpt-4.1-mini"),
prompt: "为 4 个人写一份素食千层面食谱。",
experimental_telemetry: {
isEnabled: true,
// highlight-start
metadata: {
ls_run_name: "我的自定义运行名称",
},
// highlight-end
},
});