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

無料レッスン

ドリフトと再学習

このレッスンのあとで: 調整したモデルが古くなったことに気づける。

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

調整したモデルも、古くなる

ドリフトとは、誰もモデルを変えていないのに、モデルが時間とともに悪くなることです。世の中は動いています。新しい商品、新しい言い回し、新しい種類の問い合わせが現れますが、モデルは去年のデータで調整されています。

誰も点数を見ていなければ、最初の知らせは、困ったお客さんからになります。

このレッスンのゴール

メモ

調整したモデルが古くなったことに気づける。

キーワード

ことばいみ
ドリフト世の中が変わり、モデルが悪くなること
監視点数を何度も確かめること
トリガー今すぐ動け、と告げるしるし
スケジュール何があっても動くと決めた日
再学習新しい例で、もう一度調整すること

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

点数を毎週見る

新しいケースを少し用意して、毎週モデルに解かせます。数字は記録に残します。公開後の最初の数週間が、ベースラインになります。

悪い週が一回だけなら、偶然かもしれません。点数が下がったと言うには、警告の線を下回る週が二週続くことを求めます。

例: 週ごとの点数

週点数分かること
1 から 388、90、89ベースラインは 89(平均を切り捨て)
4 から 688、87、86少し下がったが、警告の線 84 より上
7 と 880、79二週続けて 84 を下回った。点数が落ちた
9 から 1278、79、77、76低いまま

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

原因は、入力を見て探す

点数が落ちたら、新しい入力を読みます。学習データになかった言葉、商品、話題が入っていないでしょうか。新しい単語を一覧にします。

それが、足すべき例を教えてくれます。新しい単語の一覧が長ければ、入力が変わった強いしるしです。

トリガーか、スケジュールか

スケジュールは、四週ごとのように、決まった日に再学習します。簡単ですが、何も変わっていないのに学習したり、変わったのに遅すぎたりします。

トリガーは、点数が落ちたときに再学習します。証拠に基づいて動きます。まずトリガーを使い、スケジュールは最後の備えに残すチームが多いです。

よくある間違い

注意

「調整したモデルは、試験に通れば、ずっと良いままだ」と考えがちです。試験が表すのは、実行した日のことだけです。新しいケースで点数を見続け、落ちたら再学習して、また比べます。

モデル用の補助を書く(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\");' '// 問い合わせ仕分けの、記録済みの週ごとの点数(パーセント)。1 週目が最初。' 'const scores = [88, 90, 89, 88, 87, 86, 80, 79, 78, 79, 77, 76];' 'const THRESHOLD = 5;' > adapt6.js"

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

ドリフトの確認を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function baseline(list) {' '  return Math.floor((list[0] + list[1] + list[2]) / 3);' '}' 'function findDrop(list, drop) {' '  const cut = baseline(list) - drop;' '  for (let i = 3; i < list.length - 1; i++) {' '    if (list[i] < cut && list[i + 1] < cut) return i + 1;' '  }' '  return 0;' '}' >> adapt6.js"

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

ドリフトの確認を書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function newWords(oldTexts, newTexts) {' '  const seen = oldTexts.flat();' '  const out = [];' '  for (const w of newTexts.flat()) {' '    if (seen.includes(w) === false && out.includes(w) === false) out.push(w);' '  }' '  return out;' '}' 'const before = [[\"荷物\", \"どこ\"], [\"請求書\", \"違う\"]];' 'const now = [[\"ドローン\", \"荷物\", \"どこ\"], [\"受け取り\", \"コード\"]];' >> adapt6.js"

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

ドリフトの確認を書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  console.log(\"基準 \" + baseline(scores) + \"%、\" + (baseline(scores) - THRESHOLD) + \"% を下回ったら警告\");' '  console.log(\"点数が落ちたのは \" + findDrop(scores, THRESHOLD) + \" 週目\");' '  console.log(\"新しい単語: \" + newWords(before, now).join(\" \"));' '  const q = \"誰もモデルを変えていないのに、モデルが悪くなることがあるのは、なぜですか。短い一文で答えてください。\";' '  const sample = \"世の中も入力も変わるので、古い入力で調整したモデルは、新しい入力に合いにくくなるからです。\";' '  const reply = await ask([{ role: \"user\", content: q }], sample, 60);' '  console.log(\"返事: \" + reply.text);' '}' 'main();' >> adapt6.js"

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

ドリフトの確認を実行する

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

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

確認の出力

十二の点数は、記録されたものとしてスクリプトに書いてあります。確認は、ベースラインを求め、点数が落ちた週を見つけ、架空のメッセージの新しい単語を並べます。

日本語は空白で単語に分かれないので、メッセージは単語に分けた形で渡しています。最後の行は、短いモデルの呼び出しか、「記録済みサンプル」です。

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

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