Ollama チャット

Ollama (英語) を使用すると、さまざまな大規模言語モデル (LLM) をローカルで実行し、そこからテキストを生成できます。Spring AI は、OllamaChatModel API を使用して Ollama チャット補完機能をサポートします。

Ollama は、OpenAI API 互換エンドポイントも提供します。OpenAI API 互換性セクションでは、Spring AI OpenAI を使用して Ollama サーバーに接続する方法について説明します。

前提条件

まず、Ollama インスタンスにアクセスする必要があります。次のようないくつかのオプションがあります。

アプリケーションで使用するモデルを Ollama モデルライブラリ (英語) から取得できます。

ollama pull <model-name>

何千もの中からフリーで GGUF Hugging Face モデル (英語) を引くこともできます:

ollama pull hf.co/<username>/<model-repository>

あるいは、必要なモデル自動プルモデルを自動的にダウンロードするオプションを有効にすることもできます。

自動構成

Spring AI は、Ollama チャット統合用の Spring Boot 自動構成を提供します。これを有効にするには、プロジェクトの Maven pom.xml または Gradle build.gradle ビルドファイルに次の依存関係を追加します。

  • Maven

  • Gradle

<dependency>
   <groupId>org.springframework.ai</groupId>
   <artifactId>spring-ai-ollama-spring-boot-starter</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-ollama-spring-boot-starter'
}
Spring AI BOM をビルドファイルに追加するには、"依存関係管理" セクションを参照してください。

基本プロパティ

プレフィックス spring.ai.ollama は、Ollama への接続を構成するためのプロパティプレフィックスです。

プロパティ

説明

デフォルト

spring.ai.ollama.base-url

Ollama API サーバーが実行されているベース URL。

localhost:11434

Ollama 統合および自動プルモデルを初期化するためのプロパティを次に示します。

プロパティ

説明

デフォルト

spring.ai.ollama.init.pull-model-strategy

起動時にモデルをプルするかどうか、およびその方法。

never

spring.ai.ollama.init.timeout

モデルがプルされるまで待機する時間。

5m

spring.ai.ollama.init.max-retries

モデルプル操作の最大再試行回数。

0

spring.ai.ollama.init.chat.include

この型のモデルを初期化タスクに含めます。

true

spring.ai.ollama.init.chat.additional-models

デフォルトのプロパティで構成されたモデル以外に初期化する追加のモデル。

[]

チャットのプロパティ

プレフィックス spring.ai.ollama.chat.options は、Ollama チャットモデルを構成するプロパティプレフィックスです。これには、modelkeep-aliveformat などの Ollama リクエスト (詳細) パラメーターと、Ollama モデル options プロパティが含まれます。

Ollama チャットモデルの高度なリクエストパラメーターは次のとおりです。

プロパティ

説明

デフォルト

spring.ai.ollama.chat.enabled

Ollama チャットモデルを有効にします。

true

spring.ai.ollama.chat.options.model

使用するサポートされているモデル [GitHub] (英語) の名前。

ミストラル

spring.ai.ollama.chat.options.format

レスポンスを返す形式。現在受け入れられる値は json のみです

-

spring.ai.ollama.chat.options.keep_alive

リクエスト後にモデルがメモリにロードされたままになる時間を制御します

5 分

残りの options プロパティは、Ollama の有効なパラメーターと値 [GitHub] (英語) および Ollama 型 [GitHub] (英語) に基づいています。デフォルト値は、Ollama 型のデフォルト [GitHub] (英語) に基づいています。

プロパティ

説明

デフォルト

spring.ai.ollama.chat.options.numa

NUMA を使用するかどうか。

false

spring.ai.ollama.chat.options.num-ctx

次のトークンの生成に使用されるコンテキストウィンドウのサイズを設定します。

2048

spring.ai.ollama.chat.options.num-batch

プロンプト処理の最大バッチサイズ。

512

spring.ai.ollama.chat.options.num-gpu

GPU に送信するレイヤーの数。macOS では、メタルサポートを有効にする場合はデフォルトで 1、無効にする場合は 0 です。ここで 1 は、NumGPU を動的に設定する必要があることを示します

