新しいモデルは安く、答えが違う
機能の裏のモデルを変えるとは、同じケースを両方の版で走らせ、利用者を少しずつ移すことです。新しい版は平均では良くても、一部のケースでは悪くなり、利用者が最初に気づきます。
ここのラボはどれもモデルを学習も提供もしないので、記録した二つの版を比べます。方法は、本物でも同じです。
このレッスンのゴール
メモ
記録した二つの実行から、機能を別のモデルへ移すかを決められます。
キーワード
| ことば | いみ |
|---|---|
| 退行 | 以前は通り、今は失敗するケース |
| カナリア | 最初に新しい版を使う少数の利用者 |
| ロールバック | 古い版へ戻る道 |
| バケツ | 利用者がいつも入る固定の数 |
| コストの上昇 | 新しい版が何パーセント高いか |
学生が入力するセルは、このプレビューでは空白です。
同じケースで両方の版を走らせる
両方の版に同じケースを使い、ケースごとに通ったか、いくらかかったかを記録します。通った件数を比べるだけでなく、退行も並べます。
通った件数が同じでも、版は違いえます。一方が通ったケースを、他方は落とすことがあります。重要なケースの退行は、平均の改善より重いことがあります。
例: 六つのケースでの旧と新
| 版 | 通った件数 | コスト | 退行 |
|---|---|---|---|
| 旧 | 6 件中 5 | 180 | なし |
| 新 | 6 件中 5 | 144 | c3 は以前は通り、今は失敗 |
学生が入力するセルは、このプレビューでは空白です。
まず少数を移す
全員を一度に切り替えてはいけません。少数の利用者だけを新しい版へ送り、様子を見ます。同じ人がいつも同じ版になるよう、固定の決まりで選びます。
古い版は動かしたままにして、一歩で戻れるようにします。請求も見ます。価格の変更は利益を消すことがあるので、見る前に許容する上昇を決めます。
よくある間違い
注意
「新しいモデルは必ず良いので、軽い試験で足りる」と考えがちです。新しいモデルは平均で良くても、あなたのケースでは悪いことがあります。自分のケースを走らせ、少数から移し、戻る道を残します。
モデル用の補助を書く(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"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
モデル用の補助を書く(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 d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"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\");' '' '// 同じ六つのケースに対する、機能の二つの記録済みの版。コストは架空の単位。' 'const oldRun = [1, 1, 1, 0, 1, 1].map(function (ok, i) { return { case: \"c\" + (i + 1), ok: ok === 1, cost: 30 }; });' 'const newRun = [1, 1, 0, 1, 1, 1].map(function (ok, i) { return { case: \"c\" + (i + 1), ok: ok === 1, cost: 24 }; });' 'const MAX_REGRESSIONS = 1;' 'function passes(run) { return run.filter(function (r) { return r.ok; }).length; }' 'function total(run) { return run.reduce(function (sum, r) { return sum + r.cost; }, 0); }' > change.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
比較を書く(2)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function regressions(a, b) {' ' return a.filter(function (r, i) { return r.ok && b[i].ok === false; }).map(function (r) { return r.case; });' '}' '// 名前の文字コードの合計が作るバケツが、割合より小さい利用者はカナリアに入る。' 'function inCanary(user, percent) {' ' let n = 0;' ' for (const ch of user) n = n + ch.charCodeAt(0);' ' return n % 100 < percent;' '}' >> change.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
比較を書く(3)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' console.log(\"旧: 6 件中 \" + passes(oldRun) + \" 件、コスト \" + total(oldRun));' ' console.log(\"新: 6 件中 \" + passes(newRun) + \" 件、コスト \" + total(newRun));' ' const bad = regressions(oldRun, newRun);' ' console.log(\"退行: \" + bad.join(\", \") + (bad.length <= MAX_REGRESSIONS ? \"(許容)\" : \"(多すぎる)\"));' ' const users = [\"ana\", \"cy\", \"eva\", \"gus\", \"li\", \"zoe\"];' ' console.log(\"10 パーセントのカナリア: \" + users.filter(function (u) { return inCanary(u, 10); }).join(\", \"));' ' const r = await ask([{ role: \"user\", content: \"20,000 円の 15 パーセントはいくらですか。短く一文で答えてください。\" }], \"20,000 円の 15 パーセントは 3,000 円です。\", 40);' ' console.log(\"今日のライブ呼び出し(記録とは別): \" + r.text);' '}' 'main();' >> change.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
比較を実行する
docker exec -w /home/node/project agent node change.jsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
出力の例
| 行 | 示していること |
|---|---|
| 旧: 6 件中 5 件、コスト 180 | 記録済みの古い版 |
| 新: 6 件中 5 件、コスト 144 | 記録済みの新しい版。安い |
| 退行: c3(許容) | 退行が一つで、上限の一つ以内 |
| 10 パーセントのカナリア: ana | 固定の決まりで少数に入る利用者 |
| 今日のライブ呼び出し(記録とは別): ... | あなた自身の呼び出し。実行ごとに変わるか、記録済みサンプルと出る |
学生が入力するセルは、このプレビューでは空白です。