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

無料レッスン

ルールで返事を採点する方法

このレッスンのあとで: 私は、モデルを使わないルールで、返事を採点できます。

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

別のモデルを使わずに採点する

ルールで返事を採点するとは、ふつうのコードで確かめることです。JSON として読めるか、ラベルは合っているか、数は範囲内か、といった確認です。ルールは速く、モデルの費用がかからず、いつも同じ答えを返すので役に立ちます。

ショップの振り分け機能は、ラベル、緊急度、客への1文を JSON で返すようになりました。どの部分も、ルールで確かめられます。

このレッスンのゴール

メモ

私は、モデルを使わないルールで、返事を採点できます。

キーワード

ことばいみれい
ルール返事が通るか落ちるかを決める、コードで書いた確認
完全一致値が期待する値と等しいこと請求
JSON として読める返事が求めた形式として解釈できること
範囲内数が2つの限度のあいだにあること
点数返事が通ったルールの数
禁止フレーズ返事に決して入れてはいけない言葉

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

4種類のルールで、ほとんど足りる

確認の多くは、4種類に収まります。JSON として読める: 返事が求めた JSON である。完全一致: 項目が期待する値である。範囲内: 数が限度のあいだにある。含む: あるフレーズが入っている、または入っていてはいけない。

どのルールも数行です。モデルは要らないので、実行に費用はかかりません。

例: 部分ごとに1つのルール

返事の部分ルール落ちる例
返事全体有効な JSON のオブジェクトもちろんです。これは配送のメッセージです
labelケースとの完全一致配送が期待なのに請求
urgency1から3の整数7
reply120文字まで、禁止フレーズなし返金を承認しました

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

ケースごとの点数で、壊れた場所が分かる

返事が通ったルール1つにつき、1点を与えます。最初の失敗で止めてはいけません。点数を見れば、どのルールが壊れたかが分かります。ケースが合格になるのは、すべてのルールを満たしたときだけです。

返事が JSON として読めなければ、後のルールは動かせないので、点数は 0 です。

モデルの補助を書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '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 || 200 }),' '      signal: AbortSignal.timeout(30000),' '    });' '    if (res.ok === false) throw new Error(\"status \" + res.status);' '    return (await res.json()).choices[0].message.content;' > model.js"

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

モデルの補助を書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  } catch (error) {' '    console.log(\"記録済みサンプル: モデルが答えませんでした (\" + error.message + \")。\");' '    const list = [].concat(sample);' '    const turn = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' '    return list[Math.min(turn, list.length - 1)];' '  }' '}' 'module.exports = { ask };' >> model.js"

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

ルールを書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const forbidden = [\"返金を承認しました\", \"保証します\"];' 'function score(text, want) {' '  const out = { parses: false, label: false, range: false, reply: false };' '  let data = null;' '  try { data = JSON.parse(text); } catch (error) { return out; }' '  if (data === null || Array.isArray(data) || typeof data === \"string\" || typeof data === \"number\" || typeof data === \"boolean\") return out;' '  out.parses = true;' '  out.label = data.label === want;' > score.js"

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

ルールを書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  out.range = Number.isInteger(data.urgency) && data.urgency >= 1 && data.urgency <= 3;' '  const said = typeof data.reply === \"string\" ? data.reply : \"\";' '  const low = said.toLowerCase();' '  const banned = forbidden.some(function (phrase) { return low.includes(phrase); });' '  out.reply = said.length > 0 && said.length <= 120 && banned === false;' '  return out;' '}' 'function points(out) {' '  return (out.parses ? 1 : 0) + (out.label ? 1 : 0) + (out.range ? 1 : 0) + (out.reply ? 1 : 0);' '}' 'module.exports = { score, points };' >> score.js"

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

確認のスクリプトを書く(1)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const { score, points } = require(\"./score\");' 'function reply(label, urgency, text) {' '  return JSON.stringify({ label: label, urgency: urgency, reply: text });' '}' 'const recorded = [' '  { id: 1, want: \"請求\", text: reply(\"請求\", 2, \"二重のご請求について確認いたします。\") },' '  { id: 2, want: \"配送\", text: reply(\"請求\", 2, \"確認いたします。\") },' '  { id: 3, want: \"その他\", text: \"もちろんです。これは配送のメッセージです。\" },' > check2.js"

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

確認のスクリプトを書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' '  { id: 8, want: \"配送\", text: reply(\"配送\", 7, \"申し訳ありません。\") },' '  { id: 10, want: \"不明\", text: reply(\"不明\", 1, \"返金を承認しました。\") },' '];' 'function yesNo(value) { return value ? \"はい\" : \"いいえ\"; }' 'function show(name, out) {' '  console.log(name + \": \" + points(out) + \" / 4 (JSON \" + yesNo(out.parses) + \", ラベル \" + yesNo(out.label) + \", 範囲 \" + yesNo(out.range) + \", 返事 \" + yesNo(out.reply) + \")\");' '}' 'for (const one of recorded) show(\"記録したケース \" + one.id, score(one.text, one.want));' >> check2.js"

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

確認のスクリプトを書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const sample = reply(\"請求\", 2, \"ご注文の内容を確認いたします。\");' '  const prompt = \"このお店のメッセージを仕分けてください。3つのキーを持つ JSON だけで答えてください。label (請求、配送、その他、不明のどれか)、urgency (1から3の整数)、reply (100文字より短い丁寧な1文) です。\n\nメッセージ: 同じ注文が二重に請求されました\";' '  const text = await ask([{ role: \"user\", content: prompt }], sample, 120);' '  console.log(\"実際の返事: \" + text);' '  show(\"実際のケース 1\", score(text, \"請求\"));' '}' 'main();' >> check2.js"

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

記録5つと実際の1つを採点する

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

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

出力の一例

行示す内容
記録したケース 14 / 4、すべてのルールを満たす
記録したケース 23 / 4、ラベルが違う
記録したケース 30 / 4、JSON ではなく文章
記録したケース 83 / 4、緊急度 7 が範囲の外
記録したケース 103 / 4、禁止フレーズ
実際のケース 1たいてい 3 か 4 / 4。実行のたびに変わることがある

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

試してみましょう

ヒント

score.js に3つ目の禁止フレーズ「二重のご請求について」を足して、もう一度実行します。記録したケース 1 は、最後の1点を失うはずです。

よくある間違い

注意

ルールで満点なら良い返事だと考える人が多くいます。ルールが確かめるのは形と事実だけです。JSON として読め、ラベルも合っていて、それでも失礼で役に立たない返事はありえます。ルールはコードで決められることに使いましょう。

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

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