-1

spring.ai.ollama.chat.options.main-gpu

複数の GPU を使用する場合、このオプションは、すべての GPU に計算を分割するオーバーヘッドが価値のない小さなテンソルに使用する GPU を制御します。問題の GPU は、一時的な結果用のスクラッチバッファーを保存するために、わずかに多くの VRAM を使用します。

0

spring.ai.ollama.chat.options.low-vram

-

false

spring.ai.ollama.chat.options.f16-kv

-

true

spring.ai.ollama.chat.options.logits-all

最後のトークンだけでなく、すべてのトークンの logits を返します。補完が logprob を返すようにするには、これが true である必要があります。

-

spring.ai.ollama.chat.options.vocab-only

重みではなく語彙のみをロードします。

-

spring.ai.ollama.chat.options.use-mmap

デフォルトでは、モデルはメモリにマップされるため、システムは必要に応じてモデルの必要な部分のみを読み込むことができます。ただし、モデルが RAM の合計量よりも大きい場合、またはシステムの使用可能なメモリが少ない場合は、mmap を使用するとページアウトのリスクが高まり、パフォーマンスに悪影響を与える可能性があります。mmap を無効にすると読み込み時間が遅くなりますが、mlock を使用していない場合はページアウトが減る可能性があります。モデルが RAM の合計量よりも大きい場合、mmap をオフにするとモデルがまったく読み込まれなくなることに注意してください。

null

spring.ai.ollama.chat.options.use-mlock

モデルをメモリにロックし、メモリマップ時にスワップアウトされないようにします。これによりパフォーマンスは向上しますが、実行により多くの RAM が必要になり、モデルが RAM にロードされるときにロード時間が遅くなる可能性があるため、メモリマッピングの利点の一部が失われます。

false

spring.ai.ollama.chat.options.num-thread

計算中に使用するスレッドの数を設定します。デフォルトでは、Ollama は最適なパフォーマンスを得るためにこれを検出します。この値を、(論理コア数ではなく) システムに搭載されている物理 CPU コア数に設定することをお勧めします。0 = ランタイムに決定させる

0

spring.ai.ollama.chat.options.num-keep

-

4

spring.ai.ollama.chat.options.seed

生成に使用する乱数シードを設定します。これを特定の数値に設定すると、モデルは同じプロンプトに対して同じテキストを生成します。

-1

spring.ai.ollama.chat.options.num-predict

テキストを生成するときに予測するトークンの最大数。(-1 = 無限生成、-2 = コンテキストを埋める)

-1

spring.ai.ollama.chat.options.top-k

ナンセンスが生成される確率を減らします。値が大きいほど (100 など)、より多様な回答が得られますが、値が小さいほど (10 など) より保守的になります。

40

spring.ai.ollama.chat.options.top-p

top-k と連携します。値が大きいほど (0.95 など)、より多様なテキストが生成され、値が小さいほど (0.5 など)、より焦点が絞られた控えめなテキストが生成されます。

0.9

spring.ai.ollama.chat.options.tfs-z

テールフリーサンプリングは、出力からの可能性の低いトークンの影響を軽減するために使用されます。値が大きいほど (2.0 など)、影響はさらに軽減されますが、値 1.0 はこの設定を無効にします。

1.0

spring.ai.ollama.chat.options.typical-p

-

1.0

spring.ai.ollama.chat.options.repeat-last-n

繰り返しを防ぐために、モデルがどこまで遡るかを設定します。(デフォルト: 64, 0 = 無効、-1 = num_ctx)

64

spring.ai.ollama.chat.options.temperature

モデルの温度。温度を上げると、モデルはより創造的に答えられるようになります。

0.8

spring.ai.ollama.chat.options.repeat-penalty

繰り返しをどの程度強くペナルティするかを設定します。値が大きいほど (1.5 など)、繰り返しに対するペナルティがより強くなり、値が小さいほど (0.9 など) ペナルティがより緩やかになります。

1.1

