AI 聊天

通过 Vercel AI SDK 与 AI Elements 流式返回 OpenAI 响应。

AI 聊天是基于 Vercel AI SDK、OpenAI 与 AI Elements 的可运行示例。它流式 传输 UI message,可渲染 Markdown、reasoning、source,支持附件与允许模型选择。 接口当前公开,上线前必须补齐产品访问控制。

请求流程

ChatBot → useChat + DefaultChatTransport → POST /api/chat
        → Zod 解析 → 允许的 OpenAI 模型 → streamText
        → UI message stream → AI Elements 渲染
文件作用
src/components/ai/ChatBot.tsx聊天状态、附件、模型/搜索控制、流式 UI、复制/重试/停止
src/components/ai-elements/*Conversation、message、prompt、reasoning、source 与附件 primitive
src/routes/api/chat.ts请求 schema、model message 转换、system prompt 与 stream response
src/lib/ai/chat-config.ts模型白名单、默认值、search-preview 映射与 system prompt
src/lib/ai/index.ts解析 runtime model 并创建 OpenAI model handle
{-$locale}/_marketing/ai/chat.tsx公开示例页与 SEO

配置

本地加入 key,生产环境保存为 Worker secret:

# .env(仅本地)
OPENAI_API_KEY=sk-your-key

pnpm wrangler secret put OPENAI_API_KEY

本地 secret 变化后重启 pnpm dev。绝不要改成 VITE_* 值。

模型与搜索模式

白名单目前包含默认的 gpt-4o-minigpt-4o。客户端传入未知值时, resolveAiChatModelId() 会回退默认模型,因此仅修改请求不能选择任意模型。

新增模型时更新 aiChatModels 的展示标签与可选 search-preview ID;暴露前检查 能力、附件支持、价格与流式行为。

“Web search”开关没有注册 AI SDK tool。它把所选模型切换到 gpt-4o-mini-search-previewgpt-4o-search-preview,并通过 sendSources 返回该模型产生的 source part。不要把它描述成自定义搜索工具,也 不要假设这里已有 tool policy。

路由启用 sendReasoning: true,并按搜索模式启用 sendSources。只有 provider 真正返回对应 part 时 UI 才会显示,具体取决于模型和响应。

自定义行为

  • 修改 aiChatSystemPrompt 定义产品范围与拒答规则。
  • 修改 PromptInput 的附件类型时,同步增加服务端大小、MIME 与数量限制。
  • 若需要历史记录,在 D1 持久化会话;当前聊天只存在组件 state 中。
  • 通过 streamText 明确增加检索/tool,并为每个 tool 定义授权、超时与输出策略。
  • 产品双语时,本地化当前英文聊天标签。

生产加固

POST /api/chat 当前没有 session 校验、限流、配额、消息大小限制、审核层或用户 成本追踪。上线前应:

  • 要求登录,或明确设计受限的匿名权限;
  • 强制请求/body/附件限制与服务端模型白名单;
  • 增加用户/IP 限流、配额、预算上限与滥用监控;
  • 不返回原始 provider 错误,也不记录含敏感数据的 prompt/文件;
  • 保存会话前定义保留期限与用户同意;
  • 测试断连、取消与超时行为。

Cloudflare Workers 支持流式响应,但 CPU 时间、subrequest 限制、客户端断连与 provider 延迟仍需考虑。同步预处理应保持轻量、尽早开始 stream,并监控长请求。

验证

  • OPENAI_API_KEY 缺失/无效时有可见服务端错误,且不泄露 key。
  • 默认与备选模型可流式返回、停止和重新生成。
  • 未知模型 ID 回退默认值。
  • 只有 search-preview 模型提供 source 时,搜索模式才显示来源。
  • 附件只能在服务端产品策略范围内使用。
  • 加固后会拒绝未登录、超配额与被限流请求。

相关页面

On this page