シュッと Cloudflare の Worker AI を触ってみる
ちゃっす(/・ω・)/
前から気になってはいた Cloudflare さんの Worker AI を触った見たぞ☆
Cloudflare Workers っちゅーのはもともとあったでございますが、こやつはシュッと AI の機能を使える感じでございますな(/・ω・)/
今使えるモデルはこんな感じ
Models
んで、まぁ使い方は公式チュートリアルを見てもらうのがよいでござる(/・ω・)/
ざっくり書いておくと
アカウントがない人はとりあえず Cloudflare に登録する
wrangler ってのを手元の環境で使えるようにする
npm create cloudflare@latest みたいな感じでプロジェクトを作る
コード書きかき
ローカルデバッグ
でぷろーい
ってな感じ(/・ω・)/
チュートリアルでは Worker を経由して AI の機能を使う方法と AI の機能を Cloudflare の API として呼び出す方法が書かれているけれど、今回は Worker から AI 機能を呼び出すぞ☆
先にコード書いておく(書き捨てなので適当である)
import { Ai } from '@cloudflare/ai'
export interface Env {
// If you set another name in wrangler.toml as the value for 'binding',
// replace "AI" with the variable name you defined.
AI: any;
}
const handler: ExportedHandler = {
async fetch(request: Request, env: Env) {
if (request.method === "GET") {
return new Response("The request was a GET");
}
const BASIC_USER = "admin";
const BASIC_PASS = "admin";
/**
* Throws exception on verification failure.
* @param {string} user
* @param {string} pass
* @throws {UnauthorizedException}
*/
async function verifyCredentials(user, pass) {
if (BASIC_USER !== user) {
throw new UnauthorizedException("Invalid credentials.");
}
if (BASIC_PASS !== pass) {
throw new UnauthorizedException("Invalid credentials.");
}
}
/**
* Parse HTTP Basic Authorization value.
* @param {Request} request
* @throws {BadRequestException}
* @returns {{ user: string, pass: string }}
*/
async function basicAuthentication(request) {
const Authorization = request.headers.get("Authorization");
const [scheme, encoded] = Authorization.split(" ");
// The Authorization header must start with Basic, followed by a space.
if (!encoded || scheme !== "Basic") {
throw new BadRequestException("Malformed authorization header.");
}
// Decodes the base64 value and performs unicode normalization.
// @see https://datatracker.ietf.org/doc/html/rfc7613#section-3.3.2 (and #section-4.2.2)
// @see https://dev.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
const buffer = Uint8Array.from(atob(encoded), (character) =>
character.charCodeAt(0)
);
const decoded = new TextDecoder().decode(buffer).normalize();
// The username & password are split by the first colon.
//=> example: "username:password"
const index = decoded.indexOf(":");
// The user & password are split by the first colon and MUST NOT contain control characters.
// @see https://tools.ietf.org/html/rfc5234#appendix-B.1 (=> "CTL = %x00-1F / %x7F")
if (index === -1 || /[\0-\x1F\x7F]/.test(decoded)) {
throw new BadRequestException("Invalid authorization value.");
}
return {
user: decoded.substring(0, index),
pass: decoded.substring(index + 1),
};
}
async function UnauthorizedException(reason) {
this.status = 401;
this.statusText = "Unauthorized";
this.reason = reason;
}
async function BadRequestException(reason) {
this.status = 400;
this.statusText = "Bad Request";
this.reason = reason;
}
/**
* readRequestBody reads in the incoming request body
* Use await readRequestBody(..) in an async function to get the string
* @param {Request} request the incoming request to read from
*/
async function readRequestBody(request: Request) {
const contentType = request.headers.get("content-type");
if (contentType.includes("application/json")) {
const jsonData = await request.json();
return jsonData.query;
} else {
// Perhaps some other type of data was submitted in the form
// like an image, or some other binary data.
return "a file";
}
}
const { protocol, pathname } = new URL(request.url);
// In the case of a Basic authentication, the exchange MUST happen over an HTTPS (TLS) connection to be secure.
if (
"https:" !== protocol ||
"https" !== request.headers.get("x-forwarded-proto")
) {
throw new BadRequestException("Please use a HTTPS connection.");
}
if (!request.headers.has("Authorization")) {
// Not authenticated.
return new Response("You need to set credentials.", {
status: 401,
headers: {
// Prompts the user for credentials.
"WWW-Authenticate": 'Basic realm="my scope", charset="UTF-8"',
},
});
}
// Throws exception when authorization fails.
const { user, pass } = basicAuthentication(request);
verifyCredentials(user, pass);
switch (pathname) {
case "/":
const query = await readRequestBody(request);
const ai = new Ai(env.AI);
const preprocess_response = await ai.run('@cf/meta/m2m100-1.2b', {
text: query,
source_lang: "japanese",
target_lang: "english"
}
);
const llm_response = await ai.run('@cf/meta/llama-2-7b-chat-int8', {
messages: [
{ "role": "system", "content": "You are a friendly assistant" },
{ "role": "user", "content": preprocess_response.translated_text }
]
// prompt: preprocess_response.translated_text
}
);
const response = await ai.run('@cf/meta/m2m100-1.2b', {
text: llm_response.response,
source_lang: "english",
target_lang: "japanese"
}
);
// Only returns this response when no exception is thrown.
return new Response(response.translated_text, {
status: 200,
headers: {
"Cache-Control": "no-store",
},
});
case "/favicon.ico":
case "/robots.txt":
return new Response(null, { status: 204 });
}
return new Response("Not Found.", { status: 404 });
}
};
export default handler;
内容をざくっというと
リクエストとして受け取った query をプロンプトとして LLM を実行して結果を返しているぞ(/・ω・)/
ただ LLM のモデルが日本語得意なものじゃないので、LLM の呼び出し前後で japanese -> english, english -> japanese の翻訳モデルを利用しているぞ(/・ω・)/
でまぁ、デプロイするとグローバルに公開されるので Example の内容を基にベーシック認証をいれておりますのよ(/・ω・)/
んでまぁこんな感じでよびだしますん
import requests
import json
from requests.auth import HTTPBasicAuth
# 認証情報
username = 'admin'
password = 'admin'
# URL とデータ
url = 'http://localhost:8787/'
data = {
'query': 'AI ってなんですか?',
}
headers = {
'Content-Type': 'application/json'
}
response = requests.post(url, data=json.dumps(data), headers=headers, auth=HTTPBasicAuth(username, password))
# レスポンスを表示
print(response.status_code)
print(response.text)
お返事
AIは人工知能の発展を意味し、通常、人間の知能を必要とするタスクを実行することができる
コンピュータシステムを指します。
AIシステムはアルゴリズムや機械学習技術を使用してデータを分析し、
パターンを認識し、そのデータに基づいて予測や決定を下します。
AIには、以下のような多くの異なるタイプがあります:
1.狭いまたは弱いAI:このタイプのAIは、顔認識、言語翻訳、
またはチェスやGoのようなゲームをプレイするように設計されています。
2.一般的または強力なAI:このタイプのAIは、人間のような理由、問題解決、
学習などの知的タスクを実行するように設計されています。
3.スーパーインテリジェンス:このタイプのAIは、人間の頭脳よりもはるかに知的であり、
人間の能力を超えた複雑な問題
んで、使ってみて気づいたのでございますが結構制限がきびすぃ( ・ω・)
一度に処理できるトークン数が日本語だとむむむという感じ。
一問一答の短文回答とかならいいかなぁ。
まぁしょうがないよねぇということでベクトル検索ができるようになるチュートリアルページがあったのでこっちもやろうと思ったのだけれど
Vectorize の機能は有料プランじゃないとまだ使えないっぽ(/・ω・)/
ので、今回は断念でござる( ・ω・)
ちなみに、Cloudflare で提供される embeddings モデルは日本語弱そうであるが、別の API を使うこともできるようである(未検証)
っちゅーことで非常に簡単ではあるけれど触ってみた(/・ω・)/
Platform として色々と Cloudflare が整備されてきているので今後に期待大だけれど丸っと日本語対応した LLM アプリを Cloudflare だけで完結できるかというと今のところ微妙かも(/・ω・)/
というわけでおしまい。
この記事が気に入ったらサポートをしてみませんか?