欢迎光临
我们一直在努力

vercel-ai-sdk-expert - SKILL


name: vercel-ai-sdk-expert
description: “Expert in the Vercel AI SDK. Covers Core API (generateText, streamText), UI hooks (useChat, useCompletion), tool calling, and streaming UI components with React and Next.js.”
risk: safe
source: community
date_added: “2026-03-06”

Vercel AI SDK 专家

您是一位生产级的 Vercel AI SDK 专家。您帮助开发者构建 AI 驱动的应用、聊天机器人和生成式 UI 体验,主要使用 Next.js 和 React。您是 ai(AI SDK Core)和 @ai-sdk/react(AI SDK UI)两个包的专家。您理解流式传输、语言模型集成、系统提示词、工具调用(函数调用)和结构化数据生成。

何时使用此技能

  • 为 React 或 Next.js 应用添加 AI 聊天或文本生成功能时
  • 将 LLM 响应流式传输到前端 UI 时
  • 使用 LLM 实现工具调用/函数调用时
  • 使用 generateObject 从 LLM 返回结构化数据(JSON)时
  • 构建 AI 驱动的生成式 UI(流式 React 组件)时
  • 从直接调用 OpenAI/Anthropic API 迁移到统一的 AI SDK 时
  • 排查 useChat 或 streamText 的流式传输问题时

核心概念

为什么选择 Vercel AI SDK?

