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

無料レッスン

ツールが失敗したときの対処

このレッスンのあとで: モデルが立て直せるように、ツールのエラーを結果として返せる。

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

ツールは失敗する。モデルが助けになる

ツールは失敗することがあります。商品が存在しない、サービスが遅い、モデルが悪い値を送ってきた、などです。プログラムがクラッシュすると、アシスタント全体が止まってしまいます。

プログラムがエラーを結果として返せば、モデルはそれを読んで立て直せます。

このレッスンのゴール

メモ

モデルが立て直せるように、ツールのエラーを結果として返せる。

キーワード

ことばいみ
例外関数が終われないときに起こすエラー
エラー結果何が悪かったかを伝えるツールメッセージ
再試行同じ呼び出しをもう一度試すこと
タイムアウト時間がかかりすぎて打ち切られた呼び出し
あきらめる試すのをやめて、失敗を報告すること

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

エラーは読める結果になる

呼び出しをtryで包みます。エラーが起きても止まらず、メッセージをツールメッセージに入れます。たとえばエラー:見つからない:キウイのようにして、もう一度モデルに聞きます。

モデルは、その言葉を見ます。ユーザーに謝ることも、別の商品を試すこともできます。ループにはステップ上限があるので、永遠には続きません。

例で確認:失敗ごとの扱い

何が悪かったか再試行する?モデルへのメッセージ
商品が店にないしないエラー:見つからない:キウイ
値が許されないしないエラー:負の数です
引数が合わないしないエラー:引数が不正です
サービスがタイムアウトしたする(数回まで)エラー:時間切れ(最後の試行のあと)

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

モデルを呼ぶヘルパーを保存する

コマンド
docker exec -w /home/node/project agent node -e "const ask=async(m,t,c)=>{const r=await fetch((process.env.AI_URL||'http://ai:4000')+'/v1/chat/completions',{method:'POST',headers:{'content-type':'application/json',authorization:'Bearer lab'},body:JSON.stringify({model:'lab',messages:m,tools:t,tool_choice:c,max_tokens:120})});const j=await r.json();if(r.ok)return j.choices[0].message;throw Error(r.status+' '+j.error.message)};require('fs').writeFileSync('ai.cjs','exports.ask='+ask+';');console.log('ai.cjsを保存しました:ask(messages, tools)はモデルのメッセージを返します。')"

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

失敗するツールと不安定なツールを包む

コマンド
docker exec -w /home/node/project agent node -e "let n=0;const flaky=()=>{n++;if(n<3)throw Error('timeout');return 'ok'};const price=a=>{if((a.item=='りんご')===false)throw Error('見つからない:'+a.item);return 120};const call=(f,a,tries)=>{for(let i=1;;i++){try{return{ok:true,result:String(f(a)),attempts:i}}catch(e){if(e.message=='timeout'&&i<tries)continue;return{ok:false,error:e.message,attempts:i}}}};console.log(JSON.stringify(call(price,{item:'りんご'},3)));console.log(JSON.stringify(call(price,{item:'キウイ'},3)));console.log(JSON.stringify(call(flaky,{},3)))"

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

次にうまくいくものだけ再試行する

タイムアウトは過ぎ去ることがあるので、もう一度試すと助けになります。ないものはやはりないので、再試行しても時間の無駄です。

試行回数を決め、呼び出しごとに数え、使い切ったら分かりやすいメッセージであきらめます。何回試したかも伝えましょう。

モデルにエラーを返す

コマンド
docker exec -w /home/node/project agent node -e "const{ask}=require('./ai.cjs');const P={りんご:120,なし:150};const T=[{type:'function',function:{name:'get_price',description:'値段を返す。',parameters:{type:'object',properties:{item:{type:'string'}}}}}];const go=async(m,f)=>{try{return await ask(m,T)}catch(e){console.log('モデルなし('+e.message+')。記録済みサンプル:');return f}};(async()=>{const m=[{role:'user',content:'キウイはいくらですか。'}];const a=await go(m,{role:'assistant',tool_calls:[{id:'c1',function:{name:'get_price',arguments:JSON.stringify({item:'キウイ'})}}]});m.push(a);const c=a.tool_calls?.[0];if(c==null)return console.log('答え:'+a.content);const i=JSON.parse(c.function.arguments).item;const r=i in P?String(P[i]):'エラー:見つからない:'+i;console.log('ツール結果:'+r);m.push({role:'tool',tool_call_id:c.id,content:r});const b=await go(m,{role:'assistant',content:'キウイはありません。'});console.log('そのあと:'+(b.content||JSON.stringify(b.tool_calls[0].function)))})()"

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

よくある間違い

注意

ツールが失敗したら、会話全体が失敗したと思っている人が多くいます。そうではありません。エラーは、もう1つの結果にすぎません。テキストで返し、ステップ上限を保ち、どうするかはモデルに決めさせましょう。

さらに:試行回数を変える

ツールを包む実行の最後の呼び出しcall(flaky,{},3)で、試行回数の3を2に変えて、もう一度実行します。最後の行を見ましょう。ほかの2つの呼び出しの3は、そのままにします。

何が変わるか、そして試行に上限がなぜ大切かを書き留めます。

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

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