OpenAI チャット

Spring AI は、OpenAI の AI 言語モデルである ChatGPT をサポートしています。ChatGPT は、業界をリードするテキスト生成モデルと埋め込みの作成により、AI 駆動型テキスト生成への関心を高めるのに役立っています。

前提条件

ChatGPT モデルにアクセスするには、OpenAI で API を作成する必要があります。OpenAI サインアップページ (英語) でアカウントを作成し、API キーページ (英語) でトークンを生成します。Spring AI プロジェクトでは、spring.ai.openai.api-key という名前の構成プロパティが定義されており、これを openai.com から取得した API Key の値に設定する必要があります。環境変数をエクスポートすることは、その構成プロパティを設定する 1 つの方法です。

export SPRING_AI_OPENAI_API_KEY=<INSERT KEY HERE>

リポジトリと BOM の追加

Spring AI アーティファクトは、Spring マイルストーンおよびスナップショットリポジトリで公開されます。これらのリポジトリをビルドシステムに追加するには、リポジトリセクションを参照してください。

依存関係の管理を支援するために、Spring AI は BOM (部品表) を提供し、一貫したバージョンの Spring AI がプロジェクト全体で使用されるようにします。Spring AI BOM をビルドシステムに追加するには、"依存関係管理" セクションを参照してください。

自動構成

Spring AI は、OpenAI チャットクライアント用の Spring Boot 自動構成を提供します。これを有効にするには、プロジェクトの Maven pom.xml ファイルに次の依存関係を追加します。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

または、Gradle build.gradle ビルドファイルに保存します。

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

チャットのプロパティ

再試行プロパティ

プレフィックス spring.ai.retry は、OpenAI チャットモデルの再試行メカニズムを構成できるプロパティプレフィックスとして使用されます。

プロパティ 説明 デフォルト

spring.ai.retry.max-attempts

再試行の最大回数。

10

spring.ai.retry.backoff.initial-interval

指数関数的バックオフポリシーの初期スリープ期間。

2 秒

spring.ai.retry.backoff.multiplier

バックオフ間隔の乗数。

5

spring.ai.retry.backoff.max-interval

最大バックオフ期間。

3 分

spring.ai.retry.on-client-errors

false の場合、NonTransientAiException をスローし、4xx クライアントエラーコードの再試行を試行しません。

false

spring.ai.retry.exclude-on-http-codes

再試行をトリガーすべきではない HTTP ステータスコードのリスト (NonTransientAiException をスローするなど)。

spring.ai.retry.on-http-codes

再試行をトリガーする必要がある HTTP ステータスコードのリスト (例: TransientAiException をスローする)。

接続プロパティ

接頭辞 spring.ai.openai は、OpenAI への接続を可能にするプロパティ接頭辞として使用されます。

プロパティ 説明 デフォルト

spring.ai.openai.base-url

接続先の URL

api.openai.com (英語)

spring.ai.openai.api-key

API キー

-

spring.ai.openai.organization-id

オプションで、API リクエストに使用する組織を指定できます。

-

spring.ai.openai.project-id

必要に応じて、API リクエストに使用するプロジェクトを指定できます。

-

複数の組織に属しているユーザー(または従来のユーザー API キーを使用してプロジェクトにアクセスしているユーザー)の場合は、オプションで、API リクエストに使用する組織とプロジェクトを指定できます。これらの API リクエストからの使用量は、指定された組織とプロジェクトの使用量としてカウントされます。

プロパティの構成

プレフィックス spring.ai.openai.chat は、OpenAI のチャットモデル実装を構成できるプロパティプレフィックスです。

プロパティ 説明 デフォルト

spring.ai.openai.chat.enabled

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

true

spring.ai.openai.chat.base-url

オプションで spring.ai.openai.base-url をオーバーライドして、チャット固有の URL を提供します

-

spring.ai.openai.chat.completions-path

ベース URL に追加するパス

/v1/chat/completions

spring.ai.openai.chat.api-key

オプションで spring.ai.openai.api-key をオーバーライドしてチャット固有の API キーを提供します

-

spring.ai.openai.chat.organization-id

オプションで、API リクエストに使用する組織を指定できます。

-

spring.ai.openai.chat.project-id

必要に応じて、API リクエストに使用するプロジェクトを指定できます。

-

spring.ai.openai.chat.options.model

