Cloudflare Workers AI 무료 모델 식용 가이드

AI 실습 튜토리얼11개월 전 업데이트 AI 공유 서클
3.5K 00

개요

Cloudflare Workers AI를 사용하면 서버리스 GPU를 사용하여 Cloudflare의 글로벌 네트워크에서 머신 러닝 모델을 실행할 수 있습니다. Workers, Pages 또는 Cloudflare API를 통해 이러한 모델을 자체 코드에 통합할 수 있습니다. 이 플랫폼은 이미지 분류, 텍스트 생성, 물체 감지 등 다양한 AI 작업을 지원합니다.

 

주요 기능

모델. 다양한 AI 작업을 위한 다양한 오픈 소스 모델을 선택할 수 있습니다.
청구. 2024년 4월 1일부터는 비테스트 모델의 사용료가 청구됩니다.
리소스. 벡터라이즈, R2, D1 등 관련 제품에 액세스하세요.
스트라이크(키보드에서) 공식 빅 모델 플라자 방문하기

 

청구

무료 플랜 하루 10,000카우(카우는 CF의 AI 화폐 단위로 사용 가능) 공식 계산기 계산), 10,000마리의 소를 사용할 수 있습니다:

  • 100-200개의 대화
  • 500개 번역
  • 500초 음성-텍스트 변환
  • 10,000개의 텍스트 분류
  • 1,500~15,000개 임베드

 

2024년 4월 1일부터 다음 모델은 하루 10,000카우를 초과하는 경우 일당 $0.011/카우로 청구됩니다.

  • BGE-SMALL-EN-V1.5
  • BGE-BASE-EN-V1.5
  • BGE-LARGE-EN-V1.5
  • 디스틸버트-SST-2-INT8
  • LLAMA-2-7B-CHAT-INT8
  • LLAMA-2-7B-CHAT-FP16
  • 미스트랄-7B-인스트럭트-V0.1
  • M2M100-1.2B
  • resnet-50
  • 속삭임

크레딧 사용량은 CF 패널의 AI 탭에서 확인할 수 있으며, 구체적인 청구 요율은 해당 페이지를 참조하세요:가격 책정 | Cloudflare Workers AI 문서

 

최신 Workers AI 무료 플랜 한도(2024년 11월 1일부터 새로운 요금 체계에 따라 모든 모델에 과금이 시작됩니다.)

모델무료 레이어 크기
텍스트 생성 - LLM每天 10,000 个 token,适用于任何模型大小
임베딩每天 10,000 个 token,适用于任何模型大小
사진250 步之和,最高 1024x1024 分辨率
음성-텍스트 변환每天 10 分钟音频

 

쉽게 시작하기

시작하기 전에 먼저 자신의 계정을 등록하고 로그인해야 합니다.

 

계정 ID 가져오기

쇼(티켓) 패널 페이지주소 표시줄의 마지막 / 뒤에 오는 문자열이 계정 ID입니다.

 

토큰 받기

쇼(티켓) 토큰 페이지 토큰을 생성하고, 작업자 AI를 선택한 것을 확인합니다.

 

OneAPI 설정

대화 모델

Cloudflare Workers AI 免费模型食用指南

 

