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

無料レッスン

AIエージェントの評価スイートを作る

このレッスンのあとで: 軌跡、状態、繰り返した実行を、1つのゲートにまとめられる。

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

平均では良いのに、安全ではない

エージェントの評価スイートは、最終状態、道のり、繰り返した実行を、変更が通らなければならない1つのゲートにまとめます。必要な理由は、どのチェックも単独では、別の悪い変更を通してしまうからです。

店の新しいエージェントは、61%に対して77%を出しました。それでも、決して失敗してはならないケースが、ときどき失敗するようになりました。

このレッスンのゴール

メモ

軌跡、状態、繰り返した実行を、1つのゲートにまとめられる。

キーワード

ことばいみ
ゲート実行の前に決めておく合格の基準
必須ケースどの実行でも失敗してはならないケース
ステップの増加新バージョンが余計に踏んでよいステップの量
終了コードスクリプトが返す数。0 は成功
スイート変更のたびにまとめて動かすチェック

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

ゲートごとに、捕まえる変更が違う

結果を見る前に、各ゲートを決めます。1つ目は、最終状態が十分な頻度で正しいこと。2つ目は、ステップが増えすぎていないこと。3つ目は、必須ケースを名指しします。4つ目は、変更が明らかに悪くはないことです。

ステップのゲートは、ステップの増加を制限します。エージェントにとってはコストのゲートです。ステップごとに費用がかかるからです。

例: 4つのゲート

ゲート規則捕まえるもの
状態の率実行の70%以上が、正しく終わる失敗が多すぎるバージョン
ステップステップの増加が20%以内正しいが遅いバージョン
必須ケースケース4が、どの実行でも合格する最も大切な部分の破損
悪化なし符号検定が悪化と言わない少し直して、多く壊した変更

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

ゲートは終了コードで終わる

各ゲートは、失敗したときに自分の名前を、失敗のリストに加えます。スイートはリストを表示し、終了コードを返します。リストが空なら 0、そうでなければ 1 です。

ラボにはCIがありません。CIとは継続的インテグレーションの略で、変更のたびにチェックを動かす仕組みです。そこでは本物のスイートが、このスクリプトを動かし、1が返ったら公開を止めます。

記録済みの実行を書く

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// 各ケースの記録済みの3回の実行: [状態が正しい(1 か 0), 踏んだステップ数]。' 'const oldVersion = [' '  [[1, 4], [1, 4], [1, 5]], [[1, 5], [0, 6], [1, 5]], [[0, 6], [0, 7], [1, 6]],' '  [[1, 4], [1, 4], [1, 4]], [[1, 5], [1, 5], [0, 5]], [[0, 7], [0, 7], [0, 6]],' '];' 'const newVersion = [' '  [[1, 4], [1, 4], [1, 4]], [[1, 5], [1, 5], [1, 6]], [[1, 6], [0, 7], [1, 6]],' '  [[1, 5], [0, 5], [1, 5]], [[1, 5], [1, 5], [1, 5]], [[0, 7], [1, 7], [0, 7]],' '];' 'const settings = { minState: 70, stepGrowth: 20, must: [3] };' 'module.exports = { oldVersion, newVersion, settings };' > runs.js"

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

スイートを書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { oldVersion, newVersion, settings } = require(\"./runs\");' 'function states(version) {' '  return version.map(function (runs) {' '    return runs.filter(function (run) { return run[0] === 1; }).length;' '  });' '}' 'function stateRate(version) {' '  const total = states(version).reduce(function (a, b) { return a + b; }, 0);' '  return Math.floor(total * 100 / (version.length * version[0].length));' '}' 'function steps(version) {' '  let sum = 0;' '  version.forEach(function (runs) { runs.forEach(function (run) { sum = sum + run[1]; }); });' '  return sum;' '}' > suite.js"

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

スイートを書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function signP(better, worse) {' '  const n = better + worse;' '  if (n === 0) return 1;' '  let total = 0;' '  let ways = 1;' '  for (let i = 0; i <= Math.min(better, worse); i = i + 1) {' '    total = total + ways;' '    ways = ways * (n - i) / (i + 1);' '  }' '  return Math.min(1, 2 * total / Math.pow(2, n));' '}' 'const before = states(oldVersion);' 'const after = states(newVersion);' 'let better = 0;' 'let worse = 0;' 'before.forEach(function (n, at) {' '  if (after[at] > n) better = better + 1;' '  if (after[at] < n) worse = worse + 1;' '});' >> suite.js"

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

スイートを書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const failures = [];' 'const rate = stateRate(newVersion);' 'console.log(\"状態の率 \" + rate + \"%、必要なのは \" + settings.minState + \"%\");' 'if (rate < settings.minState) failures.push(\"状態の率\");' 'console.log(\"ステップ \" + steps(newVersion) + \"、旧は \" + steps(oldVersion) + \"、上限は \" + settings.stepGrowth + \"% 増\");' 'if (steps(newVersion) * 100 > steps(oldVersion) * (100 + settings.stepGrowth)) failures.push(\"ステップ\");' 'const broken = settings.must.filter(function (at) { return after[at] < newVersion[at].length; });' 'console.log(\"実行で失敗した必須ケース: \" + broken.map(function (at) { return at + 1; }).join(\"、\"));' 'if (broken.length > 0) failures.push(\"必須ケース\");' >> suite.js"

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

スイートを書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const p = signP(better, worse);' 'console.log(\"良い \" + better + \"、悪い \" + worse + \"、p \" + p.toFixed(3));' 'if (p < 0.05 && worse > better) failures.push(\"悪化\");' 'console.log(failures.length === 0 ? \"すべてのゲートを通過\" : \"失敗したゲート: \" + failures.join(\"、\"));' 'process.exit(failures.length === 0 ? 0 : 1);' >> suite.js"

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

スイートを動かし終了コードを読む

コマンド
docker exec -w /home/node/project agent node suite.js; echo 終了コード $?

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

スイートが表示するもの

行示すこと
状態の率77%、必要なのは70%。通過
ステップ旧95に対して98、上限は20%増。通過
必須ケースケース4が実行で失敗
良い悪い良い4、悪い1、p 0.375。通過
結果失敗したゲート: 必須ケース
終了コード1

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

試してみましょう

ヒント

runs.js で、新バージョンの4つ目のケースの2回目の実行を [0, 5] から [1, 5] に変えて、もう一度動かします。必須ケースのゲートは通り、終了コードは 0 になります。

よくある間違い

注意

良い変更がゲートに引っかかると、ゲートをゆるめる人がいます。失敗のあとに動かしたゲートは、何も守りません。ゲートが誤っていたなら、理由を書いて別の見直しで直します。そのゲートに失敗した変更の中では、決して直しません。

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

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