以编程方式使用文档

您可以使用 LangSmith 追踪 Vercel AI SDK 的运行。本指南将向您展示如何为 AI SDK v5、v6 和 v7 设置追踪功能。

安装

安装 Vercel AI SDK、一个模型提供商包和 LangSmith。本指南使用 Vercel 的 OpenAI 集成作为代码示例,但您可以使用其他任何 Vercel AI SDK 提供商。

AI SDK v7

        npm install ai @ai-sdk/openai zod langsmith
        
        yarn add ai @ai-sdk/openai zod langsmith
        
        pnpm add ai @ai-sdk/openai zod langsmith
        

AI SDK v5 and v6

        npm install ai @ai-sdk/openai zod langsmith
        
        yarn add ai @ai-sdk/openai zod langsmith
        
        pnpm add ai @ai-sdk/openai zod langsmith
        

环境配置

# The examples use OpenAI, but you can use any LLM provider of choice


# For LangSmith API keys linked to multiple workspaces, set the LANGSMITH_WORKSPACE_ID environment variable to specify which workspace to use.

基本设置

AI SDK v7

注册 LangSmithTelemetry 一次,然后按常规方式使用 AI SDK 方法。

        registerTelemetry(LangSmithTelemetry());

        await generateText({
            model: openai("gpt-5.5"),
            prompt: "Write a vegetarian lasagna recipe for 4 people.",
        });
        

您应该能在 LangSmith 仪表板中看到一个追踪 类似这样的.

您也可以追踪包含工具调用的运行:

        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 v5 and v6

使用 wrapAISDK包装一次 AI SDK 方法,然后按常规方式调用包装后的方法。

        const { generateText } = wrapAISDK(ai);

        await generateText({
            model: openai("gpt-5.5"),
            prompt: "Write a vegetarian lasagna recipe for 4 people.",
        });
        

您也可以追踪包含工具调用的运行:

        const { generateText, tool } = wrapAISDK(ai);

        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",
                    parameters: 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",
                    parameters: z.object({ orderId: z.string() }),
                    execute: async ({ orderId }) => `Here is the tracking information for ${orderId}`,
                }),
            },
            maxSteps: 5,
        });
        

您可以像往常一样使用其他 AI SDK 方法。

使用 traceable

您可以包装 traceable 调用以包装 AI SDK 调用或在 AI SDK 工具调用内部使用。这在您想要在 LangSmith 中将运行分组在一起时很有用。

AI SDK v7

        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.");
        

生成的追踪将看起来 像这样.

AI SDK v5 and v6

        const { generateText, tool } = wrapAISDK(ai);

        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",
                            parameters: 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",
                            parameters: z.object({ orderId: z.string() }),
                            execute: async ({ orderId }) => `Here is the tracking information for ${orderId}`,
                        }),
                    },
                    maxSteps: 5,
                });
                return text;
            },
            { name: "wrapper" },
        );

        await wrapper("What are my orders and where are they? My user ID is 123.");
        

在无服务器环境中追踪

在无服务器环境中追踪时,请等待所有运行在环境关闭前完全刷新。

AI SDK v7

将 LangSmith Client 实例传递给 LangSmithTelemetry,然后调用 await client.awaitPendingTraceBatches()。请确保也将其传递给任何您创建的 traceable 包装器:

        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();
        }
        

AI SDK v5 and v6

将 LangSmith Client 实例传递给 wrapAISDK 和任何 traceable 包装器,然后调用 await client.awaitPendingTraceBatches():

        const client = new Client();
        const { generateText, tool } = wrapAISDK(ai, { 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",
                            parameters: 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",
                            parameters: z.object({ orderId: z.string() }),
                            execute: async ({ orderId }) => `Here is the tracking information for ${orderId}`,
                        }),
                    },
                    maxSteps: 5,
                });
                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 钩子,您可以将此逻辑放在那里:

    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 v7

如果您全局注册集成,该配置将适用于未来的 AI SDK 调用:

        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 调用中传递一个遥测集成:

        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 v5 and v6

如果将配置传递给 wrapAISDK,则配置将应用于包装的方法:

        const { generateText } = wrapAISDK(ai, {
            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 调用中传递 LangSmith provider 选项:

            createLangSmithProviderOptions,
            wrapAISDK,
        } from "langsmith/experimental/vercel";

        const { generateText } = wrapAISDK(ai);

        await generateText({
            model: openai("gpt-5.5"),
            prompt: "Write a vegetarian lasagna recipe for 4 people.",
            providerOptions: {
                langsmith: createLangSmithProviderOptions<typeof ai.generateText>({
                    metadata: { individual_key: "value" },
                    name: "my_individual_run",
                }),
            },
        });
        

数据脱敏

You can customize what inputs and outputs the AI SDK sends to LangSmith by specifying custom input/output processing functions. This is useful if you are dealing with sensitive data that you would like to avoid sending to LangSmith.

由于输出格式因您使用的 AI SDK 方法不同而有所差异,我们建议在各个 AI SDK 调用中单独定义并传递 telemetry 配置。您还需要在 AI SDK 调用中为子 LLM 运行提供单独的函数,因为调用 generateText 在顶层会内部调用 LLM,且可能会多次调用。

以下是用于 generateText:

AI SDK v7

        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);
        

AI SDK v5 and v6

            createLangSmithProviderOptions,
            wrapAISDK,
        } from "langsmith/experimental/vercel";

        const { generateText } = wrapAISDK(ai);

        const langsmith = createLangSmithProviderOptions<typeof ai.generateText>({
            processInputs: (inputs) => {
                return {
                    messages: inputs.messages?.map((message) => ({
                        providerMetadata: message.providerOptions,
                        role: "assistant",
                        content: "REDACTED",
                    })),
                    prompt: "REDACTED",
                };
            },
            processOutputs: () => {
                return {
                    role: "assistant",
                    content: "REDACTED",
                };
            },
            processChildLLMRunInputs: (inputs) => {
                return {
                    messages: inputs.prompt.map((message) => ({
                        ...message,
                        content: "REDACTED CHILD INPUTS",
                    })),
                };
            },
            processChildLLMRunOutputs: () => {
                return {
                    content: "REDACTED CHILD OUTPUTS",
                    role: "assistant",
                };
            },
        });

        const { text } = await generateText({
            model: openai("gpt-5.5"),
            prompt: "What is the capital of France?",
            providerOptions: { langsmith },
        });

        console.log(text);
        

实际返回值将包含原始的、未脱敏的结果,但 LangSmith 中的 trace 将被脱敏。

For redacting tool input/output, wrap your execute 方法在 traceable 中像这样使用:

AI SDK v7

        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();
        

AI SDK v5 and v6

        const client = new Client();
        const { generateText, tool } = wrapAISDK(ai, { 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",
                    parameters: 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>,
                }),
            },
            maxSteps: 5,
        });

        await client.awaitPendingTraceBatches();
        

traceable 返回类型比较复杂,因此需要进行类型转换。您也可以省略 AI SDK tool helper 函数来避免类型转换。