spring.ai.ollama.chat.options.presence-penalty

-

0.0

spring.ai.ollama.chat.options.frequency-penalty

-

0.0

spring.ai.ollama.chat.options.mirostat

複雑さを制御するために Mirostat サンプリングを有効にします。(default: 0, 0 = 無効、1 = ミロスタット、2 = ミロスタット 2.0)

0

spring.ai.ollama.chat.options.mirostat-tau

出力の一貫性と多様性の間のバランスを制御します。値を低くすると、より焦点が絞られた一貫したテキストになります。

5.0

spring.ai.ollama.chat.options.mirostat-eta

生成されたテキストからのフィードバックにアルゴリズムがどれだけ早く応答するかに影響します。学習率が低いと調整が遅くなり、学習率が高いとアルゴリズムの応答性が高くなります。

0.1

spring.ai.ollama.chat.options.penalize-newline

-

true

spring.ai.ollama.chat.options.stop

使用する停止シーケンスを設定します。このパターンが発生すると、LLM はテキストの生成を停止して戻ります。モデルファイルで複数の個別の停止パラメーターを指定することにより、複数の停止パターンを設定できます。

-

spring.ai.ollama.chat.options.functions

単一のプロンプトリクエストで関数呼び出しを有効にするために、名前で識別される関数のリスト。これらの名前を持つ関数は、functionCallbacks レジストリに存在する必要があります。

-

spring.ai.ollama.chat.options.proxy-tool-calls

true の場合、Spring AI は関数呼び出しを内部で処理せず、クライアントにプロキシします。関数呼び出しを処理し、適切な関数にディスパッチして、結果を返すのはクライアントの責任です。false (デフォルト) の場合、Spring AI は関数呼び出しを内部で処理します。関数呼び出しをサポートするチャットモデルにのみ適用されます。

false

spring.ai.ollama.chat.options で始まるすべてのプロパティは、リクエスト固有のランタイムオプションを Prompt 呼び出しに追加することによって実行時にオーバーライドできます。

ランタイムオプション

OllamaOptions.java [GitHub] (英語) クラスは、使用するモデル、温度などのモデル構成を提供します。

起動時に、OllamaChatModel(api, options) コンストラクターまたは spring.ai.ollama.chat.options.* プロパティを使用してデフォルトのオプションを構成できます。

実行時に、Prompt 呼び出しに新しいリクエスト固有のオプションを追加することで、デフォルトのオプションをオーバーライドできます。例: 特定のリクエストのデフォルトのモデルと温度をオーバーライドするには、次のようにします。

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        OllamaOptions.builder()
            .model(OllamaModel.LLAMA3_1)
            .temperature(0.4)
            .build()
    ));
モデル固有の OllamaOptions [GitHub] (英語) に加えて、ChatOptionsBuilder#builder() [GitHub] (英語) で作成されたポータブル ChatOptions [GitHub] (英語) インスタンスを使用することもできます。

自動プルモデル

Spring AI Ollama は、Ollama インスタンスでモデルが利用できない場合に自動的にモデルをプルできます。この機能は、開発とテスト、アプリケーションを新しい環境にデプロイする場合に特に便利です。

また、何千ものフリー GGUF Hugging Face モデル (英語) のいずれかを名前でプルすることもできます。

モデルをプルするための戦略は 3 つあります。

  • always (PullModelStrategy.ALWAYS で定義): モデルがすでに利用可能であっても、常にモデルをプルします。モデルの最新バージョンを使用していることを確認できます。

  • when_missing (PullModelStrategy.WHEN_MISSING で定義): モデルがまだ利用できない場合にのみモデルをプルします。これにより、モデルの古いバージョンが使用される可能性があります。

  • never (PullModelStrategy.NEVER で定義): モデルを自動的にプルしません。

モデルのダウンロード中に遅延が発生する可能性があるため、本番環境では自動プルは推奨されません。代わりに、必要なモデルを事前に評価して事前ダウンロードすることを検討してください。

