ツールはモデルの説明書
エージェント向けのツールを設計するとは、モデルが正しく使えるように、名前、説明、引数、エラーを書くことです。これらの言葉が、モデルにとって唯一の説明書です。
do という名前で、曖昧なオプションが五つあるツールは、当てずっぽうで使われます。read_file という名前で、パスが一つのツールは、うまく使われます。
このレッスンのゴール
メモ
モデルが正しく使えるツールを、分かりやすい名前、示した制限、役に立つエラーで書ける。
キーワード
| ことば | いみ |
|---|---|
| ツール | エージェントがハーネスに実行を頼める関数 |
| 説明 | いつツールを使うかをモデルに伝える言葉 |
| 狭いツール | 仕事を一つだけするツール |
| 引数 | ツールが受け取る、名前の付いた入力 |
| 曖昧さ | 一つの作業に合いそうに見える二つのツール |
| ツールのエラー | ツールが失敗したときに返す文章 |
学生が入力するセルは、このプレビューでは空白です。
狭いツールは広いツールに勝つ
狭いツールは、仕事を一つだけして、引数も少ないツールです。run_anything(options) のような広いツールは、モデルに小さな言語を作らせるので、よく間違えます。
仕事ごとにツールを分けます。read_file、write_file、list_files のようにします。引数は四つ以下にします。それ以上必要なツールは、たいてい二つのツールです。
名前と説明は、使わない場面も伝える
名前は動詞と名詞にします。helper ではなく search_text です。説明は、ツールが何をするかに加えて、いつ使わないかも書きます。
この二つ目の文が、似た二つのツールを分けます。これがないと、モデルは read_file と search_text を当てずっぽうで選び、トレースを見て初めて気づきます。
確かめる欠点
| 欠点 | 見た目 | 直し方 |
|---|---|---|
| 曖昧な名前 | `do`、`helper` | 動詞と名詞にする |
| 短い説明 | `いろいろします` | 何を読み、何を変えるかを書く |
| 制限がない | 「使わないでください」がない | 何には向かないかを足す |
| 引数が多すぎる | 五つ以上 | ツールを分ける |
学生が入力するセルは、このプレビューでは空白です。
エラーはモデルのために書く
ツールのエラーは、モデルが次に読む入力です。だからモデルのために書きます。何がうまくいかなかったかと、次に何をするかです。
エラー: src/app.pyy にファイルがありません。list_files を呼んでから、もう一度試してください。 は、立ち直り方を伝えます。ENOENT(ファイルがないときにシステムが返す記号)だけでは伝わりません。拒否のときは、再試行しないよう書きます。そうしないと、モデルは何度も繰り返します。
よくある間違い
注意
多くの人は、ツールの言葉を自分のために、短く書きます。モデルには、それしか手がかりがありません。コードを一度も見ていない同僚に向けて、説明を書きます。
モデル用の補助を書く(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 VAGUE = [\"do\", \"run\", \"handle\", \"tool\", \"helper\", \"process\", \"util\"];' 'const tools = [' ' { name: \"read_file\", description: \"ファイルのパスを受け取り、その文字を読みます。フォルダには使わないでください。\", params: [\"path\"] },' ' { name: \"search_text\", description: \"プロジェクトの全ファイルから、ある単語を含む行を探します\", params: [\"word\"] },' ' { name: \"do\", description: \"いろいろします\", params: [\"a\", \"b\", \"c\", \"d\", \"e\"] },' '];' > tools2.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ツールの点検を書く(2)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function faults(tool) {' ' const found = [];' ' if (VAGUE.includes(tool.name)) found.push(\"vague-name\");' ' if (Array.from(tool.description).length < 20) found.push(\"short-description\");' ' if (tool.description.includes(\"使わないでください\") === false) found.push(\"no-limit\");' ' if (tool.params.length > 4) found.push(\"too-many-params\");' ' return found;' '}' >> tools2.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ツールの点検を書く(3)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function errorText(e) {' ' if (e.code === \"not_found\") return \"エラー: \" + e.path + \" にファイルがありません。list_files を呼んでから、もう一度試してください。\";' ' if (e.code === \"too_big\") return \"エラー: \" + e.path + \" は \" + e.size + \" 行あり、上限は \" + e.limit + \" 行です。行の範囲を指定してください。\";' ' return \"エラー: \" + e.code + \"。再試行しないでください。\";' '}' >> tools2.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ツールの点検を書く(4)
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' for (const t of tools) console.log(t.name + \": \" + (faults(t).join(\", \") || \"欠点なし\"));' ' console.log(errorText({ code: \"not_found\", path: \"src/app.pyy\" }));' ' console.log(errorText({ code: \"too_big\", path: \"data.csv\", size: 9000, limit: 500 }));' ' const list = tools.slice(0, 2).map(function (t) { return t.name + \": \" + t.description; }).join(\" | \");' ' const task = \"src/app.py の最初の数行を見せてください。ツールの名前だけで答えてください。\";' ' const reply = await ask([{ role: \"user\", content: \"ツール: \" + list + \" | \" + task }], \"read_file\", 10);' ' console.log(\"モデルが選んだもの: \" + reply.text);' '}' 'main();' >> tools2.js"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ツールの点検を実行する
docker exec -w /home/node/project agent node tools2.jsここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
呼び出しが示すこと
ラボのモデルは、ツール呼び出し機能のない、ふつうの文章で使います。そこで Run は、ツールの説明をプロンプトに貼り付けて、ツールの名前を尋ねます。言葉が説明書だと示すには、それで十分です。
点検と二つのエラーには、モデルは要りません。
出力の一例
| 行 | 示すこと |
|---|---|
| read_file: 欠点なし | 制限のある、狭いツール |
| search_text: no-limit | いつ使わないかを言っていない |
| do: vague-name, short-description, no-limit, too-many-params | 一つのツールに四つの欠点 |
| エラー: src/app.pyy にファイルがありません。list_files を呼んでから、もう一度試してください。 | 次の手順のあるエラー |
| エラー: data.csv は 9000 行あり、上限は 500 行です。行の範囲を指定してください。 | 要求を減らす方法のあるエラー |
| モデルが選んだもの: ... | たぶん read_file です。言葉は実行のたびに変わる |
学生が入力するセルは、このプレビューでは空白です。