Skip to content

Commit c0aa6b5

Browse files
stainless-app[bot]yoshioteradaYoshio TeradaTomerAberbach
authored
release: 2.19.0 (#553)
* docs: fix missing readme comment * feat(client): support base64 embeddings and use as default (#519) * Add EmbeddingValue union type and Base64 support for embeddings This implementation adds support for Base64-encoded embeddings as the default response format, while maintaining complete backward compatibility with existing `List<Float>` usage. ### 1. Default Behavior Change - **New Default**: Embedding requests now default to Base64 encoding format - **Backward Compatibility**: Existing code using `embedding()` method continues to work unchanged - **Performance**: Base64 encoding reduces network payload size significantly Introduces the EmbeddingValue class to support both float list and base64-encoded embedding data, enabling efficient handling and backward compatibility. Embedding, EmbeddingCreateParams, and related classes are updated to use EmbeddingValue, with automatic decoding and encoding between formats. Adds EmbeddingDefaults for global default encoding configuration, and comprehensive tests for new behaviors and compatibility. * Deleted invalid EmbeddingDefaults.kt Deleted invalid EmbeddingDefaults.kt * fix: actually add system properties * Modified the field name for floats and base64 Modified the field name for floats and base64 * Deleted DebutTest Deleted DebutTest * Modified validate method and refactored apply scope function * validate() methods validate anything the "shape" of the data being correct * The code has been refactored to use Kotlin's apply scope function for improved conciseness and consistency. * Modified default encoding Modified default encoding * Modified the implementation of default encoding Modified the implementation of default encoding * Modified format Modified format * Delete plan2.md Delete plan2.md * fix: set the default correctly * fix: rename some things * chore: EmbeddingValue refactor * refactor: embedding data model * chore: delete test with no asserts * chore: test changes * fix: little-endian --------- Co-authored-by: Yoshio Terada <[email protected]> Co-authored-by: Tomer Aberbach <[email protected]> * release: 2.19.0 --------- Co-authored-by: stainless-app[bot] <142633134+stainless-app[bot]@users.noreply.github.com> Co-authored-by: Yoshio Terada <[email protected]> Co-authored-by: Yoshio Terada <[email protected]> Co-authored-by: Tomer Aberbach <[email protected]>
1 parent 3b809df commit c0aa6b5

File tree

9 files changed

+364
-28
lines changed

9 files changed

+364
-28
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.18.2"
2+
".": "2.19.0"
33
}

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# Changelog
22

3+
## 2.19.0 (2025-07-23)
4+
5+
Full Changelog: [v2.18.2...v2.19.0](https://github.com/openai/openai-java/compare/v2.18.2...v2.19.0)
6+
7+
### Features
8+
9+
* **client:** support base64 embeddings and use as default ([#519](https://github.com/openai/openai-java/issues/519)) ([12b0ff7](https://github.com/openai/openai-java/commit/12b0ff75cf2a3bc93cf5c41adbbf2b5097a8e941))
10+
11+
12+
### Documentation
13+
14+
* fix missing readme comment ([720ed2c](https://github.com/openai/openai-java/commit/720ed2cff555977efa00043b3f424920811ce339))
15+
316
## 2.18.2 (2025-07-22)
417

518
Full Changelog: [v2.18.1...v2.18.2](https://github.com/openai/openai-java/compare/v2.18.1...v2.18.2)

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

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

5-
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/2.18.2)
6-
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/2.18.2/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/2.18.2)
5+
[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/2.19.0)
6+
[![javadoc](https://javadoc.io/badge2/com.openai/openai-java/2.19.0/javadoc.svg)](https://javadoc.io/doc/com.openai/openai-java/2.19.0)
77

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

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

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

14-
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/2.18.2).
14+
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/2.19.0).
1515

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

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

2626
```kotlin
27-
implementation("com.openai:openai-java:2.18.2")
27+
implementation("com.openai:openai-java:2.19.0")
2828
```
2929

3030
### Maven
@@ -33,7 +33,7 @@ implementation("com.openai:openai-java:2.18.2")
3333
<dependency>
3434
<groupId>com.openai</groupId>
3535
<artifactId>openai-java</artifactId>
36-
<version>2.18.2</version>
36+
<version>2.19.0</version>
3737
</dependency>
3838
```
3939

@@ -118,7 +118,7 @@ import com.openai.client.okhttp.OpenAIOkHttpClient;
118118

119119
OpenAIClient client = OpenAIOkHttpClient.builder()
120120
// Configures using the `openai.apiKey`, `openai.orgId`, `openai.projectId`, `openai.webhookSecret` and `openai.baseUrl` system properties
121-
Or configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID`, `OPENAI_WEBHOOK_SECRET` and `OPENAI_BASE_URL` environment variables
121+
// Or configures using the `OPENAI_API_KEY`, `OPENAI_ORG_ID`, `OPENAI_PROJECT_ID`, `OPENAI_WEBHOOK_SECRET` and `OPENAI_BASE_URL` environment variables
122122
.fromEnv()
123123
.apiKey("My API Key")
124124
.build();
@@ -1321,7 +1321,7 @@ If you're using Spring Boot, then you can use the SDK's [Spring Boot starter](ht
13211321
#### Gradle
13221322

13231323
```kotlin
1324-
implementation("com.openai:openai-java-spring-boot-starter:2.18.2")
1324+
implementation("com.openai:openai-java-spring-boot-starter:2.19.0")
13251325
```
13261326

13271327
#### Maven
@@ -1330,7 +1330,7 @@ implementation("com.openai:openai-java-spring-boot-starter:2.18.2")
13301330
<dependency>
13311331
<groupId>com.openai</groupId>
13321332
<artifactId>openai-java-spring-boot-starter</artifactId>
1333-
<version>2.18.2</version>
1333+
<version>2.19.0</version>
13341334
</dependency>
13351335
```
13361336

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ repositories {
88

99
allprojects {
1010
group = "com.openai"
11-
version = "2.18.2" // x-release-please-version
11+
version = "2.19.0" // x-release-please-version
1212
}
1313

1414
subprojects {

openai-java-core/src/main/kotlin/com/openai/models/embeddings/Embedding.kt

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import com.openai.core.JsonMissing
1212
import com.openai.core.JsonValue
1313
import com.openai.core.checkKnown
1414
import com.openai.core.checkRequired
15-
import com.openai.core.toImmutable
1615
import com.openai.errors.OpenAIInvalidDataException
1716
import java.util.Collections
1817
import java.util.Objects
@@ -21,7 +20,7 @@ import kotlin.jvm.optionals.getOrNull
2120
/** Represents an embedding vector returned by embedding endpoint. */
2221
class Embedding
2322
private constructor(
24-
private val embedding: JsonField<List<Float>>,
23+
private val embedding: JsonField<EmbeddingValue>,
2524
private val index: JsonField<Long>,
2625
private val object_: JsonValue,
2726
private val additionalProperties: MutableMap<String, JsonValue>,
@@ -31,7 +30,7 @@ private constructor(
3130
private constructor(
3231
@JsonProperty("embedding")
3332
@ExcludeMissing
34-
embedding: JsonField<List<Float>> = JsonMissing.of(),
33+
embedding: JsonField<EmbeddingValue> = JsonMissing.of(),
3534
@JsonProperty("index") @ExcludeMissing index: JsonField<Long> = JsonMissing.of(),
3635
@JsonProperty("object") @ExcludeMissing object_: JsonValue = JsonMissing.of(),
3736
) : this(embedding, index, object_, mutableMapOf())
@@ -43,7 +42,16 @@ private constructor(
4342
* @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is
4443
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
4544
*/
46-
fun embedding(): List<Float> = embedding.getRequired("embedding")
45+
fun embedding(): List<Float> = embeddingValue().asFloats()
46+
47+
/**
48+
* The embedding data in its original format (either float list or base64 string). This method
49+
* provides efficient access to the embedding data without unnecessary conversions.
50+
*
51+
* @throws OpenAIInvalidDataException if the JSON field has an unexpected type or is
52+
* unexpectedly missing or null (e.g. if the server responded with an unexpected value).
53+
*/
54+
fun embeddingValue(): EmbeddingValue = embedding.getRequired("embedding")
4755

4856
/**
4957
* The index of the embedding in the list of embeddings.
@@ -71,7 +79,16 @@ private constructor(
7179
*
7280
* Unlike [embedding], this method doesn't throw if the JSON field has an unexpected type.
7381
*/
74-
@JsonProperty("embedding") @ExcludeMissing fun _embedding(): JsonField<List<Float>> = embedding
82+
fun _embedding(): JsonField<List<Float>> = embedding.map { it.asFloats() }
83+
84+
/**
85+
* Returns the raw JSON value of [embedding].
86+
*
87+
* Unlike [embeddingValue], this method doesn't throw if the JSON field has an unexpected type.
88+
*/
89+
@JsonProperty("embedding")
90+
@ExcludeMissing
91+
fun _embeddingValue(): JsonField<EmbeddingValue> = embedding
7592

7693
/**
7794
* Returns the raw JSON value of [index].
@@ -109,25 +126,38 @@ private constructor(
109126
/** A builder for [Embedding]. */
110127
class Builder internal constructor() {
111128

112-
private var embedding: JsonField<MutableList<Float>>? = null
129+
private var embeddingFloats: MutableList<Float>? = null
130+
private var embedding: JsonField<EmbeddingValue>? = null
113131
private var index: JsonField<Long>? = null
114132
private var object_: JsonValue = JsonValue.from("embedding")
115133
private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()
116134

117135
@JvmSynthetic
118136
internal fun from(embedding: Embedding) = apply {
119-
this.embedding = embedding.embedding.map { it.toMutableList() }
137+
this.embedding = embedding.embedding
120138
index = embedding.index
121139
object_ = embedding.object_
122140
additionalProperties = embedding.additionalProperties.toMutableMap()
123141
}
124142

143+
/**
144+
* The embedding vector. The length of vector depends on the model as listed in the
145+
* [embedding guide](https://platform.openai.com/docs/guides/embeddings).
146+
*/
147+
fun embedding(embedding: EmbeddingValue) = embedding(JsonField.of(embedding))
148+
125149
/**
126150
* The embedding vector, which is a list of floats. The length of vector depends on the
127151
* model as listed in the
128152
* [embedding guide](https://platform.openai.com/docs/guides/embeddings).
129153
*/
130-
fun embedding(embedding: List<Float>) = embedding(JsonField.of(embedding))
154+
fun embedding(floats: List<Float>) = embedding(EmbeddingValue.ofFloats(floats))
155+
156+
/**
157+
* The embedding vector, which is a base64 string. The length of vector depends on the model
158+
* as listed in the [embedding guide](https://platform.openai.com/docs/guides/embeddings).
159+
*/
160+
fun embedding(base64: String) = embedding(EmbeddingValue.ofBase64(base64))
131161

132162
/**
133163
* Sets [Builder.embedding] to an arbitrary JSON value.
@@ -136,8 +166,9 @@ private constructor(
136166
* instead. This method is primarily for setting the field to an undocumented or not yet
137167
* supported value.
138168
*/
139-
fun embedding(embedding: JsonField<List<Float>>) = apply {
140-
this.embedding = embedding.map { it.toMutableList() }
169+
fun embedding(embedding: JsonField<EmbeddingValue>) = apply {
170+
embeddingFloats = null
171+
this.embedding = embedding
141172
}
142173

143174
/**
@@ -146,10 +177,12 @@ private constructor(
146177
* @throws IllegalStateException if the field was previously set to a non-list.
147178
*/
148179
fun addEmbedding(embedding: Float) = apply {
149-
this.embedding =
150-
(this.embedding ?: JsonField.of(mutableListOf())).also {
151-
checkKnown("embedding", it).add(embedding)
152-
}
180+
embeddingFloats =
181+
(this.embedding?.let { checkKnown("embedding", it) }?.asFloats()?.toMutableList()
182+
?: embeddingFloats
183+
?: mutableListOf())
184+
.apply { add(embedding) }
185+
this.embedding = null
153186
}
154187

155188
/** The index of the embedding in the list of embeddings. */
@@ -211,7 +244,10 @@ private constructor(
211244
*/
212245
fun build(): Embedding =
213246
Embedding(
214-
checkRequired("embedding", embedding).map { it.toImmutable() },
247+
checkRequired(
248+
"embedding",
249+
embedding ?: embeddingFloats?.let { JsonField.of(EmbeddingValue.ofFloats(it)) },
250+
),
215251
checkRequired("index", index),
216252
object_,
217253
additionalProperties.toMutableMap(),
@@ -225,7 +261,7 @@ private constructor(
225261
return@apply
226262
}
227263

228-
embedding()
264+
embeddingValue().validate()
229265
index()
230266
_object_().let {
231267
if (it != JsonValue.from("embedding")) {
@@ -250,7 +286,7 @@ private constructor(
250286
*/
251287
@JvmSynthetic
252288
internal fun validity(): Int =
253-
(embedding.asKnown().getOrNull()?.size ?: 0) +
289+
(embedding.asKnown().getOrNull()?.validity() ?: 0) +
254290
(if (index.asKnown().isPresent) 1 else 0) +
255291
object_.let { if (it == JsonValue.from("embedding")) 1 else 0 }
256292

openai-java-core/src/main/kotlin/com/openai/models/embeddings/EmbeddingCreateParams.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,8 @@ private constructor(
581581
private var input: JsonField<Input>? = null
582582
private var model: JsonField<EmbeddingModel>? = null
583583
private var dimensions: JsonField<Long> = JsonMissing.of()
584-
private var encodingFormat: JsonField<EncodingFormat> = JsonMissing.of()
584+
private var encodingFormat: JsonField<EncodingFormat> =
585+
JsonField.of(EncodingFormat.BASE64)
585586
private var user: JsonField<String> = JsonMissing.of()
586587
private var additionalProperties: MutableMap<String, JsonValue> = mutableMapOf()
587588

0 commit comments

Comments
 (0)