Ollama × Jevライクモデルで始める意思決定モデルの活用

ChatGPTをはじめとするLLMは、チャットや文章生成では既に「超人的」と言えるレベルに達しています。しかし、実際の業務システムに目を向けると、「このサポートチケットはどのチームが担当すべきか」「この問い合わせは緊急か」といった、地味だけれど量が多い判定・分岐処理は、依然として人手のルールベース実装やLLMへの力任せな問い合わせに頼っているケースが少なくありません。
LLMにこうした判定を丸投げすると、応答に数秒〜数十秒かかり、1トークンあたりのコストもかかるうえ、たまに期待した形式で返ってこない(ハルシネーション)という問題が付きまといます。チャットには向いているLLMのアーキテクチャが、「型が決まった小さな決定を高速に、安く、確実に下す」という用途にはあまり向いていないのです。
この課題に対して2026年9月、TypeSafe AI社がSystem One Modelsという新しいモデル層と、その第一号モデルJevを発表しました。そして同時期、Ollama上でも同じ思想を持つ「決定モデル」が複数公開され、その一つが今回実際に手元で動かしてみた tev1 です。
この記事では、Jev / System One Models がどういう発想のモデルなのかを整理した上で、Ollamaで実際にtev1を動かし、公式クライアント(ollamaパッケージ)と、TypeSafe社のSDK(typesafe-sdk)の両方から呼び出せることを確認します。
Jev / System One Models とは
Jevは、TypeSafe AI創業者のDiogo Almeida氏(OpenAI出身、InstructGPT/RLHFの共同発明者)が発表した、判断に特化したAIモデルです。自由な文章を生成する代わりに、あらかじめ定義した「質問」に対して型付きの値と確率を返します。
3つの質問タイプ
Jev、および以降で紹介するOllama上の同系モデルは、いずれも次の3種類の質問タイプをサポートします。
| タイプ | 用途 | 返り値 |
|---|---|---|
choice | 複数の候補から1つを選ぶ | 選択結果 + 候補ごとの確率 + confidence |
noul | はい/いいえを判定する | 0〜1の確率値(1に近いほど「真」) |
score | 段階的な評価をする | 期待値(score) + 確率分布 + legend(段階の説明) + confidence |
noulというあまり聞かない単語が出てきますが、これは「真である確率」を表すJev独自の用語です。
既存LLM(System Two的アプローチ)との対比
TypeSafe社は、人間の「速い・直感的な思考」と「遅い・論理的な思考」を対比したカーネマンの「システム1 / システム2」という概念に倣って、既存のLLMを「System Two的アプローチ」、Jevのような新しいモデル層を「System One Models」と位置づけています。
| 項目 | 既存LLM(System Two的) | System One + Jev |
|---|---|---|
| 最適化目標 | 人間の好み (RLHF/RLVR) | 校正済み決定の正確性 |
| 出力形式 | 自由文字列(柔軟だが曖昧) | 型安全な構造化値 |
| サンプリング | 逐次(トークン単位) | 並列(単一クエリで全出力) |
| 入力コスト | $0.20〜10/MTok | $0.042/MTok |
| 出力コスト | 入力の約5倍 | 無料(計測不能レベル) |
| 応答速度 | 3〜329秒 | 70〜500ms |
| ハルシネーション | 発生する | 型エラーとしては発生しない |
学習方法にはRLCD (Reinforcement Learning for Calibrated Decisions) という手法が使われており、「確率的に校正された決定」、つまり「80%と答えたときには実際に80%の確率で正しい」という性質を学習させることに重点を置いています。
向いている用途・向いていない用途
公式ブログ等の情報を総合すると、次のような整理になります。
向いている用途
- サポートチケットやメールの自動振り分け
- ポリシー該当性の判定、コンテンツ審査
- LLMの出力やプロンプトの検証・ガードレール
- 大量データに対するマップ・リデュース的な特徴抽出
向いていない用途
- 長文生成や根拠の説明が必要な処理
- 画像・音声・動画の直接判断(※一部モデルはマルチモーダル対応、後述)
- 数値計算や日付の境界判定など、本来コードで正確に処理すべきもの
Ollamaで使えるJevライクモデル
Jev自体は2026年10月時点ではTypeSafe社のクラウドAPI上での早期アクセス提供ですが、同じ「状態(state)と型付き質問(questions)から決定を返す」というコンセプトを持つモデルが、Ollama上でも複数公開されています。いずれも/v1/systemoneという共通のAPIエンドポイントを実装しているのが特徴です。
| モデル | 提供元 | パラメータ数 | 特徴 |
|---|---|---|---|
| tev1 | Together AI | 4B / 0.8B | 標準的な決定モデル。精度73.3%(4B)/63.5%(0.8B) |
| nimble | Bespoke Labs | 9B | 精度75.7%(4モデル中最高)。M5 Max搭載Macで100ms未満 |
| clef | Cloudflare | 27B | マルチモーダル対応、256Kコンテキスト、高精度 |
| clef-flash | Cloudflare | 9B | clefの軽量版。約5倍高速、低遅延(中央値38.8ms) |
精度はOllama公開の評価(13の公開データセット、3,880件の決定)による比較値[^4]。
選び方のざっくりした指針は次の通りです。
- 精度最優先・画像入力も使いたい → clef
- 精度と速度のバランスを取りたい → nimble
- とにかく軽量に、手元でまず試したい → tev1(本記事の検証対象)
- 低遅延最優先でマルチモーダルも欲しい → clef-flash
今回は手元の環境に最初にインストールしたtev1を使って、実際にコードから呼び出してみます。
Ollama 公式クライアントを利用する場合
事前準備
Ollama環境にtev1をインストールし、サーバーを起動しておきます。
ollama pull tev1
ollama serve
今回は、Pythonの依存関係を uv で管理し、公式クライアントを追加します。
uv add ollama
サンプルコード
サポートチケットの本文を渡し、「カテゴリ分類(choice)」「緊急対応が必要か(noul)」「深刻度(score)」の3つを一度に判定させる例です。
"""tev1 (Ollama の System One モデル) を使った意思決定サンプル。"""
from __future__ import annotations
import sys
import ollama
if sys.stdout.encoding is not None and sys.stdout.encoding.lower() != "utf-8":
sys.stdout.reconfigure(encoding="utf-8")
def classify_support_ticket(ticket_text: str) -> None:
response = ollama.systemone(
model="tev1",
state=ticket_text,
questions={
"category": {
"type": "choice",
"instructions": "このチケットはどのカテゴリに分類されますか?",
"criteria": {
"billing": "請求・支払いに関する問い合わせ",
"technical": "製品の不具合やエラーに関する問い合わせ",
"account": "アカウントやログインに関する問い合わせ",
"other": "それ以外の問い合わせ",
},
},
"is_urgent": {
"type": "noul",
"instructions": "このチケットは緊急対応が必要ですか?",
"criteria": {
"true": "サービス停止やデータ損失など、即時対応が必要な内容",
"false": "即時対応が不要な内容",
},
},
"severity": {
"type": "score",
"instructions": "このチケットの深刻度はどの程度ですか?",
"criteria": [
"軽微: 利用に支障はない",
"中度: 一部の機能に影響がある",
"重大: 主要機能が使用できない",
"致命的: サービス全体が停止している",
],
},
},
)
category = response.answers["category"]
is_urgent = response.answers["is_urgent"]
severity = response.answers["severity"]
print(f"モデル: {response.model}")
print(f"カテゴリ: {category.choice} (確信度 {category.confidence:.2f})")
print(f" 内訳: {category.probabilities}")
print(f"緊急フラグ: {is_urgent.noul:.2f} (真である確率)")
print(f"深刻度スコア: {severity.score:.2f} -> {severity.legend}")
sample_ticket = (
"本日未明からアプリにログインできず、決済処理も全て失敗しています。"
"至急対応をお願いします。"
)
classify_support_ticket(sample_ticket)
実行結果は次のようになりました。
モデル: tev1
カテゴリ: account (確信度 0.47)
内訳: {'billing': 0.002, 'technical': 0.472, 'account': 0.520, 'other': 0.006}
緊急フラグ: 0.97 (真である確率)
深刻度スコア: 1.89 -> {'0': '軽微: 利用に支障はない', '1': '中度: 一部の機能に影響がある', '2': '重大: 主要機能が使用できない', '3': '致命的: サービス全体が停止している'}
「ログインできず決済も失敗している」という状態に対して、カテゴリはaccount(確信度0.47、technicalも0.47とほぼ同率で割れている)、緊急フラグは0.97とほぼ確実に緊急と判定、深刻度スコアは1.89で「中度〜重大」の間、という結果が得られました。カテゴリ判定が割れている点は、このチケットが本当にaccount/technicalどちらの問題とも言える内容だったことを考えると、むしろ妥当な「迷い」の表現だと言えます。
なお、Windowsのコンソールは既定の文字コードがUTF-8でない場合があるため、sys.stdout.reconfigure(encoding="utf-8")で明示的にUTF-8へ切り替えています。これを入れないと日本語部分が文字化けするので、Windows環境で試す場合は注意してください。
typesafe-sdk を利用する場合
TypeSafe社が配布しているtypesafe-sdk(Jevをクラウド経由で呼ぶための公式SDK)を、ローカルのtev1に対して使いいます。
サンプルコード
"""TypeSafe AI の System One モデル『Jev』を使った意思決定サンプル。"""
from __future__ import annotations
import sys
from typesafe_sdk import Choice, Noul, Score, TypeSafeClient
if sys.stdout.encoding is not None and sys.stdout.encoding.lower() != "utf-8":
sys.stdout.reconfigure(encoding="utf-8")
def classify_support_ticket(ticket_text: str) -> None:
with TypeSafeClient() as client: # model は省略時 "jev-latest"
result = client.system_one(
state=ticket_text,
questions={
"category": Choice(
instructions="このチケットはどのカテゴリに分類されますか?",
criteria={
"billing": "請求・支払いに関する問い合わせ",
"technical": "製品の不具合やエラーに関する問い合わせ",
"account": "アカウントやログインに関する問い合わせ",
"other": "それ以外の問い合わせ",
},
),
"is_urgent": Noul(
instructions="このチケットは緊急対応が必要ですか?",
criteria={
"true": "サービス停止やデータ損失など、即時対応が必要な内容",
"false": "即時対応が不要な内容",
},
),
"severity": Score(
instructions="このチケットの深刻度はどの程度ですか?",
criteria=[
"軽微: 利用に支障はない",
"中度: 一部の機能に影響がある",
"重大: 主要機能が使用できない",
"致命的: サービス全体が停止している",
],
),
},
)
category = result.choices["category"]
is_urgent = result.nouls["is_urgent"]
severity = result.scores["severity"]
print(f"モデル: {result.model}")
print(f"カテゴリ: {category.choice} (確信度 {category.confidence:.2f})")
print(f"緊急フラグ: {is_urgent.noul:.2f} (真である確率)")
print(f"深刻度スコア: {severity.score:.2f} (確信度 {severity.confidence:.2f})")
このコードをローカルのtev1に向けて実行するには、次の3つの環境変数を設定します。
set TYPESAFE_BASE_URL=http://localhost:11434
set TYPESAFE_API_KEY=dummy-local-key
set TYPESAFE_DEFAULT_MODEL=tev1
TYPESAFE_BASE_URL: 接続先をTypeSafeのクラウドAPIからローカルのOllamaに変更TYPESAFE_API_KEY: クライアント生成時に必須のパラメータ。Ollamaはキーの内容を検証しないため、空でない適当な文字列でよいTYPESAFE_DEFAULT_MODEL: 省略時はjev-latest(TypeSafeのクラウドモデル名)になってしまうため、明示的にtev1を指定
この状態で実行すると、ollama公式クライアント版と完全に同じ結果が得られます。
モデル: tev1
カテゴリ: account (確信度 0.47)
緊急フラグ: 0.97 (真である確率)
深刻度スコア: 1.89 (確信度 0.44)
ローカルのOllamaモデルを、クラウドサービス向けに作られたSDKでそのまま叩けるというのは地味に嬉しいポイントです。例えば開発中はtev1でコストをかけずに試作し、本番ではTYPESAFE_BASE_URL等の環境変数を外すだけでJevのクラウドAPIに切り替える、といった運用もできそうです。
過信してはいけないポイント
ここまで動かしてみると、Jev / tev1系のモデルは「速くて安い」という印象が強く残りますが、関連する解説記事や論文を読むと、過信すべきでない点がいくつか見えてきます。
confidenceは「正答率」ではない
confidenceとして返る値は「この判定が正しい確率」ではなく、あくまで確率分布の広がりを要約した値です。確信度が高くても、実際には誤っているケースはあります。
同じ入力でも結果が揺れる(非決定性)
同じstate・questionsを送っても、再実行すると確率値が微妙に変動します(例: 0.33→0.35など)。閾値判定でギリギリのケースを扱う場合は、この揺れを考慮したマージンが必要です。
質問は必ず一括送信する
10個の質問を1問ずつ逐次送信すると計6,110入力トークンかかったのに対し、1回のリクエストに全てまとめると773トークンまで圧縮でき、約90%のコスト削減、応答時間も約1/8に短縮されたという報告があります。この記事のサンプルコードも、3つの質問を1回のquestionsにまとめているのはこのためです。
「カスケード」は効く場面と効かない場面がある
Jevの確信度が低いときだけ、より強力なLLM(GPT-6など)にエスカレートする「カスケード戦略」を検証した論文では、テキストから読み取れる判定(選好判定、事実性チェックなど)では費用を25〜41%削減しつつ精度を維持できる一方、数学・コード・論理パズルのように導出が必要な判定ではJevの精度が大きく劣るため、カスケードの効果が薄いことが示されています。
さらに別の論文では、Jevと軽量LLM(GPT-5.6 Luna、Gemini 3.8 Flash、DeepSeek V4.1 Flash)をルーブリック評価者として比較した結果、設計が全く異なるにもかかわらず、同じ箇所で同じ間違いを犯す「相関エラー」が報告されています。Jevの最も確信度が高い誤り84件のうち、実に96.0%でLLM判定も同じ誤答を繰り返したとのことです。この相関エラーのため、「Jevが自信なさげなときだけLLMに任せる」という素朴なカスケード戦略は、期待したほどの精度向上をもたらさないケースがある、という点は導入前に知っておきたい知見です。
おわりに
Jev / System One Modelsは、「LLMにテキスト生成をさせるのではなく、型付きの小さな決定を高速・安価・確率付きで返す」という、チャット向けLLMとは異なる方向性を持つモデル層でした。そして、その思想を踏襲したモデル群がOllama上でも tev1・nimble・clef・clef-flash として既に利用可能で、/v1/systemone という共通APIのおかげで、TypeSafe社自身のSDKですら「接続先を変えるだけ」でローカルモデルに向けられる、という点が今回触ってみて一番の収穫でした。
一方で、「型が壊れない」ことと「判断がいつも正しい」ことは別問題である、という点は各記事・論文が共通して指摘している通りです。confidenceの意味を正しく理解し、質問は必ず一括送信し、そして「カスケードで精度を補えるはず」という期待も、相関エラーの存在を踏まえて検証してから本番導入する、という慎重さが必要そうです。
More Information