AI 集成
2026年9月6日
Vercel AI SDK 把模型调用、流式输出、前端 hook 收成一套。Next 的 Route Handler 很适合当聊天后端。
安装
按你用的模型装对应包。DeepSeek 便宜,适合练手;换成 OpenAI 只改 provider。
pnpm add ai @ai-sdk/deepseek @ai-sdk/react
# 或
pnpm add ai @ai-sdk/openai @ai-sdk/react
bash
到模型控制台生成 API Key,放进环境变量,例如 DEEPSEEK_API_KEY,不要写进仓库。
流式接口
app/api/chat/route.ts:
import { NextRequest } from "next/server";
import { convertToModelMessages, streamText } from "ai";
import { createDeepSeek } from "@ai-sdk/deepseek";
const deepseek = createDeepSeek({
apiKey: process.env.DEEPSEEK_API_KEY,
});
export async function POST(req: NextRequest) {
const { messages } = await req.json();
const result = streamText({
model: deepseek("deepseek-chat"),
messages: convertToModelMessages(messages),
system: "你是一名靠谱的工程师,回答简洁、可执行。",
});
return result.toUIMessageStreamResponse();
}
ts
useChat 默认 POST 到 /api/chat,body 里带 messages。SDK 的消息结构和模型 API 不完全一样,所以要 convertToModelMessages。
前端 useChat
"use client";
import { useChat } from "@ai-sdk/react";
import { useState } from "react";
export default function ChatPage() {
const [input, setInput] = useState("");
const { messages, sendMessage } = useChat();
return (
<div>
<ul>
{messages.map((m) => (
<li key={m.id}>
<b>{m.role}</b>
{m.parts.map((part, i) =>
part.type === "text" ? <p key={i}>{part.text}</p> : null
)}
</li>
))}
</ul>
<form
onSubmit={(e) => {
e.preventDefault();
if (!input.trim()) return;
sendMessage({ text: input });
setInput("");
}}
>
<textarea
value={input}
onChange={(e) => setInput(e.target.value)}
/>
<button type="submit">发送</button>
</form>
</div>
);
}
tsx
一条消息大致是:id、role(user / assistant)、parts 数组。文本在 type === "text" 的 part 里。流式过程中 assistant 的文本会一点点变长,直接按 messages 渲染即可。
回车发送、Shift+Enter 换行,在 onKeyDown 里判断即可。长对话记得把滚动容器钉在底部。
注意
- Key 只放服务端,Route Handler 里读
process.env - 生产要做鉴权、限流,否则接口会被刷
- 换模型:换 provider 包和
model(...)那一行,前端 hook 不用动
下一篇是 Next 16 的 Proxy(以前叫 Middleware)。