跳到主要內容

用 Vercel AI SDK 快速建立 AI 應用:從零到 streaming chat

你想在 Next.js 裡加一個 AI chat 功能。直接呼叫 OpenAI 或 Anthropic API 當然可以,但你很快會發現自己在處理 streaming、state management、error handling、abort controller——這些跟你的產品邏輯完全無關的事。

Vercel AI SDK 就是為了解決這個問題而生的。

Vercel AI SDK 是什麼

Vercel AI SDK 是一個開源的 TypeScript 框架,提供統一的介面來串接各家 LLM provider(OpenAI、Anthropic、Google、Mistral 等),並且內建 streaming、React hooks 和 Next.js 整合。

它分成三層:

  1. AI SDK Core — 底層的 model routing 和 streaming 處理,跑在 server 端
  2. AI SDK UI — React hooks(useChatuseCompletion),處理前端 state
  3. AI SDK RSC — React Server Components 整合(進階用法)

對大多數場景來說,你只需要 Core + UI 就夠了。

為什麼比直接呼叫 API 好

直接用 fetch 打 Anthropic API,你需要自己處理:

  • SSE(Server-Sent Events)的 streaming parsing
  • 前端的 message state 累加
  • loading / error / abort 狀態管理
  • 不同 provider 的 request format 差異
  • Token 計算和 rate limit 處理

AI SDK 把這些全部抽象掉了。換 provider 只需要改一行 import,前端完全不用動。

從零開始:建一個 streaming chat

Step 1:安裝依賴

pnpm add ai @ai-sdk/anthropic

ai 是 SDK 本體,@ai-sdk/anthropic 是 Claude 的 provider adapter。

Step 2:建立 API Route

在 Next.js App Router 下建立 route handler:

// app/api/chat/route.ts
import { anthropic } from '@ai-sdk/anthropic'
import { streamText } from 'ai'

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

  const result = streamText({
    model: anthropic('claude-sonnet-4-6'),
    system: '你是一個友善的 AI 助手,用繁體中文回答問題。',
    messages,
  })

  return result.toDataStreamResponse()
}

這裡發生了幾件事:

  • anthropic() 建立一個 Claude model instance,SDK 會自動讀取 ANTHROPIC_API_KEY 環境變數
  • streamText() 發送 streaming request 並回傳一個可控的 stream 物件
  • toDataStreamResponse() 把 stream 轉成 Next.js 相容的 Response 格式

Step 3:建立前端 Chat UI

// app/chat/page.tsx
'use client'

import { useChat } from '@ai-sdk/react'

export default function ChatPage() {
  const { messages, input, handleInputChange, handleSubmit, isLoading } =
    useChat()

  return (
    <div className="mx-auto max-w-2xl p-4">
      <div className="space-y-4">
        {messages.map((m) => (
          <div
            key={m.id}
            className={m.role === 'user' ? 'text-right' : 'text-left'}
          >
            <span className="text-sm text-gray-500">
              {m.role === 'user' ? '你' : 'AI'}
            </span>
            <p className="mt-1 whitespace-pre-wrap">{m.content}</p>
          </div>
        ))}
      </div>

      <form onSubmit={handleSubmit} className="mt-8 flex gap-2">
        <input
          value={input}
          onChange={handleInputChange}
          placeholder="輸入訊息..."
          className="flex-1 rounded-lg border px-4 py-2"
          disabled={isLoading}
        />
        <button
          type="submit"
          disabled={isLoading}
          className="rounded-lg bg-indigo-600 px-4 py-2 text-white disabled:opacity-50"
        >
          送出
        </button>
      </form>
    </div>
  )
}

useChat 是整個 SDK 最核心的 hook。它幫你處理:

  • 訊息歷史的累加和管理
  • 自動發送 POST request 到 /api/chat
  • Streaming 回應的即時渲染
  • Loading 和 error 狀態

三個檔案,一個完整的 streaming chat。

Step 4:設定環境變數

# .env.local
ANTHROPIC_API_KEY=sk-ant-xxxxx

pnpm dev,打開 /chat,就能開始對話了。

useChat 的進階用法

useChat 還有幾個實用的參數:

const { messages, input, handleSubmit, stop, reload, setMessages } = useChat({
  api: '/api/custom-chat',        // 自訂 API endpoint
  initialMessages: [...],          // 預設訊息
  body: { userId: '123' },        // 額外帶入 request body
  onFinish: (message) => {         // streaming 完成時觸發
    console.log('完成:', message)
  },
  onError: (error) => {            // 錯誤處理
    console.error('錯誤:', error)
  },
})

幾個重點:

  • stop() — 中斷正在進行的 streaming(底層用 AbortController)
  • reload() — 重新生成最後一則 AI 回應
  • setMessages() — 手動操作訊息歷史(例如清除對話)

useCompletion:單次生成

如果你不需要多輪對話,只需要單次文字生成(例如摘要、翻譯、改寫),用 useCompletion

import { useCompletion } from '@ai-sdk/react'

const { completion, input, handleInputChange, handleSubmit } = useCompletion({
  api: '/api/completion',
})

對應的 API route 用 streamText 一樣能處理,差別只在前端的 state 管理方式。

搭配 Vercel AI Gateway

如果你部署在 Vercel 上,可以搭配 AI Gateway 做 model routing:

import { anthropic } from '@ai-sdk/anthropic'

const result = streamText({
  model: anthropic('claude-sonnet-4-6'),
  // Vercel AI Gateway 會自動處理 routing、caching、rate limiting
  messages,
})

AI Gateway 的好處是統一管理 API key、監控用量、自動 failover。在 Vercel dashboard 設定 AI_GATEWAY_API_KEY 就能啟用。

常見陷阱

1. 忘記加 'use client'

useChat 是 React hook,必須在 Client Component 裡使用。如果你在 Server Component 裡直接呼叫,會拿到 hooks can only be called inside a function component 錯誤。

2. 環境變數命名

ANTHROPIC_API_KEY 不要加 NEXT_PUBLIC_ 前綴。API key 只能在 server 端使用,放到 NEXT_PUBLIC_ 會暴露在前端 bundle 裡。

3. Streaming 在 Edge Runtime 的差異

預設的 Node.js runtime 可以正常使用 streamText。如果你切到 Edge Runtime,確認你用的 provider adapter 支援 Edge(Anthropic adapter 支援)。

4. Message format 不一致

useChat 送出的 messages 格式是 { role, content }[],跟 OpenAI 和 Anthropic 的 API 格式相容。但如果你自己組裝 messages,確保 role 只有 'user''assistant''system' 三種。

5. 大量訊息的效能問題

每次送出都會帶完整的 message history。對話太長時,token 數會快速膨脹。建議在 server 端做 message truncation 或 summarization。

下一步

Vercel AI SDK 還支援 tool calling、structured output(generateObject)、multi-modal input 等進階功能。如果你的應用需要讓 AI 呼叫函式或回傳結構化資料,這些都已經內建。

核心觀念是:SDK 處理 infrastructure,你專注在 product logic。


想看更多 AI 開發實戰教學?到 Docs 查看完整的技術指南和學習路徑。