使用する OpenAI チャットモデルの名前。次のようなモデルを選択できます: gpt-4ogpt-4o-minigpt-4-turbogpt-3.5-turbo … 詳細については、モデル (英語) ページを参照してください。

gpt-4o

spring.ai.openai.chat.options.temperature

生成される補完の見かけの創造性を制御するために使用するサンプリング温度。値を高くすると出力がよりランダムになり、値を低くすると結果がより集中的で決定的になります。これら 2 つの設定の相互作用を予測するのは難しいため、同じ完了リクエストに対して温度と top_p を変更することはお勧めできません。

0.8

spring.ai.openai.chat.options.frequencyPenalty

-2.0 から 2.0 までの数値。正の値を指定すると、これまでのテキスト内の既存の頻度に基づいて新しいトークンにペナルティが課され、モデルが同じ行をそのまま繰り返す可能性が低くなります。

0.0f

spring.ai.openai.chat.options.logitBias

指定したトークンが補完に表示される可能性を変更します。

-

spring.ai.openai.chat.options.maxTokens

チャット補完で生成するトークンの最大数。入力トークンと生成されたトークンの合計の長さは、モデルのコンテキストの長さによって制限されます。

-

spring.ai.openai.chat.options.n

各入力メッセージに対して生成するチャット補完の選択肢の数。すべての選択肢にわたって生成されたトークンの数に基づいて料金が請求されることに注意してください。コストを最小限に抑えるために、n を 1 に保ちます。

1

spring.ai.openai.chat.options.presencePenalty

-2.0 から 2.0 までの数値。正の値を指定すると、これまでにテキストに出現したかどうかに基づいて新しいトークンにペナルティが課され、モデルが新しいトピックについて話す可能性が高まります。

-

spring.ai.openai.chat.options.responseFormat.type

GPT-4oGPT-4o miniGPT-4 Turbo および gpt-3.5-turbo-1106 より新しいすべての GPT-3.5 Turbo モデルと互換性があります。JSON_OBJECT 型は JSON モードを有効にし、モデルが生成するメッセージが有効な JSON であることを保証します。JSON_SCHEMA 型は構造化された出力 (英語) を有効にし、モデルが指定された JSON スキーマと一致することを保証します。JSON_SCHEMA 型では、responseFormat.schema プロパティも設定する必要があります。

-

spring.ai.openai.chat.options.responseFormat.name

レスポンスフォーマットのスキーマ名。responseFormat.type=JSON_SCHEMA にのみ適用可能

custom_schema

spring.ai.openai.chat.options.responseFormat.schema

レスポンス形式 JSON スキーマ。responseFormat.type=JSON_SCHEMA にのみ適用可能

-

spring.ai.openai.chat.options.responseFormat.strict

レスポンスフォーマット JSON スキーマ準拠の厳密さ。responseFormat.type=JSON_SCHEMA にのみ適用可能

-

spring.ai.openai.chat.options.seed

この機能はベータ版です。指定した場合、システムは、同じシードとパラメーターを使用した繰り返しリクエストが同じ結果を返すように、決定論的にサンプリングするために最善の努力をします。

-

spring.ai.openai.chat.options.stop

API がさらなるトークンの生成を停止する最大 4 つのシーケンス。

-

spring.ai.openai.chat.options.topP

核サンプリングと呼ばれる、温度によるサンプリングの代替方法。モデルは、top_p 確率質量を使用してトークンの結果を考慮します。0.1 は、上位 10% の確率質量を構成するトークンのみが考慮されることを意味します。通常、これまたは温度を変更することをお勧めしますが、両方を変更することは推奨しません。

-

spring.ai.openai.chat.options.tools

モデルが呼び出す可能性のあるツールのリスト。現在、ツールとしては関数のみがサポートされています。これを使用して、モデルが JSON 入力を生成する可能性のある関数のリストを提供します。

-

spring.ai.openai.chat.options.toolChoice

