Workers AI

一、前言

Cloudflare 在今年的九月份推出了 Workers AI,Cloudflare 全局网络的无服务器 GPU 驱动推理。

最近几天使用 Cloudflare Workers AI 的 API 写了个具有多种 AI 模型的网站项目:workers-ai,演示网站:https://ai.barku.re

二、功能

  • 文本生成(@cf/meta/llama-2-7b-chat-int8
  • 文本翻译(@cf/meta/m2m100-1.2b
  • 图像分类(@cf/microsoft/resnet-50
  • 文本生图(@cf/stabilityai/stable-diffusion-xl-base-1.0

三、截图展示

四、技术细节

由于个人技术力低下,实现过程中还是遇到了不少问题,此处加以说明:

  1. 问题一

此处以 Cloudflare 提供的 Text Generation 模型 @cf/meta/llama-2-7b-chat-int8 为例,下面是其文档中使用 Python 请求 API 的一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import requests

API_BASE_URL = "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai/run/"
headers = {"Authorization": "Bearer {API_TOKEN}"}

def run(model, prompt):
input = {
"messages": [
{ "role": "system", "content": "You are a friendly assistant" },
{ "role": "user", "content": prompt }
]
}
response = requests.post(f"{API_BASE_URL}{model}", headers=headers, json=input)
return response.json()

output = run("@cf/meta/llama-2-7b-chat-int8", "Tell me a story")
print(output)

代码很好理解,值得注意的是,在请求头中有一个 Authorization 授权,其中包含 {API_TOKEN}

这个 TOKEN 放在前端是不合适的,此处对 Cloudflare Workers AI 的 API 进行反代解决此问题。下面是一个可能的 Nginx 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
add_header 'Access-Control-Allow-Headers' 'Origin,X-Requested-With,Content-Type,Accept,Authorization,token' always;
add_header 'Access-Control-Allow-Origin' 'https://ai.barku.re';
# 修改为你的前端网站地址
if ($request_method = 'OPTIONS') {
return 204;
}

location / {
proxy_pass https://api.cloudflare.com/client/v4/accounts/abcdef/ai/run/;
# 请替换 abcdef 为你的 ACCOUNT_ID
proxy_set_header Host $proxy_host; #
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Authorization 'Bearer 123456';
# 请替换 123456 为你的 Token
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
  1. 问题二

Vercel 支持部署 React 项目,但是如果还要自己反代 API 就有点麻烦了,实属不够优雅。

在一番搜寻后,发现 Vercel 的 Serverless Functions 支持运行代码,它支持 Node.js、Python、Go、Ruby 等运行。

使用方法也很简单,在项目的根目录新建文件夹 api/,在这个文件夹里编写函数就可以了。此处以本项目中的 api\proxy.js 为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const axios = require('axios');

module.exports = async (req, res) => {
try {
const path = req.url.replace('/api/proxy', '');

const response = await axios({
url: `https://api.cloudflare.com/client/v4/accounts/{% mathjax %}{process.env.REACT_APP_ACCOUNT_ID}/ai/run{% endmathjax %}{path}`,
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.REACT_APP_API_TOKEN}`,
},
data: req.body,
timeout: 30000,
});

res.status(200).json(response.data);
} catch (error) {
res.status(500).json({ error: 'Error fetching data' });
}
};

此函数实现了对 Cloudflare Workers AI API 的反代。

然后应该将请求的 baseURL 修改为 /api/proxy/。这样用户在 Vercel Deploy 本项目时,添加下面的环境变量即可:

1
2
REACT_APP_ACCOUNT_ID='abcdef'
REACT_APP_API_TOKEN='123456'

此时部署项目,会发现仍无法使用,原因在于 API 请求被路由到了 React 应用,我们需要在 项目根目录新建 vercel.json,内容如下:

1
2
3
4
5
6
7
8
{
"routes": [
{
"src": "/api/proxy/(.*)",
"dest": "/api/proxy.js"
}
]
}

这会将 API 请求路由到 api\proxy.js

  1. 问题三

在使用 Vercel 部署的网站时,会发现文本生图功能不能使用,原因如下:

Cloudflare 对画图模型(@cf/stabilityai/stable-diffusion-xl-base-1.0)的请求返回响应需要二十至三十秒左右,但 Vercel 对单个请求的时长有限制(10s),因此画图基本上不可用。

此问题暂时无解,如需画图,请自行反代 API。

dark
sans