用 Vercel AI Gateway 给博客做一个 AI 摘要服务
其实我对 AI 总结功能的有无一直是无所谓的态度,但既然可以免费做一个,那就顺手实现一下。我之前一直使用 Mabbs 大佬的 AI 摘要项目,不过项目部署在 Cloudflare 上,花了一下午才部署完成。后续因为 Cloudflare 在国内无法正常访问,加上我没有在 CF 托管域名,只能额外搭建 Vercel 反代,才正常实现 AI 摘要能力。
折腾数日得出结论:这套方案完全可行。最终技术选型为 Vercel Functions + AI Gateway + Neon Postgres,项目已开源。本文作为项目实践分享。
最终架构
请求链路较为简洁:
text
Astro 博客
│
│ POST /api/summary
▼
Vercel Function
├── Neon Postgres:查询或保存摘要缓存
└── AI Gateway:调用 Qwen 生成摘要
博客端仅提交文章 ID 和正文,缓存判断、模型调用、异常处理全部交由服务端实现。具备这些优势:
- 前端不存放任何模型密钥
- 更换模型无需修改博客代码
- 文章内容无变动直接返回缓存,节约调用成本
- 文章更新后自动重新生成摘要
- 模型调用量与开销可在 Vercel 平台统一查看
为什么选择 AI Gateway
Vercel AI Gateway 相当于统一模型调度入口,搭配 AI SDK,仅通过 provider/model 格式名称即可切换不同大模型服务商。项目默认使用:
text
alibaba/qwen3.7-flash
该模型调用成本低廉,足够满足博客摘要生成需求。后续如需更换模型,仅修改 AI_MODEL 环境变量,无需改动业务请求逻辑。
鉴权依托 Vercel OIDC Token,部署时自动注入、自动轮换,代码仓库无需存放 AI_GATEWAY_API_KEY :
ts
import { gateway, generateText } from 'ai'
const result = await generateText({
model: gateway('alibaba/qwen3.7-flash'),
instructions: SYSTEM_PROMPT,
prompt: articleContent,
maxOutputTokens: 600,
temperature: 0.2,
})
使用 Neon 实现缓存机制
如果每次打开文章都发起模型调用,响应缓慢且持续消耗额度。服务端会基于三类数据计算 SHA-256 哈希:
- 提示词版本
- 当前使用模型
- 文章正文
ts
const contentHash = createHash('sha256')
.update(${PROMPT_VERSION}\0${model}\0${content})
.digest('hex')
当数据库存在相同 id 与 content_hash 记录,则直接返回已有摘要;不存在则生成新摘要并执行更新写入。缓存不单纯依靠文章 ID 判定:正文、模型、提示词任意一项发生变更,哈希值随之改变,自动触发重新生成,避免长期展示过时摘要。
同时持久化存储每次生成的 Token 消耗、模型名称、提示词版本、耗时、生成时间,方便成本统计对账。
Neon 通过 Vercel Marketplace 一键接入,部署完成自动生成可用 DATABASE_URL 。数据库与 Function 均部署新加坡节点,减少跨区域网络延迟。
API 设计
提供两组接口:
读取缓存(不发起AI调用):
http
GET /api/summary?id=/posts/example
生成/更新摘要:
http
POST /api/summary
Content-Type: application/json
{
"id": "/posts/example",
"content": "文章正文"
}
POST 请求并非一定会调用大模型,服务端优先计算哈希,命中缓存直接返回结果。博客端只需持续传入最新文章正文即可。
成功返回示例:
json
{
"code": 1,
"message": "生成文章摘要成功",
"data": "这里是生成的摘要",
"isSave": true,
"model": "alibaba/qwen3.7-flash"
}
博客端接入方式
原先 Cloudflare 方案需要依次执行哈希校验、内容上传、缓存查询、流式读取。切换新架构后,单次 POST 请求即可完成:
js
const response = await fetch('API地址/api/summary', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
id: slug,
content: 标题: ${title}\n\n${body},
}),
signal: controller.signal,
})
const result = await response.json()
outputEl.textContent = result.data
服务端预先配置 CORS,支持跨域名调用。客户端设置 65 秒请求超时,异常场景优先展示服务端返回错误信息。
文章是否展示 AI 摘要,由文章 frontmatter 配置 aiSummary: true 控制;未开启的文章不会发起网络请求。
费用防护
Vercel AI Gateway 免费额度为每个团队每月 5 美元,需要绑定有效银行卡解锁额度,绑卡不会自动扣费,务必关闭自动充值功能。
线上项目设置月度硬性预算上限 4 美元,预留 1 美元缓冲空间:
bash
vercel ai-gateway budgets set project vercel-cf-summary
--limit 4
--refresh-period monthly
预算触达上限后,Gateway 拦截新增付费调用,但数据库内已缓存的摘要仍然可以正常读取。
安全设计
- 仓库不存储任何敏感凭证,线上依托 OIDC 临时令牌调用模型
- 系统提示词增加防护规则,要求模型忽略正文内注入攻击指令,抵御提示词劫持
- 通过 ALLOWED_ORIGIN 限制允许调用接口的域名来源
- 单篇文章正文最大限制 60000 字符
- 根路由仅返回只读 JSON 健康检测信息,不开放调试表单
补充说明:本项目定位为开源演示项目,未实现账号登录、独立用户限流。预算管控仅用于防止超额消费,无法替代完整防滥用策略。如果作为正式对外服务,需要额外增加身份认证与接口限流逻辑。
最后
对比来看,原先 Cloudflare Workers AI + D1 的整套方案,在 Vercel 生态中可以找到完整对等实现:
Cloudflare 方案 Vercel 方案
Workers Vercel Functions
Workers AI AI Gateway
D1 Neon Postgres
对比之前 Cloudflare 方案繁琐的部署流程,Vercel 整套方案上手门槛更低:AI SDK 开发体验友好,OIDC 机制省去密钥维护,切换模型、调整提示词都十分便捷,后续迭代无需改动博客侧代码。
如果你也打算为博客增加 AI 摘要功能,可以 Fork 项目,参照文档完成部署。