Usiamo i cookie. Cookie e memoria del browser ti mantengono connesso e ricordano le tue preferenze. Con il tuo consenso misuriamo anche come viene usato il sito. Puoi in qualsiasi momento. Consulta la nostra cookie policy.

Java

Guide agli SDK

Java

Usa la libreria ufficiale openai-java con api14: baseUrl, chat, streaming, strumenti, output strutturato, input di immagini, errori, timeout e retry.

Usa la libreria ufficiale openai-java con api14. Imposta baseUrl nel builder del client e passa gli id dei modelli (ad esempio openai/gpt-5-mini) come semplici stringhe.

Installazione

Gradle:

implementation("com.openai:openai-java:4.+")

Maven:

<dependency>
  <groupId>com.openai</groupId>
  <artifactId>openai-java</artifactId>
  <version>LATEST</version>
</dependency>

Poi imposta API14_API_KEY=sk-api14-... nel tuo ambiente.

Configurazione

import com.openai.client.OpenAIClient;
import com.openai.client.okhttp.OpenAIOkHttpClient;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .baseUrl("https://api14.com/api/v1")
    .apiKey(System.getenv("API14_API_KEY"))
    .build();

OpenAIOkHttpClient.fromEnv() legge invece OPENAI_BASE_URL e OPENAI_API_KEY, così puoi cambiare ambiente senza modificare il codice:

export OPENAI_BASE_URL="https://api14.com/api/v1"
export OPENAI_API_KEY="sk-api14-..."

Chat

import com.openai.models.chat.completions.ChatCompletion;
import com.openai.models.chat.completions.ChatCompletionCreateParams;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .model("openai/gpt-5-mini")
    .addUserMessage("Explain vector databases in two sentences.")
    .build();

ChatCompletion completion = client.chat().completions().create(params);
completion.choices().get(0).message().content().ifPresent(System.out::println);

Streaming

import com.openai.core.http.StreamResponse;
import com.openai.models.chat.completions.ChatCompletionChunk;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .model("anthropic/claude-sonnet-4.5")
    .addUserMessage("Write a haiku about APIs.")
    .build();

try (StreamResponse<ChatCompletionChunk> stream = client.chat().completions().createStreaming(params)) {
    stream.stream()
        .flatMap(chunk -> chunk.choices().stream())
        .flatMap(choice -> choice.delta().content().stream())
        .forEach(System.out::print);
}

Vedi Streaming.

Tool calling

Descrivi uno strumento come classe; l'SDK ne ricava lo JSON Schema e analizza gli argomenti riportandoli nella classe:

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.openai.models.chat.completions.*;
import java.util.Collection;

@JsonClassDescription("Current weather for a city")
static class GetWeather {
    public String city;
}

ChatCompletionCreateParams.Builder builder = ChatCompletionCreateParams.builder()
    .model("openai/gpt-5-mini")
    .addTool(GetWeather.class)
    .addUserMessage("What's the weather in Istanbul?");

while (true) {
    ChatCompletionMessage message = client.chat().completions().create(builder.build())
        .choices().get(0).message();
    builder.addMessage(message);
    if (message.toolCalls().map(Collection::isEmpty).orElse(true)) {
        message.content().ifPresent(System.out::println);
        break;
    }
    for (ChatCompletionMessageToolCall call : message.toolCalls().get()) {
        GetWeather args = call.asFunction().function().arguments(GetWeather.class);
        builder.addMessage(ChatCompletionToolMessageParam.builder()
            .toolCallId(call.asFunction().id())
            .contentAsJson(getWeather(args.city)) // la tua funzione
            .build());
    }
}

Il builder conserva l'intera conversazione: a ogni giro aggiunge il messaggio dell'assistente con le sue chiamate di strumento, poi un messaggio di strumento per ogni chiamata, e rinvia tutto. I campi della classe dello strumento diventano le proprietà dello schema; aggiungi @JsonPropertyDescription a un campo per dire al modello cosa significa. Nel codice di produzione limita il numero di iterazioni, così un modello che continua a chiamare strumenti non può andare in loop all'infinito. Vedi Tool calling.

