在构建 AI Chat 应用时,我们通常使用 useChat hook 来快速实现对话功能。默认情况下,它会向 /api/chat 发送标准的 HTTP POST 请求。
但在实际的企业级开发中,我们往往面临更复杂的需求:
- 鉴权 (Authentication) :需要在请求头中携带动态的 Token。
- 自定义后端 (Custom Backend) :API 路径不是
/api/chat,或者需要透传额外的上下文信息(如 Session ID、用户偏好)。 - 非 HTTP 协议:需要通过 WebSocket 通信,或者在服务端/本地环境中直接调用 Agent(无需网络请求)。
Vercel AI SDK 的 Transport(传输层) 系统正是为了解决这些问题而设计的。它允许你完全控制消息的发送方式和响应的处理逻辑。
本文将带你深入了解如何配置和自定义 Transport。
1. 默认行为 (Default Transport)
首先,回顾一下最基础的用法。当你仅仅调用 useChat() 时,SDK 内部会自动创建一个 DefaultChatTransport 实例。
TypeScript
import { useChat } from '@ai-sdk/react';
// 默认行为:向 /api/chat 发送 HTTP POST 请求
const { messages, sendMessage } = useChat();
这实际上等同于显式配置了默认传输层:
TypeScript
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai'; // 注意这里是从 'ai' 核心库导入
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
}),
});
2. 自定义请求配置 (Custom Configuration)
最常见的需求是修改 API 地址或添加静态请求头。
修改 API 路径与添加静态 Header
TypeScript
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
// 指向自定义的后端路由
api: '/api/v1/custom-chat',
// 添加静态请求头
headers: {
'Authorization': 'Bearer my-static-token',
'X-App-Version': '1.0.0',
},
// 配置 fetch 的 credentials 选项(如需要发送 Cookie)
credentials: 'include',
}),
});
3. 动态配置 (Dynamic Configuration)
在现代 Web 应用中,Token 往往是动态变化的,或者我们需要根据当前用户的状态传递不同的参数。DefaultChatTransport 允许你传入函数来动态生成配置。
这对于处理 JWT Token 刷新或传递实时上下文非常有用。
TypeScript
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
// 动态生成 Headers
headers: () => ({
'Authorization': `Bearer ${localStorage.getItem('token')}`, // 每次请求都会获取最新的 Token
'X-Team-ID': getCurrentTeamId(),
}),
// 动态生成 Body 里的额外字段
body: () => ({
theme: 'dark',
userLocation: 'CN',
timestamp: Date.now(),
}),
}),
});
4. 请求转换 (Request Transformation)
有时候,我们需要在请求发送前的最后一刻修改请求体(Body),例如为了节省 Token,只发送最近的 10 条消息,或者添加特定的追踪 ID。
这时可以使用 prepareSendMessagesRequest 回调。
TypeScript
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({
api: '/api/chat',
// 在发送前拦截并修改请求
prepareSendMessagesRequest: ({ id, messages, trigger, messageId }) => {
return {
headers: {
'X-Conversation-ID': id,
},
body: {
// 只发送最近的 10 条消息,避免上下文超长
messages: messages.slice(-10),
// 透传触发源
trigger,
// 当前消息 ID
messageId,
},
};
},
}),
});
5. 服务端/本地 Agent 直连 (Direct Agent Transport)
这是 Vercel AI SDK 一个非常强大的功能。如果你是在 服务端渲染 (SSR) 、测试环境,或者是开发 Electron/Tauri 这种本地应用,你可能并不希望发起一个 HTTP 网络请求,而是希望直接调用本地的 Agent 逻辑。
DirectChatTransport 允许 UI 直接与 Agent 通信,跳过 HTTP 层。
注意:这通常用于服务端组件或本地环境,因为如果在纯客户端使用,你需要确保 Agent 的逻辑(包括 API Key)是安全的或在服务端上下文中执行。
TypeScript
import { useChat } from '@ai-sdk/react';
import { DirectChatTransport, ToolLoopAgent } from 'ai';
// 假设你已经定义了一些工具
import { weatherTool } from './tools';
// 1. 初始化 Agent
const agent = new ToolLoopAgent({
model: 'anthropic/claude-sonnet-4.5', // 你可以替换为任何兼容的模型
instructions: '你是一个乐于助人的助手。',
tools: {
weather: weatherTool,
},
});
// 2. 在 useChat 中使用直连传输层
const { messages, sendMessage } = useChat({
transport: new DirectChatTransport({
agent,
// 可选:配置是否向客户端发送推理过程或来源
sendReasoning: true,
sendSources: true
}),
});
工作原理
DirectChatTransport接收 UI 消息。- 使用
convertToModelMessages将其转换为模型可理解的格式。 - 直接调用 Agent 的
stream()方法(在同一进程内)。 - 通过
toUIMessageStream()将结果流式传回给 UI。
总结
Vercel AI SDK 的 Transport 设计采用了极具扩展性的策略:
- 简单的 HTTP 请求:使用默认配置即可。
- 复杂的鉴权/上下文:使用
headers和body的动态函数配置。 - 精细的控制:使用
prepareSendMessagesRequest裁剪或转换数据。 - 非 HTTP 环境:使用
DirectChatTransport实现进程内直连。
掌握这些配置,你就可以轻松应对各种复杂的企业级集成场景,无论是对接私有网关还是构建本地 AI 应用。