From 14e7033a8e4dee9e34d3b46de80ec2772c2b99a4 Mon Sep 17 00:00:00 2001 From: jonghoon park Date: Thu, 6 Mar 2025 16:20:47 +0900 Subject: [PATCH] refactor(openai): change voice parameter to string in OpenAI Audio Speech API (#2395) This change modifies the voice parameter in OpenAI Audio Speech API from using the Voice enum directly to using the string value of the enum. This provides more flexibility for handling voice options, especially for custom voices or when voice names come from configuration. - Change voice parameter type from Voice enum to String - Add overloaded methods to accept both enum and string values - Update tests and documentation to reflect these changes Signed-off-by: jonghoon park --- .../OpenAiAudioSpeechProperties.java | 3 +- .../autoconfigure/OpenAiPropertiesTests.java | 10 +++--- .../ai/openai/OpenAiAudioSpeechModel.java | 5 +-- .../ai/openai/OpenAiAudioSpeechOptions.java | 28 ++++++++++------ .../ai/openai/api/OpenAiAudioApi.java | 14 +++++--- .../ai/openai/audio/api/OpenAiAudioApiIT.java | 5 +-- .../api/OpenAiAudioModelNoOpApiKeysIT.java | 3 +- .../audio/speech/OpenAiSpeechModelIT.java | 14 +++++--- ...hModelWithSpeechResponseMetadataTests.java | 3 +- .../pages/api/audio/speech/openai-speech.adoc | 32 +++++++++++-------- 10 files changed, 74 insertions(+), 43 deletions(-) diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechProperties.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechProperties.java index 98a12d12b..d9c9c7a44 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechProperties.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/main/java/org/springframework/ai/model/openai/autoconfigure/OpenAiAudioSpeechProperties.java @@ -29,6 +29,7 @@ import org.springframework.boot.context.properties.NestedConfigurationProperty; * * @author Ahmed Yousri * @author Stefan Vassilev + * @author Jonghoon Park */ @ConfigurationProperties(OpenAiAudioSpeechProperties.CONFIG_PREFIX) public class OpenAiAudioSpeechProperties extends OpenAiParentProperties { @@ -39,7 +40,7 @@ public class OpenAiAudioSpeechProperties extends OpenAiParentProperties { private static final Float SPEED = 1.0f; - private static final OpenAiAudioApi.SpeechRequest.Voice VOICE = OpenAiAudioApi.SpeechRequest.Voice.ALLOY; + private static final String VOICE = OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue(); private static final OpenAiAudioApi.SpeechRequest.AudioResponseFormat DEFAULT_RESPONSE_FORMAT = OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3; diff --git a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java index 1e3098a7f..b1c547eec 100644 --- a/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java +++ b/auto-configurations/models/spring-ai-autoconfigure-model-openai/src/test/java/org/springframework/ai/model/openai/autoconfigure/OpenAiPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Christian Tzolov * @author Thomas Vitale + * @author Jonghoon Park * @since 0.8.0 */ public class OpenAiPropertiesTests { @@ -177,7 +178,7 @@ public class OpenAiPropertiesTests { assertThat(speechProperties.getOptions().getModel()).isEqualTo("TTS_1"); assertThat(speechProperties.getOptions().getVoice()) - .isEqualTo(OpenAiAudioApi.SpeechRequest.Voice.ALLOY); + .isEqualTo(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()); assertThat(speechProperties.getOptions().getResponseFormat()) .isEqualTo(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3); assertThat(speechProperties.getOptions().getSpeed()).isEqualTo(0.75f); @@ -205,7 +206,7 @@ public class OpenAiPropertiesTests { assertThat(speechProperties.getOptions().getModel()).isEqualTo("TTS_1"); assertThat(speechProperties.getOptions().getVoice()) - .isEqualTo(OpenAiAudioApi.SpeechRequest.Voice.ALLOY); + .isEqualTo(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()); assertThat(speechProperties.getOptions().getResponseFormat()) .isEqualTo(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3); assertThat(speechProperties.getOptions().getSpeed()).isEqualTo(0.75f); @@ -237,7 +238,8 @@ public class OpenAiPropertiesTests { assertThat(speechProperties.getBaseUrl()).isEqualTo("TEST_BASE_URL2"); assertThat(speechProperties.getOptions().getModel()).isEqualTo("TTS_2"); - assertThat(speechProperties.getOptions().getVoice()).isEqualTo(OpenAiAudioApi.SpeechRequest.Voice.ECHO); + assertThat(speechProperties.getOptions().getVoice()) + .isEqualTo(OpenAiAudioApi.SpeechRequest.Voice.ECHO.getValue()); assertThat(speechProperties.getOptions().getResponseFormat()) .isEqualTo(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.OPUS); assertThat(speechProperties.getOptions().getSpeed()).isEqualTo(0.5f); diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java index baf772ed4..2ea526222 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechModel.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import org.springframework.util.Assert; * @author Ahmed Yousri * @author Hyunjoon Choi * @author Thomas Vitale + * @author Jonghoon Park * @see OpenAiAudioApi * @since 1.0.0-M1 */ @@ -81,7 +82,7 @@ public class OpenAiAudioSpeechModel implements SpeechModel, StreamingSpeechModel OpenAiAudioSpeechOptions.builder() .model(OpenAiAudioApi.TtsModel.TTS_1.getValue()) .responseFormat(AudioResponseFormat.MP3) - .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()) .speed(SPEED) .build()); } diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechOptions.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechOptions.java index 6e9fcdb87..6e5d1a8ec 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechOptions.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/OpenAiAudioSpeechOptions.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,14 +29,15 @@ import org.springframework.ai.openai.api.OpenAiAudioApi.SpeechRequest.Voice; * @author Ahmed Yousri * @author Hyunjoon Choi * @author Ilayaperumal Gopinathan + * @author Jonghoon Park * @since 1.0.0-M1 */ @JsonInclude(JsonInclude.Include.NON_NULL) public class OpenAiAudioSpeechOptions implements ModelOptions { /** - * ID of the model to use for generating the audio. One of the available TTS models: - * tts-1 or tts-1-hd. + * ID of the model to use for generating the audio. For OpenAI's TTS API, use one of + * the available models: tts-1 or tts-1-hd. */ @JsonProperty("model") private String model; @@ -48,11 +49,11 @@ public class OpenAiAudioSpeechOptions implements ModelOptions { private String input; /** - * The voice to use for synthesis. One of the available voices for the chosen model: - * 'alloy', 'echo', 'fable', 'onyx', 'nova', and 'shimmer'. + * The voice to use for synthesis. For OpenAI's TTS API, One of the available voices + * for the chosen model: 'alloy', 'echo', 'fable', 'onyx', 'nova', and 'shimmer'. */ @JsonProperty("voice") - private Voice voice; + private String voice; /** * The format of the audio output. Supported formats are mp3, opus, aac, and flac. @@ -88,14 +89,18 @@ public class OpenAiAudioSpeechOptions implements ModelOptions { this.input = input; } - public Voice getVoice() { + public String getVoice() { return this.voice; } - public void setVoice(Voice voice) { + public void setVoice(String voice) { this.voice = voice; } + public void setVoice(Voice voice) { + this.voice = voice.getValue(); + } + public AudioResponseFormat getResponseFormat() { return this.responseFormat; } @@ -197,11 +202,16 @@ public class OpenAiAudioSpeechOptions implements ModelOptions { return this; } - public Builder voice(Voice voice) { + public Builder voice(String voice) { this.options.voice = voice; return this; } + public Builder voice(Voice voice) { + this.options.voice = voice.getValue(); + return this; + } + public Builder responseFormat(AudioResponseFormat responseFormat) { this.options.responseFormat = responseFormat; return this; diff --git a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java index 83eb491c0..8974081b2 100644 --- a/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java +++ b/models/spring-ai-openai/src/main/java/org/springframework/ai/openai/api/OpenAiAudioApi.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,6 +47,7 @@ import org.springframework.web.reactive.function.client.WebClient; * * @author Christian Tzolov * @author Ilayaperumal Gopinathan + * @author Jonghoon Park * @since 0.8.1 */ public class OpenAiAudioApi { @@ -330,7 +331,7 @@ public class OpenAiAudioApi { // @formatter:off @JsonProperty("model") String model, @JsonProperty("input") String input, - @JsonProperty("voice") Voice voice, + @JsonProperty("voice") String voice, @JsonProperty("response_format") AudioResponseFormat responseFormat, @JsonProperty("speed") Float speed) { // @formatter:on @@ -419,7 +420,7 @@ public class OpenAiAudioApi { private String input; - private Voice voice; + private String voice; private AudioResponseFormat responseFormat = AudioResponseFormat.MP3; @@ -435,11 +436,16 @@ public class OpenAiAudioApi { return this; } - public Builder voice(Voice voice) { + public Builder voice(String voice) { this.voice = voice; return this; } + public Builder voice(Voice voice) { + this.voice = voice.getValue(); + return this; + } + public Builder responseFormat(AudioResponseFormat responseFormat) { this.responseFormat = responseFormat; return this; diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java index 4b4fd9d24..6c933dec2 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioApiIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat; /** * @author Christian Tzolov + * @author Jonghoon Park */ @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") public class OpenAiAudioApiIT { @@ -53,7 +54,7 @@ public class OpenAiAudioApiIT { .createSpeech(SpeechRequest.builder() .model(TtsModel.TTS_1_HD.getValue()) .input("Hello, my name is Chris and I love Spring A.I.") - .voice(Voice.ONYX) + .voice(Voice.ONYX.getValue()) .build()) .getBody(); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioModelNoOpApiKeysIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioModelNoOpApiKeysIT.java index 2f0e09888..247dd76d4 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioModelNoOpApiKeysIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/api/OpenAiAudioModelNoOpApiKeysIT.java @@ -31,6 +31,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; /** * @author Ilayaperumal Gopinathan + * @author Jonghoon Park */ @SpringBootTest(classes = OpenAiAudioModelNoOpApiKeysIT.Config.class) @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") @@ -46,7 +47,7 @@ public class OpenAiAudioModelNoOpApiKeysIT { .createSpeech(OpenAiAudioApi.SpeechRequest.builder() .model(OpenAiAudioApi.TtsModel.TTS_1_HD.getValue()) .input("Hello, my name is Chris and I love Spring A.I.") - .voice(OpenAiAudioApi.SpeechRequest.Voice.ONYX) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ONYX.getValue()) .build()) .getBody(); }).isInstanceOf(NonTransientAiException.class); diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelIT.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelIT.java index 8bfa2f90e..7f4a81d3e 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelIT.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelIT.java @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 the original author or authors. + * Copyright 2023-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,6 +33,10 @@ import org.springframework.boot.test.context.SpringBootTest; import static org.assertj.core.api.Assertions.assertThat; +/** + * @author Ahmed Yousri + * @author Jonghoon Park + */ @SpringBootTest(classes = OpenAiTestConfiguration.class) @EnabledIfEnvironmentVariable(named = "OPENAI_API_KEY", matches = ".+") class OpenAiSpeechModelIT extends AbstractIT { @@ -57,7 +61,7 @@ class OpenAiSpeechModelIT extends AbstractIT { @Test void shouldGenerateNonEmptyMp3AudioFromSpeechPrompt() { OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() - .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()) .speed(SPEED) .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) .model(OpenAiAudioApi.TtsModel.TTS_1.value) @@ -93,7 +97,7 @@ class OpenAiSpeechModelIT extends AbstractIT { @Test void speechRateLimitTest() { OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() - .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()) .speed(SPEED) .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) .model(OpenAiAudioApi.TtsModel.TTS_1.value) @@ -113,7 +117,7 @@ class OpenAiSpeechModelIT extends AbstractIT { void shouldStreamNonEmptyResponsesForValidSpeechPrompts() { OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() - .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()) .speed(SPEED) .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) .model(OpenAiAudioApi.TtsModel.TTS_1.value) @@ -135,7 +139,7 @@ class OpenAiSpeechModelIT extends AbstractIT { @ValueSource(strings = { "alloy", "echo", "fable", "onyx", "nova", "shimmer", "sage", "coral", "ash" }) void speechVoicesTest(String voice) { OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() - .voice(OpenAiAudioApi.SpeechRequest.Voice.valueOf(voice.toUpperCase())) + .voice(voice) .speed(SPEED) .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) .model(OpenAiAudioApi.TtsModel.TTS_1.value) diff --git a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelWithSpeechResponseMetadataTests.java b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelWithSpeechResponseMetadataTests.java index 3a6c4b2d1..9d98b5d9b 100644 --- a/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelWithSpeechResponseMetadataTests.java +++ b/models/spring-ai-openai/src/test/java/org/springframework/ai/openai/audio/speech/OpenAiSpeechModelWithSpeechResponseMetadataTests.java @@ -46,6 +46,7 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat /** * @author Ahmed Yousri + * @author Jonghoon Park */ @RestClientTest(OpenAiSpeechModelWithSpeechResponseMetadataTests.Config.class) public class OpenAiSpeechModelWithSpeechResponseMetadataTests { @@ -71,7 +72,7 @@ public class OpenAiSpeechModelWithSpeechResponseMetadataTests { prepareMock(); OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() - .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) + .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY.getValue()) .speed(SPEED) .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) .model(OpenAiAudioApi.TtsModel.TTS_1.value) diff --git a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc index 4f5a13a88..6b6060c8f 100644 --- a/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc +++ b/spring-ai-docs/src/main/antora/modules/ROOT/pages/api/audio/speech/openai-speech.adoc @@ -85,8 +85,8 @@ The prefix `spring.ai.openai.audio.speech` is used as the property prefix that l | spring.ai.openai.audio.speech.api-key | The API Key | - | spring.ai.openai.audio.speech.organization-id | Optionally you can specify which organization used for an API request. | - | spring.ai.openai.audio.speech.project-id | Optionally, you can specify which project is used for an API request. | - -| spring.ai.openai.audio.speech.options.model | ID of the model to use. Only tts-1 is currently available. | tts-1 -| spring.ai.openai.audio.speech.options.voice | The voice to use for the TTS output. Available options are: alloy, echo, fable, onyx, nova, and shimmer. | alloy +| spring.ai.openai.audio.speech.options.model | ID of the model to use for generating the audio. For OpenAI's TTS API, use one of the available models: tts-1 or tts-1-hd. | tts-1 +| spring.ai.openai.audio.speech.options.voice | The voice to use for synthesis. For OpenAI's TTS API, One of the available voices for the chosen model: alloy, echo, fable, onyx, nova, and shimmer. | alloy | spring.ai.openai.audio.speech.options.response-format | The format of the audio output. Supported formats are mp3, opus, aac, flac, wav, and pcm. | mp3 | spring.ai.openai.audio.speech.options.speed | The speed of the voice synthesis. The acceptable range is from 0.25 (slowest) to 4.0 (fastest). | 1.0 |==== @@ -113,8 +113,8 @@ OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() .speed(1.0f) .build(); -SpeechPrompt speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", this.speechOptions); -SpeechResponse response = openAiAudioSpeechModel.call(this.speechPrompt); +SpeechPrompt speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", speechOptions); +SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt); ---- == Manual Configuration @@ -144,9 +144,11 @@ Next, create an `OpenAiAudioSpeechModel`: [source,java] ---- -var openAiAudioApi = new OpenAiAudioApi(System.getenv("OPENAI_API_KEY")); +var openAiAudioApi = new OpenAiAudioApi() + .apiKey(System.getenv("OPENAI_API_KEY")) + .build(); -var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(this.openAiAudioApi); +var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(openAiAudioApi); var speechOptions = OpenAiAudioSpeechOptions.builder() .responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3) @@ -154,13 +156,13 @@ var speechOptions = OpenAiAudioSpeechOptions.builder() .model(OpenAiAudioApi.TtsModel.TTS_1.value) .build(); -var speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", this.speechOptions); -SpeechResponse response = this.openAiAudioSpeechModel.call(this.speechPrompt); +var speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", speechOptions); +SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt); // Accessing metadata (rate limit info) -OpenAiAudioSpeechResponseMetadata metadata = this.response.getMetadata(); +OpenAiAudioSpeechResponseMetadata metadata = response.getMetadata(); -byte[] responseAsBytes = this.response.getResult().getOutput(); +byte[] responseAsBytes = response.getResult().getOutput(); ---- == Streaming Real-time Audio @@ -169,9 +171,11 @@ The Speech API provides support for real-time audio streaming using chunk transf [source,java] ---- -var openAiAudioApi = new OpenAiAudioApi(System.getenv("OPENAI_API_KEY")); +var openAiAudioApi = new OpenAiAudioApi() + .apiKey(System.getenv("OPENAI_API_KEY")) + .build(); -var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(this.openAiAudioApi); +var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(openAiAudioApi); OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() .voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY) @@ -180,9 +184,9 @@ OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder() .model(OpenAiAudioApi.TtsModel.TTS_1.value) .build(); -SpeechPrompt speechPrompt = new SpeechPrompt("Today is a wonderful day to build something people love!", this.speechOptions); +SpeechPrompt speechPrompt = new SpeechPrompt("Today is a wonderful day to build something people love!", speechOptions); -Flux responseStream = this.openAiAudioSpeechModel.stream(this.speechPrompt); +Flux responseStream = openAiAudioSpeechModel.stream(speechPrompt); ---- == Example Code