在 AI 应用开发中,除了常见的对话机器人(Chatbot),我们经常需要一种“单轮文本生成”的场景,比如:智能代码补全、邮件草稿生成、文章润色或自动摘要。
Vercel AI SDK 提供的 useCompletion 也就是为此而生。它比 useChat 更轻量,专注于处理单次的 Prompt-to-Text 流式响应。
本文将带你从零实现一个基于 Next.js 的流式文本补全应用,并包含错误处理、加载状态以及国内模型适配等实战技巧。
🛠️ 环境准备
首先,确保你安装了最新的 AI SDK 核心库和 React 集成库:
Bash
npm install ai @ai-sdk/react zod
注:Vercel AI SDK 目前已升级至 3.x/4.x+ 版本,请确保你的 ai 包版本是最新的。
💻 第一步:构建后端 API (Route Handler)
我们需要创建一个 API 路由来处理前端的请求,并调用大模型进行流式输出。
新建文件:app/api/completion/route.ts
TypeScript
import { streamText } from 'ai';
import { createOpenAI } from '@ai-sdk/openai';
// 1. 配置模型提供商
// 💡 小贴士:如果你使用国内模型(如 DeepSeek、通义千问等),
// 可以通过 baseURL 和 apiKey 进行配置兼容 OpenAI 协议的接口。
const openai = createOpenAI({
// 若使用国内中转或本地模型,在此替换 baseURL
// baseURL: 'https://api.deepseek.com/v1',
apiKey: process.env.OPENAI_API_KEY,
});
// 允许流式响应最长持续 30 秒
export const maxDuration = 30;
export async function POST(req: Request) {
// 从请求体中解析 prompt
const { prompt }: { prompt: string } = await req.json();
// 2. 调用模型
const result = streamText({
model: openai('gpt-4o-mini'), // 或使用 'deepseek-chat' 等
prompt: prompt,
// 可选:设置系统提示词,规范输出风格
system: '你是一个专业的助手,请以简洁、专业的风格通过 Markdown 格式回答用户的问题。',
});
// 3. 返回流式响应
return result.toDataStreamResponse();
}
关键点解析:
streamText: 核心函数,用于生成流式文本。toDataStreamResponse(): 将流转换为前端useCompletion能识别的格式。
🎨 第二步:构建前端 UI (Client Component)
在前端,我们使用 useCompletion hook 来管理输入状态、提交请求和渲染流式结果。
新建或修改页面:app/page.tsx
TypeScript
'use client';
import { useCompletion } from '@ai-sdk/react';
export default function CompletionPage() {
// 解构 useCompletion 提供的核心对象和方法
const {
completion, // 当前生成的补全结果(实时更新)
input, // 输入框的当前值
handleInputChange,// 绑定到 input onChange 的处理函数
handleSubmit, // 绑定到 form onSubmit 的处理函数
isLoading, // 是否正在生成中
stop, // 用于停止生成的函数
error // 错误对象(如有)
} = useCompletion({
api: '/api/completion', // 指定后端接口地址
// 可选:错误回调
onError: (err) => {
console.error('生成出错:', err);
alert('生成失败,请稍后重试');
},
// 可选:完成回调
onFinish: (prompt, completion) => {
console.log('生成完成:', completion);
}
});
return (
<div className="max-w-2xl mx-auto p-4 py-10">
<h1 className="text-2xl font-bold mb-4">AI 文本补全助手</h1>
<form onSubmit={handleSubmit} className="space-y-4">
{/* 输入区域 */}
<div>
<label className="block text-sm font-medium mb-1">请输入提示词:</label>
<textarea
className="w-full p-3 border rounded-lg focus:ring-2 focus:ring-blue-500 min-h-[100px] text-black"
value={input}
onChange={handleInputChange}
placeholder="例如:帮我写一封请假邮件..."
disabled={isLoading}
/>
</div>
{/* 按钮区域 */}
<div className="flex gap-2">
<button
type="submit"
disabled={isLoading || !input.trim()}
className="bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 disabled:opacity-50"
>
{isLoading ? '生成中...' : '开始生成'}
</button>
{isLoading && (
<button
type="button"
onClick={stop}
className="bg-red-500 text-white px-4 py-2 rounded-md hover:bg-red-600"
>
停止生成
</button>
)}
</div>
</form>
{/* 错误提示 */}
{error && (
<div className="mt-4 p-3 bg-red-100 text-red-700 rounded-md">
出错了:{error.message}
</div>
)}
{/* 结果展示区域 */}
{(completion || isLoading) && (
<div className="mt-8 border-t pt-6">
<h2 className="text-lg font-semibold mb-2">生成结果:</h2>
<div className="prose bg-gray-50 p-6 rounded-lg whitespace-pre-wrap text-gray-800">
{completion}
</div>
</div>
)}
</div>
);
}
⚙️ 进阶配置:传递自定义参数
很多时候,我们需要传额外的参数给后端(比如用户选择的 tone 或 creative level)。可以通过 body 选项实现。
前端修改
TypeScript
const { handleSubmit } = useCompletion({
api: '/api/completion',
// 在这里添加额外的请求体
body: {
userId: 'user_123',
tone: 'professional' // 用户选择的语气
}
});
后端修改 (app/api/completion/route.ts)
TypeScript
export async function POST(req: Request) {
// 解析额外的 body 参数
const { prompt, tone }: { prompt: string, tone: string } = await req.json();
const result = streamText({
model: openai('gpt-4o-mini'),
// 将参数整合进 prompt 或 system message
system: `你是一个助手,请用 ${tone || 'neutral'} 的语气回答。`,
prompt: prompt,
});
return result.toDataStreamResponse();
}
🌟 总结
useCompletion 是构建非对话式 AI 应用的利器。相比于 useChat,它不需要维护复杂的 messages 数组,非常适合**“输入->输出”**的直观场景。
核心要点回顾:
- 后端:使用
streamText处理流,配合toDataStreamResponse返回。 - 前端:使用
useCompletion一键获取input、completion和isLoading状态。 - 兼容性:通过
createOpenAI的baseURL配置,可以轻松接入 DeepSeek、通义千问等国内优质模型。
希望这篇教程能帮你在 Next.js 项目中快速落地 AI 功能!如果有问题,欢迎在评论区交流。 👇