借助Cloudflare Workers打造一个专属OpenAI API
目前已上线积薪,未来会支持本博客
2023年6月29日
本文共有1470字,预计阅读时间7分钟
前提
1npm install wrangler
1npm create cloudflare@latest
通用AI接口
workers.ts
是主入口,所有请求都会经过这里。/summary
并发送一段文本,就会返回摘要;请求/category
会返回这段文本的分类。1// 接收一个propmt和内容,请求OpenAI,返回结果
2interface OpenAIResponse {
3 choices: {
4 "finish_reason": string;
5 "index": number;
6 "message": {
7 "content": string;
8 "role": string;
9 }
10 } [];
11 created: number;
12 id: string;
13 model: string;
14 object: string;
15 usage: {
16 "completion_tokens": number;
17 "prompt_tokens": number;
18 "total_tokens": number;
19 }
20}
21
22async function openAI(prompt: string, content: string, key: string) {
23 const message = [
24 { "role": "system", "content": prompt },
25 { "role": "user", "content": content }
26 ];
27 const apiURL = 'https://api.openai.com/v1/chat/completions';
28 const model = content.length > 3000 ? 'gpt-3.5-turbo-16k-0613' : 'gpt-3.5-turbo-0613';
29
30 const response = await fetch(apiURL, {
31 method: 'POST',
32 headers: {
33 'Content-Type': 'application/json',
34 'Authorization': `Bearer ${key}`
35 },
36 body: JSON.stringify({
37 messages: message,
38 model: model,
39 max_tokens: 500,
40 temperature: 0.5,
41 stop: ['\n']
42 })
43 });
44
45 const data: OpenAIResponse = await response.json();
46 const result = data.choices[0].message.content;
47 return result;
48}
49
50export default openAI;
设定prompt
/seo
时,返回这段文字适用于SEO展示的摘要。1// 导入刚才的通用函数
2import openAI from "./open-ai";
3
4interface Env {
5 API_KEY: string;
6}
7
8const prompt = "我需要根据下面的这段文字, 针对搜索引擎优化, 写一段摘要, 要求写明文字的主要内容, 字数不得超过120个汉字";
9
10export default {
11 async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
12 const content = await request.text();
13
14 return new Response(await openAI(prompt, content, env.API_KEY), { headers: { "Content-Type": "text/plain" } });
15 }
16}
根据文本内容,输出1-3个与内容相关的标签。格式如下: “标签1”, “标签2”
配置路由
workers.ts
里进行设置,以便在请求 /seo
的时候能访问到相应代码。1import generateSEO from './seo';
2
3interface Env {
4 API_KEY: string;
5}
6
7// Export a default object containing event handlers
8export default {
9 async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
10
11 const url = new URL(request.url);
12
13 switch (url.pathname) {
14 case '/seo':
15 return generateSEO.fetch(request, env, ctx);
16 }
17
18 return new Response(
19 `This is a private API and cannot be accessed without authorization`,
20 { headers: { 'Content-Type': 'text/html' } }
21 );
22 },
23};
安全性
workers.ts
的代码是这样的:1import generateSEO from './seo';
2
3interface Env {
4 API_KEY: string;
5 TOKEN: string;
6}
7
8export default {
9 async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
10 // verify if the bearer token is valid
11 const auth = request.headers.get('Authorization');
12 if (!auth || auth !== `Bearer ${env.TOKEN}`) {
13 return new Response(
14 `This is a private API and cannot be accessed without authorization`,
15 { headers: { 'Content-Type': 'text/html' } }
16 );
17 }
18
19 const url = new URL(request.url);
20
21 switch (url.pathname) {
22 case '/seo':
23 return generateSEO.fetch(request, env, ctx);
24 }
25
26 return new Response(
27 `This is a private API and cannot be accessed without authorization`,
28 { headers: { 'Content-Type': 'text/html' } }
29 );
30 },
31};
测试
npx wrangler deploy
即可上传代码。