音频多模态:使用 Spring AI 和 OpenAI 扩展 AI 交互

工程 | Christian Tzolov | 2024年12月05日 | ...

这篇博文由我们优秀的贡献者 Thomas Vitale 合著。

OpenAI 提供用于语音转文本文本转语音转换的专用模型,这些模型以其性能和成本效益而闻名。Spring AI 通过 语音转文本文本转语音 (TTS) 集成了这些功能。

新的 音频生成 功能 (gpt-4o-audio-preview) 更进一步,支持混合输入和输出模态。音频输入可以包含比纯文本更丰富的数据。音频可以传达语气和语调等细微信息,并且结合音频输出可以实现异步的语音转语音交互。此外,这种新的多模态为创新应用开辟了可能性,例如结构化数据提取。开发者不仅可以从简单的文本中提取结构化信息,还可以从图像和音频中提取,无缝地构建复杂的结构化对象。

Spring AI 音频集成

Spring AI 多模态消息 API 简化了多模态功能与各种 AI 模型的集成。

现在,它完全支持 OpenAI 的 音频输入音频输出 模态,这在很大程度上归功于为该功能开发做出贡献的社区成员 Thomas Vitale

设置

请遵循 Spring AI-OpenAI 集成文档来准备您的环境。

音频输入

OpenAI 的 用户消息 API 支持使用 Media 类型在消息中包含 base64 编码的音频文件。支持的格式包括 audio/mp3audio/wav

示例:向输入提示添加音频

// Prepare the audio resource
var audioResource = new ClassPathResource("speech1.mp3");

// Create a user message with audio and send it to the chat model
String response = chatClient.prompt()
        .user(u -> u.text("What is this recording about?")
                    .media(MimeTypeUtils.parseMimeType("audio/mp3"), audioResource))                    
        .options(OpenAiChatOptions.builder()
            .withModel(OpenAiApi.ChatModel.GPT_4_O_AUDIO_PREVIEW).build())
        .call()
        .content();

音频输出生成

OpenAI 助手消息 API 可以使用 Media 类型返回 base64 编码的音频文件。

示例:生成音频输出

// Generate an audio response
ChatResponse response = chatClient
    .prompt("Tell me a joke about the Spring Framework")
    .options(OpenAiChatOptions.builder()
        .withModel(OpenAiApi.ChatModel.GPT_4_O_AUDIO_PREVIEW)
        .withOutputModalities(List.of("text", "audio"))
        .withOutputAudio(new AudioParameters(Voice.ALLOY, AudioResponseFormat.WAV))
        .build())
    .call()
    .chatResponse();

// Access the audio transcript
String audioTranscript = response.getResult().getOutput().getContent();

// Retrieve the generated audio
byte[] generatedAudio = response.getResult().getOutput().getMedia().get(0).getDataAsByteArray();

要生成音频输出,请在 OpenAiChatOptions 中指定音频模态。使用 AudioParameters 类自定义语音和音频格式。

语音聊天机器人演示

此示例演示了如何使用 Spring AI 构建支持输入和输出音频的交互式聊天机器人。它展示了 AI 如何通过自然流畅的音频响应增强用户交互。

设置

添加 Spring AI OpenAI Starter

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>

application.properties 中配置 API 密钥、模型名称和输出音频模态

spring.main.web-application-type=none

spring.ai.openai.api-key=${OPENAI_API_KEY}
spring.ai.openai.chat.options.model=gpt-4o-audio-preview

spring.ai.openai.chat.options.output-modalities=text,audio
spring.ai.openai.chat.options.output-audio.voice=ALLOY
spring.ai.openai.chat.options.output-audio.format=WAV

实现

下方详细介绍了语音聊天机器人的 Java 实现,它使用音频输入和输出来创建一个会话式 AI 助手。它利用 Spring AI 与 OpenAI 模型的集成来实现与用户的无缝交互。

VoiceAssistantApplication

  • VoiceAssistantApplication 用作主应用程序。

  • CommandLineRunner bean 初始化聊天机器人

    • 使用 systemPrompt 配置 ChatClient 以获取上下文理解,并使用内存中的聊天记忆来存储会话历史。
    • Audio 工具用于录制用户的语音输入,并播放 AI 生成的音频响应。
  • 聊天循环: 在循环内部

    • 语音录制: audio.startRecording()audio.stopRecording() 方法处理录制过程,暂停以等待用户输入。
    • 处理 AI 响应: 用户消息通过 chatClient.prompt() 发送给 AI 模型。音频数据封装在 Media 对象中。
    • 响应处理: AI 生成的响应以文本形式检索,并使用 Audio.play() 方法播放为音频。

