vercel-ai-sdk
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVercel AI SDK
Vercel AI SDK
The Vercel AI SDK provides React hooks and server utilities for building streaming chat interfaces with support for tool calls, file attachments, and multi-step reasoning.
Vercel AI SDK 提供React钩子和服务器工具,用于构建支持工具调用、文件附件和多步推理的流式聊天界面。
Quick Reference
快速参考
Basic useChat Setup
基础useChat设置
typescript
import { useChat } from '@ai-sdk/react';
const { messages, status, sendMessage, stop, regenerate } = useChat({
id: 'chat-id',
messages: initialMessages,
onFinish: ({ message, messages, isAbort, isError }) => {
console.log('Chat finished');
},
onError: (error) => {
console.error('Chat error:', error);
}
});
// Send a message
sendMessage({ text: 'Hello', metadata: { createdAt: Date.now() } });
// Send with files
sendMessage({
text: 'Analyze this',
files: fileList // FileList or FileUIPart[]
});typescript
import { useChat } from '@ai-sdk/react';
const { messages, status, sendMessage, stop, regenerate } = useChat({
id: 'chat-id',
messages: initialMessages,
onFinish: ({ message, messages, isAbort, isError }) => {
console.log('Chat finished');
},
onError: (error) => {
console.error('Chat error:', error);
}
});
// Send a message
sendMessage({ text: 'Hello', metadata: { createdAt: Date.now() } });
// Send with files
sendMessage({
text: 'Analyze this',
files: fileList // FileList or FileUIPart[]
});ChatStatus States
ChatStatus状态
The field indicates the current state of the chat:
status- : Chat is idle and ready to accept new messages
ready - : Message sent to API, awaiting response stream start
submitted - : Response actively streaming from the API
streaming - : An error occurred during the request
error
status- :聊天处于空闲状态,可接受新消息
ready - :消息已发送至API,等待响应流开始
submitted - :响应正从API流式传输中
streaming - :请求过程中发生错误
error
Message Structure
消息结构
Messages use the type with a parts-based structure:
UIMessagetypescript
interface UIMessage {
id: string;
role: 'system' | 'user' | 'assistant';
metadata?: unknown;
parts: Array<UIMessagePart>; // text, file, tool-*, reasoning, etc.
}Part types include:
- : Text content with optional streaming state
text - : File attachments (images, documents)
file - : Tool invocations with state machine
tool-{toolName} - : AI reasoning traces
reasoning - : Custom data parts
data-{typeName}
消息采用类型,基于部件的结构:
UIMessagetypescript
interface UIMessage {
id: string;
role: 'system' | 'user' | 'assistant';
metadata?: unknown;
parts: Array<UIMessagePart>; // text, file, tool-*, reasoning, etc.
}部件类型包括:
- :带可选流式状态的文本内容
text - :文件附件(图片、文档)
file - :带状态机的工具调用
tool-{toolName} - :AI推理轨迹
reasoning - :自定义数据部件
data-{typeName}
Server-Side Streaming
服务器端流式传输
typescript
import { streamText } from 'ai';
import { convertToModelMessages } from 'ai';
const result = streamText({
model: openai('gpt-4'),
messages: convertToModelMessages(uiMessages),
tools: {
getWeather: tool({
description: 'Get weather',
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => {
return { temperature: 72, weather: 'sunny' };
}
})
}
});
return result.toUIMessageStreamResponse({
originalMessages: uiMessages,
onFinish: ({ messages }) => {
// Save to database
}
});typescript
import { streamText } from 'ai';
import { convertToModelMessages } from 'ai';
const result = streamText({
model: openai('gpt-4'),
messages: convertToModelMessages(uiMessages),
tools: {
getWeather: tool({
description: 'Get weather',
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => {
return { temperature: 72, weather: 'sunny' };
}
})
}
});
return result.toUIMessageStreamResponse({
originalMessages: uiMessages,
onFinish: ({ messages }) => {
// Save to database
}
});Tool Handling Patterns
工具处理模式
Client-Side Tool Execution:
typescript
const { addToolOutput } = useChat({
onToolCall: async ({ toolCall }) => {
if (toolCall.toolName === 'getLocation') {
addToolOutput({
tool: 'getLocation',
toolCallId: toolCall.toolCallId,
output: 'San Francisco'
});
}
}
});Rendering Tool States:
typescript
{message.parts.map(part => {
if (part.type === 'tool-getWeather') {
switch (part.state) {
case 'input-streaming':
return <pre>{JSON.stringify(part.input, null, 2)}</pre>;
case 'input-available':
return <div>Getting weather for {part.input.city}...</div>;
case 'output-available':
return <div>Weather: {part.output.weather}</div>;
case 'output-error':
return <div>Error: {part.errorText}</div>;
}
}
})}客户端工具执行:
typescript
const { addToolOutput } = useChat({
onToolCall: async ({ toolCall }) => {
if (toolCall.toolName === 'getLocation') {
addToolOutput({
tool: 'getLocation',
toolCallId: toolCall.toolCallId,
output: 'San Francisco'
});
}
}
});渲染工具状态:
typescript
{message.parts.map(part => {
if (part.type === 'tool-getWeather') {
switch (part.state) {
case 'input-streaming':
return <pre>{JSON.stringify(part.input, null, 2)}</pre>;
case 'input-available':
return <div>Getting weather for {part.input.city}...</div>;
case 'output-available':
return <div>Weather: {part.output.weather}</div>;
case 'output-error':
return <div>Error: {part.errorText}</div>;
}
}
})}Reference Files
参考文档
Detailed documentation on specific aspects:
- use-chat.md: Complete useChat API reference
- messages.md: UIMessage structure and part types
- streaming.md: Server-side streaming implementation
- tools.md: Tool definition and execution patterns
各特定方面的详细文档:
- use-chat.md:完整的useChat API参考
- messages.md:UIMessage结构和部件类型
- streaming.md:服务器端流式传输实现
- tools.md:工具定义和执行模式
Common Patterns
常见模式
Error Handling
错误处理
typescript
const { error, clearError } = useChat({
onError: (error) => {
toast.error(error.message);
}
});
// Clear error and reset to ready state
if (error) {
clearError();
}typescript
const { error, clearError } = useChat({
onError: (error) => {
toast.error(error.message);
}
});
// Clear error and reset to ready state
if (error) {
clearError();
}Message Regeneration
消息重新生成
typescript
const { regenerate } = useChat();
// Regenerate last assistant message
await regenerate();
// Regenerate specific message
await regenerate({ messageId: 'msg-123' });typescript
const { regenerate } = useChat();
// Regenerate last assistant message
await regenerate();
// Regenerate specific message
await regenerate({ messageId: 'msg-123' });Custom Transport
自定义传输
typescript
import { DefaultChatTransport } from 'ai';
const { messages } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
prepareSendMessagesRequest: ({ id, messages, trigger, messageId }) => ({
body: {
chatId: id,
lastMessage: messages[messages.length - 1],
trigger,
messageId
}
})
})
});typescript
import { DefaultChatTransport } from 'ai';
const { messages } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
prepareSendMessagesRequest: ({ id, messages, trigger, messageId }) => ({
body: {
chatId: id,
lastMessage: messages[messages.length - 1],
trigger,
messageId
}
})
})
});Performance Optimization
性能优化
typescript
// Throttle UI updates to reduce re-renders
const chat = useChat({
experimental_throttle: 100 // Update max once per 100ms
});typescript
// Throttle UI updates to reduce re-renders
const chat = useChat({
experimental_throttle: 100 // Update max once per 100ms
});Automatic Message Sending
自动消息发送
typescript
import { lastAssistantMessageIsCompleteWithToolCalls } from 'ai';
const chat = useChat({
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls
// Automatically resend when all tool calls have outputs
});typescript
import { lastAssistantMessageIsCompleteWithToolCalls } from 'ai';
const chat = useChat({
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls
// Automatically resend when all tool calls have outputs
});Type Safety
类型安全
The SDK provides full type inference for tools and messages:
typescript
import { InferUITools, UIMessage } from 'ai';
const tools = {
getWeather: tool({
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({ weather: 'sunny' })
})
};
type MyMessage = UIMessage<
{ createdAt: number }, // Metadata type
UIDataTypes,
InferUITools<typeof tools> // Tool types
>;
const { messages } = useChat<MyMessage>();SDK为工具和消息提供完整的类型推断:
typescript
import { InferUITools, UIMessage } from 'ai';
const tools = {
getWeather: tool({
inputSchema: z.object({ city: z.string() }),
execute: async ({ city }) => ({ weather: 'sunny' })
})
};
type MyMessage = UIMessage<
{ createdAt: number }, // Metadata type
UIDataTypes,
InferUITools<typeof tools> // Tool types
>;
const { messages } = useChat<MyMessage>();Key Concepts
核心概念
Parts-Based Architecture
基于部件的架构
Messages use a parts array instead of a single content field. This allows:
- Streaming text while maintaining other parts
- Tool calls with independent state machines
- File attachments and custom data mixed with text
消息使用部件数组而非单一内容字段。这支持:
- 在流式传输文本的同时保留其他部件
- 带独立状态机的工具调用
- 文件附件和自定义数据与文本混合
Tool State Machine
工具状态机
Tool parts progress through states:
- : Tool input streaming (optional)
input-streaming - : Tool input complete
input-available - : Waiting for user approval (optional)
approval-requested - : User approved/denied (optional)
approval-responded - : Tool execution complete
output-available - : Tool execution failed
output-error - : User denied approval
output-denied
工具部件会经历以下状态:
- :工具输入流式传输(可选)
input-streaming - :工具输入完成
input-available - :等待用户批准(可选)
approval-requested - :用户已批准/拒绝(可选)
approval-responded - :工具执行完成
output-available - :工具执行失败
output-error - :用户拒绝批准
output-denied
Streaming Protocol
流式传输协议
The SDK uses Server-Sent Events (SSE) with UIMessageChunk types:
- ,
text-start,text-deltatext-end - ,
tool-input-availabletool-output-available - ,
reasoning-start,reasoning-deltareasoning-end - ,
start,finishabort
SDK使用Server-Sent Events (SSE)和UIMessageChunk类型:
- ,
text-start,text-deltatext-end - ,
tool-input-availabletool-output-available - ,
reasoning-start,reasoning-deltareasoning-end - ,
start,finishabort
Client vs Server Tools
客户端与服务器端工具
Server-side tools have an function and run on the API route.
executeClient-side tools omit and are handled via and .
executeonToolCalladdToolOutput服务器端工具包含函数,在API路由上运行。
execute客户端工具省略函数,通过和处理。
executeonToolCalladdToolOutputBest Practices
最佳实践
- Always handle the state and provide user feedback
error - Use for high-frequency updates
experimental_throttle - Implement proper loading states based on
status - Type your messages with custom metadata and tools
- Use for multi-turn tool workflows
sendAutomaticallyWhen - Handle all tool states in the UI for better UX
- Use to allow users to cancel long-running requests
stop() - Validate messages with on the server
validateUIMessages
- 始终处理状态并向用户提供反馈
error - 对于高频更新,使用
experimental_throttle - 根据实现合适的加载状态
status - 为消息添加自定义元数据和工具的类型定义
- 对于多轮工具工作流,使用
sendAutomaticallyWhen - 在UI中处理所有工具状态以提升用户体验
- 使用允许用户取消长时间运行的请求
stop() - 在服务器端使用验证消息
validateUIMessages