構成プロパティとデフォルトオプションで定義されたすべてのモデルは、起動時に自動的にプルできます。構成プロパティを使用して、プル戦略、タイムアウト、再試行の最大回数を構成できます。

spring:
  ai:
    ollama:
      init:
        pull-model-strategy: always
        timeout: 60s
        max-retries: 1
指定されたすべてのモデルが Ollama で利用可能になるまで、アプリケーションは初期化を完了しません。モデルのサイズとインターネット接続速度によっては、アプリケーションの起動時間が大幅に遅くなる可能性があります。

起動時に追加のモデルを初期化できます。これは、実行時に動的に使用されるモデルに便利です。

spring:
  ai:
    ollama:
      init:
        pull-model-strategy: always
        chat:
          additional-models:
            - llama3.2
            - qwen2.5

プル戦略を特定の型のモデルにのみ適用する場合は、初期化タスクからチャットモデルを除外できます。

spring:
  ai:
    ollama:
      init:
        pull-model-strategy: always
        chat:
          include: false

この構成では、チャットモデルを除くすべてのモデルにプル戦略が適用されます。

関数呼び出し

OllamaChatModel にカスタム Java 関数を登録し、Ollama モデルで、登録された関数の 1 つまたは複数を呼び出すための引数を含む JSON オブジェクトをインテリジェントに出力するように選択できます。これは、LLM 機能を外部ツールや API に接続するための強力な手法です。Ollama 関数呼び出しの詳細については、こちらを参照してください。

関数呼び出し機能を使用するには Ollama 0.2.8 以降が必要であり、ストリーミングモードで使用するには Ollama 0.4.6 以降が必要です。

マルチモーダル

マルチモーダル性とは、テキスト、イメージ、音声、その他のデータ形式を含むさまざまなソースからの情報を同時に理解して処理するモデルの機能を指します。

マルチモダリティをサポートする Ollama で利用可能なモデルには、LLaVa (英語) bakllava (英語) があります ( 完全なリスト (英語) を参照)。詳細については、ラヴァ: 大型言語・視覚アシスタント (英語) を参照してください。

Ollama メッセージ API [GitHub] (英語) は、メッセージに base64 でエンコードされたイメージのリストを組み込むための "images" パラメーターを提供します。

Spring AI のメッセージ [GitHub] (英語) インターフェースは、メディア [GitHub] (英語) 型を導入することで、マルチモーダル AI モデルを促進します。この型には、メッセージ内のメディア添付ファイルに関するデータと詳細が含まれており、Spring の org.springframework.util.MimeType と、生のメディアデータ用の org.springframework.core.io.Resource が利用されます。

以下は、OllamaChatModelMultimodalIT.java [GitHub] (英語) から抜粋した、ユーザーテキストとイメージの融合を示す簡単なコード例です。

var imageResource = new ClassPathResource("/multimodal.test.png");

var userMessage = new UserMessage("Explain what do you see on this picture?",
        new Media(MimeTypeUtils.IMAGE_PNG, this.imageResource));

ChatResponse response = chatModel.call(new Prompt(this.userMessage,
        OllamaOptions.builder().model(OllamaModel.LLAVA)).build());

この例では、multimodal.test.png イメージを入力として受け取るモデルを示します。

Multimodal Test Image

「この写真に何が写っているか説明してください」というテキストメッセージとともに、次のようなレスポンスが生成されます。

The image shows a small metal basket filled with ripe bananas and red apples. The basket is placed on a surface,
which appears to be a table or countertop, as there's a hint of what seems like a kitchen cabinet or drawer in
the background. There's also a gold-colored ring visible behind the basket, which could indicate that this
photo was taken in an area with metallic decorations or fixtures. The overall setting suggests a home environment
where fruits are being displayed, possibly for convenience or aesthetic purposes.

構造化された出力

Ollama は、モデルが指定された JSON Schema に厳密に準拠したレスポンスを生成することを保証するカスタム構造化された出力 (英語) API を提供します。既存の Spring AI モデルに依存しない構造化出力コンバーターに加えて、これらの API は強化された制御と精度を提供します。

構成