请参阅以下代码片段以了解实现细节

@Bean
public CommandLineRunner chatBot(ChatClient.Builder chatClientBuilder,
        @Value("${chatbot.prompt:classpath:/marvin.paranoid.android.txt}") Resource systemPrompt) {
    return args -> {

        var chatClient = chatClientBuilder.defaultSystem(systemPrompt)
            .defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory()))
            .build();

        try (Scanner scanner = new Scanner(System.in)) {

            Audio audio = new Audio();

            while (true) {                    
                audio.startRecording();
                System.out.print("Recording your question ... press <Enter> to stop! ");
                scanner.nextLine();
                audio.stopRecording();

                System.out.print("PROCESSING ... ");

                AssistantMessage response = chatClient.prompt()
                    .messages(new UserMessage("Please answer the questions in the audio input",
                            new Media(MediaType.parseMediaType("audio/wav"),
                                    new ByteArrayResource(audio.getLastRecording()))))
                    .call()
                    .chatResponse()
                    .getResult()
                    .getOutput();

                System.out.println("ASSISTANT: " + response.getContent());
                Audio.play(response.getMedia().get(0).getDataAsByteArray());
            }
        }
    };
}

用于捕获和播放音频的 Audio 工具是一个单独的类,它利用了原生的 Java Sound API

 ▗▄▄▖▗▄▄▖ ▗▄▄▖ ▗▄▄▄▖▗▖  ▗▖ ▗▄▄▖     ▗▄▖ ▗▄▄▄▖                                    
▐▌   ▐▌ ▐▌▐▌ ▐▌  █  ▐▛▚▖▐▌▐▌       ▐▌ ▐▌  █                                      
 ▝▀▚▖▐▛▀▘ ▐▛▀▚▖  █  ▐▌ ▝▜▌▐▌▝▜▌    ▐▛▀▜▌  █                                      
▗▄▄▞▘▐▌   ▐▌ ▐▌▗▄█▄▖▐▌  ▐▌▝▚▄▞▘    ▐▌ ▐▌▗▄█▄▖                                    
▗▄▄▖  ▗▄▖ ▗▄▄▖  ▗▄▖ ▗▖  ▗▖ ▗▄▖ ▗▄▄▄▖▗▄▄▄      ▗▄▖ ▗▖  ▗▖▗▄▄▄ ▗▄▄▖  ▗▄▖ ▗▄▄▄▖▗▄▄▄ 
▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌▐▛▚▖▐▌▐▌ ▐▌  █  ▐▌  █    ▐▌ ▐▌▐▛▚▖▐▌▐▌  █▐▌ ▐▌▐▌ ▐▌  █  ▐▌  █
▐▛▀▘ ▐▛▀▜▌▐▛▀▚▖▐▛▀▜▌▐▌ ▝▜▌▐▌ ▐▌  █  ▐▌  █    ▐▛▀▜▌▐▌ ▝▜▌▐▌  █▐▛▀▚▖▐▌ ▐▌  █  ▐▌  █
▐▌   ▐▌ ▐▌▐▌ ▐▌▐▌ ▐▌▐▌  ▐▌▝▚▄▞▘▗▄█▄▖▐▙▄▄▀    ▐▌ ▐▌▐▌  ▐▌▐▙▄▄▀▐▌ ▐▌▝▚▄▞▘▗▄█▄▖▐▙▄▄▀

2024-12-01T11:00:11.274+01:00  INFO 31297 --- [voice-assistant-chatbot] [           main] s.a.d.a.m.VoiceAssistantApplication      : Started VoiceAssistantApplication in 0.827 seconds (process running for 1.054)

Recording your question ... press <Enter> to stop!

完整的演示可在 GitHub 上获取:voice-assistant-chatbot

重要注意事项

  • 一小时音频输入大约相当于 128k token。
  • 该模型目前支持 modalities = ["text", "audio"]
  • 未来的更新可能会提供更灵活的模态控制。

结论

gpt-4o-audio-preview 模型为动态音频交互开辟了新的可能性,使开发者能够构建丰富的、AI 驱动的音频应用。

免责声明:API 功能和特性可能会发生变化。请参考最新的 OpenAI 和 Spring AI 文档获取更新信息。

获取 Spring 时事通讯

订阅 Spring 时事通讯以保持联系

订阅

抢先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获取支持

Tanzu Spring 提供对 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一个简单的订阅。

了解更多

即将举行的活动

查看 Spring 社区即将举行的所有活动。

查看全部