クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

キャッシュとAI機能の費用

このレッスンのあとで: 機能の費用と、キャッシュが節約する額を、見積もることができる。

65分のレッスンコマンド7件AI コーディングエージェントのラボ:opencode でコードを説明・修正し、その結果を確かめる

機能の費用を見積もるには

AI機能の費用は、代金を払う呼び出しの数に、一回の値段をかけたものです。キャッシュは、前の答えを覚えておくので、同じ質問のたびに払う数を減らします。

コスト、トレース、信頼性のモジュールでは、キャッシュのキーの作り方と、期限の決め方を学びます。このレッスンは、さらに進んで、一週間のトラフィックでヒットを数え、一か月の費用を予測します。

このレッスンのゴール

メモ

機能の費用と、キャッシュが節約する額を、見積もることができる。

キーワード

ことばいみれい
キャッシュ代金を払った答えを覚えておく場所
ヒットキャッシュから答えられたリクエスト
ミスキャッシュで答えられず、代金を払うリクエスト
ヒット率ヒットだったリクエストの百分率50
有効期限(ttl)保存した答えを使える長さ。ここではリクエストの回数で数え、ttl と書く5
予測過去の数から、先の数を計算で求めること

学生が入力するセルは、このプレビューでは空白です。

一回の呼び出しの費用

呼び出し一回の費用は、入力トークンに入力の値段をかけたものと、出力トークンに出力の値段をかけたものの合計です。ふつう、出力のほうが高くなります。

計算を整数にするため、「ユニット」で数えます。1 ユニットは 1000 分の 1 円です。ここでの値段は作り話です。

例: 一回の呼び出し

部分トークン1 トークンの値段ユニット
入力1203360
出力80151200
一回の合計2001560(1.56 円)

学生が入力するセルは、このプレビューでは空白です。

よくある間違い

注意

キャッシュは、どの機能でも同じだけ節約すると考える人が多いです。節約できるのは、繰り返される質問の分だけです。誰も同じことを二度聞かない機能では、ほとんど節約できません。

トラフィックをキャッシュに通す

ヒット率を測るには、本物か種つきのリクエストを、順に通します。番号は 0 から数えます。ttl は、保存した答えを使えるリクエストの回数です。

保存した番号から今の番号までの差が ttl より小さければ、ヒットです。ttl 以上ならミスで、今の番号で保存し直します。ヒットは、保存した答えの期限を延ばしません。期限は自分の時計で切れるので、人気の質問でも、期限が来れば新しい答えを取ります。

例: ttl が 3 のとき

リクエストの番号質問保存した番号結果
0aなしミス。0 で保存
1a0ヒット。差は 1 で、3 より小さい
2bなしミス。2 で保存
3a0ミス。差は 3 で、3 以上。3 で保存
4a3ヒット。差は 1

学生が入力するセルは、このプレビューでは空白です。

一週間から一か月を予測する

一週間のリクエストを足します。一か月は約 30 日なので、一か月のリクエスト数は、一週間の合計に 30 をかけて 7 で割った数です。

代金を払うのはミスだけです。100 からヒット率を引いた数をかけて 100 で割り、一回の費用をかけます。

例: 一週間が 835 リクエスト

手順式結果
一週間の合計120 + 135 + 150 + 160 + 170 + 60 + 40835
一か月のリクエスト835 × 30 ÷ 73578
ヒット率 50 パーセントで払う回数3578 × 50 ÷ 1001789
費用(ユニット)1789 × 15602790840(約 2791 円)

学生が入力するセルは、このプレビューでは空白です。

助っ人 model.js を書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// 応答のトークン数。なければ null。' 'function count(data, name) {' '  return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

助っ人 model.js を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' '  try {' '    const res = await fetch(base + \"/v1/chat/completions\", {' '      method: \"POST\",' '      headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' '      body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"status \" + res.status);' '    const data = await res.json();' '    const text = data.choices[0].message.content;' '    return { text, inTokens: count(data, \"prompt_tokens\"), outTokens: count(data, \"completion_tokens\"), recorded: false };' '  } catch (error) {' '    console.log(\"記録済みサンプル: モデルが答えませんでした (\" + error.message + \")。\");' '    return { text: sample, inTokens: null, outTokens: null, recorded: true };' '  }' '}' 'module.exports = { ask };' >> model.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キャッシュのスクリプトを書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'function next(seed) { return (seed * 75 + 74) % 65537; }' 'const table = [0, 0, 0, 1, 1, 2, 3, 4, 5, 6];' 'function traffic(seed, count) {' '  const out = [];' '  for (let i = 0; i < count; i++) { seed = next(seed); out.push(\"q\" + table[seed % 10]); }' '  return out;' '}' > cache.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キャッシュのスクリプトを書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function replay(requests, ttl) {' '  const stored = {};' '  let hits = 0;' '  requests.forEach(function (key, i) {' '    if (key in stored && i - stored[key] < ttl) hits = hits + 1;' '    else stored[key] = i;' '  });' '  return hits;' '}' 'const week = [120, 135, 150, 160, 170, 60, 40];' 'const perCall = 120 * 3 + 80 * 15;' >> cache.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キャッシュのスクリプトを書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const requests = traffic(7, 40);' '  console.log(\"最初の 8 件: \" + requests.slice(0, 8).join(\" \"));' '  for (const ttl of [5, 10, 20]) {' '    const hits = replay(requests, ttl);' '    const percent = Math.floor(hits * 100 / 40);' '    const month = Math.floor(week.reduce(function (a, b) { return a + b; }, 0) * 30 / 7);' '    const paid = Math.floor(month * (100 - percent) / 100);' '    console.log(\"ttl \" + ttl + \": ヒット \" + hits + \" 回、\" + percent + \" パーセント、1か月の支払いは \" + paid + \" 回、\" + paid * perCall + \" ユニット\");' '  }' >> cache.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キャッシュのスクリプトを書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  const reply = await ask([{ role: \"user\", content: \"短く一文で答えてください。キャッシュで機能が安くなることがあるのは、なぜですか。\" }], \"同じ質問には記憶から答えるので、新しい呼び出しの代金がかからないからです。\", 80);' '  console.log(\"モデル: \" + reply.text);' '  console.log(\"出力トークン: \" + (reply.outTokens === null ? \"報告なし\" : reply.outTokens));' '}' 'main();' >> cache.js"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

キャッシュを再生する

コマンド
docker exec -w /home/node/project agent node cache.js

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

Run の出力

行意味
最初の 8 件: q6 q6 q0 q2 q0 q0 q5 q0種つきのトラフィック。全員で同じ
ttl 5: ヒット 16 回、40 パーセント、1か月の支払いは 2146 回、3347760 ユニット期限が短いと、ヒットが少ない
ttl 10: ヒット 20 回、50 パーセント、1か月の支払いは 1789 回、2790840 ユニット中くらいの期限
ttl 20: ヒット 27 回、67 パーセント、1か月の支払いは 1180 回、1840800 ユニット期限が長いと、ヒットが増え、請求が減る
モデル: ...ラボからの一文。モデルが答えなければ記録済みサンプル
出力トークン: ...応答が報告した数。なければ報告なし

学生が入力するセルは、このプレビューでは空白です。

このラボとソースについて: AI コーディングエージェントのラボ:opencode でコードを説明・修正し、その結果を確かめる

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。