Spring AI を使用すると、OllamaOptions ビルダーを使用してレスポンス形式をプログラムで構成できます。

チャットオプションビルダーの使用

次に示すように、OllamaOptions ビルダーを使用してプログラムでレスポンス形式を設定できます。

String jsonSchema = """
        {
            "type": "object",
            "properties": {
                "steps": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "explanation": { "type": "string" },
                            "output": { "type": "string" }
                        },
                        "required": ["explanation", "output"],
                        "additionalProperties": false
                    }
                },
                "final_answer": { "type": "string" }
            },
            "required": ["steps", "final_answer"],
            "additionalProperties": false
        }
        """;

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
        OllamaOptions.builder()
            .withModel(OllamaModel.LLAMA3_2.getName())
            .withFormat(new ObjectMapper().readValue(jsonSchema, Map.class))
            .build());

ChatResponse response = this.ollamaChatModel.call(this.prompt);

BeanOutputConverter ユーティリティとの統合

既存の BeanOutputConverter ユーティリティを活用して、ドメインオブジェクトから JSON スキーマを自動的に生成し、後で構造化されたレスポンスをドメイン固有のインスタンスに変換できます。

record MathReasoning(
    @JsonProperty(required = true, value = "steps") Steps steps,
    @JsonProperty(required = true, value = "final_answer") String finalAnswer) {

    record Steps(
        @JsonProperty(required = true, value = "items") Items[] items) {

        record Items(
            @JsonProperty(required = true, value = "explanation") String explanation,
            @JsonProperty(required = true, value = "output") String output) {
        }
    }
}

var outputConverter = new BeanOutputConverter<>(MathReasoning.class);

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
        OllamaOptions.builder()
            .withModel(OllamaModel.LLAMA3_2.getName())
            .withFormat(outputConverter.getJsonSchemaMap())
            .build());

ChatResponse response = this.ollamaChatModel.call(this.prompt);
String content = this.response.getResult().getOutput().getText();

MathReasoning mathReasoning = this.outputConverter.convert(this.content);
フィールドを required として正確にマークするスキーマを生成するには、必ず @JsonProperty(required = true,…​) アノテーションを使用してください。これは JSON スキーマではオプションですが、構造化されたレスポンスが正しく機能するためには推奨されます。

OpenAI API 互換性

Ollama は OpenAI API と互換性があり、Spring AI OpenAI クライアントを使用して Ollama と通信し、ツールを使用できます。そのためには、OpenAI ベース URL を Ollama インスタンス: spring.ai.openai.chat.base-url=http://localhost:11434 に設定し、提供されている Ollama モデルの 1 つ: spring.ai.openai.chat.options.model=mistral を選択する必要があります。

Ollama OpenAI API compatibility

Spring AI OpenAI ではなく Ollama を使用する例については、OllamaWithOpenAiChatModelIT.java [GitHub] (英語) テストを確認してください。

HuggingFace モデル

Ollama は、すぐにすべての GGUF Hugging Face (英語) チャットモデルにアクセスできます。これらのモデルのいずれかを名前でプルできます: ollama pull hf.co/<username>/<model-repository> または自動プル戦略を構成できます: 自動プルモデル :

spring.ai.ollama.chat.options.model=hf.co/bartowski/gemma-2-2b-it-GGUF
spring.ai.ollama.init.pull-model-strategy=always
  • spring.ai.ollama.chat.options.model: 使用する Hugging Face GGUF モデル (英語) を指定します。

  • spring.ai.ollama.init.pull-model-strategy=always: (オプション) 起動時に自動的にモデルを取得できるようにします。本番環境では、遅延を避けるためにモデルを事前にダウンロードする必要があります。: ollama pull hf.co/bartowski/gemma-2-2b-it-GGUF.

サンプルコントローラー

新しい Spring Boot プロジェクトを作成し、spring-ai-ollama-spring-boot-starter を pom (または gradle) の依存関係に追加します。

src/main/resources ディレクトリに application.yaml ファイルを追加して、Ollama チャットモデルを有効にして構成します。

