フック
フックは、Projectで何かが起きたとき(きっかけ)に、決めておいたJobを起動する仕組みです。左のサイドバーの「実行」にある[Hooks]で開きます。モデル登録後の自動実行はモデルの登録だけをきっかけにしますが、フックはRunの終了、checkpointの保存、外部からのwebhookもきっかけにでき、実行先にsiteも選べます。
フックは所有者の権限でJobを起動し、作るRunの作成者も所有者になります。所有者は、最初はフックを作った人です。
こんなときに向いています
- 学習Runが終わったら、そのRunのモデルと出力データで評価を回したい
- 学習中にcheckpointを保存するたびに、評価を回したい
- GitHubへのpushやデータの更新を合図に、外からJobを起動したい
- 決まった設定のJobを、本文(JSON)だけ変えて手で起動したい
きっかけ
| きっかけ | 起動するとき | Jobに渡すもの |
|---|---|---|
| 手動・起動API | フックの詳細の[手動で起動]か、API・Python SDKから起動したとき | 起動したときの本文(JSON) |
| モデルバージョンの登録 | モデルバージョンを登録したとき。学習中に登録したバージョンは、学習Runが終わるのを待ちます | 登録されたモデルバージョン |
| Runの終了 | Runが終わったとき。失敗・中止も含みます([Runの終了状態]で絞れます) | 選べば、そのRunのモデルバージョンと出力データセットバージョン |
| arrayの終了 | arrayのすべての番号の最後の試行が終わったとき | 選べば、すべての番号の出力データセットバージョン |
| checkpointの保存 | 学習RunがSDKでcheckpointを保存したとき | そのcheckpoint(Jobの中ではMMT_INPUT_CHECKPOINT_DIR、ふつうは/mmt/inputs/checkpoint) |
| 外部webhook | 署名の合うPOSTを受け取ったとき | 送られた本文 |
- MLflowの
checkpoints/step-N/に置いたcheckpointでは起動しません。ファイルが揃った時点が分からないためです。SDKのrun.log_checkpoint()を使ってください(学習の途中再開)。 - 学習中に登録したモデルバージョンは、学習Runが成功すると起動します。失敗・中止したときは起動しません。7日待っても終わらないときも起動しません。
- 同じ出来事では1回だけ起動します。webhookの再送や、終わったRunの再開と再終了でも、Jobは増えません。
Jobの中では、きっかけの内容を/mmt/context/trigger-payload.json(環境変数MMT_TRIGGER_PAYLOAD_FILE)として読めます。手動の起動では起動したときの本文、webhookでは送られた本文(JSONのオブジェクトでなければ{"body": "<本文>"})、そのほかのきっかけでは{"event": "run_finished", "runId": …}のような出来事の説明が入ります。
フックを作る
フックを作れるのはProjectのeditor以上です。
- [Hooks]を開き、右上の[フックを作成]を押します。
- 次の項目を入力して[作成]を押します。
- 一覧に追加されたフックを選び、詳細に設定が表示されることを確かめます。
作るときに、コードバージョン、実行先、Runtime、GPU、入力を、実際に起動するときと同じように確かめます。起動できない設定のフックは作れません。
きっかけ
| 項目 | 内容 |
|---|---|
| 名前 | フックの名前。例:学習後の評価 |
| きっかけ | 上の表から選びます |
| 署名の形式 | 外部webhookのとき。GitHub(X-Hub-Signature-256)かMMT(X-MMT-Signature)(webhookで起動する) |
| checkpointごとの起動 | checkpointの保存のとき。下の表 |
| 何個ごとに起動するか | [checkpointごとの起動]が「k個ごと」のとき。1〜100,000 |
| checkpointごとの起動 | 動き |
|---|---|
| 毎回 | 保存のたびに起動します(既定) |
| k個ごと | そのRunのk個ごとに起動します |
| 最新だけ(評価中に増えた分は最新の1つにまとめる) | 評価のJobが動いている間に来たcheckpointは、最新の1つだけが待ち、前の評価が終わると起動します |
| 実行中なら飛ばす | 評価のJobが動いている間に来たcheckpointでは起動しません |
きっかけの絞り込み
手動・起動APIと外部webhook以外のきっかけでは、どの出来事で起動するかを絞り込めます。空の項目では絞り込みません。条件に合わない出来事では起動せず、実行履歴も残しません。
| 項目 | 内容 |
|---|---|
| モデル系列 | 対象のモデル系列 |
| 実験 | 対象のExperiment |
| Runの実行種別 | 学習、推論など |
| Runの終了状態 | 完了、失敗、中止。Runの終了とarrayの終了のときだけ選べます(モデルバージョンの登録とcheckpointの保存の時点では、学習Runがまだ終わっていないため) |
| Runのタグ(JSON・すべて一致) | 例:{"dataset": "speech-v3"}。すべてのタグが一致するRunだけで起動します |
起動するJob
| 項目 | 内容 |
|---|---|
| Experiments | Runを記録するExperiment |
| 実行種別 | 学習、ファインチューニング、推論、評価、データ処理 |
| モデルバージョン | 固定のバージョン、または「きっかけのRunのモデルバージョンを使う」(Runの終了、arrayの終了、checkpointの保存)。モデルバージョンの登録では欄が無く、登録されたバージョンで起動します |
| コードバージョン | 実行種別とモデル系列に合うものだけを選べます |
| 入力データセットバージョン | 毎回渡すデータセットバージョン。任意 |
| きっかけのRunの出力データセットバージョンも入力にする | Runの終了とarrayの終了のとき |
| コンピュータ | コードバージョンのRuntimeを使えるコンピュータだけを選べます |
| GPU(選ばなければCPUのみ) | SSH・Localのコンピュータを選ぶと出ます。コンピュータに登録したGPUをチェックボックスで選びます。選ばなければCPUだけで実行します。GPUの無いコンピュータでは「このコンピュータにはGPUがないため、CPUのみで実行します。」と出ます |
| GPU数、制限時間、arrayの個数、arrayで分ける入力データセットバージョン | siteのとき。arrayの個数を入れると、1回の起動でarrayを作ります |
| パラメータ(JSON)、タグ(JSON) | automation.とmmt.で始まるタグはサーバーが付けるので使えません |
| 最大試行回数 | 1〜100。既定は1です。自動の再実行の上限で、Jobsの[新しいRunで再実行]で人が流し直す分は数えません |
| 失敗したら最初から再実行する、時間切れなら最新のcheckpointから再実行する | siteのとき。フックのJobが自動で再実行されるのは、これを選んだときです |
| このJobのコードから子Jobを作れる(ドライバー) | Jobのコードが、自分のJob tokenで子Jobを作れるようにします |
フックの詳細の[Jobごとの資源]には、SSH・LocalではGPU ID、siteではGPU数・制限時間・arrayの個数をまとめて出します。
手動投入のsiteを選ぶと、「この実行先は手動投入のsiteです。フックが作ったJobは、所有者がsiteのログインノードでmado-tracking submitを実行するまで待機します。」と出ます。一覧と詳細の実行先にも「手動投入」の印が付きます。投入のしかたは外部のコンピュータ(site)を参照してください。
起動の制限
| 項目 | 内容 |
|---|---|
| 前のJobが終わる前のイベント | 「すべて起動する」(既定)か「前のJobが実行中ならイベントをスキップする」。後者では、このフックのJobが動いている間に来た出来事では起動しません(後で起動もしません) |
| 1時間あたりの起動回数の上限 | 1〜10,000。既定は60です。直近1時間の起動が上限に達している間は、出来事が来ても起動しません |
手動で起動する
きっかけが「手動・起動API」のフックは、詳細の「手動で起動」から起動できます。起動できるのはProjectのeditor以上で、フックが有効なときだけです。
- 必要なら[本文(JSON・任意)]にJSONのオブジェクトを書きます。256KiBまでです。
- [手動で起動]を押し、確認で[起動する]を押します。
- 「起動を受け付けました(Jobを登録)。その後の結果は実行履歴で確認できます。」と出たら、[実行履歴]かJobsで進み具合を確かめます。
本文は、Jobの中で/mmt/context/trigger-payload.json(環境変数MMT_TRIGGER_PAYLOAD_FILE)として読めます。
Python SDKからも起動できます。人のAPI tokenを使います。Jobの中のJob tokenではフックを起動できません。
from mado_tracking import Client
with Client() as client:
client.trigger_hook("PROJECT_ID", "HOOK_ID", {"ref": "refs/heads/main"}, idempotency_key="deploy-42")同じidempotency_keyで送り直しても、起動は1回です。省くとSDKが付けます。
webhookで起動する
始める前に
API serverにMMT_HOOK_SECRET_KEY(base64の32 byte。openssl rand -base64 32で作れます)の設定が要ります。設定が無いと、きっかけが外部webhookのフックを作れません。サーバーの管理者に設定を頼んでください。この鍵を替えると、それまでのwebhookのフックは受け付けなくなるので、作り直して送信元の秘密鍵も替えます。
作る
- [フックを作成]で[きっかけ]を「外部webhook」にし、[署名の形式]を選んで作成します。
- 作成するとすぐに「Webhookの設定」が開き、「署名の秘密鍵」と「受け口のURL」がコピーボタン付きで出ます。
- 送信元に受け口のURLと秘密鍵を設定してから、[閉じる]を押します。
秘密鍵はこの画面で一度だけ表示します。閉じると二度と表示できません。受け口のURL(https://<この画面のホスト>/api/hooks/<フックのID>/webhook)は、後からでもフックの詳細にコピーボタン付きで出ます。APIをこの画面と別の名前で公開しているときは、そのホストにpathを付けます。
署名の形式
| 署名の形式 | 送信元の設定 | 再送の判定 |
|---|---|---|
| GitHub(X-Hub-Signature-256) | GitHubのリポジトリのWebhooksで、Payload URLに受け口のURL、Content typeにapplication/json、Secretに秘密鍵を設定します | X-GitHub-Deliveryが同じ再送は1回として扱います |
| MMT(X-MMT-Signature) | X-MMT-Signature: t=<unix秒>,v1=<HMAC-SHA256(秘密鍵, "<t>.<本文>")の16進>を付けて送ります。時刻のずれは5分まで受け付けます | X-MMT-Deliveryが同じ再送は1回として扱います |
再送を判定するヘッダが無い要求は、それぞれ別の出来事として起動します。LANの中の送信元やCIからは、MMTの形式が使えます。
body='{"dataset":"speech-v3"}'
t=$(date +%s)
sig=$(printf '%s.%s' "$t" "$body" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | sed 's/^.* //')
curl -sS -X POST "https://tracking.example.internal/api/hooks/$HOOK_ID/webhook" \
-H 'Content-Type: application/json' -H "X-MMT-Signature: t=$t,v1=$sig" \
-H "X-MMT-Delivery: $(uuidgen)" -d "$body"| 応答 | 意味 |
|---|---|
| 202 | 受け付けました。executionIdが実行履歴の記録です |
| 401 | 署名が一致しません |
| 409 | フックが無効です |
本文は256KiBまでです。受け口のURLを外へ公開するときは、入口のproxyで/api/hooks/*/webhookだけを通してください。
設定を変える
フックの設定は作成後に変えられません。変えられるのは、有効・無効と所有者だけです。過去の起動がどの設定で動いたかを、後から確かめられるようにするためです。
- 一覧の[操作]の[無効にする][有効にする]で切り替えます(editor以上)。無効にすると、以後の出来事では起動しません。待っている実行も起動しなくなります。
- 設定を変えたいときは、フックの詳細で[複製して新しく作る]を押します。今の設定を写した作成画面(「フックを複製して作成」、名前は
<元の名前>(複製))が開くので、変えたいところだけ直して[作成]を押します。元のフックはそのまま残るので、不要なら[無効にする]で止めます。 - 外部webhookのフックを複製すると、新しい受け口と秘密鍵になります。送信元の設定も変えてください。
- フックはまだ削除できません。無効にしたフックは、一覧に「無効」として残ります。
所有者をService Accountへ移す
フックを作った人がProjectのeditorでなくなると、そのフックは「起動せず(所有者がプロジェクトの権限を失っている)」になり、Jobを起動しなくなります。長く使うフックは、人に紐付かないService Accountへ所有者を移しておきます。
- Projectの設定で、roleがeditorかadminのService Accountを作ります。tokenを発行する必要はありません(API tokenとService Account)。
- フックの詳細の「Service Accountへ移す」で、[移管先のService Account]を選び、[Service Accountへ移す]を押して確定します。
- 一覧と詳細の[所有者]が、そのService Accountになったことを確かめます。
移管できるのはProject adminと全体管理者です。移管先は、同じProjectの有効なService Accountで、roleがeditorかadminのものに限ります。以後の起動はそのService Accountの権限で動き、作るRunの作成者もそのService Accountになります。フックを作った人の記録([作成者])は変わらず、移管は監査ログに残ります。
実行先がPrivateのコンピュータなら、そのコンピュータの所有者が作ったService Accountへ移します。ほかの人が作ったService Accountではそのコンピュータを使えないため、起動に失敗します(コンピュータと公開範囲)。
実行履歴を見る
[実行履歴]のタブ(フックの詳細の[実行履歴を見る]からも開けます)に、起動ごとの記録が新しい順に並びます。[表示するフック]で1つのフックに絞り込めます。古い記録は[さらに読み込む]で読み込みます。
| 列 | 内容 |
|---|---|
| 作成日時 | 出来事を受け取った日時 |
| フック | どのフックか(すべてのフックを表示しているとき) |
| 結果 | 下の表 |
| 対象 | きっかけの出来事(手動、モデルバージョン、Run、array、checkpoint、webhook)。モデルバージョン、Run、arrayは押すとその画面へ移ります |
| Jobの状態 | 作ったJobの状態 |
| 関連 | [Runを開く][Jobを開く][array][待っているRun] |
| ジョブエラー | 起動に失敗した理由 |
| 結果 | 意味 |
|---|---|
| Jobを登録 | JobかarrayのJobを作りました |
| Runの終了待ち | 学習中に登録したバージョンで、学習Runの終了を待っています。checkpointの保存の「最新だけ」で、前の評価の終了を待っているときにも出ます |
| 起動せず(理由) | 条件により起動しませんでした。理由は下の表です |
| 起動に失敗 | JobやRunを作れませんでした。理由は[ジョブエラー]に出ます。出来事そのものは取り消しません |
| 起動せずの理由 | 意味 |
|---|---|
| 同じ連鎖でこのフックが起動済み | このフックが起動したJobの終了で、同じフックがまた起動しようとしました。フックが自分のJobで起動し続けることはありません |
| 連鎖の深さが上限(10段)を超える | フックとドライバーのつながりが10段を超えました |
| 1時間あたりの起動回数の上限 | 直近1時間の起動が上限に達しました |
| 前のJobが終わっていない | 「前のJobが実行中ならイベントをスキップする」か「実行中なら飛ばす」で、このフックのJobがまだ動いています |
| 所有者がプロジェクトの権限を失っている | 所有者がProjectのeditorでなくなりました |
| 新しいcheckpointに置き換え | 「最新だけ」で、より新しいcheckpointが来ました |
| きっかけのRunが失敗・停止 | 学習中に登録したバージョンの学習Runが、成功しませんでした |
| Runの終了待ちの期限切れ | 学習Runが7日待っても終わりませんでした |
| フックが無効 | 待っている間にフックが無効にされました |
失敗したJobを流し直す
フックのJobの最大試行回数は、既定で1(自動の再実行なし)です。失敗したJobは、Jobsの[新しいRunで再実行]で人が流し直せます。最大試行回数に達したJobも流し直せます。流し直せるのは、Jobの作成者(フックの所有者)とProject adminです。再実行したJobにも、起動元としてフックが出ます。詳しくはJobsの画面を参照してください。
権限
| 操作 | 必要な権限 |
|---|---|
| フックと実行履歴を見る | viewer以上 |
| フックの作成、有効・無効の切り替え、手動の起動 | editor以上(API tokenはjobs:write) |
| 所有者の移管 | Project adminか全体管理者(API tokenはadmin scope) |
| webhookの受け口へ送る | 署名の秘密鍵を持つ送信元(ログインは要りません) |