키: 가져올 토큰
base_url: https://api.cloudflare.com/client/v4/accounts/AccountID/ai, AccountID 대체
모델::

  • @cf/deepseek-ai/deepseek-math-7b-instruct
  • @cf/defog/sqlcoder-7b-2
  • @cf/fblgit/una-cybertron-7b-v2-awq
  • @cf/fblgit/una-cybertron-7b-v2-bf16
  • @cf/google/gemma-2b-it-lora
  • @cf/google/gemma-7b-it-lora
  • @cf/meta-llama/llama-2-7b-chat-hf-lora
  • @cf/meta/llama-2-7b-chat-fp16
  • @cf/meta/llama-2-7b-chat-int8
  • @cf/meta/llama-3-8b-instruct
  • @cf/meta/llama-3-8b-instruct-awq
  • @cf/마이크로소프트/phi-2
  • @cf/미스트랄/미스트랄-7b-인스트럭트-v0.1
  • @cf/미스트랄/미스트랄-7b-인스트럭트-v0.1-vllm
  • @cf/미스트랄/미스트랄-7b-인스트럭트-v0.2-lora
  • @cf/openchat/openchat-3.5-0106
  • @cf/qwen/qwen1.5-0.5b-chat
  • @cf/qwen/qwen1.5-1.8b-chat
  • @cf/qwen/qwen1.5-14b-chat-awq
  • @cf/qwen/qwen1.5-7b-chat-awq
  • @cf/thebloke/discolm-german-7b-v1-awq
  • @cf/티아이유에/팔콘-7B-인스트럭트
  • @cf/tinyllama/tinyllama-1.1b-chat-v1.0
  • @hf/google/gemma-7b-it
  • @hf/미스트랄/미스트랄-7b-인스트럭트-v0.2
  • @hf/넥서스플로우/스타링-lm-7b-beta
  • @hf/nousresearch/hermes-2-pro-mistral-7b
  • @hf/더블록/코델라마-7b-인스트럭트-awq
  • @hf/더블록/딥시크-코더-6.7b-base-awq
  • @hf/더블록/딥시크-코더-6.7b-인스트럭트-awq
  • @hf/thebloke/llama-2-13b-chat-awq
  • @hf/thebloke/llamaguard-7b-awq
  • @hf/더블록/미스트랄-7b-인스트럭트-v0.1-awq
  • @hf/thebloke/neural-chat-7b-v3-1-awq
  • @hf/더블록/오펜헤르메스-2.5-미스트랄-7b-awq
  • @hf/더블록/제퍼-7b-베타-awq

 

POST 예제:

curl --request POST \
--url https://api.cloudflare.com/client/v4/accounts/${AccountID}//ai/v1/chat/completions \
--header 'Authorization: Bearer 令牌' \
--header 'Content-Type: application/json' \
--data '
{
"model": "@cf/meta/llama-3-8b-instruct",
"messages": [
{
"role": "user",
"content": "how to build a wooden spoon in 3 short steps? give as short as answer as possible"
}
]
}
'

 

모델 임베딩

모델이 다르다는 점을 제외하면 대화와 정확히 동일하며 대화와 동일한 채널에 배치할 수 있습니다.

토큰 획득
base_url::https://api.cloudflare.com/client/v4/accounts/AccountID/ai계정 ID 바꾸기
모델::

  • @cf/baai/bge-base-en-v1.5
  • @cf/baai/bge-large-en-v1.5
  • @cf/baai/bge-small-en-v1.5

 

빈센느 모델

토큰 획득
base_url: 작업자의 주소, 기본 주소는 벽으로 차단되어 있으므로 라우팅해야 합니다.
모델::

  • @cf/bytedance/stable-diffusion-xl-lightning
  • @cf/lykon/dreamshaper-8-lcm
  • @cf/runwayml/stable-diffusion-v1-5-img2img
  • @cf/runwayml/stable-diffusion-v1-5-inpainting
  • @cf/stabilityai/stable-diffusion-xl-base-1.0

 

worker.js 코드(계정ID 교체에 유의하세요)

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
if (request.method === "OPTIONS") {
return new Response("", {
headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*'
}, status: 204
});
}

if (/^(https?:\/\/[^\/]*?)\/file\//i.test(request.url)) {
if (request.headers.get("if-modified-since")) {
return new Response("", { status: 304, headers: {
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*',
"Last-Modified": request.headers.get("If-Modified-Since")
}});
}

const img = await fetch(request.url.replace(/^(https?:\/\/[^\/]*?)\//, "https://telegra.ph/"));
return new Response(img.body, { status: img.status, headers: {
"content-type": img.headers.get("content-type"),
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*',
"Last-Modified": (new Date()).toUTCString(),
"Cache-Control": "public, max-age=31536000"
}});
}

const url = new URL(request.url);
const search = url.searchParams;

if (!search.get("debug")) {
if (url.pathname !== "/v1/chat/completions" || request.method !== "POST") {
return new Response("Not Found or Method Not Allowed", {
status: 404,
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*'
}
});
}
}

const authHeader = request.headers.get("Authorization") || "Bearer " + search.get("key");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
return new Response("Unauthorized: Missing or invalid Authorization header", {
status: 401,
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*'
}
});
}

