バージョン 0.35 以降、Ollama は TypeSafe の Jev API に基づいて構築された意思決定モデルをサポートします。これらは通常の意味でのチャット モデルではありません。テキストは書きませんが、転送された状態について入力された一連の質問に答えます。分類、ルーティング、モデレーション、トリアージに関しては、通常の LLM に JSON を返すように要求してその応答を解析するよりも、この方が高速で信頼性が高いことがわかります。
この投稿では、意思決定モデルとは何か、意思決定モデルが HTTP レベルでどのように機能するか、すでに利用可能なモデルとは何か、そして通常の生成モデルが引き続き機能するようにそれらのモデルを既存のコードに組み込む方法について説明します。
意思決定モデルと通常の意思決定モデルの違い
通常の LLM はプロンプトを受け取り、トークンごとにテキスト トークンを生成します。たとえ一言で答えるように頼んだとしても、心の中では生成が発生し、答えの形式は図、指示、その後の検証によって制御されなければなりません。意思決定モデルの動作は異なります。状態と質問をタイプで渡し、モデルは確率と選択されたオプションを返します。フリー テキストや応答からの JSON の解析はありません。
新しいエンドポイントは /v1/systemone と呼ばれます。 1 つのリクエストで一度に複数の質問をすることができ、モデルはすべての質問に答えます。これは、チームの決定、返品の必要性、チケットの緊急性など、いくつかの関連する決定を行う必要があるタスクに便利です。
利用可能なモデル
これで、Ollama を通じて 3 つの意思決定モデルを実行できるようになりました。
- nimble は、Bespoke Labs が提供する 90 億のパラメーターを備えたオープン モデルです。これは利用可能な中で最大かつ最も正確です。
- tev1 は Together AI の 40 億個のパラメーターを備えた実験モデルです。
- tev1:0.8b は、Togetter AI の 8 億個のパラメーターを備えた実験モデルです。最も速くて簡単です。
これらはすべてローカルで動作し、支払いを必要とせず、外部サービスにデータを送信しません。 Ollama 0.35 以降がサポートされています。
インストール
まず Ollama のバージョンを確認します。
ollama --version
次に、目的のモデルをダウンロードします。最も簡単な方法としては、次のとおりです。
ollama pull tev1:0.8b
tev1 の完全バージョンの場合:
ollama pull tev1
軽快な場合:
ollama pull nimble
軽快なモデルは約 9.5 GB のディスク領域を占有するため、ダウンロードする前にある程度の領域を空けておくことをお勧めします。 tev1:0.8b の占有量は 1 GB 未満です。
curl 経由の最初のリクエスト
最も単純な例は、テキストが求人広告であるかどうかを判断することです。
curl http://localhost:11434/v1/systemone -d '{
"model": "tev1:0.8b",
"state": {
"message": "Senior Swift developer, Berlin, remote friendly"
},
"questions": {
"isJob": {
"type": "noul",
"instructions": "Does the message advertise a job posting that someone can apply to?"
}
}
}'
答えは次のようになります。
{
"model": "tev1:0.8b",
"answers": {
"isJob": {
"type": "noul",
"noul": 0.921
}
},
"usage": {
"input_tokens": 42,
"output_tokens": 0
}
}
noul フィールドは 0 から 1 までの確率です。決定は、しきい値 (通常は 0.5) との比較によって行われます。生成モデルとは異なり、JSON 形式で応答を要求し、モデルが壊れていないことを確認する必要はありません。
質問の種類
意思決定モデルは 3 種類の質問をサポートします。
noul は二項質問です。ステートメントが true である確率を返します。
{
"questions": {
"refund": {
"type": "noul",
"instructions": "Does the customer explicitly ask for a refund?"
}
}
}
選択 – 指定されたセットから 1 つのオプションを選択します。選択したオプション、すべてのオプションの確率、および信頼度を返します。
{
"questions": {
"team": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {
"billing": "Payments and refunds",
"technical": "Bugs and integrations",
"other": "None of the above"
}
}
}
}
スコア – スケール上の評価。各スケール ポイントの数値、凡例、確率を返します。
{
"questions": {
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": ["Routine", "Soon", "Urgent"]
}
}
}
1 つのリクエストに、さまざまな種類の複数の質問を同時に含めることができます。これにより、意思決定モデルがトリアージに便利になります (1 つの操作、1 つの状態、複数の独立した決定)。
追加のライブラリを使用しない Python
リクエストの場合は、標準の urllib で十分です。別個の SDK は必要ありません。
import json
from urllib.request import Request, urlopen
OLLAMA_DECISION_URL = "http://localhost:11434/v1/systemone"
def ask_decision(state, questions, model="tev1:0.8b"):
payload = {
"model": model,
"state": state,
"questions": questions,
}
request = Request(
OLLAMA_DECISION_URL,
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
with urlopen(request, timeout=3600) as response:
return json.loads(response.read().decode())["answers"]
使用法:
answers = ask_decision(
{"message": "Senior Swift developer, Berlin, remote friendly"},
{
"isJob": {
"type": "noul",
"instructions": "Does the message advertise a job posting that someone can apply to?"
}
},
)
probability = answers["isJob"]["noul"]
is_job = probability >= 0.5
公式の Python SDK が必要な場合は、typesafe-sdk と呼ばれます。 localhost の場合、環境変数 TYPESAFE_BASE_URL、TYPESAFE_API_KEY、および TYPESAFE_DEFAULT_MODEL を使用して Ollama に送信できます。ただし、単純なタスクの場合は、直接の HTTP リクエストで十分です。
モデルが意思決定をサポートしていることを理解する方法
意思決定モデルは、/api/generate または /api/chat 経由で応答できません。このようなリクエストを送信すると、Ollama は次のようなテキストを含む 400 エラーを返します。
"tev1:0.8b" does not support generate
これは、/api/generate を介して通常のモデルで動作するコードがすでにある場合に重要です。モデルを意思決定モデルに変更すると、動作しなくなります。 /api/show を介してモデルの機能を事前に確認し、適切な呼び出し方法を選択することをお勧めします。
import json
from urllib.request import Request, urlopen
OLLAMA_SHOW_URL = "http://localhost:11434/api/show"
def supports_decision(model):
request = Request(
OLLAMA_SHOW_URL,
data=json.dumps({"model": model}).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urlopen(request, timeout=30) as response:
capabilities = json.loads(response.read().decode()).get("capabilities", [])
except (OSError, TypeError, ValueError):
return False
return "decision" in capabilities
意思決定モデルの機能には意思決定のみが含まれます。通常のモデルには、完成品、ツール、またはその他の機能が含まれています。 Ollama が利用できない場合は、モデルを標準とみなして生成パスを使用するのが合理的です。
既存のコードに埋め込む方法
最も簡単な方法は、分類子を書き直すのではなく、分類子を 2 つの戦略に分割することです。生成戦略は以前と同様に機能します。プロンプトを収集し、/api/generate に送信して、JSON を解析します。決定戦略は、状態と入力された質問を /v1/systemone に送信し、確率をしきい値と比較します。
戦略の選択は、分類子の作成時に 1 か所で行われます。
def create_classifier(model):
if supports_decision(model):
return DecisionClassifier(model)
return GenerativeClassifier(model)
このアプローチにはいくつかの利点があります。生成モデルは変更せずに実行し続けます。意思決定モデルは、1 つの環境変数を変更することで有効にできます。そして、2 つの方法の違い全体は 2 つの小さなクラスに集中しており、アプリケーション全体には広がりません。
二項分類の場合、決定戦略は次のようになります。
async def classify(text):
answers = await ask_decision(
{"message": text},
{
"isJob": {
"type": "noul",
"instructions": instructions,
}
},
model,
)
probability = answers["isJob"]["noul"]
return probability >= 0.5, probability
決定モデルは説明を返さないことに注意してください。結果の形式に理由フィールドがある場合は、確率から理由フィールドを構築できます。たとえば、確率自体、または「モデルはメッセージを空席として 0.935 と評価しました」のような文字列を格納します。これは、モデルが示さなかった理由をでっち上げるよりも正直です。
指示は質問であるべきです
これは最も重要な実際的な結論です。意思決定モデルは、「メッセージを分類し、… の場合は true、そうでない場合は false と答える」というスタイルの長いプロンプトを理解できません。彼らは短くて直接的な質問を望んでいます。
欠員に関する同じメッセージで、次の確率を受け取りました。
- 直接的な質問「このメッセージは求人情報ですか?」 — 0.921.
- 欠員とみなされるものを説明する長い説明 – 0.026
- 最後に質問がある長い説明 – 0.391
その差は30倍近くあります。モデルは分類が間違っているのではなく、質問が段落内に隠されている場合、モデルに何を求めているのかを理解していないだけです。したがって、意思決定モデルについては、短い命令を個別に保持し、生成モデルについては長いプロンプトを残しておく価値があります。
別の環境変数を作成すると便利です。
OLLAMA_JOB_CLASSIFIER_DECISION_INSTRUCTIONS=Does the message advertise a job posting that someone can apply to?
また、生成パスに対してのみ通常のプロンプトを使用します。
しきい値と確率
しきい値 0.5 はデフォルト値として適切ですが、設定に含めると便利です。タスクが異なれば、偽陽性応答と偽陰性応答のコストも異なります。適度にするには、しきい値を上げる方が安全です。求人情報を探す場合は、有益なメッセージを見逃さないように、値を下げた方が安全です。
結果のブール値だけでなく、確率自体をログに記録することも役立ちます。分類器がエラーを起こした場合、それが自信を持った答えだったのか、それとも境界上の決定であったのかがログに表示されます。選択肢の質問については、確率と信頼度を保存する価値があります。確率と信頼度は、モデルが選択肢間でどれだけ変動するかを示します。
パフォーマンスとメモリ
速度はモデルのサイズとハードウェアに大きく依存します。私のテストでは CPU で次の数値が得られました。
- tev1:0.8b – 数秒で解けるので、簡単に記憶に残ります。
- tev1 – 4B、かなり遅いですが、それでもインタラクティブなタスクに適しています。
- 軽快 – Q8_0 では 9B、メモリは約 10 GB。モデルの読み込みを含む最初のリクエストには約 137 秒かかり、その後のソリューションには CPU で 12 ~ 32 秒かかりました。
Nimble は大量の RAM を必要とします。 16 GB と約 8 GB の制限がある Docker/WSL を備えたマシンでは、このモデルは適合しません。システムがスワップを開始し、コンテナーが応答を停止します。 .wslconfig ファイルを使用して WSL 制限を 12 GB に増やすと、次のことが役に立ちました。
[wsl2]
memory=12GB
swap=8GB
変更後は、wsl –shutdown を実行して Docker Desktop を再起動する必要があります。しかし、12 GB であっても、リザーブは小さいままです。モデルは約 10 GB を占有し、システムにあまり残されていません。
デフォルトでは、Ollama は 5 分間非アクティブな状態が続いた後にモデルをアンロードし、メモリを解放します。これは便利です。nimble は常に 10 GB をビジー状態に保つわけではありませんが、一時停止後に新たに起動するたびに、モデルの読み込みが再開されます。
意思決定モデルを使用する場合
意思決定モデルは、明確に定式化された質問に対して迅速かつ安価な回答が必要なタスクに適しています。
- メッセージ、チケット、リクエストの分類
- コマンドまたはエグゼキュータによるルーティング。
- コンテンツの管理とセキュリティ チェック
- ゲームやインタラクティブ アプリケーションにおける高速なバイナリおよび多変量ソリューション
これらは、説明、フィールドの抽出、要約、回答の生成など、詳細なテキストが必要なタスクにはあまり適していません。この目的のために、通常の生成モデルが残ります。最良の結果は、意思決定モデルが意思決定を行い、生成モデルがそれを説明するかデータを抽出するという組み合わせで得られます。
合計
Ollama の意思決定モデルは、通常の LLM よりも範囲が狭い独立したツールです。これらは生成モデルを置き換えるものではありませんが、入力された応答、テキスト解析の代わりの確率、予測可能な形式など、作業の日常的な部分を取り除きます。すでに分類パイプラインがある場合、移行はモデルの機能、別個の呼び出し戦略、および短い説明用の質問を確認することになります。
情報源
https://ollama.com/blog/ollama-now-supports-jev-style-decision-models
https://ollama.com/library/nimble
https://ollama.com/library/tev1
https://typesafe.ai
Leave a Reply