Output strutturato

Passa una classe a responseFormat; l'SDK genera da essa uno JSON Schema rigoroso e analizza il contenuto di ogni choice in un'istanza. Usa un modello che elenca structured_outputs o response_format nei suoi supported_parameters:

static class Person {
    public String name;
    public int born;
    public String city;
}

StructuredChatCompletionCreateParams<Person> params = ChatCompletionCreateParams.builder()
    .model("openai/gpt-5-mini")
    .responseFormat(Person.class)
    .addUserMessage("Extract: Ada Lovelace, born 1815 in London.")
    .build();

client.chat().completions().create(params).choices().stream()
    .flatMap(choice -> choice.message().content().stream())
    .forEach(person -> System.out.println(person.name + " " + person.born));

Vedi Output strutturati.

Input di immagini

import java.util.List;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .model("google/gemini-2.5-flash")
    .addUserMessageOfArrayOfContentParts(List.of(
        ChatCompletionContentPart.ofText(ChatCompletionContentPartText.builder()
            .text("What is in this picture?").build()),
        ChatCompletionContentPart.ofImageUrl(ChatCompletionContentPartImage.builder()
            .imageUrl(ChatCompletionContentPartImage.ImageUrl.builder()
                .url("https://example.com/photo.jpg") // oppure un URL data:image/png;base64,...
                .build())
            .build())))
    .build();

Vedi Visione e file.

Parametri aggiuntivi

I campi del gateway senza un setter tipizzato (reasoning, provider, models) passano tramite putAdditionalBodyProperty:

import com.openai.core.JsonValue;
import java.util.Map;

ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
    .model("anthropic/claude-sonnet-4.5")
    .addUserMessage("Prove there are infinitely many primes.")
    .putAdditionalBodyProperty("reasoning", JsonValue.from(Map.of("effort", "high")))
    .build();

Errori

Le risposte non 2xx lanciano sottoclassi di OpenAIServiceException, che espongono lo stato e gli header:

import com.openai.errors.OpenAIServiceException;

try {
    client.chat().completions().create(params);
} catch (OpenAIServiceException e) {
    if (e.statusCode() == 402) {
        System.err.println("Balance too low, add funds (insufficient_balance)");
    } else if (e.statusCode() == 429) {
        System.err.println("Rate limited, retry after " + e.headers().values("Retry-After") + "s");
    } else {
        throw e;
    }
}

Vedi Errori.

Timeout e retry

Per impostazione predefinita il client ripete due volte gli errori di connessione, 408, 409, 429 e 5xx con backoff esponenziale. Configura il numero di retry e il timeout nel builder, oppure per singola richiesta:

import com.openai.core.RequestOptions;
import java.time.Duration;

OpenAIClient client = OpenAIOkHttpClient.builder()
    .baseUrl("https://api14.com/api/v1")
    .apiKey(System.getenv("API14_API_KEY"))
    .maxRetries(4)
    .timeout(Duration.ofSeconds(60))
    .build();

client.chat().completions().create(params,
    RequestOptions.builder().timeout(Duration.ofMinutes(5)).build());

Il timeout del builder si applica a ogni tentativo. Le richieste di reasoning lunghe possono richiedere minuti, quindi dai loro un timeout più lungo per singola richiesta oppure usa lo streaming. Riprovare non serve con daily_limit_reached o insufficient_balance; intercetta RateLimitException e controlla il codice di errore prima di pianificare un altro tentativo. Vedi Limiti di frequenza.

Tutte le funzionalità

import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api14.com/api/v1",
  apiKey: process.env.API14_API_KEY,
});

const result = await client.chat.completions.create({
  "model": "openai/gpt-5-mini",
  "messages": [
    {
      "role": "user",
      "content": "Explain vector databases in two sentences."
    }
  ]
});
console.log(result.choices[0].message.content);