openai/openai-java

Public

mirrored from https://github.com/openai/openai-javaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.4.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

README.md

971lines · modeblame

6eb3f62eStainless Bot3 years ago1# OpenAI Java API Library
2
11c62f22Stainless Bot1 years ago3<!-- x-release-please-start-version -->
4
de59688dstainless-app[bot]1 years ago5[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/1.4.0)
6[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/1.4.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/1.4.0)
6eb3f62eStainless Bot3 years ago7
11c62f22Stainless Bot1 years ago8<!-- x-release-please-end -->
9
d6a37429stainless-app[bot]1 years ago10The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https://platform.openai.com/docs) from applications written in Java.
6eb3f62eStainless Bot3 years ago11
22a4cb9astainless-app[bot]1 years ago12<!-- x-release-please-start-version -->
13
de59688dstainless-app[bot]1 years ago14The REST API documentation can be found on [platform.openai.com](https://platform.openai.com/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.openai/openai-java/1.4.0).
6eb3f62eStainless Bot3 years ago15
22a4cb9astainless-app[bot]1 years ago16<!-- x-release-please-end -->
17
1c7fc105stainless-app[bot]1 years ago18## Installation
6eb3f62eStainless Bot3 years ago19
11c62f22Stainless Bot1 years ago20<!-- x-release-please-start-version -->
21
1c7fc105stainless-app[bot]1 years ago22### Gradle
23
6eb3f62eStainless Bot3 years ago24```kotlin
de59688dstainless-app[bot]1 years ago25implementation("com.openai:openai-java:1.4.0")
6eb3f62eStainless Bot3 years ago26```
27
1c7fc105stainless-app[bot]1 years ago28### Maven
6eb3f62eStainless Bot3 years ago29
30```xml
31<dependency>
d6a37429stainless-app[bot]1 years ago32<groupId>com.openai</groupId>
33<artifactId>openai-java</artifactId>
de59688dstainless-app[bot]1 years ago34<version>1.4.0</version>
6eb3f62eStainless Bot3 years ago35</dependency>
36```
37
11c62f22Stainless Bot1 years ago38<!-- x-release-please-end -->
39
47ff5b11stainless-app[bot]1 years ago40## Requirements
41
42This library requires Java 8 or later.
43
1c7fc105stainless-app[bot]1 years ago44## Usage
45
8ec229bbTomer Aberbach1 years ago46See the [`openai-java-example`](openai-java-example/src/main/java/com/openai/example) directory for complete and runnable examples.
47
589ea32fTomer Aberbach1 years ago48The primary API for interacting with OpenAI models is the [Responses API](https://platform.openai.com/docs/api-reference/responses). You can generate text from the model with the code below.
49
50```java
51import com.openai.client.OpenAIClient;
52import com.openai.client.okhttp.OpenAIOkHttpClient;
53import com.openai.models.ChatModel;
54import com.openai.models.responses.Response;
55import com.openai.models.responses.ResponseCreateParams;
56
57// Configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID` and `OPENAI_PROJECT_ID` environment variables
58OpenAIClient client = OpenAIOkHttpClient.fromEnv();
59
60ResponseCreateParams params = ResponseCreateParams.builder()
61.input("Say this is a test")
de59688dstainless-app[bot]1 years ago62.model(ChatModel.GPT_4_1)
589ea32fTomer Aberbach1 years ago63.build();
64Response response = client.responses().create(params);
65```
66
67The previous standard (supported indefinitely) for generating text is the [Chat Completions API](https://platform.openai.com/docs/api-reference/chat). You can use that API to generate text from the model with the code below.
68
3e7910c3stainless-app[bot]1 years ago69```java
70import com.openai.client.OpenAIClient;
71import com.openai.client.okhttp.OpenAIOkHttpClient;
72import com.openai.models.ChatModel;
1a65445fstainless-app[bot]1 years ago73import com.openai.models.chat.completions.ChatCompletion;
74import com.openai.models.chat.completions.ChatCompletionCreateParams;
3e7910c3stainless-app[bot]1 years ago75
b8fe68a5stainless-app[bot]1 years ago76// Configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID` and `OPENAI_BASE_URL` environment variables
3e7910c3stainless-app[bot]1 years ago77OpenAIClient client = OpenAIOkHttpClient.fromEnv();
78
79ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
80.addUserMessage("Say this is a test")
2912dacdstainless-app[bot]1 years ago81.model(ChatModel.GPT_4_1)
3e7910c3stainless-app[bot]1 years ago82.build();
83ChatCompletion chatCompletion = client.chat().completions().create(params);
84```
85
86## Client configuration
87
88Configure the client using environment variables:
89
90```java
91import com.openai.client.OpenAIClient;
92import com.openai.client.okhttp.OpenAIOkHttpClient;
6eb3f62eStainless Bot3 years ago93
b8fe68a5stainless-app[bot]1 years ago94// Configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID` and `OPENAI_BASE_URL` environment variables
3e7910c3stainless-app[bot]1 years ago95OpenAIClient client = OpenAIOkHttpClient.fromEnv();
96```
97
98Or manually:
6eb3f62eStainless Bot3 years ago99
100```java
af9f9a27Robert Craigie2 years ago101import com.openai.client.OpenAIClient;
102import com.openai.client.okhttp.OpenAIOkHttpClient;
6eb3f62eStainless Bot3 years ago103
af9f9a27Robert Craigie2 years ago104OpenAIClient client = OpenAIOkHttpClient.builder()
105.apiKey("My API Key")
6eb3f62eStainless Bot3 years ago106.build();
107```
108
3e7910c3stainless-app[bot]1 years ago109Or using a combination of the two approaches:
6eb3f62eStainless Bot3 years ago110
111```java
a1977ca8stainless-app[bot]1 years ago112import com.openai.client.OpenAIClient;
113import com.openai.client.okhttp.OpenAIOkHttpClient;
114
af9f9a27Robert Craigie2 years ago115OpenAIClient client = OpenAIOkHttpClient.builder()
b8fe68a5stainless-app[bot]1 years ago116// Configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID` and `OPENAI_BASE_URL` environment variables
af9f9a27Robert Craigie2 years ago117.fromEnv()
3e7910c3stainless-app[bot]1 years ago118.apiKey("My API Key")
af9f9a27Robert Craigie2 years ago119.build();
6eb3f62eStainless Bot3 years ago120```
121
3e7910c3stainless-app[bot]1 years ago122See this table for the available options:
af9f9a27Robert Craigie2 years ago123
b8fe68a5stainless-app[bot]1 years ago124| Setter | Environment variable | Required | Default value |
125| -------------- | -------------------- | -------- | ----------------------------- |
126| `apiKey` | `OPENAI_API_KEY` | true | - |
127| `organization` | `OPENAI_ORG_ID` | false | - |
128| `project` | `OPENAI_PROJECT_ID` | false | - |
129| `baseUrl` | `OPENAI_BASE_URL` | true | `"https://api.openai.com/v1"` |
6eb3f62eStainless Bot3 years ago130
3e7910c3stainless-app[bot]1 years ago131> [!TIP]
132> Don't create more than one client in the same application. Each client has a connection pool and
133> thread pools, which are more efficient to share between requests.
6eb3f62eStainless Bot3 years ago134
3e7910c3stainless-app[bot]1 years ago135## Requests and responses
6eb3f62eStainless Bot3 years ago136
3e7910c3stainless-app[bot]1 years ago137To send a request to the OpenAI API, build an instance of some `Params` class and pass it to the corresponding client method. When the response is received, it will be deserialized into an instance of a Java class.
138
139For example, `client.chat().completions().create(...)` should be called with an instance of `ChatCompletionCreateParams`, and it will return an instance of `ChatCompletion`.
140
088a8980stainless-app[bot]1 years ago141## Immutability
142
143Each class in the SDK has an associated [builder](https://blogs.oracle.com/javamagazine/post/exploring-joshua-blochs-builder-design-pattern-in-java) or factory method for constructing it.
144
145Each class is [immutable](https://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html) once constructed. If the class has an associated builder, then it has a `toBuilder()` method, which can be used to convert it back to a builder for making a modified copy.
146
147Because each class is immutable, builder modification will _never_ affect already built class instances.
148
3e7910c3stainless-app[bot]1 years ago149## Asynchronous execution
150
151The default client is synchronous. To switch to asynchronous execution, call the `async()` method:
6eb3f62eStainless Bot3 years ago152
153```java
3e7910c3stainless-app[bot]1 years ago154import com.openai.client.OpenAIClient;
155import com.openai.client.okhttp.OpenAIOkHttpClient;
a1977ca8stainless-app[bot]1 years ago156import com.openai.models.ChatModel;
1a65445fstainless-app[bot]1 years ago157import com.openai.models.chat.completions.ChatCompletion;
158import com.openai.models.chat.completions.ChatCompletionCreateParams;
3e7910c3stainless-app[bot]1 years ago159import java.util.concurrent.CompletableFuture;
160
b8fe68a5stainless-app[bot]1 years ago161// Configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID` and `OPENAI_BASE_URL` environment variables
3e7910c3stainless-app[bot]1 years ago162OpenAIClient client = OpenAIOkHttpClient.fromEnv();
af9f9a27Robert Craigie2 years ago163
164ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
e4537896stainless-app[bot]1 years ago165.addUserMessage("Say this is a test")
2912dacdstainless-app[bot]1 years ago166.model(ChatModel.GPT_4_1)
6eb3f62eStainless Bot3 years ago167.build();
3e7910c3stainless-app[bot]1 years ago168CompletableFuture<ChatCompletion> chatCompletion = client.async().chat().completions().create(params);
6eb3f62eStainless Bot3 years ago169```
170
3e7910c3stainless-app[bot]1 years ago171Or create an asynchronous client from the beginning:
303b5f25Stainless Bot2 years ago172
173```java
3e7910c3stainless-app[bot]1 years ago174import com.openai.client.OpenAIClientAsync;
175import com.openai.client.okhttp.OpenAIOkHttpClientAsync;
176import com.openai.models.ChatModel;
1a65445fstainless-app[bot]1 years ago177import com.openai.models.chat.completions.ChatCompletion;
178import com.openai.models.chat.completions.ChatCompletionCreateParams;
3e7910c3stainless-app[bot]1 years ago179import java.util.concurrent.CompletableFuture;
303b5f25Stainless Bot2 years ago180
b8fe68a5stainless-app[bot]1 years ago181// Configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID` and `OPENAI_BASE_URL` environment variables
3e7910c3stainless-app[bot]1 years ago182OpenAIClientAsync client = OpenAIOkHttpClientAsync.fromEnv();
183
184ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
185.addUserMessage("Say this is a test")
2912dacdstainless-app[bot]1 years ago186.model(ChatModel.GPT_4_1)
3e7910c3stainless-app[bot]1 years ago187.build();
188CompletableFuture<ChatCompletion> chatCompletion = client.chat().completions().create(params);
303b5f25Stainless Bot2 years ago189```
190
3e7910c3stainless-app[bot]1 years ago191The asynchronous client supports the same options as the synchronous one, except most methods return `CompletableFuture`s.
303b5f25Stainless Bot2 years ago192
3e7910c3stainless-app[bot]1 years ago193## Streaming
a1977ca8stainless-app[bot]1 years ago194
3e7910c3stainless-app[bot]1 years ago195The SDK defines methods that return response "chunk" streams, where each chunk can be individually processed as soon as it arrives instead of waiting on the full response. Streaming methods generally correspond to [SSE](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) or [JSONL](https://jsonlines.org) responses.
303b5f25Stainless Bot2 years ago196
3e7910c3stainless-app[bot]1 years ago197Some of these methods may have streaming and non-streaming variants, but a streaming method will always have a `Streaming` suffix in its name, even if it doesn't have a non-streaming variant.
303b5f25Stainless Bot2 years ago198
6633c380stainless-app[bot]1 years ago199These streaming methods return [`StreamResponse`](openai-java-core/src/main/kotlin/com/openai/core/http/StreamResponse.kt) for synchronous clients:
3e7910c3stainless-app[bot]1 years ago200
201```java
202import com.openai.core.http.StreamResponse;
1a65445fstainless-app[bot]1 years ago203import com.openai.models.chat.completions.ChatCompletionChunk;
3e7910c3stainless-app[bot]1 years ago204
205try (StreamResponse<ChatCompletionChunk> streamResponse = client.chat().completions().createStreaming(params)) {
206streamResponse.stream().forEach(chunk -> {
207System.out.println(chunk);
208});
209System.out.println("No more chunks!");
210}
303b5f25Stainless Bot2 years ago211```
212
6633c380stainless-app[bot]1 years ago213Or [`AsyncStreamResponse`](openai-java-core/src/main/kotlin/com/openai/core/http/AsyncStreamResponse.kt) for asynchronous clients:
303b5f25Stainless Bot2 years ago214
3e7910c3stainless-app[bot]1 years ago215```java
216import com.openai.core.http.AsyncStreamResponse;
1a65445fstainless-app[bot]1 years ago217import com.openai.models.chat.completions.ChatCompletionChunk;
3e7910c3stainless-app[bot]1 years ago218import java.util.Optional;
6eb3f62eStainless Bot3 years ago219
3e7910c3stainless-app[bot]1 years ago220client.async().chat().completions().createStreaming(params).subscribe(chunk -> {
221System.out.println(chunk);
222});
223
224// If you need to handle errors or completion of the stream
225client.async().chat().completions().createStreaming(params).subscribe(new AsyncStreamResponse.Handler<>() {
226@Override
227public void onNext(ChatCompletionChunk chunk) {
228System.out.println(chunk);
229}
6eb3f62eStainless Bot3 years ago230
3e7910c3stainless-app[bot]1 years ago231@Override
232public void onComplete(Optional<Throwable> error) {
233if (error.isPresent()) {
234System.out.println("Something went wrong!");
235throw new RuntimeException(error.get());
236} else {
f35de10estainless-app[bot]1 years ago237System.out.println("No more chunks!");
3e7910c3stainless-app[bot]1 years ago238}
239}
240});
f35de10estainless-app[bot]1 years ago241
242// Or use futures
243client.async().chat().completions().createStreaming(params)
244.subscribe(chunk -> {
245System.out.println(chunk);
246})
247.onCompleteFuture();
248.whenComplete((unused, error) -> {
249if (error != null) {
250System.out.println("Something went wrong!");
251throw new RuntimeException(error);
252} else {
253System.out.println("No more chunks!");
254}
255});
3e7910c3stainless-app[bot]1 years ago256```
6eb3f62eStainless Bot3 years ago257
6633c380stainless-app[bot]1 years ago258Async streaming uses a dedicated per-client cached thread pool [`Executor`](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executor.html) to stream without blocking the current thread. This default is suitable for most purposes.
6eb3f62eStainless Bot3 years ago259
3e7910c3stainless-app[bot]1 years ago260To use a different `Executor`, configure the subscription using the `executor` parameter:
6eb3f62eStainless Bot3 years ago261
3e7910c3stainless-app[bot]1 years ago262```java
263import java.util.concurrent.Executor;
264import java.util.concurrent.Executors;
6eb3f62eStainless Bot3 years ago265
3e7910c3stainless-app[bot]1 years ago266Executor executor = Executors.newFixedThreadPool(4);
267client.async().chat().completions().createStreaming(params).subscribe(
268chunk -> System.out.println(chunk), executor
269);
270```
6eb3f62eStainless Bot3 years ago271
3e7910c3stainless-app[bot]1 years ago272Or configure the client globally using the `streamHandlerExecutor` method:
6eb3f62eStainless Bot3 years ago273
274```java
3e7910c3stainless-app[bot]1 years ago275import com.openai.client.OpenAIClient;
276import com.openai.client.okhttp.OpenAIOkHttpClient;
277import java.util.concurrent.Executors;
a1977ca8stainless-app[bot]1 years ago278
3e7910c3stainless-app[bot]1 years ago279OpenAIClient client = OpenAIOkHttpClient.builder()
280.fromEnv()
281.streamHandlerExecutor(Executors.newFixedThreadPool(4))
282.build();
6eb3f62eStainless Bot3 years ago283```
284
25f6953bstainless-app[bot]1 years ago285### Streaming helpers
286
287The SDK provides conveniences for streamed chat completions. A
288[`ChatCompletionAccumulator`](openai-java-core/src/main/kotlin/com/openai/helpers/ChatCompletionAccumulator.kt)
289can record the stream of chat completion chunks in the response as they are processed and accumulate
290a [`ChatCompletion`](openai-java-core/src/main/kotlin/com/openai/models/chat/completions/ChatCompletion.kt)
291object similar to that which would have been returned by the non-streaming API.
292
293For a synchronous response add a
294[`Stream.peek()`](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#peek-java.util.function.Consumer-)
295call to the stream pipeline to accumulate each chunk:
296
297```java
298import com.openai.core.http.StreamResponse;
299import com.openai.helpers.ChatCompletionAccumulator;
300import com.openai.models.chat.completions.ChatCompletion;
301import com.openai.models.chat.completions.ChatCompletionChunk;
302
303ChatCompletionAccumulator chatCompletionAccumulator = ChatCompletionAccumulator.create();
304
305try (StreamResponse<ChatCompletionChunk> streamResponse =
306client.chat().completions().createStreaming(createParams)) {
307streamResponse.stream()
308.peek(chatCompletionAccumulator::accumulate)
309.flatMap(completion -> completion.choices().stream())
310.flatMap(choice -> choice.delta().content().stream())
311.forEach(System.out::print);
312}
313
314ChatCompletion chatCompletion = chatCompletionAccumulator.chatCompletion();
315```
316
317For an asynchronous response, add the `ChatCompletionAccumulator` to the `subscribe()` call:
318
319```java
320import com.openai.helpers.ChatCompletionAccumulator;
321import com.openai.models.chat.completions.ChatCompletion;
322
323ChatCompletionAccumulator chatCompletionAccumulator = ChatCompletionAccumulator.create();
324
325client.chat()
326.completions()
327.createStreaming(createParams)
328.subscribe(chunk -> chatCompletionAccumulator.accumulate(chunk).choices().stream()
329.flatMap(choice -> choice.delta().content().stream())
330.forEach(System.out::print))
331.onCompleteFuture()
332.join();
333
334ChatCompletion chatCompletion = chatCompletionAccumulator.chatCompletion();
335```
336
a9782b0cstainless-app[bot]1 years ago337## File uploads
338
339The SDK defines methods that accept files.
340
341To upload a file, pass a [`Path`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html):
342
343```java
1a65445fstainless-app[bot]1 years ago344import com.openai.models.files.FileCreateParams;
345import com.openai.models.files.FileObject;
346import com.openai.models.files.FilePurpose;
a9782b0cstainless-app[bot]1 years ago347import java.nio.file.Paths;
348
349FileCreateParams params = FileCreateParams.builder()
350.purpose(FilePurpose.FINE_TUNE)
351.file(Paths.get("input.jsonl"))
352.build();
353FileObject fileObject = client.files().create(params);
354```
355
356Or an arbitrary [`InputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/InputStream.html):
357
358```java
1a65445fstainless-app[bot]1 years ago359import com.openai.models.files.FileCreateParams;
360import com.openai.models.files.FileObject;
361import com.openai.models.files.FilePurpose;
a9782b0cstainless-app[bot]1 years ago362import java.net.URL;
363
364FileCreateParams params = FileCreateParams.builder()
365.purpose(FilePurpose.FINE_TUNE)
88df0366stainless-app[bot]1 years ago366.file(new URL("https://example.com/input.jsonl").openStream())
a9782b0cstainless-app[bot]1 years ago367.build();
368FileObject fileObject = client.files().create(params);
369```
370
371Or a `byte[]` array:
372
373```java
1a65445fstainless-app[bot]1 years ago374import com.openai.models.files.FileCreateParams;
375import com.openai.models.files.FileObject;
376import com.openai.models.files.FilePurpose;
a9782b0cstainless-app[bot]1 years ago377
378FileCreateParams params = FileCreateParams.builder()
379.purpose(FilePurpose.FINE_TUNE)
380.file("content".getBytes())
381.build();
382FileObject fileObject = client.files().create(params);
383```
384
4453173cstainless-app[bot]1 years ago385Note that when passing a non-`Path` its filename is unknown so it will not be included in the request. To manually set a filename, pass a [`MultipartField`](openai-java-core/src/main/kotlin/com/openai/core/Values.kt):
a9782b0cstainless-app[bot]1 years ago386
387```java
388import com.openai.core.MultipartField;
1a65445fstainless-app[bot]1 years ago389import com.openai.models.files.FileCreateParams;
390import com.openai.models.files.FileObject;
391import com.openai.models.files.FilePurpose;
a9782b0cstainless-app[bot]1 years ago392import java.io.InputStream;
393import java.net.URL;
394
395FileCreateParams params = FileCreateParams.builder()
396.purpose(FilePurpose.FINE_TUNE)
397.file(MultipartField.<InputStream>builder()
88df0366stainless-app[bot]1 years ago398.value(new URL("https://example.com/input.jsonl").openStream())
a9782b0cstainless-app[bot]1 years ago399.filename("input.jsonl")
400.build())
401.build();
402FileObject fileObject = client.files().create(params);
403```
404
3e7910c3stainless-app[bot]1 years ago405## Binary responses
6eb3f62eStainless Bot3 years ago406
3e7910c3stainless-app[bot]1 years ago407The SDK defines methods that return binary responses, which are used for API responses that shouldn't necessarily be parsed, like non-JSON data.
408
6633c380stainless-app[bot]1 years ago409These methods return [`HttpResponse`](openai-java-core/src/main/kotlin/com/openai/core/http/HttpResponse.kt):
6eb3f62eStainless Bot3 years ago410
411```java
3e7910c3stainless-app[bot]1 years ago412import com.openai.core.http.HttpResponse;
1a65445fstainless-app[bot]1 years ago413import com.openai.models.files.FileContentParams;
a1977ca8stainless-app[bot]1 years ago414
3e7910c3stainless-app[bot]1 years ago415FileContentParams params = FileContentParams.builder()
416.fileId("file_id")
417.build();
418HttpResponse response = client.files().content(params);
419```
6eb3f62eStainless Bot3 years ago420
6633c380stainless-app[bot]1 years ago421To save the response content to a file, use the [`Files.copy(...)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#copy-java.io.InputStream-java.nio.file.Path-java.nio.file.CopyOption...-) method:
6eb3f62eStainless Bot3 years ago422
3e7910c3stainless-app[bot]1 years ago423```java
424import com.openai.core.http.HttpResponse;
425import java.nio.file.Files;
426import java.nio.file.Paths;
427import java.nio.file.StandardCopyOption;
428
429try (HttpResponse response = client.files().content(params)) {
430Files.copy(
431response.body(),
432Paths.get(path),
433StandardCopyOption.REPLACE_EXISTING
434);
435} catch (Exception e) {
436System.out.println("Something went wrong!");
437throw new RuntimeException(e);
6eb3f62eStainless Bot3 years ago438}
439```
440
6633c380stainless-app[bot]1 years ago441Or transfer the response content to any [`OutputStream`](https://docs.oracle.com/javase/8/docs/api/java/io/OutputStream.html):
6eb3f62eStainless Bot3 years ago442
443```java
3e7910c3stainless-app[bot]1 years ago444import com.openai.core.http.HttpResponse;
445import java.nio.file.Files;
446import java.nio.file.Paths;
447
448try (HttpResponse response = client.files().content(params)) {
449response.body().transferTo(Files.newOutputStream(Paths.get(path)));
450} catch (Exception e) {
451System.out.println("Something went wrong!");
452throw new RuntimeException(e);
453}
6eb3f62eStainless Bot3 years ago454```
455
cdf6cd11stainless-app[bot]1 years ago456## Raw responses
457
458The SDK defines methods that deserialize responses into instances of Java classes. However, these methods don't provide access to the response headers, status code, or the raw response body.
459
460To access this data, prefix any HTTP method call on a client or service with `withRawResponse()`:
461
462```java
463import com.openai.core.http.Headers;
464import com.openai.core.http.HttpResponseFor;
465import com.openai.models.ChatModel;
1a65445fstainless-app[bot]1 years ago466import com.openai.models.chat.completions.ChatCompletion;
467import com.openai.models.chat.completions.ChatCompletionCreateParams;
cdf6cd11stainless-app[bot]1 years ago468
469ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
470.addUserMessage("Say this is a test")
2912dacdstainless-app[bot]1 years ago471.model(ChatModel.GPT_4_1)
cdf6cd11stainless-app[bot]1 years ago472.build();
473HttpResponseFor<ChatCompletion> chatCompletion = client.chat().completions().withRawResponse().create(params);
474
475int statusCode = chatCompletion.statusCode();
476Headers headers = chatCompletion.headers();
477```
478
479You can still deserialize the response into an instance of a Java class if needed:
480
481```java
1a65445fstainless-app[bot]1 years ago482import com.openai.models.chat.completions.ChatCompletion;
cdf6cd11stainless-app[bot]1 years ago483
484ChatCompletion parsedChatCompletion = chatCompletion.parse();
485```
486
5d89bd2astainless-app[bot]1 years ago487### Request IDs
488
489> For more information on debugging requests, see [the API docs](https://platform.openai.com/docs/api-reference/debugging-requests).
490
491When using raw responses, you can access the `x-request-id` response header using the `requestId()` method:
492
493```java
494import com.openai.core.http.HttpResponseFor;
495import com.openai.models.chat.completions.ChatCompletion;
496import java.util.Optional;
497
498HttpResponseFor<ChatCompletion> chatCompletion = client.chat().completions().withRawResponse().create(params);
499Optional<String> requestId = chatCompletion.requestId();
500```
501
502This can be used to quickly log failing requests and report them back to OpenAI.
503
3e7910c3stainless-app[bot]1 years ago504## Error handling
505
506The SDK throws custom unchecked exception types:
507
6633c380stainless-app[bot]1 years ago508- [`OpenAIServiceException`](openai-java-core/src/main/kotlin/com/openai/errors/OpenAIServiceException.kt): Base class for HTTP errors. See this table for which exception subclass is thrown for each HTTP status code:
3e7910c3stainless-app[bot]1 years ago509
d6a37429stainless-app[bot]1 years ago510| Status | Exception |
511| ------ | ---------------------------------------------------------------------------------------------------------------------- |
512| 400 | [`BadRequestException`](openai-java-core/src/main/kotlin/com/openai/errors/BadRequestException.kt) |
513| 401 | [`UnauthorizedException`](openai-java-core/src/main/kotlin/com/openai/errors/UnauthorizedException.kt) |
514| 403 | [`PermissionDeniedException`](openai-java-core/src/main/kotlin/com/openai/errors/PermissionDeniedException.kt) |
515| 404 | [`NotFoundException`](openai-java-core/src/main/kotlin/com/openai/errors/NotFoundException.kt) |
516| 422 | [`UnprocessableEntityException`](openai-java-core/src/main/kotlin/com/openai/errors/UnprocessableEntityException.kt) |
517| 429 | [`RateLimitException`](openai-java-core/src/main/kotlin/com/openai/errors/RateLimitException.kt) |
518| 5xx | [`InternalServerException`](openai-java-core/src/main/kotlin/com/openai/errors/InternalServerException.kt) |
519| others | [`UnexpectedStatusCodeException`](openai-java-core/src/main/kotlin/com/openai/errors/UnexpectedStatusCodeException.kt) |
520
521[`SseException`](openai-java-core/src/main/kotlin/com/openai/errors/SseException.kt) is thrown for errors encountered during [SSE streaming](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) after a successful initial HTTP response.
3e7910c3stainless-app[bot]1 years ago522
6633c380stainless-app[bot]1 years ago523- [`OpenAIIoException`](openai-java-core/src/main/kotlin/com/openai/errors/OpenAIIoException.kt): I/O networking errors.
3e7910c3stainless-app[bot]1 years ago524
6633c380stainless-app[bot]1 years ago525- [`OpenAIInvalidDataException`](openai-java-core/src/main/kotlin/com/openai/errors/OpenAIInvalidDataException.kt): Failure to interpret successfully parsed data. For example, when accessing a property that's supposed to be required, but the API unexpectedly omitted it from the response.
3e7910c3stainless-app[bot]1 years ago526
6633c380stainless-app[bot]1 years ago527- [`OpenAIException`](openai-java-core/src/main/kotlin/com/openai/errors/OpenAIException.kt): Base class for all exceptions. Most errors will result in one of the previously mentioned ones, but completely generic errors may be thrown using the base class.
6eb3f62eStainless Bot3 years ago528
303b5f25Stainless Bot2 years ago529## Pagination
530
a1977ca8stainless-app[bot]1 years ago531For methods that return a paginated list of results, this library provides convenient ways access the results either one page at a time, or item-by-item across all pages.
303b5f25Stainless Bot2 years ago532
533### Auto-pagination
534
a1977ca8stainless-app[bot]1 years ago535To iterate through all results across all pages, you can use `autoPager`, which automatically handles fetching more pages for you:
303b5f25Stainless Bot2 years ago536
537### Synchronous
538
539```java
1a65445fstainless-app[bot]1 years ago540import com.openai.models.finetuning.jobs.FineTuningJob;
541import com.openai.models.finetuning.jobs.JobListPage;
a1977ca8stainless-app[bot]1 years ago542
303b5f25Stainless Bot2 years ago543// As an Iterable:
1a65445fstainless-app[bot]1 years ago544JobListPage page = client.fineTuning().jobs().list(params);
303b5f25Stainless Bot2 years ago545for (FineTuningJob job : page.autoPager()) {
546System.out.println(job);
547};
548
549// As a Stream:
550client.fineTuning().jobs().list(params).autoPager().stream()
551.limit(50)
552.forEach(job -> System.out.println(job));
553```
554
555### Asynchronous
556
557```java
558// Using forEach, which returns CompletableFuture<Void>:
559asyncClient.fineTuning().jobs().list(params).autoPager()
560.forEach(job -> System.out.println(job), executor);
561```
562
563### Manual pagination
564
a1977ca8stainless-app[bot]1 years ago565If none of the above helpers meet your needs, you can also manually request pages one-by-one. A page of results has a `data()` method to fetch the list of objects, as well as top-level `response` and other methods to fetch top-level data about the page. It also has methods `hasNextPage`, `getNextPage`, and `getNextPageParams` methods to help with pagination.
303b5f25Stainless Bot2 years ago566
567```java
1a65445fstainless-app[bot]1 years ago568import com.openai.models.finetuning.jobs.FineTuningJob;
569import com.openai.models.finetuning.jobs.JobListPage;
a1977ca8stainless-app[bot]1 years ago570
1a65445fstainless-app[bot]1 years ago571JobListPage page = client.fineTuning().jobs().list(params);
303b5f25Stainless Bot2 years ago572while (page != null) {
573for (FineTuningJob job : page.data()) {
574System.out.println(job);
575}
576
577page = page.getNextPage().orElse(null);
578}
579```
580
3e7910c3stainless-app[bot]1 years ago581## Logging
6eb3f62eStainless Bot3 years ago582
3e7910c3stainless-app[bot]1 years ago583The SDK uses the standard [OkHttp logging interceptor](https://github.com/square/okhttp/tree/master/okhttp-logging-interceptor).
6eb3f62eStainless Bot3 years ago584
3e7910c3stainless-app[bot]1 years ago585Enable logging by setting the `OPENAI_LOG` environment variable to `info`:
6eb3f62eStainless Bot3 years ago586
3e7910c3stainless-app[bot]1 years ago587```sh
588$ export OPENAI_LOG=info
589```
6eb3f62eStainless Bot3 years ago590
3e7910c3stainless-app[bot]1 years ago591Or to `debug` for more verbose logging:
6eb3f62eStainless Bot3 years ago592
3e7910c3stainless-app[bot]1 years ago593```sh
594$ export OPENAI_LOG=debug
595```
6eb3f62eStainless Bot3 years ago596
de59688dstainless-app[bot]1 years ago597## Jackson
598
599The SDK depends on [Jackson](https://github.com/FasterXML/jackson) for JSON serialization/deserialization. It is compatible with version 2.13.4 or higher, but depends on version 2.18.2 by default.
600
601The SDK throws an exception if it detects an incompatible Jackson version at runtime (e.g. if the default version was overridden in your Maven or Gradle config).
602
603If the SDK threw an exception, but you're _certain_ the version is compatible, then disable the version check using the `checkJacksonVersionCompatibility` on [`OpenAIOkHttpClient`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt) or [`OpenAIOkHttpClientAsync`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt).
604
605> [!CAUTION]
606> We make no guarantee that the SDK works correctly when the Jackson version check is disabled.
607
3e7910c3stainless-app[bot]1 years ago608## Microsoft Azure
f3c75d75Shawn Fang1 years ago609
610To use this library with [Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/overview), use the same
8ec229bbTomer Aberbach1 years ago611OpenAI client builder but with the Azure-specific configuration.
f3c75d75Shawn Fang1 years ago612
613```java
8ec229bbTomer Aberbach1 years ago614OpenAIClient client = OpenAIOkHttpClient.builder()
b8fe68a5stainless-app[bot]1 years ago615// Gets the API key and endpoint from the `AZURE_OPENAI_KEY` and `OPENAI_BASE_URL` environment variables, respectively
8ec229bbTomer Aberbach1 years ago616.fromEnv()
617// Set the Azure Entra ID
618.credential(BearerTokenCredential.create(AuthenticationUtil.getBearerTokenSupplier(
619new DefaultAzureCredentialBuilder().build(), "https://cognitiveservices.azure.com/.default")))
620.build();
f3c75d75Shawn Fang1 years ago621```
622
8ec229bbTomer Aberbach1 years ago623See the complete Azure OpenAI example in the [`openai-java-example`](openai-java-example/src/main/java/com/openai/example/AzureEntraIdExample.java) directory. The other examples in the directory also work with Azure as long as the client is configured to use it.
f3c75d75Shawn Fang1 years ago624
6eb3f62eStainless Bot3 years ago625## Network options
626
627### Retries
628
3e7910c3stainless-app[bot]1 years ago629The SDK automatically retries 2 times by default, with a short exponential backoff.
630
631Only the following error types are retried:
632
633- Connection errors (for example, due to a network connectivity problem)
634- 408 Request Timeout
635- 409 Conflict
636- 429 Rate Limit
637- 5xx Internal
638
639The API may also explicitly instruct the SDK to retry or not retry a response.
640
641To set a custom number of retries, configure the client using the `maxRetries` method:
6eb3f62eStainless Bot3 years ago642
643```java
a1977ca8stainless-app[bot]1 years ago644import com.openai.client.OpenAIClient;
645import com.openai.client.okhttp.OpenAIOkHttpClient;
646
af9f9a27Robert Craigie2 years ago647OpenAIClient client = OpenAIOkHttpClient.builder()
6eb3f62eStainless Bot3 years ago648.fromEnv()
649.maxRetries(4)
650.build();
651```
652
653### Timeouts
654
3e7910c3stainless-app[bot]1 years ago655Requests time out after 10 minutes by default.
656
657To set a custom timeout, configure the method call using the `timeout` method:
658
659```java
660import com.openai.models.ChatModel;
1a65445fstainless-app[bot]1 years ago661import com.openai.models.chat.completions.ChatCompletion;
662import com.openai.models.chat.completions.ChatCompletionCreateParams;
3e7910c3stainless-app[bot]1 years ago663
664ChatCompletion chatCompletion = client.chat().completions().create(
665params, RequestOptions.builder().timeout(Duration.ofSeconds(30)).build()
666);
667```
668
669Or configure the default for all method calls at the client level:
6eb3f62eStainless Bot3 years ago670
671```java
a1977ca8stainless-app[bot]1 years ago672import com.openai.client.OpenAIClient;
673import com.openai.client.okhttp.OpenAIOkHttpClient;
674import java.time.Duration;
675
af9f9a27Robert Craigie2 years ago676OpenAIClient client = OpenAIOkHttpClient.builder()
6eb3f62eStainless Bot3 years ago677.fromEnv()
678.timeout(Duration.ofSeconds(30))
679.build();
680```
681
682### Proxies
683
3e7910c3stainless-app[bot]1 years ago684To route requests through a proxy, configure the client using the `proxy` method:
6eb3f62eStainless Bot3 years ago685
686```java
a1977ca8stainless-app[bot]1 years ago687import com.openai.client.OpenAIClient;
688import com.openai.client.okhttp.OpenAIOkHttpClient;
689import java.net.InetSocketAddress;
690import java.net.Proxy;
691
af9f9a27Robert Craigie2 years ago692OpenAIClient client = OpenAIOkHttpClient.builder()
6eb3f62eStainless Bot3 years ago693.fromEnv()
3e7910c3stainless-app[bot]1 years ago694.proxy(new Proxy(
695Proxy.Type.HTTP, new InetSocketAddress(
696"https://example.com", 8080
697)
698))
6eb3f62eStainless Bot3 years ago699.build();
af9f9a27Robert Craigie2 years ago700```
701
de59688dstainless-app[bot]1 years ago702### Custom HTTP client
703
704The SDK consists of three artifacts:
705
706- `openai-java-core`
707- Contains core SDK logic
708- Does not depend on [OkHttp](https://square.github.io/okhttp)
709- Exposes [`OpenAIClient`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClient.kt), [`OpenAIClientAsync`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsync.kt), [`OpenAIClientImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt), and [`OpenAIClientAsyncImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt), all of which can work with any HTTP client
710- `openai-java-client-okhttp`
711- Depends on [OkHttp](https://square.github.io/okhttp)
712- Exposes [`OpenAIOkHttpClient`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt) and [`OpenAIOkHttpClientAsync`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt), which provide a way to construct [`OpenAIClientImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt) and [`OpenAIClientAsyncImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt), respectively, using OkHttp
713- `openai-java`
714- Depends on and exposes the APIs of both `openai-java-core` and `openai-java-client-okhttp`
715- Does not have its own logic
716
717This structure allows replacing the SDK's default HTTP client without pulling in unnecessary dependencies.
718
719#### Customized [`OkHttpClient`](https://square.github.io/okhttp/3.x/okhttp/okhttp3/OkHttpClient.html)
720
721> [!TIP]
722> Try the available [network options](#network-options) before replacing the default client.
723
724To use a customized `OkHttpClient`:
725
7261. Replace your [`openai-java` dependency](#installation) with `openai-java-core`
7272. Copy `openai-java-client-okhttp`'s [`OkHttpClient`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OkHttpClient.kt) class into your code and customize it
7283. Construct [`OpenAIClientImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt) or [`OpenAIClientAsyncImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt), similarly to [`OpenAIOkHttpClient`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt) or [`OpenAIOkHttpClientAsync`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt), using your customized client
729
730### Completely custom HTTP client
731
732To use a completely custom HTTP client:
733
7341. Replace your [`openai-java` dependency](#installation) with `openai-java-core`
7352. Write a class that implements the [`HttpClient`](openai-java-core/src/main/kotlin/com/openai/core/http/HttpClient.kt) interface
7363. Construct [`OpenAIClientImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientImpl.kt) or [`OpenAIClientAsyncImpl`](openai-java-core/src/main/kotlin/com/openai/client/OpenAIClientAsyncImpl.kt), similarly to [`OpenAIOkHttpClient`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt) or [`OpenAIOkHttpClientAsync`](openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt), using your new client class
737
3e7910c3stainless-app[bot]1 years ago738## Undocumented API functionality
af9f9a27Robert Craigie2 years ago739
3e7910c3stainless-app[bot]1 years ago740The SDK is typed for convenient usage of the documented API. However, it also supports working with undocumented or not yet supported parts of the API.
af9f9a27Robert Craigie2 years ago741
3e7910c3stainless-app[bot]1 years ago742### Parameters
9d90f9ebstainless-app[bot]1 years ago743
3e7910c3stainless-app[bot]1 years ago744To set undocumented parameters, call the `putAdditionalHeader`, `putAdditionalQueryParam`, or `putAdditionalBodyProperty` methods on any `Params` class:
af9f9a27Robert Craigie2 years ago745
5241c81estainless-app[bot]1 years ago746```java
9d90f9ebstainless-app[bot]1 years ago747import com.openai.core.JsonValue;
1a65445fstainless-app[bot]1 years ago748import com.openai.models.chat.completions.ChatCompletionCreateParams;
9d90f9ebstainless-app[bot]1 years ago749
750ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
751.putAdditionalHeader("Secret-Header", "42")
752.putAdditionalQueryParam("secret_query_param", "42")
753.putAdditionalBodyProperty("secretProperty", JsonValue.from("42"))
af9f9a27Robert Craigie2 years ago754.build();
755```
756
d3df21f3stainless-app[bot]1 years ago757These can be accessed on the built object later using the `_additionalHeaders()`, `_additionalQueryParams()`, and `_additionalBodyProperties()` methods.
758
759To set undocumented parameters on _nested_ headers, query params, or body classes, call the `putAdditionalProperty` method on the nested class:
760
761```java
762import com.openai.core.JsonValue;
1a65445fstainless-app[bot]1 years ago763import com.openai.models.chat.completions.ChatCompletionCreateParams;
d3df21f3stainless-app[bot]1 years ago764
765ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
766.responseFormat(ChatCompletionCreateParams.ResponseFormat.builder()
767.putAdditionalProperty("secretProperty", JsonValue.from("42"))
768.build())
769.build();
770```
771
772These properties can be accessed on the nested built object later using the `_additionalProperties()` method.
9d90f9ebstainless-app[bot]1 years ago773
4453173cstainless-app[bot]1 years ago774To set a documented parameter or property to an undocumented or not yet supported _value_, pass a [`JsonValue`](openai-java-core/src/main/kotlin/com/openai/core/Values.kt) object to its setter:
af9f9a27Robert Craigie2 years ago775
3e7910c3stainless-app[bot]1 years ago776```java
777import com.openai.core.JsonValue;
1a65445fstainless-app[bot]1 years ago778import com.openai.models.chat.completions.ChatCompletionCreateParams;
af9f9a27Robert Craigie2 years ago779
3e7910c3stainless-app[bot]1 years ago780ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
781.addUserMessage("Say this is a test")
782.model(JsonValue.from(42))
783.build();
784```
7944e86cstainless-app[bot]1 years ago785
4453173cstainless-app[bot]1 years ago786The most straightforward way to create a [`JsonValue`](openai-java-core/src/main/kotlin/com/openai/core/Values.kt) is using its `from(...)` method:
787
788```java
789import com.openai.core.JsonValue;
790import java.util.List;
791import java.util.Map;
792
793// Create primitive JSON values
794JsonValue nullValue = JsonValue.from(null);
795JsonValue booleanValue = JsonValue.from(true);
796JsonValue numberValue = JsonValue.from(42);
797JsonValue stringValue = JsonValue.from("Hello World!");
798
799// Create a JSON array value equivalent to `["Hello", "World"]`
800JsonValue arrayValue = JsonValue.from(List.of(
801"Hello", "World"
802));
803
804// Create a JSON object value equivalent to `{ "a": 1, "b": 2 }`
805JsonValue objectValue = JsonValue.from(Map.of(
806"a", 1,
807"b", 2
808));
809
810// Create an arbitrarily nested JSON equivalent to:
811// {
812// "a": [1, 2],
813// "b": [3, 4]
814// }
815JsonValue complexValue = JsonValue.from(Map.of(
816"a", List.of(
8171, 2
818),
819"b", List.of(
8203, 4
821)
822));
823```
824
7f36e508stainless-app[bot]1 years ago825Normally a `Builder` class's `build` method will throw [`IllegalStateException`](https://docs.oracle.com/javase/8/docs/api/java/lang/IllegalStateException.html) if any required parameter or property is unset.
826
827To forcibly omit a required parameter or property, pass [`JsonMissing`](openai-java-core/src/main/kotlin/com/openai/core/Values.kt):
828
829```java
830import com.openai.core.JsonMissing;
831import com.openai.models.ChatModel;
832import com.openai.models.chat.completions.ChatCompletionCreateParams;
833
834ChatCompletionCreateParams params = ChatCompletionCreateParams.builder()
2912dacdstainless-app[bot]1 years ago835.model(ChatModel.GPT_4_1)
7f36e508stainless-app[bot]1 years ago836.messages(JsonMissing.of())
837.build();
838```
839
3e7910c3stainless-app[bot]1 years ago840### Response properties
7944e86cstainless-app[bot]1 years ago841
3e7910c3stainless-app[bot]1 years ago842To access undocumented response properties, call the `_additionalProperties()` method:
7944e86cstainless-app[bot]1 years ago843
3e7910c3stainless-app[bot]1 years ago844```java
845import com.openai.core.JsonValue;
846import java.util.Map;
847
848Map<String, JsonValue> additionalProperties = client.chat().completions().create(params)._additionalProperties();
849JsonValue secretPropertyValue = additionalProperties.get("secretProperty");
850
851String result = secretPropertyValue.accept(new JsonValue.Visitor<>() {
852@Override
853public String visitNull() {
854return "It's null!";
855}
856
857@Override
858public String visitBoolean(boolean value) {
859return "It's a boolean!";
860}
861
862@Override
863public String visitNumber(Number value) {
864return "It's a number!";
865}
866
867// Other methods include `visitMissing`, `visitString`, `visitArray`, and `visitObject`
868// The default implementation of each unimplemented method delegates to `visitDefault`, which throws by default, but can also be overridden
869});
7944e86cstainless-app[bot]1 years ago870```
871
3e7910c3stainless-app[bot]1 years ago872To access a property's raw JSON value, which may be undocumented, call its `_` prefixed method:
7944e86cstainless-app[bot]1 years ago873
3e7910c3stainless-app[bot]1 years ago874```java
875import com.openai.core.JsonField;
1a65445fstainless-app[bot]1 years ago876import com.openai.models.chat.completions.ChatCompletionMessageParam;
3e7910c3stainless-app[bot]1 years ago877import java.util.Optional;
878
879JsonField<List<ChatCompletionMessageParam>> messages = client.chat().completions().create(params)._messages();
880
881if (messages.isMissing()) {
882// The property is absent from the JSON response
883} else if (messages.isNull()) {
884// The property was set to literal null
885} else {
886// Check if value was provided as a string
887// Other methods include `asNumber()`, `asBoolean()`, etc.
888Optional<String> jsonString = messages.asString();
889
890// Try to deserialize into a custom type
891MyClass myObject = messages.asUnknown().orElseThrow().convert(MyClass.class);
892}
893```
894
895### Response validation
896
897In rare cases, the API may return a response that doesn't match the expected type. For example, the SDK may expect a property to contain a `String`, but the API could return something else.
898
6633c380stainless-app[bot]1 years ago899By default, the SDK will not throw an exception in this case. It will throw [`OpenAIInvalidDataException`](openai-java-core/src/main/kotlin/com/openai/errors/OpenAIInvalidDataException.kt) only if you directly access the property.
3e7910c3stainless-app[bot]1 years ago900
901If you would prefer to check that the response is completely well-typed upfront, then either call `validate()`:
902
903```java
1a65445fstainless-app[bot]1 years ago904import com.openai.models.chat.completions.ChatCompletion;
3e7910c3stainless-app[bot]1 years ago905
906ChatCompletion chatCompletion = client.chat().completions().create(params).validate();
907```
908
909Or configure the method call to validate the response using the `responseValidation` method:
910
911```java
912import com.openai.models.ChatModel;
1a65445fstainless-app[bot]1 years ago913import com.openai.models.chat.completions.ChatCompletion;
914import com.openai.models.chat.completions.ChatCompletionCreateParams;
3e7910c3stainless-app[bot]1 years ago915
916ChatCompletion chatCompletion = client.chat().completions().create(
917params, RequestOptions.builder().responseValidation(true).build()
918);
919```
920
921Or configure the default for all method calls at the client level:
922
923```java
924import com.openai.client.OpenAIClient;
925import com.openai.client.okhttp.OpenAIOkHttpClient;
926
927OpenAIClient client = OpenAIOkHttpClient.builder()
928.fromEnv()
929.responseValidation(true)
930.build();
7944e86cstainless-app[bot]1 years ago931```
932
f92bf999stainless-app[bot]1 years ago933## FAQ
934
935### Why don't you use plain `enum` classes?
936
937Java `enum` classes are not trivially [forwards compatible](https://www.stainless.com/blog/making-java-enums-forwards-compatible). Using them in the SDK could cause runtime exceptions if the API is updated to respond with a new enum value.
938
939### Why do you represent fields using `JsonField<T>` instead of just plain `T`?
940
941Using `JsonField<T>` enables a few features:
942
943- Allowing usage of [undocumented API functionality](#undocumented-api-functionality)
944- Lazily [validating the API response against the expected shape](#response-validation)
945- Representing absent vs explicitly null values
946
947### Why don't you use [`data` classes](https://kotlinlang.org/docs/data-classes.html)?
948
949It is not [backwards compatible to add new fields to a data class](https://kotlinlang.org/docs/api-guidelines-backward-compatibility.html#avoid-using-data-classes-in-your-api) and we don't want to introduce a breaking change every time we add a field to a class.
950
951### Why don't you use checked exceptions?
952
953Checked exceptions are widely considered a mistake in the Java programming language. In fact, they were omitted from Kotlin for this reason.
954
955Checked exceptions:
956
957- Are verbose to handle
958- Encourage error handling at the wrong level of abstraction, where nothing can be done about the error
959- Are tedious to propagate due to the [function coloring problem](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function)
960- Don't play well with lambdas (also due to the function coloring problem)
961
af9f9a27Robert Craigie2 years ago962## Semantic versioning
963
964This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:
965
ce5c7803stainless-app[bot]1 years ago9661. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_
af9f9a27Robert Craigie2 years ago9672. Changes that we do not expect to impact the vast majority of users in practice.
968
969We take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.
970
11c62f22Stainless Bot1 years ago971We are keen for your feedback; please open an [issue](https://www.github.com/openai/openai-java/issues) with questions, bugs, or suggestions.