Ollama
Ollama は、Nimble、Tev1、Clef などの意思決定モデルをお使いのマシン上でローカルに実行します。
API キーは不要で、リクエストごとの費用もかかりません。OllamaDecisionModel は、Ollama の System One API
(POST /v1/systemone、Ollama v0.35.0 以降で利用可能)上に DecisionModel API を実装したものです。
この統合は実験的なものであり、今後のリリースで変更される可能性があります。
Maven の依存関係
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-ollama</artifactId>
<version>1.23.0</version>
</dependency>
使い方
まず、意思決定モデルをダウンロードします。
ollama pull nimble
次に、以下のようにします。
DecisionModel decisionModel = OllamaDecisionModel.builder()
.baseUrl("http://localhost:11434")
.modelName("nimble")
.build();
DecisionRequest request = DecisionRequest.builder()
.input("Help! My payouts have been failing for 3 days and nobody answers my emails.")
.question("team", ChoiceQuestion.builder()
.text("Which team should handle this ticket?")
.option("billing", "Payments, payouts, invoices, refunds")
.option("support", "Problems using the product")
.option("sales", "Pricing, upgrades, new accounts")
.build())
.question("urgent", YesNoQuestion.from("Does this need attention today?"))
.build();
DecisionResponse response = decisionModel.decide(request);
response.choice("team").value(); // "billing"
response.yesNo("urgent").probability(); // 0.97
モデル名は必ず設定する必要があり、ビルダーまたは各リクエストのいずれかで設定します。ダウンロードされていないモデルは
Ollama に拒否され、リクエストは ModelNotFoundException で失敗します。
GPU がない場合や、Ollama がモデルをロードしている間は、リクエストに数秒かかることがあるため、より長い
timeout(...) を設定することを検討してください。Ollama は、リクエストがないまま 5 分経過するとモデルをアンロードします(サーバー側で別途設定していない場合)。
ロード状態をより長く維持するには、keepAlive(...) を秒単位で設定するか、負の値を設定して常にロードしたままにします。その他 の設定項目は
httpClientBuilder、maxRetries、logRequests、logResponses、logger、customHeaders、customParameters
(カスタムパラメータを参照)、listeners です。
decide() と decideAsync() の両方がサポートされています。
カスタムパラメータ
OllamaDecisionModel がまだサポートしていないパラメータを送信するには、customParameters(...) で設定します。設定したパラメータは
すべてのリクエストの JSON ボディに追加されます。
DecisionModel decisionModel = OllamaDecisionModel.builder()
.baseUrl("http://localhost:11434")
.modelName("nimble")
.customParameters(Map.of("parameter_name", "value"))
.build();
単一のリクエストにだけカスタムパラメータを設定するには、OllamaDecisionRequestParameters を使用します。空でない場合、それらは
ビルダーに設定されたカスタムパラメータを置き換えます(マージはされません)。
DecisionRequest request = DecisionRequest.builder()
.input(...)
.question(...)
.parameters(OllamaDecisionRequestParameters.builder()
.customParameters(Map.of("parameter_name", "another value"))
.build())
.build();
値はそのまま JSON に書き込まれるため 、Map の値は JSON オブジェクトになり、String は文字列のままです。
LangChain4j が送信するパラメータ(model など)と同じ名前のカスタムパラメータは、そのパラメータを置き換えます。
モデルを選択するには modelName(...) を使用してください。model カスタムパラメータは、modelName() やリスナーが
受け取る内容には反映されません。回答は常に DecisionRequest の質問に対して読み取られるため、questions や
state を置き換えないでください。
別の意思決定モデルのパラメータクラスを OllamaDecisionModel に渡すと、
IllegalArgumentException で失敗します。すべての意思決定モデルに共通のパラメータのみを持つ DecisionRequestParameters.builder() は、
どのモデルでも使用できます。
入力
入力には次のものを指定できます。
- テキスト(
input(...)) - 名前付きフィールド(
inputFields(...))。JSON オブジェクトとして送信されます TextContentとImageContentのリスト(inputContents(...))。テキストは空行で連結されます
会話(inputMessages(...))は、{"messages": [...]} の形式でトランスクリプトとして送信され、
その中の画像は他の画像と同じ方法で送信されます。出力ガードレールは、デフォルトで会話の最後の 50 件のメッセージを送信します。
Ollama を使用す る場合は、リクエストを 64 KiB の上限内に収めやすくするために、ガードレールに maxMessages(...) と maxMessageLength(...) を
設定してください(例: maxMessages(4) と maxMessageLength(4000))。チャットモデルルーター、クエリルーター、
ツールフィルタリングは、1 件あたり最大 2,000 文字のメッセージを最大 10 件送信します。いずれの場合も、システムメッセージは
全文が送信されます。システムメッセージが長い場合や、1 文字が複数バイトになる文字体系のテキストを扱う場合は、これらの上限を下げるか、
messageFilter(...) でメッセージを除外してください。
入力全体は、モデルがロードされているコンテキストウィンドウに収まる必要があります(モデルと Ollama サーバーの設定によって異なります)。Ollama が入力を切り詰めることはありません。また、リクエストボディは最大 64 KiB(画像を含む場合は 32 MiB)でなければなりません。
画像
Clef や Clef Flash などのビジョン対応モデル (Ollama v0.35.1 以降)は、PNG、JPEG、WebP 画像を判定できます。
DecisionModel decisionModel = OllamaDecisionModel.builder()
.baseUrl("http://localhost:11434")
.modelName("clef-flash")
.build();
DecisionRequest request = DecisionRequest.builder()
.inputContents(List.of(
TextContent.from("The customer says the package arrived like this."),
ImageContent.from(base64Image, "image/jpeg")))
.question("damaged", YesNoQuestion.from("Is the item visibly damaged?"))
.build();
Ollama は画像を入力の残りの部分とは別に受け取るため、入力内の各画像は、画像全体の中での
位置に置き換えられます。上記の入力は、
The customer says the package arrived like this. の後に [image 1] が続く形で送信されます。
名前付きフィールドでも、画像は同じように置き換えられるため、その名前から何の画像かがわかります。
Map.of("comment", comment, "photo", ImageContent.from(...)) は
{"comment": "...", "photo": "[image 1]"} として送信されます。画像には、入力に現れる順に、すべての
フィールドをまたいで 1 から番号が振られるため、質問から参照できます(例: 「[image 2] は
[image 1] と同じ品物を写していますか?」)。この [image N] の規則は Ollama ではなく LangChain4j のものです。
画像は、base64 データとして、または http、https、file の URL で指定できます。URL の場合、画像はリクエストの送信前に、
呼び出しスレッド上(decideAsync() の場合も同様)でアプリケーションによってダウンロードまたは読み込まれます。data: URL は
サポートされていません。音声などの他のコンテンツは、Ollama を呼び出す前に UnsupportedFeatureException で拒否されます。
ユーザー、ツール、取得したコンテンツなど、信頼できないソースからの画像 URL を渡さないでください。アプリケーションが
任意の http URL をダウンロードし、任意のローカル file URL を読み込んで、その内容を Ollama に送信してしまいます。そのような
画像は自分でダウンロードして確認し、base64 データとして渡してください。
質問と回答
DecisionModel | Ollama | 備考 |
|---|---|---|
YesNoQuestion | noul | yesWhen と noWhen の両方が設定されている場合は、判断基準として送信されます。片方だけの場合は、代わりに質問の末尾に追加されます(例: Answer yes when: ...) |
ChoiceQuestion | choice | 選択肢は説明とともに送信されます |
ScaleQuestion | score | レベルはテキストとして送信されます。説明がある場合は label: description の形式になります |
はい/いいえの回答には、「はい」の確率が含まれます。選択式とスケール式の回答には、各選択肢または レベルの確率と、信頼度が含まれます。
1 つのリクエストに含められる質問は最大 64 個です。スケール質問のレベルは 2 ~ 10 個で、選択質問には少なくとも 2 つの選択肢が必要です。選択肢の最大数はモデルによって異なります(たとえば Tev1 では 26)。
これらの制限があるため、ツールが 64 個を超える場合は、
ツール選択コンポーネントに maxToolsPerDecisionRequest(64) を設定してください。また、
再ランキングでは、1 つのリクエストのセグメントがコンテキストウィンドウに
収まるように maxSegmentsPerRequest(...) を小さくしてください。
response.tokenUsage() は、Ollama がカウントした入力トークン数と出力トークン数を報告します。
どのモデルを使用しても、OllamaDecisionModel はプロバイダーとして ModelProvider.OLLAMA を報告します(たとえばリスナーや
メトリクスにおいて)。
TypeSafeDecisionModel からの切り替え
Ollama の意思決定モデルは、TypeSafeDecisionModel
とカスタムのベース URL を使って呼び出すこともできますが、Ollama は一部のリクエスト(たとえば説明付きのスケールレベル)を拒否し、
画像もサポートしません。OllamaDecisionModel に切り替えるには、クラス名を置き換えるだけです。ベース URL とモデル名は
そのままで構いません。切り替え後は、リスナーとメトリクスが報告するプロバイダーは TYPESAFE ではなく OLLAMA になります。