Hexo 看板娘 AI 切到通义千问


前面已经把 Hexo 看板娘接上了 AI 聊天,这篇继续记录一下怎么把 AI 接口从 Cloudflare Workers AI 切到通义千问,用阿里云函数计算做一层中转,让国内访问更稳定一点。

一开始我用的是 Cloudflare Workers AI。

这个方案本身挺方便,Worker 和 AI 能力都在 Cloudflare 里,写起来也比较简单。
但是实际放到国内访问的时候,还是会遇到一个问题:workers.dev 有时候需要科学上网才能稳定访问,看板娘聊天就可能出现接口请求失败。

所以这次换一个更适合国内博客访问的方案:

1
博客前端 -> 阿里云函数计算 -> 通义千问 -> 函数计算 -> 博客前端

为什么选通义千问

这次主要看中几个点。

  1. 国内访问函数计算比较稳定。
  2. 通义千问可以通过百炼 API 调用。
  3. 控制台里能看到免费 Token 额度。
  4. 函数计算可以只做一层很轻的接口转发。
  5. 后面如果想换模型,主要改后端,不需要大改前端。

博客看板娘这种场景,不需要特别大的模型。
用户问一句,看板娘回一句,内容一般也不会特别长。

所以模型可以先选 qwen-plus

它的回复质量够用,速度也还可以。
而且百炼 Token Plan 里可以看到通义千问的免费额度,个人博客先跑起来没什么压力。

开通通义千问

通义千问的 API 调用入口在阿里云百炼里,所以先进入百炼控制台:

1
https://bailian.console.aliyun.com/

如果之前没用过,可以按下面步骤走。

  1. 登录阿里云账号。
  2. 进入 阿里云百炼
  3. 顶部可以看到 模型应用订阅Token Plan体验文档API 参考 这些入口。
  4. 先点 Token Plan
  5. 左侧选择 免费额度
  6. 大语言模型 里找到要用的模型,比如 qwen-plus

这里能看到类似这样的额度:

1
2
qwen-plus
剩 1,000,000 / 共 1,000,000

这个就是当前模型的免费 Token。
不同模型的免费额度一般是分开的,不是所有模型共用一个池子。

旁边还有一个开关,叫 免费额度用完即停
这个建议打开。

打开以后,免费额度用完就会停止,不会继续产生额外 Token 费用。
如果只是个人博客聊天,这个开关开着更安心。

创建 API Key

模型要通过接口调用,就需要一个 API Key。

在百炼控制台里可以这样找:

  1. 进入百炼控制台。
  2. 找到 API Key 管理入口。
  3. 创建一个新的 API Key。
  4. 复制生成的 Key。

这个 Key 只在后端用。

不要写到前端 JS 里。
不要提交到 Git 仓库里。
不要放到公开文章里。

前端如果直接带着 Key 请求模型,别人打开浏览器控制台就能看到。
所以中间必须有一层自己的后端接口。

这次我用的就是阿里云函数计算。

创建函数计算接口

进入阿里云函数计算控制台:

1
https://fcnext.console.aliyun.com/

然后创建一个函数。

我这里的思路是:

  1. 地域选国内,比如 华东1 杭州
  2. 函数名称写成 waifu-ai-chat
  3. 运行环境选择 Node.js。
  4. 创建 HTTP 触发器。
  5. 请求路径用 /api/waifu-chat
  6. 允许 POSTOPTIONS

函数计算在这里不是做复杂业务。
它只负责几件事:

  1. 接收前端发来的聊天内容。
  2. 处理跨域请求。
  3. 从环境变量里读取百炼 API Key。
  4. 调用通义千问模型接口。
  5. 把模型回复整理成 { reply: '...' } 返回给前端。

配置环境变量

函数里不要直接写 API Key。

在函数计算的配置里添加环境变量:

1
2
3
DASHSCOPE_API_KEY=你的百炼 API Key
WAIFU_AI_MODEL=qwen-plus
ALLOWED_ORIGIN=https://www.chensheng.group