const apiKey = authHeader.slice(7);
let data;
try {
data = await request.json();
} catch (error) {
if (!search.get("debug")) return new Response("Bad Request: Invalid JSON", { status: 400 });
data = { model: search.get("model") || "@cf/stabilityai/stable-diffusion-xl-base-1.0", messages: [{ role: "user", content: search.get("prompt") || "cat" }] };
}

if (!data || !data.model || !data.messages || data.messages.length === 0) {
return new Response("Bad Request: Missing required fields", { status: 400 });
}

const prompt = data.messages[data.messages.length - 1].content;
const cloudflareUrl = `https://api.cloudflare.com/client/v4/AccountID/ai/run/${data.model}`;

const requestBody = JSON.stringify({
prompt: prompt,
num_inference_steps: 20,
guidance_scale: 7.5,
strength: 1
});

const currentTimestamp = Math.floor(Date.now() / 1000);
const uniqueId = `imggen-${currentTimestamp}`;

try {
const apiResponse = await fetch(cloudflareUrl, {
method: 'POST',
headers: {
'Authorization': authHeader,
'Content-Type': 'application/json',
},
body: requestBody,
});

if (!apiResponse.ok) {
throw new Error("Request error: " + apiResponse.status);
}

const imageBlob = await apiResponse.blob();
const formData = new FormData();
formData.append("file", imageBlob, "image.jpg");

const uploadResponse = await fetch("https://telegra.ph/upload", {
method: 'POST',
body: formData,
});

if (!uploadResponse.ok) {
throw new Error("Failed to upload image");
}

const uploadResult = await uploadResponse.json();
const imageUrl = request.url.match(/^(https?:\/\/[^\/]*?)\//)[1] + uploadResult[0].src;

const responsePayload = {
id: uniqueId,
object: "chat.completion.chunk",
created: currentTimestamp,
model: data.model,
choices: [
{
index: 0,
delta: {
content: `![](${imageUrl})`,
},
finish_reason: "stop",
},
],
};

const dataString = JSON.stringify(responsePayload);

return new Response(`data: ${dataString}\n\n`, {
status: 200,
headers: {
"Content-Type": "text/event-stream",
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*',
},
});
} catch (error) {
return new Response("Internal Server Error: " + error.message, {
status: 500,
headers: {
"Content-Type": "application/json",
'Access-Control-Allow-Origin': '*',
"Access-Control-Allow-Headers": '*',
},
});
}
}

 

텍스트 음성 변환 모델

토큰 획득
base_url작업자의 주소
모델::

  • @cf/openai/whisper
  • @cf/openai/whisper-sherpa
  • @cf/openai/whisper-tiny-en

POST 예제:

도메인.com이 작업자의 주소로 대체되었는지 확인하세요.

curl -X POST https://domain.com/v1/audio/transcriptions \
-H "Authorization: Bearer 令牌" \
-F file=@C:\Users\Folders\audio.mp3 \
-F model="@cf/openai/whisper"

 

worker.js 코드(계정ID 교체에 유의하세요)

addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})

async function handleRequest(request) {
const url = new URL(request.url)
const { pathname } = url

if (request.method === 'POST' && pathname === '/v1/audio/transcriptions') {
const formData = await request.formData()
const file = formData.get('file')
const model = formData.get('model')

if (!file || !model) {
return new Response('File or model not provided', { status: 400 })
}

const apiUrl = `https://api.cloudflare.com/client/v4/accounts/AccountID/ai/run/${model}`

const apiResponse = await fetch(apiUrl, {
method: 'POST',
headers: {
'Authorization': request.headers.get('Authorization'),
'Content-Type': 'application/octet-stream'
},
body: file.stream()
})

const apiResult = await apiResponse.json()

const textResult = apiResult.result.text

const formattedResult = JSON.stringify({ text: textResult })

return new Response(formattedResult, {
headers: { 'Content-Type': 'application/json' }
})
} else {
return new Response('Not Found', { status: 404 })
}
}

 

