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

無料レッスン

LLM ゲートウェイの役割

このレッスンのあとで: 私は、モデル呼び出しの前に置くゲートウェイの役割を説明できます。

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

なぜゲートウェイを通すのか

LLM ゲートウェイは、すべてのモデル呼び出しが通る一つのサービスです。提供元のキーを持ち、上限を適用し、呼び出しを記録し、モデルを選びます。チームごとにモデルを直接呼ぶと、同じ規則をチームの数だけ作ることになるからです。

ある会社に、モデルを呼ぶ製品が三つあります。一つはビルドのログにキーを漏らしました。もう一つは上限がなく、一晩で一か月分の予算を使いました。ゲートウェイがあれば、直す場所は一つで済みます。

このレッスンのゴール

メモ

私は、モデル呼び出しの前に置くゲートウェイの役割を説明できます。

キーワード

ことばいみ
ゲートウェイすべてのモデル呼び出しが通るサービス
クライアントキーチームがゲートウェイに入るためのキー
レート制限一定の時間に受け付ける数の上限
ルーティングどのモデルに任せるかを選ぶこと
リクエストログ呼び出しごとの記録。本文は含めない

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

ゲートウェイの四つの仕事

仕事はどれも、呼び出しの前か後に適用する規則です。キー: 呼び出す側はクライアントキーを持ち、提供元のキーを持つのはゲートウェイだけです。上限: チームと分ごとの数え方です。ルーティング: 規則でモデルを選びます。ログ: 呼び出しごとに一行残します。

すべての呼び出しが一つの関数を通るので、規則を変える場所は一か所です。

例: 五つのリクエスト、上限は二

リクエストキー語数結果
1key-tokyo40ok、小モデル
2key-tokyo500ok、大モデル
3key-tokyo20制限: tokyo はすでに二件
4key-zzz10拒否: そのキーはない
5key-osaka80ok、小モデル

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

ログに残してよいもの

ログには、ID、チーム、ステータス、モデル、サイズ、時刻を残します。プロンプトの本文は残しません。プロンプトには個人情報が入ることがあり、ログは機能そのものより多くの人が読むからです。

ゲートウェイは、止まるとすべての呼び出しが止まる点にもなります。タイムアウトを決め、コピーを複数動かし、規則は小さく保ちます。

よくある間違い

注意

キーを確かめるから呼び出しが安全になる、と考える人は多いです。確かめるのは誰が呼んだかで、何を頼んだかではありません。正しいキーでも、有害なプロンプトは送れます。上限とログは被害を小さくしますが、本文の良し悪しは判断しません。

モデル用の補助を書く(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 { ask } = require(\"./model\");' 'const KEYS = { \"key-tokyo\": \"tokyo\", \"key-osaka\": \"osaka\" }; // 作り物のキー' 'const LIMIT = 2; // チームごとに受け付ける数' 'const counts = {};' 'const log = [];' > gateway.js"

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

ゲートウェイを書く(2)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function choose(request) {' '  return request.words > 300 ? \"大モデル\" : \"小モデル\";' '}' 'function gateway(request) {' '  const team = KEYS[request.key];' '  let status = \"ok\";' '  if (team === undefined) status = \"拒否\";' '  else if ((counts[team] || 0) >= LIMIT) status = \"制限\";' '  if (status === \"ok\") counts[team] = (counts[team] || 0) + 1;' '  const model = status === \"ok\" ? choose(request) : \"なし\";' '  log.push({ id: request.id, team: team || \"不明\", status: status, model: model });' '}' >> gateway.js"

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

ゲートウェイを書く(3)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const requests = [' '  { id: 1, key: \"key-tokyo\", words: 40 },' '  { id: 2, key: \"key-tokyo\", words: 500 },' '  { id: 3, key: \"key-tokyo\", words: 20 },' '  { id: 4, key: \"key-zzz\", words: 10 },' '  { id: 5, key: \"key-osaka\", words: 80 },' '];' 'requests.forEach(function (r) { gateway(r); });' 'log.forEach(function (row) { console.log(row.id, row.team, row.status, row.model); });' >> gateway.js"

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

ゲートウェイを書く(4)

コマンド
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' '  const sample = \"ゲートウェイは、キーと上限とログを一か所にまとめます。\";' '  const messages = [{ role: \"user\", content: \"一文で答えてください。モデル呼び出しの前にゲートウェイを置くのはなぜですか。\" }];' '  console.log(\"リクエスト 1 の本物の呼び出し:\", await ask(messages, sample, 60));' '}' 'main();' >> gateway.js"

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

ゲートウェイを動かす

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

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

本物ではなく代用品です

このゲートウェイは、リストに対する関数です。ラボにはサービスのネットワークがないので、上限は変数に入っています。本物のゲートウェイは、数を共有の保管場所に置くサービスで、どのコピーも同じ数を見ます。

ここでは、プラットフォームがすでにその役をしています。あなたのトークンを付け、本物の呼び出し一回分のモデルを選びます。

出力の一例

行何を示すか
1 tokyo ok 小モデル受け付けて、小さいモデルに送った
3 tokyo 制限 なし断った。モデルには何も送らない
4 不明 拒否 なし断った。チームが分からない
本物の呼び出しモデルからの短い一文。または、ラベル付きの記録済みサンプル

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

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

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