其中:

  1. DASHSCOPE_API_KEY 是百炼的 API Key。
  2. WAIFU_AI_MODEL 是当前使用的模型。
  3. ALLOWED_ORIGIN 是允许访问这个接口的博客域名。

本地调试的时候,也可以临时允许:

1
2
http://localhost:4000
http://127.0.0.1:4000

线上还是尽量只放自己的博客域名。

函数里的核心逻辑

通义千问在百炼里提供了 OpenAI 兼容模式接口。
这样写起来比较直观。

请求地址是:

1
https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions

核心请求大概是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const response = await fetch('https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.DASHSCOPE_API_KEY}`
},
body: JSON.stringify({
model: process.env.WAIFU_AI_MODEL || 'qwen-plus',
messages: [
{
role: 'system',
content: '你叫小兰,是陈先生的小前端博客里的看板娘 AI 助手。只用简体中文回答,语气自然、轻松、友好。'
},
...messages
],
temperature: 0.7,
max_tokens: 220
})
});

返回以后,从结果里取出模型回复:

1
2
const data = await response.json();
const reply = data.choices?.[0]?.message?.content || '我收到啦,但刚才没有组织好语言。';

最后返回给前端:

1
2
3
4
5
6
7
8
9
10
11
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Access-Control-Allow-Origin': 'https://www.chensheng.group'
},
body: JSON.stringify({
reply,
model: process.env.WAIFU_AI_MODEL || 'qwen-plus'
})
};

前端只关心 reply 字段。
所以后端不管是 Cloudflare Workers AI,还是通义千问,只要最后返回结构保持一致,前端改动就很小。

处理跨域和预检请求

浏览器从博客页面请求函数计算接口,会遇到跨域。

所以函数里需要处理 OPTIONS 请求。

大概逻辑是:

1
2
3
4
5
6
7
8
9
10
11
12
if (method === 'OPTIONS') {
return {
statusCode: 204,
headers: {
'Access-Control-Allow-Origin': 'https://www.chensheng.group',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Max-Age': '86400'
},
body: ''
};
}

如果不处理这个,前端可能还没真正发出聊天请求,就先被浏览器拦住。

前端切换接口地址

原来前端请求的是 Cloudflare Worker。

这次改成优先请求阿里云函数计算:

1
2
const defaultAiChatEndpoint = 'https://你的函数域名/api/waifu-chat';
const fallbackAiChatEndpoint = 'https://你的-worker.workers.dev/api/waifu-chat';

我这里保留了 Cloudflare Worker 作为备用。

也就是说:

  1. 优先请求阿里云函数计算。
  2. 如果阿里云接口异常,再尝试 Cloudflare Worker。
  3. 如果两个都失败,再给用户一个兜底提示。

这样做的好处是,前端体验更稳一点。
如果某一边临时有问题,不至于完全不能聊。

为什么不直接请求通义千问

前端直接请求通义千问看起来好像更简单。

但不建议这样做。

原因主要有两个。

第一,API Key 会暴露。

只要写在前端 JS 里,用户就能通过浏览器看到。
这个 Key 一旦泄露,别人就能拿去消耗你的额度。

第二,前端不好做访问控制。

如果接口直接暴露在浏览器里,很难限制来源,也不好统一处理错误、限流和提示文案。

所以更稳的结构还是:

1
前端页面 -> 自己的后端接口 -> 模型服务

函数计算刚好可以承担这个轻量后端。

这次踩到的点

这次主要有几个地方要注意。

  1. workers.dev 在国内访问不一定稳定,所以 AI 接口换到国内云更合适。
  2. 百炼 API Key 只能放后端,不能放前端。
  3. 函数计算要处理 OPTIONS,否则跨域预检会失败。
  4. 前端和后端约定一个简单返回结构,比如 { reply: '...' }
  5. 先在浏览器控制台看接口请求,再去百炼和函数计算看用量。

整个流程跑通以后,前端其实不用关心模型来自哪里。

只要自己的接口稳定返回 reply,看板娘就可以继续在原来的气泡里回答问题。

以上就是我把 Hexo 看板娘 AI 切到通义千问的一些整理,如有错误,欢迎大佬指出。

-------------本文结束感谢您的阅读-------------