主题
追踪 Vercel AI SDK 应用(仅 JS/TS)
使用 LangSmith 追踪 Vercel AI SDK 应用,支持 AI SDK v5、v6 和 v7。
你可以使用 LangSmith 追踪 Vercel AI SDK 的运行。本指南展示如何为 AI SDK v5、v6 和 v7 设置追踪。
安装
安装 Vercel AI SDK、模型提供程序包和 LangSmith。本指南的以下代码片段使用 Vercel 的 OpenAI 集成,但你也可以使用任何其他 Vercel AI SDK 提供程序。
NOTE
LangSmithTelemetry 需要 AI SDK v7,并在 langsmith>=0.7.2 中可用。
bash
npm install ai @ai-sdk/openai zod langsmithbash
yarn add ai @ai-sdk/openai zod langsmithbash
pnpm add ai @ai-sdk/openai zod langsmith环境配置
bash
export LANGSMITH_TRACING=true
export LANGSMITH_API_KEY=<your-api-key>
# The examples use OpenAI, but you can use any LLM provider of choice
export OPENAI_API_KEY=<your-openai-api-key>
# For LangSmith API keys linked to multiple workspaces, set the LANGSMITH_WORKSPACE_ID environment variable to specify which workspace to use.
export LANGSMITH_WORKSPACE_ID=<your-workspace-id>基本设置
注册一次 LangSmithTelemetry,然后像平常一样使用 AI SDK 方法。
typescript
import { openai } from "@ai-sdk/openai";
import { generateText, registerTelemetry } from "ai";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
registerTelemetry(LangSmithTelemetry());
await generateText({
model: openai("gpt-5.5"),
prompt: "Write a vegetarian lasagna recipe for 4 people.",
});你应该会在 LangSmith 仪表板中看到一条类似这样的追踪。
你也可以追踪带工具调用的运行:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText, registerTelemetry, stepCountIs, tool } from "ai";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
import { z } from "zod";
registerTelemetry(LangSmithTelemetry());
await generateText({
model: openai("gpt-5.5"),
messages: [
{
role: "user",
content: "What are my orders and where are they? My user ID is 123",
},
],
tools: {
listOrders: tool({
description: "list all orders",
inputSchema: z.object({ userId: z.string() }),
execute: async ({ userId }) => `User ${userId} has the following orders: 1`,
}),
viewTrackingInformation: tool({
description: "view tracking information for a specific order",
inputSchema: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => `Here is the tracking information for ${orderId}`,
}),
},
stopWhen: stepCountIs(5),
});这会生成一条类似这样的追踪。
你可以完全像平常一样使用其他 AI SDK 方法。
使用 traceable
你可以将 traceable 调用包装在 AI SDK 调用之外,或放在 AI SDK 工具调用内部。如果你想在 LangSmith 中将运行分组在一起,这会很有用。
typescript
import { openai } from "@ai-sdk/openai";
import { generateText, registerTelemetry, stepCountIs, tool } from "ai";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
import { traceable } from "langsmith/traceable";
import { z } from "zod";
registerTelemetry(LangSmithTelemetry());
const wrapper = traceable(
async (input: string) => {
const { text } = await generateText({
model: openai("gpt-5.5"),
messages: [
{
role: "user",
content: input,
},
],
tools: {
listOrders: tool({
description: "list all orders",
inputSchema: z.object({ userId: z.string() }),
execute: async ({ userId }) => `User ${userId} has the following orders: 1`,
}),
viewTrackingInformation: tool({
description: "view tracking information for a specific order",
inputSchema: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => `Here is the tracking information for ${orderId}`,
}),
},
stopWhen: stepCountIs(5),
});
return text;
},
{ name: "wrapper" },
);
await wrapper("What are my orders and where are they? My user ID is 123.");生成的追踪将如下所示。
在无服务器环境中追踪
在无服务器环境中进行追踪时,请在你的环境关闭之前等待所有运行完成刷新。
将 LangSmith Client 实例传给 LangSmithTelemetry,然后调用 await client.awaitPendingTraceBatches()。请确保也将其传入你创建的任何 traceable 包装器:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText, stepCountIs, tool } from "ai";
import { Client } from "langsmith";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
import { traceable } from "langsmith/traceable";
import { z } from "zod";
const client = new Client();
const telemetry = LangSmithTelemetry({ client });
const wrapper = traceable(
async (input: string) => {
const { text } = await generateText({
model: openai("gpt-5.5"),
messages: [
{
role: "user",
content: input,
},
],
tools: {
listOrders: tool({
description: "list all orders",
inputSchema: z.object({ userId: z.string() }),
execute: async ({ userId }) => `User ${userId} has the following orders: 1`,
}),
viewTrackingInformation: tool({
description: "view tracking information for a specific order",
inputSchema: z.object({ orderId: z.string() }),
execute: async ({ orderId }) => `Here is the tracking information for ${orderId}`,
}),
},
stopWhen: stepCountIs(5),
telemetry: { integrations: [telemetry] },
});
return text;
},
{
name: "wrapper",
client,
},
);
try {
await wrapper("What are my orders and where are they? My user ID is 123.");
} finally {
await client.awaitPendingTraceBatches();
}如果你使用 Next.js,有一个方便的 after 钩子,可以把这段逻辑放在那里:
typescript
import { after } from "next/server";
import { Client } from "langsmith";
export async function POST(request: Request) {
const client = new Client();
const body = await request.json();
after(async () => {
await client.awaitPendingTraceBatches();
});
return Response.json({ ok: true, body });
}详情请参阅在无服务器环境中追踪 JS 函数,包括在无服务器环境中管理速率限制的相关信息。
传递 LangSmith 配置
你可以传入 LangSmith 特有的配置,例如元数据、运行名称、标签和自定义客户端实例。
如果在全局注册该集成,配置会应用于后续的 AI SDK 调用:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText, registerTelemetry } from "ai";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
registerTelemetry(
LangSmithTelemetry({
metadata: { key_for_all_runs: "value" },
tags: ["myrun"],
}),
);
await generateText({
model: openai("gpt-5.5"),
prompt: "Write a vegetarian lasagna recipe for 4 people.",
});要将配置应用于单次运行,请在该 AI SDK 调用中传入遥测集成:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
await generateText({
model: openai("gpt-5.5"),
prompt: "Write a vegetarian lasagna recipe for 4 people.",
telemetry: {
integrations: [
LangSmithTelemetry({
metadata: { individual_key: "value" },
name: "my_individual_run",
}),
],
},
});编辑数据
你可以通过指定自定义输入/输出处理函数,自定义 AI SDK 发送给 LangSmith 的输入和输出。如果你要处理不希望发送到 LangSmith 的敏感数据,这会很有用。
由于输出格式会因所使用的 AI SDK 方法而异,我们建议在 AI SDK 调用中单独定义并传入遥测配置。你还需要为 AI SDK 调用中的子 LLM 运行提供单独的函数,因为在顶层调用 generateText 会在内部调用 LLM,并且可能多次调用。
以下是 generateText 的示例:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText } from "ai";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
const telemetry = LangSmithTelemetry({
processInputs: (inputs) => {
const messages = inputs.messages as Array<Record<string, unknown>> | undefined;
return {
messages: messages?.map((message) => ({
providerMetadata: message.providerOptions,
role: "assistant",
content: "REDACTED",
})),
prompt: "REDACTED",
};
},
processOutputs: (outputs) => {
return {
providerMetadata: outputs.providerMetadata,
role: "assistant",
content: "REDACTED",
};
},
processChildLLMRunInputs: (inputs) => {
const messages = inputs.messages as Array<Record<string, unknown>> | undefined;
return {
messages: messages?.map((message) => ({
...message,
content: "REDACTED CHILD INPUTS",
})),
};
},
processChildLLMRunOutputs: (outputs) => {
return {
providerMetadata: outputs.providerMetadata,
content: "REDACTED CHILD OUTPUTS",
role: "assistant",
};
},
});
const { text } = await generateText({
model: openai("gpt-5.5"),
prompt: "What is the capital of France?",
telemetry: { integrations: [telemetry] },
});
console.log(text);实际返回值会包含原始的、未编辑的结果,但 LangSmith 中的追踪会经过编辑。
要编辑工具的输入/输出,请像下面这样将你的 execute 方法包装在 traceable 中:
typescript
import { openai } from "@ai-sdk/openai";
import { generateText, stepCountIs, tool } from "ai";
import { Client } from "langsmith";
import { LangSmithTelemetry } from "langsmith/experimental/vercel";
import { traceable } from "langsmith/traceable";
import { z } from "zod";
const client = new Client();
const telemetry = LangSmithTelemetry({ client });
await generateText({
model: openai("gpt-5.5"),
messages: [
{
role: "user",
content: "What are my orders? My user ID is 123.",
},
],
tools: {
listOrders: tool({
description: "list all orders",
inputSchema: z.object({ userId: z.string() }),
execute: traceable(
async ({ userId }) => {
return `User ${userId} has the following orders: 1`;
},
{
processInputs: () => ({ text: "REDACTED" }),
processOutputs: () => ({ text: "REDACTED" }),
run_type: "tool",
name: "listOrders",
},
) as (input: { userId: string }) => Promise<string>,
}),
},
stopWhen: stepCountIs(5),
telemetry: { integrations: [telemetry] },
});
await client.awaitPendingTraceBatches();traceable 的返回类型很复杂,因此需要进行类型转换。如果你希望避免类型转换,也可以省略 AI SDK 的 tool 辅助函数。