spring:
  ai:
    ollama:
      base-url: http://localhost:11434
      chat:
        options:
          model: mistral
          temperature: 0.7
base-url を Ollama サーバーの URL に置き換えます。

これにより、クラスに挿入できる OllamaChatModel 実装が作成されます。以下は、テキスト生成にチャットモデルを使用する単純な @RestController クラスの例です。

@RestController
public class ChatController {

    private final OllamaChatModel chatModel;

    @Autowired
    public ChatController(OllamaChatModel chatModel) {
        this.chatModel = chatModel;
    }

    @GetMapping("/ai/generate")
    public Map<String,String> generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return Map.of("generation", this.chatModel.call(message));
    }

    @GetMapping("/ai/generateStream")
	public Flux<ChatResponse> generateStream(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        Prompt prompt = new Prompt(new UserMessage(message));
        return this.chatModel.stream(prompt);
    }

}

手動構成

Spring Boot 自動構成を使用したくない場合は、アプリケーションで OllamaChatModel を手動で構成できます。OllamaChatModel [GitHub] (英語) は ChatModel および StreamingChatModel を実装し、低レベル OllamaApi クライアントを使用して Ollama サービスに接続します。

これを使用するには、プロジェクトの Maven pom.xml または Gradle build.gradle ビルドファイルに spring-ai-ollama 依存関係を追加します。

  • Maven

  • Gradle

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-ollama</artifactId>
</dependency>
dependencies {
    implementation 'org.springframework.ai:spring-ai-ollama'
}
Spring AI BOM をビルドファイルに追加するには、"依存関係管理" セクションを参照してください。
spring-ai-ollama 依存関係により、OllamaEmbeddingModel へのアクセスも提供されます。OllamaEmbeddingModel の詳細については、Ollama 埋め込みモデルセクションを参照してください。

次に、OllamaChatModel インスタンスを作成し、それを使用してテキスト生成のリクエストを送信します。

var ollamaApi = new OllamaApi();

var chatModel = new OllamaChatModel(this.ollamaApi,
            OllamaOptions.create()
                .model(OllamaOptions.DEFAULT_MODEL)
                .temperature(0.9));

ChatResponse response = this.chatModel.call(
    new Prompt("Generate the names of 5 famous pirates."));

// Or with streaming responses
Flux<ChatResponse> response = this.chatModel.stream(
    new Prompt("Generate the names of 5 famous pirates."));

OllamaOptions は、すべてのチャットリクエストの構成情報を提供します。

低レベル OllamaApi クライアント

OllamaApi [GitHub] (英語) は、Ollama チャット補完 API Ollama チャット補完 API [GitHub] (英語) 用の軽量 Java クライアントを提供します。

次のクラス図は、OllamaApi チャットインターフェースとビルドブロックを示しています。

OllamaApi Chat Completion API Diagram
OllamaApi は低レベルの API であり、直接使用することは推奨されません。代わりに OllamaChatModel を使用してください。

以下は、API をプログラムで使用する方法を示す簡単なスニペットです。

OllamaApi ollamaApi = new OllamaApi("YOUR_HOST:YOUR_PORT");

// Sync request
var request = ChatRequest.builder("orca-mini")
    .stream(false) // not streaming
    .messages(List.of(
            Message.builder(Role.SYSTEM)
                .content("You are a geography teacher. You are talking to a student.")
                .build(),
            Message.builder(Role.USER)
                .content("What is the capital of Bulgaria and what is the size? "
                        + "What is the national anthem?")
                .build()))
    .options(OllamaOptions.create().temperature(0.9))
    .build();

ChatResponse response = this.ollamaApi.chat(this.request);

// Streaming request
var request2 = ChatRequest.builder("orca-mini")
    .ttream(true) // streaming
    .messages(List.of(Message.builder(Role.USER)
        .content("What is the capital of Bulgaria and what is the size? " + "What is the national anthem?")
        .build()))
    .options(OllamaOptions.create().temperature(0.9).toMap())
    .build();

Flux<ChatResponse> streamingResponse = this.ollamaApi.streamingChat(this.request2);