Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "3.2.1"
".": "3.3.0"
}
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 3.3.0 (2025-09-03)

Full Changelog: [v3.2.1...v3.3.0](https://github.com/openai/openai-java/compare/v3.2.1...v3.3.0)

### Features

* **client:** support verbosity with structured outputs ([#603](https://github.com/openai/openai-java/issues/603)) ([2496464](https://github.com/openai/openai-java/commit/24964646ab02a3ff61efb9802facac66b204bdaf))

## 3.2.1 (2025-09-02)

Full Changelog: [v3.2.0...v3.2.1](https://github.com/openai/openai-java/compare/v3.2.0...v3.2.1)
Expand Down
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

<!-- x-release-please-start-version -->

[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/3.2.1)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/3.2.1/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/3.2.1)
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/3.3.0)
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/3.3.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/3.3.0)

<!-- x-release-please-end -->

The OpenAI Java SDK provides convenient access to the [OpenAI REST API](https://platform.openai.com/docs) from applications written in Java.

<!-- x-release-please-start-version -->

The 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/3.2.1).
The 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/3.3.0).

<!-- x-release-please-end -->

Expand All @@ -24,7 +24,7 @@ The REST API documentation can be found on [platform.openai.com](https://platfor
### Gradle

```kotlin
implementation("com.openai:openai-java:3.2.1")
implementation("com.openai:openai-java:3.3.0")
```

### Maven
Expand All @@ -33,7 +33,7 @@ implementation("com.openai:openai-java:3.2.1")
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java</artifactId>
<version>3.2.1</version>
<version>3.3.0</version>
</dependency>
```

Expand Down Expand Up @@ -565,6 +565,18 @@ the latter when `ResponseCreateParams.Builder.text(Class<T>)` is called.
For a full example of the usage of _Structured Outputs_ with the Responses API, see
[`ResponsesStructuredOutputsExample`](openai-java-example/src/main/java/com/openai/example/ResponsesStructuredOutputsExample.java).

Instead of using `ResponseCreateParams.text(Class<T>)`, you can build a
[`StructuredResponseTextConfig`](openai-java-core/src/main/kotlin/com/openai/models/responses/StructuredResponseTextConfig.kt)
and set it on the `ResponseCreateParams` using the `text(StructuredResponseTextConfig)` method.
Similar to using `ResponseCreateParams`, you can start with a `ResponseTextConfig.Builder` and its
`format(Class<T>)` method will change it to a `StructuredResponseTextConfig.Builder`. This also
allows you to set the `verbosity` configuration parameter on the text configuration before adding it
to the `ResponseCreateParams`.

For a full example of the usage of _Structured Outputs_ with the `ResponseTextConfig` and its
`verbosity` parameter, see
[`ResponsesStructuredOutputsVerbosityExample`](openai-java-example/src/main/java/com/openai/example/ResponsesStructuredOutputsVerbosityExample.java).

### Usage with streaming

_Structured Outputs_ can also be used with [Streaming](#streaming) and the Chat Completions API. As
Expand Down Expand Up @@ -1330,7 +1342,7 @@ If you're using Spring Boot, then you can use the SDK's [Spring Boot starter](ht
#### Gradle

```kotlin
implementation("com.openai:openai-java-spring-boot-starter:3.2.1")
implementation("com.openai:openai-java-spring-boot-starter:3.3.0")
```

#### Maven
Expand All @@ -1339,7 +1351,7 @@ implementation("com.openai:openai-java-spring-boot-starter:3.2.1")
<dependency>
<groupId>com.openai</groupId>
<artifactId>openai-java-spring-boot-starter</artifactId>
<version>3.2.1</version>
<version>3.3.0</version>
</dependency>
```

Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repositories {

allprojects {
group = "com.openai"
version = "3.2.1" // x-release-please-version
version = "3.3.0" // x-release-please-version
}

subprojects {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ internal class JsonSchemaValidator private constructor() {

/**
* Validates a schema if it has an `"anyOf"` field. OpenAI does not support the use of `"anyOf"`
* at the root of a JSON schema. The value is the field is expected to be an array of valid
* at the root of a JSON schema. The value of the field is expected to be an array of valid
* sub-schemas. If the schema has no `"anyOf"` field, no action is taken.
*/
private fun validateAnyOfSchema(schema: JsonNode, path: String, depth: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ internal fun validateSchema(
return schema
}

/** Builds a text configuration's JSON schema, deriving it from the structure of a class. */
@JvmSynthetic
internal fun jsonSchemaFromClass(
type: Class<*>,
localValidation: JsonSchemaLocalValidation = JsonSchemaLocalValidation.YES,
): ResponseFormatTextJsonSchemaConfig =
ResponseFormatTextJsonSchemaConfig.builder()
.name("json-schema-from-${type.simpleName}")
.schema(JsonValue.fromJsonNode(validateSchema(extractSchema(type), type, localValidation)))
// Ensure the model's output strictly adheres to this JSON schema. This is the essential
// "ON switch" for Structured Outputs.
.strict(true)
.build()

/**
* Builds a text configuration with its format set to a JSON schema derived from the structure of an
* arbitrary Java class.
Expand All @@ -94,21 +108,7 @@ internal fun textConfigFromClass(
type: Class<*>,
localValidation: JsonSchemaLocalValidation = JsonSchemaLocalValidation.YES,
): ResponseTextConfig =
ResponseTextConfig.builder()
.format(
ResponseFormatTextJsonSchemaConfig.builder()
.name("json-schema-from-${type.simpleName}")
.schema(
JsonValue.fromJsonNode(
validateSchema(extractSchema(type), type, localValidation)
)
)
// Ensure the model's output strictly adheres to this JSON schema. This is the
// essential "ON switch" for Structured Outputs.
.strict(true)
.build()
)
.build()
ResponseTextConfig.builder().format(jsonSchemaFromClass(type, localValidation)).build()

// "internal" instead of "private" for testing purposes.
internal data class FunctionInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ private constructor(
* Gets the arguments to the function call, converting the values from the model in JSON
* format to an instance of a class that holds those values. The class must previously have
* been used to define the JSON schema for the function definition's parameters, so that the
* JSON corresponds to structure of the given class.
* JSON corresponds to the structure of the given class.
*
* @throws OpenAIInvalidDataException If the JSON data is missing, `null`, or cannot be
* parsed to an instance of the [functionParametersType] class. This might occur if the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.util.Optional
/**
* A wrapper for [ChatCompletionCreateParams] that provides a type-safe [Builder] that can record
* the [responseType] used to derive a JSON schema from an arbitrary class when using the
* _Structured Outputs_ feature. When a JSON response is received, it is deserialized to am instance
* _Structured Outputs_ feature. When a JSON response is received, it is deserialized to an instance
* of that type. See the SDK documentation for more details on _Structured Outputs_.
*
* @param T The type of the class that will be used to derive the JSON schema in the request and to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,8 @@ private constructor(
* [StructuredResponseCreateParams.Builder] that will build a
* [StructuredResponseCreateParams] instance when `build()` is called.
*
* Use this method or the `text(StructuredResponseTextConfig<T>)` method, but not both.
*
* @param responseType A class from which a JSON schema will be derived to define the text
* configuration's format.
* @param localValidation [JsonSchemaLocalValidation.YES] (the default) to validate the JSON
Expand All @@ -1114,6 +1116,21 @@ private constructor(
localValidation: JsonSchemaLocalValidation = JsonSchemaLocalValidation.YES,
) = StructuredResponseCreateParams.builder<T>().wrap(responseType, this, localValidation)

/**
* Sets the text configuration to a [StructuredResponseTextConfig] where the format was set
* to a JSON schema derived from the structure of a class. This changes the builder to a
* type-safe [StructuredResponseCreateParams.Builder] that will build a
* [StructuredResponseCreateParams] instance when `build()` is called.
*
* Use this method or the `text(Class<T>)` method, but not both.
*
* @param text A text configuration in which the JSON schema defining the format was derived
* from the structure of a class. The `verbosity` parameter can also be set on the text
* configuration, if required.
*/
fun <T : Any> text(text: StructuredResponseTextConfig<T>) =
StructuredResponseCreateParams.builder<T>().wrap(text, this)

/**
* How the model should select which tool (or tools) to use when generating a response. See
* the `tools` parameter to see how to specify which tools the model can call.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.openai.core.Enum
import com.openai.core.ExcludeMissing
import com.openai.core.JsonField
import com.openai.core.JsonMissing
import com.openai.core.JsonSchemaLocalValidation
import com.openai.core.JsonValue
import com.openai.errors.OpenAIInvalidDataException
import com.openai.models.ResponseFormatJsonObject
Expand Down Expand Up @@ -157,6 +158,28 @@ private constructor(
fun format(jsonObject: ResponseFormatJsonObject) =
format(ResponseFormatTextConfig.ofJsonObject(jsonObject))

/**
* Sets the text configuration's format to a JSON schema derived from the structure of the
* given class. This changes the builder to a type-safe
* [StructuredResponseTextConfig.Builder] that will build a [StructuredResponseTextConfig]
* instance when `build()` is called.
*
* @param responseType A class from which a JSON schema will be derived to define the text
* configuration's format.
* @param localValidation [JsonSchemaLocalValidation.YES] (the default) to validate the JSON
* schema locally when it is generated by this method to confirm that it adheres to the
* requirements and restrictions on JSON schemas imposed by the OpenAI specification; or
* [JsonSchemaLocalValidation.NO] to skip local validation and rely only on remote
* validation. See the SDK documentation for more details.
* @throws IllegalArgumentException If local validation is enabled, but it fails because a
* valid JSON schema cannot be derived from the given class.
*/
@JvmOverloads
fun <T : Any> format(
responseType: Class<T>,
localValidation: JsonSchemaLocalValidation = JsonSchemaLocalValidation.YES,
) = StructuredResponseTextConfig.builder<T>().wrap(responseType, this, localValidation)

/**
* Constrains the verbosity of the model's response. Lower values will result in more
* concise responses, while higher values will result in more verbose responses. Currently
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import java.util.Optional
/**
* A wrapper for [ResponseCreateParams] that provides a type-safe [Builder] that can record the
* [responseType] used to derive a JSON schema from an arbitrary class when using the _Structured
* Outputs_ feature. When a JSON response is received, it is deserialized to am instance of that
* Outputs_ feature. When a JSON response is received, it is deserialized to an instance of that
* type. See the SDK documentation for more details on _Structured Outputs_.
*
* @param T The type of the class that will be used to derive the JSON schema in the request and to
Expand Down Expand Up @@ -51,6 +51,16 @@ class StructuredResponseCreateParams<T : Any>(
text(responseType, localValidation)
}

@JvmSynthetic
internal fun wrap(
textConfig: StructuredResponseTextConfig<T>,
paramsBuilder: ResponseCreateParams.Builder,
) = apply {
this.responseType = textConfig.responseType
this.paramsBuilder = paramsBuilder
text(textConfig)
}

/** Injects a given `ResponseCreateParams.Builder`. For use only when testing. */
@JvmSynthetic
internal fun inject(paramsBuilder: ResponseCreateParams.Builder) = apply {
Expand Down Expand Up @@ -342,6 +352,17 @@ class StructuredResponseCreateParams<T : Any>(
paramsBuilder.text(textConfigFromClass(responseType, localValidation))
}

/**
* Sets the text configuration to a [StructuredResponseTextConfig] where the format was set
* to a JSON schema derived from the structure of a class.
*
* @see ResponseCreateParams.Builder.text
*/
fun text(text: StructuredResponseTextConfig<T>) = apply {
this.responseType = text.responseType
paramsBuilder.text(text.rawConfig)
}

/** @see ResponseCreateParams.Builder.toolChoice */
fun toolChoice(toolChoice: ResponseCreateParams.ToolChoice) = apply {
paramsBuilder.toolChoice(toolChoice)
Expand Down Expand Up @@ -665,7 +686,7 @@ class StructuredResponseCreateParams<T : Any>(
}

/**
* Returns an immutable instance of [ResponseCreateParams].
* Returns an immutable instance of [StructuredResponseCreateParams].
*
* Further updates to this [Builder] will not mutate the returned instance.
*
Expand Down
Loading
Loading