Fragments of verbose memory

冗長な記憶の断片 - Web技術のメモをほぼ毎日更新

Sep 18, 2026 - 日記

JevをCLIから試す: 型付き判定を返す非公式jev-cli

JevをCLIから試す: 型付き判定を返す非公式jev-cli

先日、TypeSafe Jev を試しました。 Jevは文章を生成するLLM とは少し違います。 入力した状態(state)について質問すると、確率や選択肢などの型付きデータが返ります。

実際に触ると、問い合わせの振り分けや緊急度判定をシェルから試したくなりました。 そこで、非公式CLIのjev-cli を作りました。 Python標準ライブラリだけで動き、結果をJSONまたは単一の値として受け取れます。

jev-cliは個人で開発している非公式ツールです。TypeSafe AIによる公式実装ではなく、同社との提携や承認を示すものでもありません。

Jevは文章ではなく判定結果を返す

TypeSafeはJevを「System One model」と説明しています。 状態と型付きの質問を送り、コードからそのまま使える構造化データを受け取るモデルです。

利用できる質問形式は3種類あります。

  • noul:Yes/Noの確率を、0から1の値で返す
  • choice:候補から1つ選び、確率分布と確信度(confidence)も返す
  • score:順序のある基準で評価し、スコア、確率分布、確信度を返す

たとえば、「この問い合わせは緊急か」という質問ならnoulを使います。 返り値が0.92なら、Yesの確率が92%という意味です。

返答から答えを抜き出す処理は不要です。 アプリケーション側では、0.9以上なら担当者へ通知する、といった分岐をそのまま書けます。

jev-cliをインストールする

PyPIのjev-cli はPython 3.13以降に対応しています。 CLIを独立した環境へ入れるため、uv のtool機能を使います。 インストール後にバージョンが表示されれば準備完了です。

1
2
uv tool install jev-cli
jev --version

記事執筆時点のバージョンでは、次のように表示されます。

1
jev 0.4.1

APIキーを安全に保存して接続確認する

TypeSafeのAPIキーを取得したら、auth setでローカルの資格情報ストアへ保存します。 キーは非表示の対話プロンプトで入力するため、コマンドライン引数やシェル履歴へ残りません。 auth testはJevへ最小リクエストを送り、保存したキーが実際に使えるか確認します。

1
2
jev auth set
jev auth test

キーが有効なら、次のJSONが返ります。

1
{"ok": true, "valid": true, "model": "jev-1.13.0"}

自動化では環境変数TYPESAFE_API_KEYも使えます。 環境変数はローカルの資格情報ストアより優先されます。

なお、auth testで分かるのは、キーがAPIに受理されたかどうかです。 公開APIにはクレジット残額を照会するエンドポイントが見当たらないため、残額までは確認できません。

Noulで緊急度を判定する

以下の例では、問い合わせが緊急性を表しているか判定します。 -qは質問、-sは判定対象の状態です。 --valueを付けると、APIレスポンス全体ではなく判定値だけを標準出力へ出します。

1
2
3
4
jev noul \
  -q 'Does this message express urgency?' \
  -s 'Please respond today.' \
  --value

手元で実行した結果は次のとおりでした。

1
0.92

質問と状態は別の入力です。 「何を判断するか」を-qへ、「何について判断するか」を-sへ渡します。 ここを分けておくと、同じ質問を別の問い合わせへ再利用できます。

Choiceで担当チームを選ぶ

候補が決まっている分類にはchoiceを使います。 各候補はKEY=説明の形で渡します。 キーを短く安定した値にしておけば、そのままプログラムの分岐へ使えます。

1
2
3
4
5
6
7
jev choice \
  -q 'Which team should handle this?' \
  -s 'The payment integration keeps failing.' \
  -o 'billing=Payment, charge, or refund issues' \
  -o 'technical=Bugs or integration failures' \
  -o 'other=None of these' \
  --value

この例を実行すると、次の値が返りました。

1
technical

完全なJSONが必要な場合は--valueを外します。 選ばれたキーに加え、各候補の確率と確信度も確認できます。 自動処理の閾値は、この分布を実データで評価してから決めた方がよいでしょう。

複数の質問を1回で送る

同じ状態に対する質問は、runで1つのAPIリクエストへまとめられます。 Jevは各質問を独立して評価するため、担当分類と緊急度を同時に聞けます。

まず、状態と質問をJSONへまとめます。 この例では問い合わせ本文を一度だけ送り、choicenoulの2種類で評価します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "state": {
    "message": "The payment integration has failed for three days. Please fix it today."
  },
  "model": "jev-latest",
  "questions": {
    "department": {
      "type": "choice",
      "instructions": "Which team should handle `message`?",
      "criteria": {
        "billing": "Payment, charge, or refund issues",
        "technical": "Bugs or integration failures",
        "other": "None of these"
      }
    },
    "urgent": {
      "type": "noul",
      "instructions": "Does `message` express urgency?"
    }
  }
}

上の内容をrequest.jsonとして保存し、次のコマンドで送信します。 --prettyは結果を読みやすく整形するだけで、判定内容は変えません。

1
jev run request.json --pretty

手元のスモークテストでは、担当はtechnical、緊急度は0.96になりました。 関連する判定を1回のリクエストへまとめられるため、状態を質問ごとに送り直さずに済みます。

Agent Skillも同梱した

AI エージェントからCLIを正しく使えるよう、jev-cli用のAgent Skillもパッケージへ同梱しました。 以下のコマンドは、現在のプロジェクトに.agents/skills/jev-cliを作ります。 既存の同名ディレクトリがユーザー管理なら上書きしません。

Agent Skillsの仕組み自体は、以前の記事「Agent Skillsに対応した最小のAIエージェントをPythonで書いてみる 」で詳しく扱っています。

1
jev install-skills

グローバルへ入れる場合は--global、Claude向けの.claude/skillsへ入れる場合は--claudeを使います。

1
2
3
jev install-skills --global
jev install-skills --claude
jev install-skills --global --claude

CLIのコマンドだけでなく、質問形式の選び方や秘密情報を送らないといった注意点も一緒に配れます。

Jevが向く用途、向かない用途

Jevが向くのは、自然言語で表された状態を、あらかじめ決めた型で判定する用途です。

  • 問い合わせを既知の担当先へ振り分ける
  • 緊急性や返金要求の有無を確率で判定する
  • 定義した段階に沿って不満度や深刻度を評価する
  • 確信度が低い結果だけ人間へ回す

計算、日付比較、厳密な文字列照合は通常のコードで処理した方が確実です。 自由な文章生成や長い多段推論もJevの役割ではありません。

確率に万能な閾値はありません。 0.9を超えたら自動処理してよいかは、誤判定の損失と実データ上の精度で決める必要があります。 特に顧客対応や安全に関わる用途では、判定結果をそのまま最終決定にせず、人間確認へ送る境界を先に設計すべきです。

入力した状態と質問はTypeSafe APIへ送信されます。 組織として外部送信が許可されたデータだけを渡してください。

生成AIのJSON出力とは少し違う道具

最初は「LLMへJSONで答えさせるのと何が違うのだろう」と思っていました。 Jevは自由形式の回答をあとからJSONへ整形するのではなく、質問をNoulChoiceScoreのいずれかとして送ります。

何でも答えるモデルではありません。 その代わり、入力を分類し、確率に応じて次の処理を選ぶコードには組み込みやすい設計です。

jev-cliは、その使い勝手をターミナルで確かめるための薄いクライアントです。 判定軸を手早く試したい場合や、シェルスクリプトから呼び出したい場合に使ってみてください。

参考リンク