モデルによって呼び出される関数 (存在する場合) を制御します。none は、モデルが関数を呼び出さず、代わりにメッセージを生成することを意味します。auto は、モデルがメッセージを生成するか関数を呼び出すかを選択できることを意味します。{"type: "function" , "function" : {"name" : "my_function" }} で特定の関数を指定すると、モデルは強制的にその関数を呼び出します。関数が存在しない場合は none がデフォルトです。auto はデフォルトです。機能が存在します。

-

spring.ai.openai.chat.options.user

エンドユーザーを表す一意の識別子。OpenAI が不正使用を監視および検出できます。

-

spring.ai.openai.chat.options.functions

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

-

spring.ai.openai.chat.options.stream-usage

(ストリーミングのみ) リクエスト全体のトークン使用統計を含む追加のチャンクを追加するように設定します。このチャンクの choices フィールドは空の配列であり、他のすべてのチャンクにも使用状況フィールドが含まれますが、値は null になります。

false

spring.ai.openai.chat.options.parallel-tool-calls

ツールの使用中に並列関数呼び出し (英語) を有効にするかどうか。

true

spring.ai.openai.chat.options.http-headers

チャット補完リクエストに追加されるオプションの HTTP ヘッダー。API キーをオーバーライドするには、Authorization ヘッダーキーを使用し、キー値の前に `Bearer` プレフィックスを付ける必要があります。

-

ChatModel および EmbeddingModel 実装の共通の spring.ai.openai.base-url および spring.ai.openai.api-key をオーバーライドできます。spring.ai.openai.chat.base-url および spring.ai.openai.chat.api-key プロパティが設定されている場合は、共通のプロパティよりも優先されます。これは、異なるモデルおよび異なるモデルエンドポイントに異なる OpenAI アカウントを使用する場合に便利です。
spring.ai.openai.chat.options というプレフィックスが付いたすべてのプロパティは、リクエスト固有のランタイムオプションを Prompt 呼び出しに追加することで実行時にオーバーライドできます。

ランタイムオプション

OpenAiChatOptions.java [GitHub] (英語) は、使用するモデル、温度、周波数ペナルティなどのモデル構成を提供します。

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

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

ChatResponse response = chatModel.call(
    new Prompt(
        "Generate the names of 5 famous pirates.",
        OpenAiChatOptions.builder()
            .withModel("gpt-4-o")
            .withTemperature(0.4)
        .build()
    ));
モデル固有の OpenAiChatOptions [GitHub] (英語) に加えて、ChatOptionsBuilder#builder() [GitHub] (英語) で作成されたポータブル ChatOptions [GitHub] (英語) インスタンスを使用できます。

関数呼び出し

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

マルチモーダル

マルチモーダルとは、テキスト、イメージ、音声、その他のデータ形式など、さまざまなソースからの情報を同時に理解して処理するモデルの機能を指します。現在、OpenAI の gpt-4o および gpt-4o-mini モデルがマルチモーダルサポートを提供しています。詳細については、Vision (英語) ガイドを参照してください。

OpenAI ユーザーメッセージ API (英語) は、メッセージに base64 でエンコードされたイメージのリストまたはイメージ URL を組み込むことができます。Spring AI のメッセージ [GitHub] (英語) インターフェースは、メディア [GitHub] (英語) 型を導入することで、マルチモーダル AI モデルをサポートします。この型には、メッセージ内のメディア添付ファイルに関するデータと詳細が含まれており、Spring の org.springframework.util.MimeType と、生のメディアデータ用の java.lang.Object が使用されます。

以下は、OpenAiChatModelIT.java [GitHub] (英語) から抜粋したコード例であり、GPT_4_O モデルを使用してユーザーテキストとイメージを融合する方法を示しています。

byte[] imageData = new ClassPathResource("/multimodal.test.png").getContentAsByteArray();

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

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
        OpenAiChatOptions.builder().withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));
GPT_4_VISION_PREVIEW は、2024 年 6 月 17 日より、このモデルの既存ユーザーのみご利用いただけます。既存ユーザーでない場合は、GPT_4_O または GPT_4_TURBO モデルをご利用ください。詳細はこちら (英語)

または、GPT_4_O モデルを使用した同等のイメージ URL :

var userMessage = new UserMessage("Explain what do you see on this picture?",
        List.of(new Media(MimeTypeUtils.IMAGE_PNG,
                "https://docs.spring.io/spring-ai/reference/1.0-SNAPSHOT/_images/multimodal.test.png")));

ChatResponse response = chatModel.call(new Prompt(List.of(userMessage),
        OpenAiChatOptions.builder().withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));
複数のイメージを渡すこともできます。

入力イメージ multimodal.test.png :

Multimodal Test Image

"Explain what do you see on this picture?" というテキストメッセージで、次のようなレスポンスが生成されます。

This is an image of a fruit bowl with a simple design. The bowl is made of metal with curved wire edges that
create an open structure, allowing the fruit to be visible from all angles. Inside the bowl, there are two
yellow bananas resting on top of what appears to be a red apple. The bananas are slightly overripe, as
indicated by the brown spots on their peels. The bowl has a metal ring at the top, likely to serve as a handle
for carrying. The bowl is placed on a flat surface with a neutral-colored background that provides a clear
view of the fruit inside.

構造化された出力

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

現在、OpenAI は JSON スキーマ言語形式のサブセット (英語) をサポートしています。

構成

Spring AI を使用すると、OpenAiChatOptions ビルダーを使用してプログラム的に、またはアプリケーションプロパティを通じてレスポンス形式を構成できます。

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

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

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",
        OpenAiChatOptions.builder()
            .withModel(ChatModel.GPT_4_O_MINI)
            .withResponseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
            .build());

ChatResponse response = this.openAiChatModel.call(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);

var jsonSchema = outputConverter.getJsonSchema();

Prompt prompt = new Prompt("how can I solve 8x + 7 = -23",
        OpenAiChatOptions.builder()
            .withModel(ChatModel.GPT_4_O_MINI)
            .withResponseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
            .build());

ChatResponse response = this.openAiChatModel.call(prompt);
String content = response.getResult().getOutput().getContent();

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

アプリケーションプロパティによる設定

あるいは、OpenAI 自動構成を使用する場合は、次のアプリケーションプロパティを通じて必要なレスポンス形式を構成できます。

spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.options.model=gpt-4o-mini

spring.ai.openai.chat.options.response-format.type=JSON_SCHEMA
spring.ai.openai.chat.options.response-format.name=MySchemaName
spring.ai.openai.chat.options.response-format.schema={"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}
spring.ai.openai.chat.options.response-format.strict=true

サンプルコントローラー

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

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

spring.ai.openai.api-key=YOUR_API_KEY
spring.ai.openai.chat.options.model=gpt-3.5-turbo
spring.ai.openai.chat.options.temperature=0.7
api-key を OpenAI 資格情報に置き換えます。

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

@RestController
public class ChatController {

    private final OpenAiChatModel chatModel;

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

    @GetMapping("/ai/generate")
    public Map generate(@RequestParam(value = "message", defaultValue = "Tell me a joke") String message) {
        return Map.of("generation", 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 chatModel.stream(prompt);
    }
}

手動構成

OpenAiChatModel [GitHub] (英語) は ChatModel と StreamingChatModel を実装し、低レベル OpenAiApi クライアントを使用して OpenAI サービスに接続します。

spring-ai-openai 依存関係をプロジェクトの Maven pom.xml ファイルに追加します。

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai</artifactId>
</dependency>

または、Gradle build.gradle ビルドファイルに保存します。

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

次に、OpenAiChatModel を作成し、テキスト生成に使用します。

var openAiApi = new OpenAiApi(System.getenv("OPENAI_API_KEY"));
var openAiChatOptions = OpenAiChatOptions.builder()
            .withModel("gpt-3.5-turbo")
            .withTemperature(0.4)
            .withMaxTokens(200)
        .build();
var chatModel = new OpenAiChatModel(openAiApi, openAiChatOptions);


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

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

OpenAiChatOptions は、チャットリクエストの構成情報を提供します。OpenAiChatOptions.Builder は流れるようなオプションビルダーです。

低レベル OpenAiApi クライアント

OpenAiApi [GitHub] (英語) が提供するのは、OpenAI チャット API OpenAI チャット API (英語) 用の軽量 Java クライアントです。

次のクラス図は、OpenAiApi チャットインターフェースと構成要素を示しています。

OpenAiApi Chat API Diagram

API をプログラムで使用する方法の簡単なスニペットを次に示します。

OpenAiApi openAiApi =
    new OpenAiApi(System.getenv("OPENAI_API_KEY"));

ChatCompletionMessage chatCompletionMessage =
    new ChatCompletionMessage("Hello world", Role.USER);

// Sync request
ResponseEntity<ChatCompletion> response = openAiApi.chatCompletionEntity(
    new ChatCompletionRequest(List.of(chatCompletionMessage), "gpt-3.5-turbo", 0.8f, false));

// Streaming request
Flux<ChatCompletionChunk> streamResponse = openAiApi.chatCompletionStream(
        new ChatCompletionRequest(List.of(chatCompletionMessage), "gpt-3.5-turbo", 0.8f, true));

詳細については、OpenAiApi.java [GitHub] (英語) の JavaDoc を参照してください。

低レベル API の例