From 76c9652ab8d6fc0875eeb0911bfe1a9406e618a9 Mon Sep 17 00:00:00 2001 From: iammohan01 Date: Mon, 12 May 2025 23:17:32 +0530 Subject: [PATCH 1/3] feat(api): adding srt and vtt support for audio transcriptions. --- .../openai/core/handlers/AudioTextHandler.kt | 15 +++++++++++++ .../audio/TranscriptionServiceAsyncImpl.kt | 14 ++++++++++-- .../audio/TranscriptionServiceImpl.kt | 13 +++++++++-- .../example/AudioTranscriptionsExample.java | 22 +++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt diff --git a/openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt b/openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt new file mode 100644 index 00000000..77280498 --- /dev/null +++ b/openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt @@ -0,0 +1,15 @@ +package com.openai.core.handlers + +import com.openai.core.http.HttpResponse +import com.openai.core.http.HttpResponse.Handler +import com.openai.models.audio.transcriptions.Transcription +import com.openai.models.audio.transcriptions.TranscriptionCreateResponse + +@JvmSynthetic internal fun audioTextHandler(): Handler = AudioTextHandler + +private object AudioTextHandler : Handler { + override fun handle(response: HttpResponse): TranscriptionCreateResponse { + val c = response.body().readBytes().toString(Charsets.UTF_8) + return TranscriptionCreateResponse.ofTranscription(Transcription.builder().text(c).build()) + } +} \ No newline at end of file diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt index b90c2136..ff113cbe 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt @@ -9,6 +9,7 @@ import com.openai.core.handlers.errorHandler import com.openai.core.handlers.jsonHandler import com.openai.core.handlers.mapJson import com.openai.core.handlers.sseHandler +import com.openai.core.handlers.audioTextHandler import com.openai.core.handlers.withErrorHandler import com.openai.core.http.AsyncStreamResponse import com.openai.core.http.HttpMethod @@ -22,6 +23,7 @@ import com.openai.core.http.parseable import com.openai.core.http.toAsync import com.openai.core.prepareAsync import com.openai.models.ErrorObject +import com.openai.models.audio.AudioResponseFormat import com.openai.models.audio.transcriptions.TranscriptionCreateParams import com.openai.models.audio.transcriptions.TranscriptionCreateResponse import com.openai.models.audio.transcriptions.TranscriptionStreamEvent @@ -58,14 +60,22 @@ class TranscriptionServiceAsyncImpl internal constructor(private val clientOptio private val errorHandler: Handler = errorHandler(clientOptions.jsonMapper) - private val createHandler: Handler = + private val jsonHandler: Handler = jsonHandler(clientOptions.jsonMapper) .withErrorHandler(errorHandler) + private val textHandler: Handler = audioTextHandler().withErrorHandler(errorHandler) override fun create( params: TranscriptionCreateParams, requestOptions: RequestOptions, ): CompletableFuture> { + val handler = if (params.responseFormat().isPresent && listOf( + AudioResponseFormat.VTT, + AudioResponseFormat.SRT, + AudioResponseFormat.TEXT + ).contains(params.responseFormat().get()) + ) textHandler else jsonHandler + val request = HttpRequest.builder() .method(HttpMethod.POST) @@ -83,7 +93,7 @@ class TranscriptionServiceAsyncImpl internal constructor(private val clientOptio .thenApply { response -> response.parseable { response - .use { createHandler.handle(it) } + .use { handler.handle(it) } .also { if (requestOptions.responseValidation!!) { it.validate() diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt index a09d45be..a41640a2 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt @@ -9,6 +9,7 @@ import com.openai.core.handlers.errorHandler import com.openai.core.handlers.jsonHandler import com.openai.core.handlers.mapJson import com.openai.core.handlers.sseHandler +import com.openai.core.handlers.audioTextHandler import com.openai.core.handlers.withErrorHandler import com.openai.core.http.HttpMethod import com.openai.core.http.HttpRequest @@ -20,6 +21,7 @@ import com.openai.core.http.multipartFormData import com.openai.core.http.parseable import com.openai.core.prepare import com.openai.models.ErrorObject +import com.openai.models.audio.AudioResponseFormat import com.openai.models.audio.transcriptions.TranscriptionCreateParams import com.openai.models.audio.transcriptions.TranscriptionCreateResponse import com.openai.models.audio.transcriptions.TranscriptionStreamEvent @@ -52,14 +54,21 @@ class TranscriptionServiceImpl internal constructor(private val clientOptions: C private val errorHandler: Handler = errorHandler(clientOptions.jsonMapper) - private val createHandler: Handler = + private val jsonHandler: Handler = jsonHandler(clientOptions.jsonMapper) .withErrorHandler(errorHandler) + private val textHandler: Handler = audioTextHandler().withErrorHandler(errorHandler) override fun create( params: TranscriptionCreateParams, requestOptions: RequestOptions, ): HttpResponseFor { + val handler = if (params.responseFormat().isPresent && listOf( + AudioResponseFormat.VTT, + AudioResponseFormat.SRT, + AudioResponseFormat.TEXT + ).contains(params.responseFormat().get()) + ) textHandler else jsonHandler val request = HttpRequest.builder() .method(HttpMethod.POST) @@ -71,7 +80,7 @@ class TranscriptionServiceImpl internal constructor(private val clientOptions: C val response = clientOptions.httpClient.execute(request, requestOptions) return response.parseable { response - .use { createHandler.handle(it) } + .use { handler.handle(it) } .also { if (requestOptions.responseValidation!!) { it.validate() diff --git a/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java b/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java index 7a7476b0..24f87f82 100644 --- a/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java +++ b/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java @@ -3,6 +3,7 @@ import com.openai.client.OpenAIClient; import com.openai.client.okhttp.OpenAIOkHttpClient; import com.openai.models.audio.AudioModel; +import com.openai.models.audio.AudioResponseFormat; import com.openai.models.audio.transcriptions.Transcription; import com.openai.models.audio.transcriptions.TranscriptionCreateParams; import java.nio.file.Path; @@ -28,5 +29,26 @@ public static void main(String[] args) throws Exception { Transcription transcription = client.audio().transcriptions().create(createParams).asTranscription(); System.out.println(transcription.text()); + asVTT(); + } + public static void asVTT() throws Exception { + // Configures using one of: + // - The `OPENAI_API_KEY` environment variable + // - The `OPENAI_BASE_URL` and `AZURE_OPENAI_KEY` environment variables + OpenAIClient client = OpenAIOkHttpClient.fromEnv(); + + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + Path path = Paths.get(classloader.getResource("sports.wav").toURI()); + + TranscriptionCreateParams createParams = TranscriptionCreateParams.builder() + .file(path) + .model(AudioModel.WHISPER_1) + .responseFormat(AudioResponseFormat.VTT) + .build(); + + System.out.println("started transcription creation"); + Transcription transcription = + client.audio().transcriptions().create(createParams).asTranscription(); + System.out.println(transcription.text()); } } From b20d37e882eb6c3b50e22ae2b864b58fcb99a026 Mon Sep 17 00:00:00 2001 From: Tomer Aberbach Date: Wed, 14 May 2025 19:30:20 -0400 Subject: [PATCH 2/3] chore: refactoring --- .../openai/core/handlers/AudioTextHandler.kt | 15 -------- .../models/audio/AudioResponseFormat.kt | 11 ++++++ .../audio/TranscriptionServiceAsyncImpl.kt | 36 ++++++++++--------- .../audio/TranscriptionServiceImpl.kt | 33 +++++++++-------- .../example/AudioTranscriptionsExample.java | 22 ------------ .../AudioTranscriptionsVttExample.java | 34 ++++++++++++++++++ 6 files changed, 84 insertions(+), 67 deletions(-) delete mode 100644 openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt create mode 100644 openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsVttExample.java diff --git a/openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt b/openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt deleted file mode 100644 index 77280498..00000000 --- a/openai-java-core/src/main/kotlin/com/openai/core/handlers/AudioTextHandler.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.openai.core.handlers - -import com.openai.core.http.HttpResponse -import com.openai.core.http.HttpResponse.Handler -import com.openai.models.audio.transcriptions.Transcription -import com.openai.models.audio.transcriptions.TranscriptionCreateResponse - -@JvmSynthetic internal fun audioTextHandler(): Handler = AudioTextHandler - -private object AudioTextHandler : Handler { - override fun handle(response: HttpResponse): TranscriptionCreateResponse { - val c = response.body().readBytes().toString(Charsets.UTF_8) - return TranscriptionCreateResponse.ofTranscription(Transcription.builder().text(c).build()) - } -} \ No newline at end of file diff --git a/openai-java-core/src/main/kotlin/com/openai/models/audio/AudioResponseFormat.kt b/openai-java-core/src/main/kotlin/com/openai/models/audio/AudioResponseFormat.kt index 803e2de0..7b01f81b 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/audio/AudioResponseFormat.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/audio/AudioResponseFormat.kt @@ -142,6 +142,17 @@ class AudioResponseFormat @JsonCreator private constructor(private val value: Js */ @JvmSynthetic internal fun validity(): Int = if (value() == Value._UNKNOWN) 0 else 1 + @JvmSynthetic + internal fun isJson(): Boolean = + when (this) { + JSON -> true + TEXT -> false + SRT -> false + VERBOSE_JSON -> true + VTT -> false + else -> false + } + override fun equals(other: Any?): Boolean { if (this === other) { return true diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt index ff113cbe..43a83cc9 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt @@ -5,29 +5,27 @@ package com.openai.services.async.audio import com.openai.core.ClientOptions import com.openai.core.MultipartField import com.openai.core.RequestOptions +import com.openai.core.handlers.* import com.openai.core.handlers.errorHandler import com.openai.core.handlers.jsonHandler import com.openai.core.handlers.mapJson import com.openai.core.handlers.sseHandler -import com.openai.core.handlers.audioTextHandler +import com.openai.core.handlers.stringHandler import com.openai.core.handlers.withErrorHandler -import com.openai.core.http.AsyncStreamResponse -import com.openai.core.http.HttpMethod -import com.openai.core.http.HttpRequest +import com.openai.core.http.* import com.openai.core.http.HttpResponse.Handler -import com.openai.core.http.HttpResponseFor -import com.openai.core.http.StreamResponse import com.openai.core.http.map import com.openai.core.http.multipartFormData import com.openai.core.http.parseable import com.openai.core.http.toAsync import com.openai.core.prepareAsync import com.openai.models.ErrorObject -import com.openai.models.audio.AudioResponseFormat +import com.openai.models.audio.transcriptions.Transcription import com.openai.models.audio.transcriptions.TranscriptionCreateParams import com.openai.models.audio.transcriptions.TranscriptionCreateResponse import com.openai.models.audio.transcriptions.TranscriptionStreamEvent import java.util.concurrent.CompletableFuture +import kotlin.jvm.optionals.getOrNull class TranscriptionServiceAsyncImpl internal constructor(private val clientOptions: ClientOptions) : TranscriptionServiceAsync { @@ -60,22 +58,24 @@ class TranscriptionServiceAsyncImpl internal constructor(private val clientOptio private val errorHandler: Handler = errorHandler(clientOptions.jsonMapper) - private val jsonHandler: Handler = + private val createJsonHandler: Handler = jsonHandler(clientOptions.jsonMapper) .withErrorHandler(errorHandler) - private val textHandler: Handler = audioTextHandler().withErrorHandler(errorHandler) + private val createStringHandler: Handler = + object : Handler { + + private val stringHandler = stringHandler().withErrorHandler(errorHandler) + + override fun handle(response: HttpResponse): TranscriptionCreateResponse = + TranscriptionCreateResponse.ofTranscription( + Transcription.builder().text(stringHandler.handle(response)).build() + ) + } override fun create( params: TranscriptionCreateParams, requestOptions: RequestOptions, ): CompletableFuture> { - val handler = if (params.responseFormat().isPresent && listOf( - AudioResponseFormat.VTT, - AudioResponseFormat.SRT, - AudioResponseFormat.TEXT - ).contains(params.responseFormat().get()) - ) textHandler else jsonHandler - val request = HttpRequest.builder() .method(HttpMethod.POST) @@ -91,6 +91,10 @@ class TranscriptionServiceAsyncImpl internal constructor(private val clientOptio return request .thenComposeAsync { clientOptions.httpClient.executeAsync(it, requestOptions) } .thenApply { response -> + val handler = + if (params.responseFormat().getOrNull()?.isJson() != false) + createJsonHandler + else createStringHandler response.parseable { response .use { handler.handle(it) } diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt index a41640a2..e52f4874 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt @@ -5,26 +5,25 @@ package com.openai.services.blocking.audio import com.openai.core.ClientOptions import com.openai.core.MultipartField import com.openai.core.RequestOptions +import com.openai.core.handlers.* import com.openai.core.handlers.errorHandler import com.openai.core.handlers.jsonHandler import com.openai.core.handlers.mapJson import com.openai.core.handlers.sseHandler -import com.openai.core.handlers.audioTextHandler +import com.openai.core.handlers.stringHandler import com.openai.core.handlers.withErrorHandler -import com.openai.core.http.HttpMethod -import com.openai.core.http.HttpRequest +import com.openai.core.http.* import com.openai.core.http.HttpResponse.Handler -import com.openai.core.http.HttpResponseFor -import com.openai.core.http.StreamResponse import com.openai.core.http.map import com.openai.core.http.multipartFormData import com.openai.core.http.parseable import com.openai.core.prepare import com.openai.models.ErrorObject -import com.openai.models.audio.AudioResponseFormat +import com.openai.models.audio.transcriptions.Transcription import com.openai.models.audio.transcriptions.TranscriptionCreateParams import com.openai.models.audio.transcriptions.TranscriptionCreateResponse import com.openai.models.audio.transcriptions.TranscriptionStreamEvent +import kotlin.jvm.optionals.getOrNull class TranscriptionServiceImpl internal constructor(private val clientOptions: ClientOptions) : TranscriptionService { @@ -54,21 +53,24 @@ class TranscriptionServiceImpl internal constructor(private val clientOptions: C private val errorHandler: Handler = errorHandler(clientOptions.jsonMapper) - private val jsonHandler: Handler = + private val createJsonHandler: Handler = jsonHandler(clientOptions.jsonMapper) .withErrorHandler(errorHandler) - private val textHandler: Handler = audioTextHandler().withErrorHandler(errorHandler) + private val createStringHandler: Handler = + object : Handler { + + private val stringHandler = stringHandler().withErrorHandler(errorHandler) + + override fun handle(response: HttpResponse): TranscriptionCreateResponse = + TranscriptionCreateResponse.ofTranscription( + Transcription.builder().text(stringHandler.handle(response)).build() + ) + } override fun create( params: TranscriptionCreateParams, requestOptions: RequestOptions, ): HttpResponseFor { - val handler = if (params.responseFormat().isPresent && listOf( - AudioResponseFormat.VTT, - AudioResponseFormat.SRT, - AudioResponseFormat.TEXT - ).contains(params.responseFormat().get()) - ) textHandler else jsonHandler val request = HttpRequest.builder() .method(HttpMethod.POST) @@ -79,6 +81,9 @@ class TranscriptionServiceImpl internal constructor(private val clientOptions: C val requestOptions = requestOptions.applyDefaults(RequestOptions.from(clientOptions)) val response = clientOptions.httpClient.execute(request, requestOptions) return response.parseable { + val handler = + if (params.responseFormat().getOrNull()?.isJson() != false) createJsonHandler + else createStringHandler response .use { handler.handle(it) } .also { diff --git a/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java b/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java index 24f87f82..7a7476b0 100644 --- a/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java +++ b/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsExample.java @@ -3,7 +3,6 @@ import com.openai.client.OpenAIClient; import com.openai.client.okhttp.OpenAIOkHttpClient; import com.openai.models.audio.AudioModel; -import com.openai.models.audio.AudioResponseFormat; import com.openai.models.audio.transcriptions.Transcription; import com.openai.models.audio.transcriptions.TranscriptionCreateParams; import java.nio.file.Path; @@ -29,26 +28,5 @@ public static void main(String[] args) throws Exception { Transcription transcription = client.audio().transcriptions().create(createParams).asTranscription(); System.out.println(transcription.text()); - asVTT(); - } - public static void asVTT() throws Exception { - // Configures using one of: - // - The `OPENAI_API_KEY` environment variable - // - The `OPENAI_BASE_URL` and `AZURE_OPENAI_KEY` environment variables - OpenAIClient client = OpenAIOkHttpClient.fromEnv(); - - ClassLoader classloader = Thread.currentThread().getContextClassLoader(); - Path path = Paths.get(classloader.getResource("sports.wav").toURI()); - - TranscriptionCreateParams createParams = TranscriptionCreateParams.builder() - .file(path) - .model(AudioModel.WHISPER_1) - .responseFormat(AudioResponseFormat.VTT) - .build(); - - System.out.println("started transcription creation"); - Transcription transcription = - client.audio().transcriptions().create(createParams).asTranscription(); - System.out.println(transcription.text()); } } diff --git a/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsVttExample.java b/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsVttExample.java new file mode 100644 index 00000000..2d635709 --- /dev/null +++ b/openai-java-example/src/main/java/com/openai/example/AudioTranscriptionsVttExample.java @@ -0,0 +1,34 @@ +package com.openai.example; + +import com.openai.client.OpenAIClient; +import com.openai.client.okhttp.OpenAIOkHttpClient; +import com.openai.models.audio.AudioModel; +import com.openai.models.audio.AudioResponseFormat; +import com.openai.models.audio.transcriptions.Transcription; +import com.openai.models.audio.transcriptions.TranscriptionCreateParams; +import java.nio.file.Path; +import java.nio.file.Paths; + +public final class AudioTranscriptionsVttExample { + private AudioTranscriptionsVttExample() {} + + public static void main(String[] args) throws Exception { + // Configures using one of: + // - The `OPENAI_API_KEY` environment variable + // - The `OPENAI_BASE_URL` and `AZURE_OPENAI_KEY` environment variables + OpenAIClient client = OpenAIOkHttpClient.fromEnv(); + + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + Path path = Paths.get(classloader.getResource("sports.wav").toURI()); + + TranscriptionCreateParams createParams = TranscriptionCreateParams.builder() + .file(path) + .model(AudioModel.WHISPER_1) + .responseFormat(AudioResponseFormat.VTT) + .build(); + + Transcription transcription = + client.audio().transcriptions().create(createParams).asTranscription(); + System.out.println(transcription.text()); + } +} From 199cc4a17677e8341e5418c06a6102ac325bd6ac Mon Sep 17 00:00:00 2001 From: Tomer Aberbach Date: Wed, 14 May 2025 19:32:59 -0400 Subject: [PATCH 3/3] chore: fix import format --- .../services/async/audio/TranscriptionServiceAsyncImpl.kt | 8 ++++++-- .../services/blocking/audio/TranscriptionServiceImpl.kt | 7 +++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt index 43a83cc9..8ce64e0a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/async/audio/TranscriptionServiceAsyncImpl.kt @@ -5,15 +5,19 @@ package com.openai.services.async.audio import com.openai.core.ClientOptions import com.openai.core.MultipartField import com.openai.core.RequestOptions -import com.openai.core.handlers.* import com.openai.core.handlers.errorHandler import com.openai.core.handlers.jsonHandler import com.openai.core.handlers.mapJson import com.openai.core.handlers.sseHandler import com.openai.core.handlers.stringHandler import com.openai.core.handlers.withErrorHandler -import com.openai.core.http.* +import com.openai.core.http.AsyncStreamResponse +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.StreamResponse import com.openai.core.http.map import com.openai.core.http.multipartFormData import com.openai.core.http.parseable diff --git a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt index e52f4874..47f7e94a 100644 --- a/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt +++ b/openai-java-core/src/main/kotlin/com/openai/services/blocking/audio/TranscriptionServiceImpl.kt @@ -5,15 +5,18 @@ package com.openai.services.blocking.audio import com.openai.core.ClientOptions import com.openai.core.MultipartField import com.openai.core.RequestOptions -import com.openai.core.handlers.* import com.openai.core.handlers.errorHandler import com.openai.core.handlers.jsonHandler import com.openai.core.handlers.mapJson import com.openai.core.handlers.sseHandler import com.openai.core.handlers.stringHandler import com.openai.core.handlers.withErrorHandler -import com.openai.core.http.* +import com.openai.core.http.HttpMethod +import com.openai.core.http.HttpRequest +import com.openai.core.http.HttpResponse import com.openai.core.http.HttpResponse.Handler +import com.openai.core.http.HttpResponseFor +import com.openai.core.http.StreamResponse import com.openai.core.http.map import com.openai.core.http.multipartFormData import com.openai.core.http.parseable