Open6

cloudflare ai で遊ぶ

mizchimizchi

API から叩く

.env を用意して API_TOKEN と ACCOUNT_ID を書いておく

CF_API_TOKEN=""
CF_ACCOUNT_ID=""

Deno から叩く

Translate

import "https://deno.land/std@0.206.0/dotenv/load.ts";

const CF_API_TOKEN = Deno.env.get('CF_API_TOKEN')!;
const CF_ACCOUNT_ID = Deno.env.get('CF_ACCOUNT_ID')!;

async function runModel(model: string, args: any) {
  return fetch(
    `https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/ai/run/${model}`,
    {
      headers: {
        'Authorization': `Bearer ${CF_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
      method: "POST",
      body: JSON.stringify(args),
    }
  ).then((res) => res.json());
}

const response = await runModel('@cf/meta/m2m100-1.2b', {
  text: "もう食べられないよ",
  source_lang: "japanese",
  target_lang: "english"
});

console.log(JSON.stringify(response, null, 2));

出力

$ deno run -A translate.ts
{
  "result": {
    "translated_text": "I can no longer eat."
  },
  "success": true,
  "errors": [],
  "messages": []
}

これは英日も日英もうまくいった。

mizchimizchi

Text Generation

import "https://deno.land/std@0.206.0/dotenv/load.ts";

const CF_API_TOKEN = Deno.env.get('CF_API_TOKEN')!;
const CF_ACCOUNT_ID = Deno.env.get('CF_ACCOUNT_ID')!;

async function runModel(model: string, args: any) {
  return fetch(
    `https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/ai/run/${model}`,
    {
      headers: {
        'Authorization': `Bearer ${CF_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
      method: "POST",
      body: JSON.stringify(args),
    }
  ).then((res) => res.json());
}

const res = await runModel('@cf/meta/llama-2-7b-chat-int8', {
  messages: [
    { role: 'user', content: "Good morning! It's good weather" }
  ],
});

console.log(JSON.stringify(res, null, 2));
{
  "result": {
    "response": "Good morning! Yes, it's a beautiful day outside. It's great to see the sun shining and the birds singing their sweet melodies. The weather is just perfect for a day outdoors, don't you think? 🌞🌻"
  },
  "success": true,
  "errors": [],
  "messages": []
}

英語は流暢に話す。

Text Generation: 日本語

import "https://deno.land/std@0.206.0/dotenv/load.ts";

const CF_API_TOKEN = Deno.env.get('CF_API_TOKEN')!;
const CF_ACCOUNT_ID = Deno.env.get('CF_ACCOUNT_ID')!;

async function runModel(model: string, args: any) {
  return fetch(
    `https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/ai/run/${model}`,
    {
      headers: {
        'Authorization': `Bearer ${CF_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
      method: "POST",
      body: JSON.stringify(args),
    }
  ).then((res) => res.json());
}

const res = await runModel('@cf/meta/llama-2-7b-chat-int8', {
  messages: [
    { role: 'user', content: "世界で一番高い山の高さは?" }
  ],
});

console.log(JSON.stringify(res, null, 2));
$ deno run -A  run.ts 
{
  "result": {
    "response": "The highest mountain in the world is Mount Everest, located in the Himalayas on the border between Nepal and Tibet, China. It stands at an elevation of 8,848 meters (29,029 feet) above sea level. This is the highest peak on Earth and has been recognized as the highest mountain in the world since 1865, when the height was first accurately measured."
  },
  "success": true,
  "errors": [],
  "messages": []
}

いろいろ試した感じ、日本語を理解できるが、日本語を喋る能力を持たない。

mizchimizchi

Speech Recoginition

import "https://deno.land/std@0.206.0/dotenv/load.ts";

const CF_API_TOKEN = Deno.env.get('CF_API_TOKEN')!;
const CF_ACCOUNT_ID = Deno.env.get('CF_ACCOUNT_ID')!;

async function runModel(model: string, args: any) {
  return fetch(
    `https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/ai/run/${model}`,
    {
      headers: {
        'Authorization': `Bearer ${CF_API_TOKEN}`,
        'Content-Type': 'application/json',
      },
      method: "POST",
      body: JSON.stringify(args),
    }
  ).then((res) => res.json());
}

const blob = await Deno.readFile('./task-smp.mp3');
const response = await runModel('@cf/openai/whisper', {
  audio: [...blob],
});

console.log(JSON.stringify(response, null, 2));

データは https://clrd.ninjal.ac.jp/csj/sample.html からお借りした。

$ wget https://clrd.ninjal.ac.jp/csj/sound-f/task-smp.mp3
$ deno run -A run.ts
$ deno run -A whisper.ts                                 
{
  "result": {
    "text": "I'll open it. My name is... I have a name. Is that so? I'll read the name and go up. Hira's Lemy. Hira's Lemy, Lurio... Hira's Lemi. Hira's Lemi, Oryori, Oryori, Oryori, KENQIU, KANASU, Yes, I drew a picture of it. Yes. Seruji... Yes. Yes, Lemi is a hard one. Seruji O H5. This is...",
    "word_count": 55,
    "words": [
      {
        "word": "I'll",
        "start": 0,
        "end": 0.699999988079071
      },
      {
        "word": "open",
        "start": 0.699999988079071,
        "end": 0.699999988079071
      },
      {
        "word": "it.",
        "start": 0.699999988079071,
        "end": 2.4800000190734863
      },
      // 略
    ]
  },
  "success": true,
  "errors": [],
  "messages": []
}

これもテキスト生成と一緒で、日本語は理解はできているが英語に翻訳されて返ってくる。

おそらくコーパスがないのでセルジオ越後が Seruji O H5 になってるのがちょっと面白い。

mizchimizchi

Text to Image

Stable Diffusion が使える。

よくある感じのアニメ風の画像生成プロンプトを入れてみた。

import "https://deno.land/std@0.206.0/dotenv/load.ts";

const CF_API_TOKEN = Deno.env.get('CF_API_TOKEN')!;
const CF_ACCOUNT_ID = Deno.env.get('CF_ACCOUNT_ID')!;

async function runModelAsArrayBuffer(model: string, args: any) {
  return fetch(
    `https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/ai/run/${model}`,
    {
      method: "POST",
      headers: {
        'Authorization': `Bearer ${CF_API_TOKEN}`
      },
      body: JSON.stringify(args),
    }
  ).then((res) => res.arrayBuffer());
}

const response = await runModelAsArrayBuffer('@cf/stabilityai/stable-diffusion-xl-base-1.0', {
  prompt: "best quality, masterpiece, anime style, 1 girl, from above, full body, walking, in the ruin"
});

await Deno.writeFile('./girl.png', new Uint8Array(response));

日本語に関しては、cyberpunk cat の代わりに宇宙猫とか試してみたけど、普通の猫しか生成されない。あんまり言語理解が高くなさそう?