使用Cloudflare AI Worker即時生成文章摘要。
部落格轉移到VitePress後,經常思考著還能加入什麼功能,例如搭配LLM做點什麼。最先想到的就是這時代很基本的功能,文章摘要。其實一開始是想說就跟建立新文章一樣弄個JS腳本,傳到LLM生成再放進文章裡就好,想了想又覺得有點無趣,決定製作為即時生成顯示的功能。
一開始我是考慮用Transformer.js來做,但是呢,在huggingface把玩了一下,「要不乾脆在client端用WebGPU跑跑看好了」,考慮到free plan額度問題,當時樂觀地想著把計算工作交給client端。實際測試後主要覺得模型參數載入要花費的時間太久了,用小一點的模型輸出結果又不太穩定、執行又需要一些時間,對client端而言就變成無趣的漫長等待了......🥱
於是我就想到了佛心的Cloudflare,研究了一下AI Worker,free plan就夠用了🥺 搭配AI Gateway做流量控制避免濫用,就可以有很不錯的結果。最後就做了一個Vue元件給部落格用了。
要輸出中文摘要就改一下prompt囉。
js
# worker.js
const corsHeaders = {
'Access-Control-Allow-Origin': 'YOUR_HOST',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
'Content-Type': 'application/json'
};
const sendErrorResponse = (message, status = 500) => {
return new Response(JSON.stringify({ error: message }), {
status,
headers: corsHeaders
});
};
export default {
async fetch(request, env) {
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
if (request.method !== 'POST') {
return sendErrorResponse('Only POST requests are allowed', 405);
}
try {
const { message } = await request.json();
if (!message) {
return sendErrorResponse('Missing message in request body', 400);
}
const model = '@cf/meta/llama-3.1-8b-instruct';
const userID = 'YOUR_USER_ID';
const gatewayID = 'YOUR_AI_GATEWAY_NAME'
const gateway = `https://gateway.ai.cloudflare.com/v1/${userID}/{gatewayID}/workers-ai/${model}`;
const prompt = `You are a professional summarization assistant. Based on the content I provide, generate a summary no longer than 60 characters, and return only the summary—no additional text: ${message}`;
const apiResponse = await fetch(
gateway,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `${env.key}`
},
body: JSON.stringify({'prompt': prompt})
}
);
if (!apiResponse.ok) {
throw new Error(`Cloudflare Workers AI error: ${apiResponse.statusText}`);
}
const response = await apiResponse.json();
return new Response(JSON.stringify({ response }), { headers: corsHeaders });
} catch (error) {
return sendErrorResponse(error.message);
}
}
};