번역 모델

모델::

  • cf/meta/m2m100-1.2b

지원되는 언어인 source_lang과 target_lang은 같은 범위에 있습니다.

  • 영어 (ko)
  • 중국어(zh)
  • 프랑스어(fr)
  • 독일어(드)
  • 스페인어(에스)
  • 이탈리아어(it)
  • 일본어(ja)
  • 한국어(ko)
  • 포르투갈어(pt)
  • 러시아어(ru)
  • 네덜란드어(nl)
  • 스웨덴어(sv)
  • 노르웨이어(아니요)
  • 덴마크어(da)
  • 핀란드어(fi)
  • 폴란드어(pl)
  • 터키어(tr)
  • 아랍어(ar)
  • 히브리어(히)
  • 인도네시아어 (ID)
  • 태국어(th)
  • 베트남어(vi)
  • 힌디어(안녕하세요)
  • 말레이어(ms)
  • 그리스어(엘)
  • 체코어(cs)
  • 슬로바키아어(SK)
  • 루마니아어 (ro)
  • 헝가리어(hu)
  • 불가리아어 (bg)
  • 크로아티아어(시간)
  • 세르비아어(sr)
  • 우크라이나어(영국)

 

POST 예제:

curl --request POST \
--url https://api.cloudflare.com/client/v4/accounts/account_id/ai/run/${model}\
--header 'Authorization: Bearer 令牌' \
--header 'Content-Type: application/json' \
--data '{
"source_lang": "en",
"target_lang": "zh",
"text": "I love you."
}'

 

몰입 번역

개발자 설정에서 몰입형 번역 오픈 베타를 클릭하고 DeepLX (베타) 주소 입력을 선택합니다:https://你的worker地址/translate?password=${authKey}

worker.js

addEventListener('fetch', event => event.respondWith(handleRequest(event.request)));

const model = '@cf/meta/m2m100-1.2b';
const authKey = 'YOUR_PASSWORD';
const accountId = 'YOUR_ACCOUNT_ID';
const token = 'YOUR_TOKEN';

async function handleRequest(request) {
const url = new URL(request.url);

if (request.method === 'OPTIONS') return new Response(null, { status: 204, headers: { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type, Authorization' } });

if (request.method !== 'POST' || url.pathname !== '/translate' || url.searchParams.get('password') !== authKey) return new Response(request.method !== 'POST' || url.pathname !== '/translate' ? 'Not Found' : 'Unauthorized', { status: request.method !== 'POST' || url.pathname !== '/translate' ? 404 : 401 });

const data = await request.json();
if (!data.text || !data.source_lang || !data.target_lang) return new Response('Bad Request', { status: 400 });

const cloudflareUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/run/${model}`;
const init = {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ source_lang: data.source_lang.toLowerCase(), target_lang: data.target_lang.toLowerCase(), text: data.text })
};

try {
const response = await fetch(cloudflareUrl, init);
const responseData = await response.json();

return new Response(JSON.stringify({
alternatives: [], code: 200, data: responseData.result.translated_text, id: Math.floor(Math.random() * 10000000000), source_lang: data.source_lang, target_lang: data.target_lang
}), { headers: { 'Content-Type': 'application/json' } });
} catch (error) {
console.error('Translation failed:', error);
return new Response(JSON.stringify({ error: 'Translation failed' }), { headers: { 'Content-Type': 'application/json' }, status: 500 });
}
}

 

© 저작권 정책

관련 문서

댓글 없음

댓글에 참여하려면 로그인해야 합니다!
지금 로그인
없음
댓글 없음...