在本教程中,你将使用 OpenAI ↗ API 和 Cloudflare R2 创建微调模型 ↗。
OpenAI API 中的这一功能允许你基于一组自定义指令和示例回答,从 OpenAI 的各种大语言模型中派生出定制模型。这些指令和示例回答写在一个文档中,称为微调文档(fine-tune document)。该文档将存储在 R2 中,并在创建新的微调模型时动态提供给 OpenAI 的 API。
要使用此功能,你需要完成以下任务:
- 将微调文档上传到 R2。
- 读取 R2 文件并上传到 OpenAI。
- 基于该文档创建新的微调模型。
要查看本应用的完整代码,请参阅本教程的 GitHub 仓库 ↗。
开始之前,请确保你已具备:
- 拥有 R2 访问权限的 Cloudflare 账户。若尚未注册 Cloudflare 账户,请先注册 ↗,然后在 Cloudflare 仪表板中购买 R2。
- OpenAI API 密钥。
- 一份按 JSON Lines ↗ 格式组织的微调文档。可使用源码中的示例文档 ↗。
首先,使用 c3 CLI 创建新的 Cloudflare Workers 项目。
npm create cloudflare@latest -- finetune-chatgpt-modelyarn create cloudflare finetune-chatgpt-modelpnpm create cloudflare@latest finetune-chatgpt-model进行设置时,请选择以下选项:
- 对于 What would you like to start with?,选择
Hello World example。 - 对于 Which template would you like to use?,选择
Worker only。 - 对于 Which language do you want to use?,选择
TypeScript。 - 对于 Do you want to use git for version control?,选择
Yes。 - 对于 Do you want to deploy your application?,选择
No(部署前我们还会做一些修改)。
上述选项将创建 "Hello World" TypeScript 项目。
进入新创建的目录:
cd finetune-chatgpt-model接下来,将微调文档上传到 R2。R2 是一种键值存储,允许你在 Workers 应用中存储和检索文件。你将使用 Wrangler 创建新的 R2 存储桶。
要创建新的 R2 存储桶,请使用 wrangler r2 bucket create 命令。请确保你已登录 Cloudflare 账户。若尚未通过 Wrangler 登录,请使用 wrangler login 命令。
npx wrangler r2 bucket create <BUCKET_NAME>将 <BUCKET_NAME> 替换为你想要的存储桶名称。存储桶名称必须为小写,且只能包含连字符。
接下来,使用 wrangler r2 object put 命令上传文件。
npx wrangler r2 object put <PATH> -f <FILE_NAME><PATH> 是要上传文件的存储桶与文件路径组合——例如 fine-tune-ai/finetune.jsonl,其中 fine-tune-ai 是存储桶名称。将 <FILE_NAME> 替换为微调文档的本地文件名。
绑定(binding)是 Worker 与 R2 存储桶等外部资源交互的方式。
要将 R2 存储桶绑定到 Worker,请在 Wrangler 配置文件中添加以下内容。将 binding 属性更新为有效的 JavaScript 变量标识符。将 <YOUR_BUCKET_NAME> 替换为你在第 2 步中创建的存储桶名称:
{
"r2_buckets": [
{
"binding": "MY_BUCKET", // <~ valid JavaScript variable name
"bucket_name": "<YOUR_BUCKET_NAME>"
}
]
}[[r2_buckets]]
binding = "MY_BUCKET"
bucket_name = "<YOUR_BUCKET_NAME>"你将使用 Hono ↗——一个用于构建 Cloudflare Workers 应用的轻量级框架。Hono 提供定义路由和中间件函数的接口。在项目目录中运行以下命令安装 Hono:
npm i honoyarn add honopnpm add honobun add hono你还需要安装 OpenAI Node API 库 ↗。该库可在 Node.js 项目中便捷访问 OpenAI REST API。执行以下命令安装该库:
npm i openaiyarn add openaipnpm add openaibun add openai接下来,打开 src/index.ts 文件,将默认代码替换为以下代码。将 <MY_BUCKET> 替换为你在 Wrangler 配置文件中设置的绑定名称。
import { Context, Hono } from "hono";
import OpenAI from "openai";
type Bindings = {
<MY_BUCKET>: R2Bucket
OPENAI_API_KEY: string
}
type Variables = {
openai: OpenAI
}
const app = new Hono<{ Bindings: Bindings, Variables: Variables }>()
app.use('*', async (c, next) => {
const openai = new OpenAI({
apiKey: c.env.OPENAI_API_KEY,
})
c.set("openai", openai)
await next()
})
app.onError((err, c) => {
return c.text(err.message, 500)
})
export default app;在上述代码中,你首先导入所需的包并定义类型,然后将 app 初始化为新的 Hono 实例。使用 use 中间件函数,将 OpenAI API 客户端添加到所有路由的上下文中。该中间件允许你在任何路由处理程序中访问客户端。onError() 定义错误处理程序,将任何错误以 JSON 响应返回。
在本节中,你将定义负责处理文件上传的路由和函数。
在 createFile 中,Worker 从 R2 读取文件并将其转换为 File 对象。随后 Worker 使用 OpenAI API 上传文件并返回响应。
GET /files 路由监听带有查询参数 file 的 GET 请求,该参数表示 R2 中已上传微调文档的文件名。该函数使用 createFile 函数管理文件上传流程。
将 <MY_BUCKET> 替换为你在 Wrangler 配置文件中设置的绑定名称。
// New import added at beginning of file
import { toFile } from 'openai/uploads'
const createFile = async (c: Context, r2Object: R2ObjectBody) => {
const openai: OpenAI = c.get("openai")
const blob = await r2Object.blob()
const file = await toFile(blob, r2Object.key)
const uploadedFile = await openai.files.create({
file,
purpose: "fine-tune",
})
return uploadedFile
}
app.get('/files', async c => {
const fileQueryParam = c.req.query("file")
if (!fileQueryParam) return c.text("Missing file query param", 400)
const file = await c.env.<MY_BUCKET>.get(fileQueryParam)
if (!file) return c.text("Couldn't find file", 400)
const uploadedFile = await createFile(c, file)
return c.json(uploadedFile)
})本节包含 GET /models 路由和 createModel 函数。createModel 函数负责指定详情并启动与 OpenAI 的微调流程。该路由处理创建新微调模型的传入请求。
const createModel = async (c: Context, fileId: string) => {
const openai: OpenAI = c.get("openai");
const body = {
training_file: fileId,
model: "gpt-4o-mini",
};
return openai.fineTuning.jobs.create(body);
};
app.get("/models", async (c) => {
const fileId = c.req.query("file_id");
if (!fileId) return c.text("Missing file ID query param", 400);
const model = await createModel(c, fileId);
return c.json(model);
});本节描述 GET /jobs 路由及对应的 getJobs 函数。该函数与 OpenAI 的 API 交互以获取所有微调任务列表。该路由提供检索此信息的接口。
const getJobs = async (c: Context) => {
const openai: OpenAI = c.get("openai");
const resp = await openai.fineTuning.jobs.list();
return resp.data;
};
app.get("/jobs", async (c) => {
const jobs = await getJobs(c);
return c.json(jobs);
});创建 Worker 应用并添加所需函数后,即可部署应用。
部署前,你必须为应用设置 OPENAI_API_KEY 密钥。运行 wrangler secret put 命令:
npx wrangler secret put OPENAI_API_KEY要将 Worker 应用部署到 Cloudflare 全球网络:
- 确保位于 Worker 项目目录中,然后运行
wrangler deploy命令:
npx wrangler deploy-
Wrangler 将打包并上传你的代码。
-
应用部署后,Wrangler 会提供 Worker 的 URL。
要使用你的应用,请向 /files 发起请求,并带上与之前上传文件名匹配的 file 查询参数以创建新的微调任务:
curl https://your-worker-url.com/files?file=finetune.jsonl文件上传完成后,再向 /models 发起请求,传递 file_id 查询参数。该值应与 /files 路由返回的 JSON 中的 id 一致:
curl https://your-worker-url.com/models?file_id=file-abc123最后,访问 /jobs 查看 OpenAI 中微调任务的状态。微调任务完成后,你可以看到 fine_tuned_model 值,表示已创建微调模型。
访问 OpenAI Playground ↗ 以使用你的微调模型。在界面左上角的下拉菜单中选择你的微调模型。
可在对 OpenAI 聊天补全端点的任何 API 请求中使用它。例如,在以下代码示例中:
openai.chat.completions.create({
messages: [{ role: "system", content: "You are a helpful assistant." }],
model: "ft:gpt-4o-mini:my-org:custom_suffix:id",
});要基于 Workers 构建更多内容,请参阅教程。
如有疑问、需要帮助或想分享你的项目,请加入 Cloudflare 开发者社区 Discord ↗,与其他开发者和 Cloudflare 团队交流。