Simple-OpenAI Java Library

repository·main·Indexed 18 days ago

https://github.com/sashirestela/simple-openai

A Java HTTP client library providing a consistent interface for interacting with the OpenAI API. It supports a wide range of services including Chat Completions (Standard, Streaming, Vision), Audio (TTS and Transcription), Image generation, Assistants Beta v2, Realtime WebSockets, and Fine Tuning. The library requires Java 11 or greater and supports both Java's default HttpClient and OkHttp. It includes built-in features for automatic request retries with exponential backoff, structured outputs via JSON schema, and function calling.

Tokens
6.1K
Snippets
16
Records
19
Agent score
14%

What's inside Simple-OpenAI

  1. Overview of Simple-OpenAI supported services

    main

    Simple-OpenAI provides a consistent Java interface for a wide range of OpenAI services. Supported features include:

    • Audio: Speech, Transcription, Translation
    • Batch: Batches of Chat Completion
    • Chat Completion: Text Generation, Streaming, Function Calling, Vision, Structured Outputs, Audio, Web Search
    • Completion: Legacy Text Generation
    • Embedding: Vectoring Text
    • Files: Upload Files
    • Fine Tuning: Customize Models
    • Image: Generate, Edit, Variation
    • Models: List models
    • Moderation: Check harmful text
    • Realtime: Speech-to-Speech Conversation, Multimodality, Function Calling
    • Response: Text Generation, Streaming, Function Calling, Vision, Structured Outputs, Reasoning, Computer Use, File Search, Web Search, Remote MCP, Image Generation, Code Interpreter, Reusable Prompts
    • Session Token: Create Ephemeral Tokens, Create Transcription Ephemeral Tokens
    • Upload: Upload Large Files in Parts
    • Assistants Beta v2: Assistants, Threads, Messages, Runs, Steps, Vector Stores, Streaming, Function Calling, Vision, Structured Outputs
  2. Implement Chat Completion with Function Calling

    main

    Function calling allows the model to interact with your local business logic. To implement this:

    1. Create classes that implement the Functional interface.
    2. Use @JsonProperty and @JsonPropertyDescription to define the function arguments for the model.
    3. Use FunctionExecutor to enroll these functions and execute the logic when the model requests a tool call.
    4. Pass the tools to the ChatRequest using functionExecutor.getToolFunctions().
    public class Product implements Functional {
        @JsonPropertyDescription("The multiplicand part of a product")
        @JsonProperty(required = true)
        public double multiplicand;
    
        @JsonPropertyDescription("The multiplier part of a product")
        @JsonProperty(required = true)
        public double multiplier;
    
        @Override
        public Object execute() {
            return multiplicand * multiplier;
        }
    }
    
    // Usage in Chat
    var functionExecutor = new FunctionExecutor();
    functionExecutor.enrollFunction(FunctionDef.builder()
            .name("product")
            .description("Get the product of two numbers")
            .functionalClass(Product.class)
            .strict(Boolean.TRUE)
            .build());
    
    var chatRequest = ChatRequest.builder()
            .model("gpt-4o-mini")
            .messages(List.of(UserMessage.of("What is 123 * 456?")))
            .tools(functionExecutor.getToolFunctions())
            .build();
  3. Use OpenAI-compatible API providers

    main

    Simple-OpenAI supports several third-party providers via specialized builder classes. Each provider has different supported services.

    Gemini Vertex API

    Use SimpleOpenAIGeminiVertex. Requires google-auth-library-oauth2-http dependency.

    • Supported Services: chatCompletionService.
    • Setup: Requires baseUrl and an apiKeyProvider (function returning a refreshing API key).

    Gemini Google API

    Use SimpleOpenAIGeminiGoogle.

    • Supported Services: chatCompletionService, embeddingService (float format).

    Deepseek API

    Use SimpleOpenAIDeepseek.

    • Supported Services: chatCompletionService (includes thinking), modelService (list).

    Mistral API

    Use SimpleOpenAIMistral.

    • Supported Services: chatCompletionService, embeddingService (float format), modelService (list, detail, delete).

    Azure OpenAI

    Use SimpleOpenAIAzure.

    • Supported Services: chatCompletionService, fileService, assistantService beta V2.
    • Setup: Requires apiKey, baseUrl (including resourceName and deploymentId), and apiVersion.

    Anyscale

    Use SimpleOpenAIAnyscale.

    • Supported Services: chatCompletionService (tested with Mistral).
  4. Run the project demos

    main

    To run the included Java examples, follow these steps:

    1. Clone and Build:
      git clone https://github.com/sashirestela/simple-openai.git
      cd simple-openai
      mvn clean install
    2. Set API Key (Environment variable name depends on the provider, e.g., OPENAI_API_KEY or DEEPSEEK_API_KEY):
      export OPENAI_API_KEY=<your_api_key>
    3. Execute Demo:
      chmod +x rundemo.sh
      ./rundemo.sh <demo_name>
      Replace <demo_name> with the name of the Java file in the demo folder without the Demo suffix (e.g., ./rundemo.sh Chat for the Chat demo).
    # Example: Running the Chat demo
    ./rundemo.sh Chat
  5. Setup Simple-OpenAI for Android

    main

    To use Simple-OpenAI in an Android project, ensure your build.gradle is configured with the following requirements:

    1. SDK Version: minSdk must be at least 24.
    2. Java Compatibility: Set sourceCompatibility and targetCompatibility to JavaVersion.VERSION_11 and jvmTarget to '11'.
    3. Dependencies: Include simple-openai and okhttp.

    Initialization (Java):

    SimpleOpenAI openAI = SimpleOpenAI.builder()
        .apiKey(API_KEY)
        .clientAdapter(new OkHttpClientAdapter())
        .build();

    Initialization (Kotlin):

    val openAI = SimpleOpenAI.builder()
        .apiKey(API_KEY)
        .clientAdapter(OkHttpClientAdapter())
        .build()
    android {
        defaultConfig {
            minSdk 24
        }
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_11
            targetCompatibility JavaVersion.VERSION_11
        }
        kotlinOptions {
            jvmTarget = '11'
        }
    }
    
    dependencies {
        implementation 'io.github.sashirestela:simple-openai:[simple-openai_version]'
        implementation 'com.squareup.okhttp3:okhttp:[okhttp_version]'
    }
  6. Create a SimpleOpenAI object

    main

    To use the services, you must first instantiate a SimpleOpenAI object. At a minimum, you must provide an OpenAI API Key. You can also optionally provide an organizationId or a projectId to manage usage across different organizations or projects.

    It is recommended to retrieve sensitive keys from environment variables like OPENAI_API_KEY.

    var openAI = SimpleOpenAI.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .build();
    
    // With optional organization and project IDs
    var openAI = SimpleOpenAI.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .organizationId(System.getenv("OPENAI_ORGANIZATION_ID"))
        .projectId(System.getenv("OPENAI_PROJECT_ID"))
        .build();
  7. Install Simple-OpenAI via Maven or Gradle

    main

    To use Simple-OpenAI in your Java project, add the dependency to your build configuration. Note that you must use Java 11 or greater. While the library works with the default HTTP client, you can optionally add okhttp if you prefer to use it for communication.

    ### Maven
    ```xml
    <dependency>
        <groupId>io.github.sashirestela</groupId>
        <artifactId>simple-openai</artifactId>
        <version>[simple-openai_latest_version]</version>
    </dependency>
    <!-- OkHttp dependency is optional if you decide to use it with simple-openai -->
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>[okhttp_latest_version]</version>
    </dependency>

    Gradle

    dependencies {
        implementation 'io.github.sashirestela:simple-openai:[simple-openai_latest_version]'
        /* OkHttp dependency is optional if you decide to use it with simple-openai */
        implementation 'com.squareup.okhttp3:okhttp:[okhttp_latest_version]'
    }
  8. Configure HTTP clients for SimpleOpenAI

    main

    Simple-OpenAI uses either Java's HttpClient (default) or Square's OkHttp for making requests. You can customize the client by providing a clientAdapter to the builder. This is useful for configuring proxies, timeouts, or using a specific HTTP implementation.

    // Using a custom Java HttpClient
    var httpClient = HttpClient.newBuilder()
        .version(Version.HTTP_1_1)
        .followRedirects(Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
        .build();
    
    var openAI = SimpleOpenAI.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .clientAdapter(new JavaHttpClientAdpter(httpClient)) // Custom Java HttpClient
        // .clientAdapter(new JavaHttpClientAdpter())      // Default Java HttpClient
        // .clientAdapter(new OkHttpClientAdpter(okHttpClient)) // Custom OkHttpClient
        .build();
  9. Configure Realtime features with WebSockets

    main

    To use the Realtime feature, you must set the realtimeConfig attribute. This feature requires a WebSocket adapter (either JavaHttpWebSocketAdpter or OkHttpWebSocketAdpter) to handle communication. You can use the default adapters or provide a custom HTTP client for the WebSocket connection.

    var openAI = SimpleOpenAI.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        // Using default Java HttpClient for WebSocket
        .realtimeConfig(RealtimeConfig.of("model"))
        // .realtimeConfig(RealtimeConfig.of("model", new JavaHttpWebSocketAdpter()))
        // .realtimeConfig(RealtimeConfig.of("model", new OkHttpWebSocketAdpter()))
        .build();
  10. Configure automatic request retries with RetryConfig

    main

    Simple-OpenAI supports automatic retries using exponential backoff with optional jitter. You can customize the retry behavior by building a RetryConfig and passing it to the SimpleOpenAI builder.

    Configuration Options:

    • maxAttempts: Maximum number of retry attempts (Default: 3)
    • initialDelayMs: Initial delay before retrying in milliseconds (Default: 1000)
    • maxDelayMs: Maximum delay between retries in milliseconds (Default: 10000)
    • backoffMultiplier: Multiplier for exponential backoff (Default: 2.0)
    • jitterFactor: Percentage of jitter to apply to delay values (Default: 0.2)
    • retryableExceptions: List of exception types that trigger a retry (Default: IOException, ConnectException, SocketTimeoutException)
    • retryableStatusCodes: List of HTTP status codes that trigger a retry (Default: 408, 409, 429, 500-599)
    var retryConfig = RetryConfig.builder()
        .maxAttempts(4)
        .initialDelayMs(500)
        .maxDelayMs(8000)
        .backoffMultiplier(1.5)
        .jitterFactor(0.1)
        .build();
    
    var openAI = SimpleOpenAI.builder()
        .apiKey(System.getenv("OPENAI_API_KEY"))
        .retryConfig(retryConfig)
        .build();
  11. Understand ResponseToolChoice and its tool types

    main

    When a model makes a tool call, the response includes a ResponseToolChoice. This interface defines several ways a tool can be selected, categorized into HostedTool, FunctionTool, and MCPTool.

    Hosted Tools

    Hosted tools are built-in capabilities provided by the service. You can access them via static constants:

    • HostedTool.FILE_SEARCH
    • HostedTool.WEB_SEARCH_PREVIEW
    • HostedTool.COMPUTER_USE_PREVIEW
    • HostedTool.CODE_INTERPRETER
    • HostedTool.IMAGE_GENERATION

    Function Tools

    Used when the model selects a specific function defined in your request. Use FunctionTool.of(name) to represent a function selection.

    MCP Tools

    Model Context Protocol (MCP) tools are selected via a server label and an optional name. Use MCPTool.of(serverLabel) or MCPTool.of(serverLabel, name) to represent these selections.

  12. Use the Image service to generate images

    main

    The Image service allows you to generate images from text prompts. You can specify parameters like model, quality, size, n (number of images), and outputFormat.

    var imageRequest = ImageRequest.builder()
            .prompt("An image of orange cat hugging other white cat with a light blue scarf.")
            .model("gpt-image-1")
            .background(Background.TRANSPARENT)
            .outputFormat(OutputFormat.PNG)
            .quality(Quality.MEDIUM)
            .size(Size.X_1024_1024)
            .moderation(Moderation.LOW)
            .n(2)
            .build();
    var imageResponse = openAI.images().create(imageRequest).join();