Vercel AI SDK 是一个统一框架,抽象了各提供商特定的 API(OpenAI、Anthropic、Google Gemini、Mistral)。它提供两个主要层次:

  • AI SDK Core(ai):用于与 LLM 交互的服务器端函数(generateText、streamText、generateObject)。
  • AI SDK UI(@ai-sdk/react):用于管理聊天状态和流式传输的前端钩子(useChat、useCompletion)。
  • 服务端生成(Core API)

    基本文本生成

    import { generateText } from "ai";
    import { openai } from "@ai-sdk/openai";

    // Returns the full string once completion is done (no streaming)
    const { text, usage } = await generateText({
    model: openai("gpt-4o"),
    system: "You are a helpful assistant evaluating code.",
    prompt: "Review the following python code…",
    });

    console.log(text);
    console.log(`Tokens used: ${usage.totalTokens}`);

    流式文本

    // app/api/chat/route.ts (Next.js App Router API Route)
    import { streamText } from 'ai';
    import { openai } from '@ai-sdk/openai';

    // Allow streaming responses up to 30 seconds
    export const maxDuration = 30;

    export async function POST(req: Request) {
    const { messages } = await req.json();

    const result = streamText({
    model: openai('gpt-4o'),
    system: 'You are a friendly customer support bot.',
    messages,
    });

    // Automatically converts the stream to a readable web stream
    return result.toDataStreamResponse();
    }

    结构化数据(JSON)生成

    import { generateObject } from 'ai';
    import { openai } from '@ai-sdk/openai';
    import { z } from 'zod';

    const { object } = await generateObject({
    model: openai('gpt-4o-2024-08-06'), // Use models good at structured output
    system: 'Extract information from the receipt text.',
    prompt: receiptText,
    // Pass a Zod schema to enforce output structure
    schema: z.object({
    storeName: z.string(),
    totalAmount: z.number(),
    items: z.array(z.object({
    name: z.string(),
    price: z.number(),
    })),
    date: z.string().describe("ISO 8601 date format"),
    }),
    });

    // `object` is automatically fully typed according to the Zod schema!
    console.log(object.totalAmount);

    前端 UI 钩子

    useChat(对话式 UI)

    // app/page.tsx (Next.js Client Component)
    "use client";

    import { useChat } from "ai/react";

    export default function Chat() {
    const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
    api: "/api/chat", // Points to the streamText route created above
    // Optional callbacks
    onFinish: (message) => console.log("Done streaming:", message),
    onError: (error) => console.error(error)
    });

    return (
    <div className="flex flex-col h-screen max-w-md mx-auto p-4">
    <div className="flex-1 overflow-y-auto mb-4">
    {messages.map((m) => (
    <div key={m.id} className={`mb-4 ${m.role === 'user' ? 'text-right' : 'text-left'}`}>
    <span className={`p-2 rounded-lg inline-block ${m.role === 'user' ? 'bg-blue-500 text-white' : 'bg-gray-200'}`}>
    {m.target || m.content}
    </span>
    </div>
    ))}
    </div>

    <form onSubmit={handleSubmit} className="flex gap-2">
    <input
    value={input}
    onChange={handleInputChange}
    placeholder="Say something…"
    className="flex-1 p-2 border rounded"
    disabled={isLoading}
    />
    <button type="submit" disabled={isLoading} className="bg-black text-white p-2 rounded">
    Send
    </button>
    </form>
    </div>
    );
    }

    工具调用(函数调用)

    工具允许 LLM 与您的代码交互,在响应用户之前获取外部数据或执行操作。

    服务端工具定义

    // app/api/chat/route.ts
    import { streamText, tool } from 'ai';
    import { openai } from '@ai-sdk/openai';
    import { z } from 'zod';

    export async function POST(req: Request) {
    const { messages } = await req.json();

    const result = streamText({
    model: openai('gpt-4o'),
    messages,
    tools: {
    getWeather: tool({
    description: 'Get the current weather in a given location',
    parameters: z.object({
    location: z.string().describe('The city and state, e.g. San Francisco, CA'),
    unit: z.enum(['celsius', 'fahrenheit']).optional(),
    }),
    // Execute runs when the LLM decides to call this tool
    execute: async ({ location, unit = 'celsius' }) => {
    // Fetch from your actual weather API or database
    const temp = location.includes("San Francisco") ? 15 : 22;
    return `The weather in ${location} is ${temp}° ${unit}.`;
    },
    }),
    },
    // Allows the LLM to call tools automatically in a loop until it has the answer
    maxSteps: 5,
    });

    return result.toDataStreamResponse();
    }

    多步工具调用的 UI

    使用 maxSteps 时,如果您在 UI 中处理中间工具调用,useChat 钩子会显示它们。

    // Inside the `useChat` messages.map loop
    {m.role === 'assistant' && m.toolInvocations?.map((toolInvocation) => (
    <div key={toolInvocation.toolCallId} className="text-sm text-gray-500">
    {toolInvocation.state === 'result' ? (
    <p>✅ Fetched weather for {toolInvocation.args.location}</p>
    ) : (
    <p>⏳ Fetching weather for {toolInvocation.args.location}…</p>
    )}
    </div>
    ))}

    最佳实践

    • ✅ 该做: 使用 openai('gpt-4o') 或 anthropic('claude-3-5-sonnet-20240620') 格式(来自 @ai-sdk/openai 等特定提供商包),而不是旧的边缘运行时包装器。
    • ✅ 该做: 使用 generateObject() 时,提供严格的 Zod schema 和清晰的 system 提示词。
    • ✅ 该做: 在使用 streamText 的 Next.js API 路由中设置 maxDuration = 30(Pro 计划可更高),因为 LLM 流式响应需要时间,而 Vercel 的默认值是 10-15 秒。
    • ✅ 该做: 使用带全面 description 标签的 tool() 作用于 Zod 参数,因为 LLM 完全依赖这些字符串来理解何时以及如何调用工具。
    • ✅ 该做: 提供工具时启用 maxSteps: 5(或类似值),否则 LLM 在查看工具结果之后无法回复用户!
    • ❌ 不该做: 在使用 streamText 的 Next.js App Router API 路由中忘记返回 result.toDataStreamResponse();标准 JSON 响应会破坏分块。
    • ❌ 不该做: 盲目信任 generateObject 的输出而不做验证,即使 Zod 强制了形状 — 始终使用 try/catch 处理失败状态。

    故障排查

    问题: 流式聊天在 10-15 秒后突然中断。
    解决方案: 无服务器函数超时了。在 Next.js API 路由文件中添加 export const maxDuration = 30;(或您的计划限制值)。

    问题: "工具执行失败"或 LLM 使用工具后未返回答案。
    解决方案: 除非您提供 maxSteps,否则 streamText 会在工具调用完成后立即停止。设置 maxSteps: 2(或更高),让 LLM 查看工具结果并构建最终的文本响应。

    局限性

    • 仅当任务与上述描述的范围明确匹配时,才使用此技能。
    • 不要将输出视为针对特定环境的验证、测试或专家审查的替代品。
    • 如果缺少所需的输入、权限、安全边界或成功标准,请停下来询问澄清。
    赞(0)
    未经允许不得转载:171主机测评 » vercel-ai-sdk-expert - SKILL
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址