自動化とスクリプト¶
OpenTernaryのコマンドはすべて、スクリプト・CI・ほかのプログラムから操作できるように作られています。TUI自身も、これらの約束事を使う側の1つです。仕様の全体は出力のリファレンスにあり、このガイドでは使い方を説明します。
--json: stdoutに結果を1つ¶
--json を付けると、stdoutには1行だけ、バージョン付きのJSONが出ます。人間向けの出力(進捗・表・ログ・エラー)はすべてstderrに出ます。ターミナルでは両方が見えるので2回出たように見えますが、リダイレクトすると
JSONだけが保存されます:
{"schema_version": 1, "command": "quantize", "exit_code": 0,
"execution": "completed", "artifact_validation": "file_integrity", "quality_acceptance": "not_run",
"result": {"run_dir": "…/runs/ev", "run_id": "e67150d8", "artifact": "…/runs/ev/artifacts/snapshot", …},
"error": null}
exit_codeはプロセスの終了コードと同じです。execution・artifact_validation・quality_acceptanceは別々の判定です。resultの中身はコマンドごとに違います。errorは成功ならnull、失敗ならエラーの文言です。
JSONの内容は、表示言語(OPENTERNARY_LANG)に左右されません。
# シェル: jqで項目を読む
openternary plan ./my-model --json | jq -r '.result.targets | map(select(.quantizable)) | length'
--quiet は進捗の表示を止めますが、結果とエラーは出します。
終了コード¶
| コード | 意味 | よくある原因 |
|---|---|---|
0 |
成功(操作または計画が完了) | |
1 |
想定外の実行時・入出力のエラー | 不具合、ディスクの空き不足 |
2 |
設定・引数・入力の誤り | 設定の未知のキー、ファイルがない、compare で条件の違うrun |
3 |
非対応の機能 | quantize --device cuda、APIのバージョンが違うplugin |
4 |
必要な依存が入っていない | PyTorchなしでの量子化 |
5 |
必要なハードウェア・デバイスがない | setup のGPUの試験に失敗 |
6 |
明示した受入条件を満たさない/適格な候補がない | compare --require-acceptance、optimize |
7 |
探索の予算が尽きた | optimize |
130 |
中断 | Ctrl+C、TUIでの中止 |
終了コード 6 でも、コマンドは実行されています。execution は completed で、判定が否定的だったという意味です。
進捗イベント: --events-jsonl¶
ファイルの1行が1つのイベントです:
{"schema_version": 1, "sequence": 1, "command": "quantize", "run_id": null, "stage": "started", "completed": null, "total": null, "unit": null, "elapsed_s": 0.0, "detail": {}}
{"schema_version": 1, "sequence": 2, "command": "quantize", "run_id": "e67150d8", "stage": "run_created", "completed": null, "total": null, "unit": null, "elapsed_s": 0.004, "detail": {}}
{"schema_version": 1, "sequence": 3, "command": "quantize", "run_id": "e67150d8", "stage": "convert.tensors", "completed": 0, "total": 21, "unit": "tensor", "elapsed_s": 1.776, "detail": {"tensor": "lm_head.weight"}}
…
{"schema_version": 1, "sequence": 8, "command": "quantize", "run_id": "e67150d8", "stage": "completed", "completed": null, "total": null, "unit": null, "elapsed_s": 1.842, "detail": {}}
- ファイルはまだ存在しないものでなければなりません。2つの実行が誤って同じファイルに書くのを防ぐためです。親のフォルダは必要なら作られます。
- dry-runは何も書かないので、
--events-jsonlと--dry-runは併用できません。 sequenceはイベントごとに1ずつ増えます。不明な総量や単位はnullです。- 細かい段階は、段階ごとに毎秒5行までに間引きます。ただし、最初の行と
completed == totalの行は必ず書きます。
すべての段階と、その単位・detailの項目は、進捗イベントのリファレンス にあります。長い実行を別のターミナルから追うには:
対話できない環境での動作¶
OpenTernaryは、答える人がいないのに入力を待つことはありません:
- インストールには
--yesが必要です。 stdinがターミナルでないときや--json付きのとき、setupとupdateは--yesがなければ何も入れません(終了コード2)。 - パイプではTUIを開きません。 引数なしの
openternaryは、stdinとstdoutの両方がターミナルで、CIが設定されていないときだけTUIを開きます。それ以外ではhelpを表示して2で終わります。OPENTERNARY_NO_TUI=1で、どこでもこの動作にできます。 - 予期しない通信をしません。 自動で行う通信は、対話できる
doctorやTUIでの、1日1回のPyPIのバージョン確認だけです。OPENTERNARY_NO_UPDATE_CHECK=1で止められます。モデルをダウンロードすることはありません。
例: GitHub Actions¶
モデルを使わない確認は、GPUもPyTorchもモデルのダウンロードもなしに、どのrunnerでも動きます:
.github/workflows/openternary.yml
jobs:
plan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v9
- run: uv tool install openternary --python 3.12
- run: openternary doctor --json > doctor.json
- run: openternary calibrate --config configs/my-calibration.yaml --dry-run --json
GPUのあるself-hosted runnerのジョブでは、本番の流れを動かし、品質で止めることもできます:
set -e
openternary quantize "$MODEL" --config quant.yaml --output runs/candidate --json > /dev/null
openternary quality runs/candidate/artifacts/snapshot --data quality.json --device cuda --output runs/candidate-q --json > /dev/null
openternary compare runs/baseline-q runs/candidate-q --require-acceptance --output runs/gate --json > gate.json
# 候補が受け入れられなければ、ここで終了コード6になりジョブが失敗する
Pythonから¶
同じ機能を、子プロセスなしで使えます。Python APIを参照してください: