OpenAI APIをJavaで使用する: 非公式クライアント「jvm-openai」の紹介

こんにちは、皆さん！今日は、Javaを使ってOpenAI APIを簡単に利用するための非公式クライアントライブラリ「jvm-openai」について紹介します。このライブラリを使用することで、OpenAIのさまざまなAPI機能をJavaコードから直接利用できるようになります。

# jvm-openaiとは？

「[jvm-openai](https://github.com/StefanBratanov/jvm-openai)」は、Java向けの非公式OpenAI APIクライアントで、Jacksonを使用してJSONを解析するシンプルなライブラリです。このライブラリを使用することで、OpenAIのさまざまなAPI（例えばチャット、画像生成、音声生成など）を簡単に操作することができます。

## 依存関係の追加

まず、Java 17以上を使用する必要があります。プロジェクトに依存関係を追加するには、以下のように設定します。

### Gradleの場合

```groovy
implementation("io.github.stefanbratanov:jvm-openai:${version}")
```

### Mavenの場合

```xml
<dependency>
    <groupId>io.github.stefanbratanov</groupId>
    <artifactId>jvm-openai</artifactId>
    <version>${version}</version>
</dependency>
```

# 基本的な使い方

以下は、jvm-openaiを使用してチャット補完を実行する最小限のサンプルコードです。

```java
OpenAI openAI = OpenAI.newBuilder(System.getenv("OPENAI_API_KEY")).build();

ChatClient chatClient = openAI.chatClient();
CreateChatCompletionRequest createChatCompletionRequest = CreateChatCompletionRequest.newBuilder()
    .model(OpenAIModel.GPT_3_5_TURBO)
    .message(ChatMessage.userMessage("Who won the world series in 2020?"))
    .build();
ChatCompletion chatCompletion = chatClient.createChatCompletion(createChatCompletionRequest);
```

# さまざまなAPIのサポート

jvm-openaiは、以下のAPIをサポートしています：

- Audio
- Chat
- Embeddings
- Fine-tuning
- Batch
- Files
- Images
- Models
- Moderations

さらに、以下のベータAPIもサポートしています：

- Assistants
- Threads
- Messages
- Runs
- Run Steps
- Vector Stores
- Vector Store Files
- Vector Store File Batches

# 実際の使用例

例えば、指定された隠語（cant）に基づいてアクロスティック（acrostic）を生成する例を見てみましょう。このコードは、OpenAIのGPTモデルを使用してアクロスティックを生成し、その結果をJSON形式で返します。

```java
package jp.livlog.explore.now.helper.openai;

import java.util.Map;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.github.stefanbratanov.jvm.openai.ChatMessage;
import io.github.stefanbratanov.jvm.openai.CreateChatCompletionRequest;
import io.github.stefanbratanov.jvm.openai.OpenAI;
import io.github.stefanbratanov.jvm.openai.OpenAIModel;
import jp.livlog.explore.now.share.Symbol;

public class Acrostic {

    public static Map<String, Object> execute(final String cant, final String reviews, final String token) throws Exception {
        final var system = new StringBuilder();
        system.append("隠語（cant）「").append(cant).append("」という言葉を使ってアクロスティック（acrostic）を作成してください。各行の最初の文字は次のようにしてください。").append(Symbol.SEP);
        system.append(Symbol.SEP);

        // cantの文字列を一文字ずつループする
        for (var i = 0; i < cant.length(); i++) {
            final var str = String.valueOf(cant.charAt(i));
            if (i == cant.length() - 1) {
                system.append(str).append(": （「").append(str).append("」で始まるフレーズや文、「。」は文末に付けない）").append(Symbol.SEP);
            } else if ("。".equals(str)) {
                system.append("。: （ここはそのままにする）").append(Symbol.SEP);
            } else {
                final var nextChar = i < cant.length() - 1 ? String.valueOf(cant.charAt(i + 1)) : "";
                if ("。".equals(nextChar)) {
                    system.append(str).append(": （「").append(str).append("」で始まるフレーズや文、「。」は文末に付けない）").append(Symbol.SEP);
                } else {
                    system.append(str).append(": （「").append(str).append("」で始まるフレーズや文、「、」で終わらせる）").append(Symbol.SEP);
                }
            }
        }
        system.append(Symbol.SEP);
        system.append("出力方法はJSON形式で「フォーマット」を例に出力して").append(Symbol.SEP);
        system.append(Symbol.SEP);
        system.append("作成するアクロスティックの内容としては「口コミ一覧」を参考にして。").append(Symbol.SEP);
        system.append("アクロスティックの文章内には口コミの単語は利用しない").append(Symbol.SEP);
        system.append(Symbol.SEP);
        system.append("## フォーマット ## ").append(Symbol.SEP);
        system.append("{\"cant\":\"<-- 隠語 -->\", \"acrostic\":[\"<-- アクロスティック -->\"]}").append(Symbol.SEP);

        final var systemMessage = ChatMessage.systemMessage(system.toString());

        final var user = new StringBuilder();
        user.append("## 口コミ一覧 ###").append(Symbol.SEP);
        user.append(reviews);
        final var userMessage = ChatMessage.userMessage(user.toString());

        final var openAI = OpenAI.newBuilder(token).build();
        final var chatClient = openAI.chatClient();
        final var createChatCompletionRequest = CreateChatCompletionRequest.newBuilder()
                .model(OpenAIModel.GPT_4o)
                .message(systemMessage)
                .message(userMessage)
                .build();

        final var chatCompletion = chatClient.createChatCompletion(createChatCompletionRequest);
        final var choiceList = chatCompletion.choices();

        if (choiceList.isEmpty()) {
            throw new Exception("Failed to parse.");
        }

        final var choice = choiceList.get(0);
        var json = choice.message().content();
        json = json.replace("```json", "").replace("```", "");

        final var objectMapper = new ObjectMapper();
        return objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {});
    }
}
```

このクラスは、指定された隠語を使ってアクロスティックを生成するためのものです。OpenAIのGPTモデルを使用し、与えられた隠語と口コミ一覧に基づいて生成されたアクロスティックをJSON形式で返します。

# まとめ

「[jvm-openai](https://github.com/StefanBratanov/jvm-openai)」を使用すると、JavaからOpenAI APIを簡単に利用できるようになります。この記事で紹介した基本的な使用例や、実際のアクロスティック生成の例を参考にして、自分のプロジェクトでも活用してみてください。これからもAIの力を借りて、さまざまな創造的なプロジェクトを実現していきましょう！