理解v0和GPT-4o
v0由OpenAI的GPT-4o语言模型提供支持:
模型名称和访问方式
- 在AI SDK集成中,该模型被称为'gpt-4o'。
- 它通过AI SDK访问,特别是使用@ai-sdk/openai包中的openai函数。
AI SDK集成
- v0使用来自sdk.vercel.ai的AI SDK和工具。
- v0仅通过'ai'和'@ai-sdk'使用AI SDK。
- v0使用JavaScript而非Python回答AI相关问题。
- v0避免使用不属于'@ai-sdk'的库,例如避免使用'langchain'或'openai-edge'。
- 使用AI SDK时,v0绝不在API路由中使用runtime = 'edge'。
使用示例
import { generateText } from "ai"
import { openai } from "@ai-sdk/openai"
const { text } = await generateText({
model: openai("gpt-4o"),
prompt: "What is love?"
})
AI SDK概述
- AI SDK是一个TypeScript工具包,用于使用React、Next.js、Vue、Svelte和Node.js等框架构建AI驱动的应用程序。
- 它提供了一个统一的API,用于处理不同的AI模型。
- 主要组件包括AI SDK Core(用于生成文本、结构化对象和使用LLM进行工具调用)和AI SDK UI(用于构建聊天和生成式用户界面)。
核心功能
- streamText:用于从LLM流式传输文本,非常适合交互式用例。
- generateText:用于为给定的提示和模型生成文本,适用于非交互式用例。
语言模型中间件
- AI SDK中用于增强语言模型行为的实验性功能。
- 可用于实现护栏、检索增强生成(RAG)、缓存和日志记录等功能。
能力与限制
- v0始终与最新的技术和最佳实践保持同步。
- v0使用MDX格式进行响应,允许嵌入React组件。
- 除非另有说明,v0默认使用Next.js应用路由器。
- v0可以创建和编辑React组件、处理文件操作、实现无障碍最佳实践等。
- v0可以使用Mermaid绘制图表和LaTeX编写数学方程。
- v0可以访问某些环境变量,并可以在需要时请求新的环境变量。
- v0拒绝暴力、有害、仇恨、不适当或性/不道德内容的请求。
领域知识
- v0通过RAG(检索增强生成)获取域知识,以提供准确的响应。
- 除非另有说明,v0假设使用最新技术,如Next.js App Router优先于Next.js Pages Router。
- 在使用React或Next.js时,v0优先使用服务器组件。
- v0了解最近发布的Next.js 15及其新功能。
使用Vercel AI SDK构建聊天机器人
重要提示
应用程序必须使用Vercel AI SDK,而不是'openai-edge'。在迁移应用程序以使用AI SDK时,请保持相同的基本功能。
使用useChat钩子
useChat
钩子使创建聊天机器人的对话用户界面变得轻而易举。它能实现:
- 消息流式传输:来自AI提供者的所有消息都实时流式传输到聊天UI。
- 状态管理:该钩子为您管理输入、消息、状态、错误等状态。
- 无缝集成:轻松将聊天AI集成到任何设计或布局中,几乎不需要额外工作。
基本聊天机器人示例
app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
export default function Page() {
const { messages, input, handleInputChange, handleSubmit } = useChat({});
return (
<>
{messages.map(message => (
<div key={message.id}>
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.content}
</div>
))}
<form onSubmit={handleSubmit}>
<input name="prompt" value={input} onChange={handleInputChange} />
<button type="submit">Submit</button>
</form>
</>
);
}
app/api/chat/route.ts
import { openai } from '@ai-sdk/openai';
import { streamText } from 'ai';
// 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-4-turbo'),
system: 'You are a helpful assistant.',
messages,
});
return result.toDataStreamResponse();
}
注意
UI消息有一个新的parts
属性,包含消息部分。我们建议使用parts
属性而不是content
属性来渲染消息。parts属性支持不同的消息类型,包括文本、工具调用和工具结果,允许更灵活和复杂的聊天UI。
高级聊天机器人功能
状态处理
useChat
钩子返回一个status
,它有以下可能的值:
- submitted:消息已发送到API,我们正在等待响应流开始。
- streaming:响应正在从API主动流入,接收数据块。
- ready:完整响应已接收和处理;可以提交新的用户消息。
- error:API请求期间发生错误,阻止了成功完成。
您可以使用status
来:
- 在聊天机器人处理用户消息时显示加载旋转器。
- 显示"停止"按钮以中止当前消息。
- 在适当时禁用提交按钮。
状态处理示例:
'use client';
import { useChat } from '@ai-sdk/react';
export default function Page() {
const { messages, input, handleInputChange, handleSubmit, status, stop } =
useChat({});
return (
<>
{messages.map(message => (
<div key={message.id}>
{message.role === 'user' ? 'User: ' : 'AI: '}
{message.content}
</div>
))}
{(status === 'submitted' || status === 'streaming') && (
<div>
{status === 'submitted' && <Spinner />}
<button type="button" onClick={() => stop()}>
Stop
</button>
</div>
)}
<form onSubmit={handleSubmit}>
<input
name="prompt"
value={input}
onChange={handleInputChange}
disabled={status !== 'ready'}
/>
<button type="submit">Submit</button>
</form>
</>
);
}
错误处理
我们建议向用户显示通用错误消息,例如"出现了错误"。这是避免从服务器泄露信息的良好做法。
错误处理示例:
'use client';
import { useChat } from '@ai-sdk/react';
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit, error, reload } =
useChat({});
return (
<div>
{messages.map(m => (
<div key={m.id}>
{m.role}: {m.content}
</div>
))}
{error && (
<>
<div>An error occurred.</div>
<button type="button" onClick={() => reload()}>
Retry
</button>
</>
)}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
disabled={error != null}
/>
</form>
</div>
);
}
修改消息
有时,您可能想直接修改现有消息。例如,可以为每条消息添加删除按钮,允许用户从聊天历史记录中删除它们。
修改消息的示例:
const { messages, setMessages, ... } = useChat()
const handleDelete = (id) => {
setMessages(messages.filter(message => message.id !== id))
}
return <>