030-Spring AI Alibaba OpenAI Chat 功能完整案例

本案例将引导您一步步构建一个 Spring Boot 应用,演示如何利用 Spring AI Alibaba 集成 OpenAI Chat 模型,实现多种对话交互方式,包括简单对话、流式对话、自定义参数对话和 JSON 模式对话。
1. 案例目标
我们将创建一个包含多种对话交互方式的 Web 应用:
- 简单对话 (
/openai/chat-model/simple/chat):最基本的 OpenAI 对话调用方式,没有任何额外参数配置。 - 流式对话 (
/openai/chat-model/stream/chat):实现打字机效果的流式输出,提升用户体验。 - 自定义参数对话 (
/openai/chat-model/custom/chat):通过编程方式自定义大模型参数,如温度、最大令牌数等。 - JSON 模式对话 (
/openai/chat-model/custom/chat/json-mode):使大模型返回标准 JSON 格式数据,便于程序处理。 - ChatClient 简单对话 (
/openai/chat-client/simple/chat):使用 Spring AI 的高级 ChatClient API 进行对话。 - ChatClient 流式对话 (
/openai/chat-client/stream/chat):使用 ChatClient API 实现流式输出。 - ChatClient 流式响应 (
/openai/chat-client/stream/response):使用 Server-Sent Events (SSE) 格式返回流式响应。
2. 技术栈与核心依赖
- Spring Boot 3.x
- Spring AI (用于对接 OpenAI 模型)
- Maven (项目构建工具)
在 pom.xml 中,你需要引入以下核心依赖:
<dependencies>
<!-- Spring Web 用于构建 RESTful API -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI 启动器 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
3. 项目配置
在 src/main/resources/application.yml 文件中,配置你的 OpenAI API Key 和基础 URL。
server:
port: 10003
spring:
application:
name: spring-ai-alibaba-openai-chat-model-example
ai:
openai:
api-key: ${OPENAI_API_KEY}
base-url: https://api.openai-hk.com
# 兼容其他OpenAI格式的大模型配置示例
# 以下为字节火山引擎·方舟大模型(Ark LLM)配置示例
# ai:
# openai:
# # API密钥配置
# api-key: ${OPENAI_API_KEY}
# # 方舟大模型API地址
# base-url: https://ark.cn-beijing.volces.com/api/
# chat:
# options:
# # 模型ID,需要替换为实际的接入点ID
# model: ${OPENAI_MODEL_ID}
# # Chat接口路径,与OpenAI接口保持一致
# completions-path: /v3/chat/completions
重要提示:请将 OPENAI_API_KEY 环境变量设置为你从 OpenAI 获取的有效 API Key。你也可以直接将其写在配置文件中,但这不推荐用于生产环境。
4. 编写 Java 代码
4.1 OpenAiChatModelApplication.java
Spring Boot 主程序类。
package com.alibaba.cloud.ai.example.chat.openai;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OpenAiChatModelApplication {
public static void main(String[] args) {
SpringApplication.run(OpenAiChatModelApplication.class, args);
}
}
4.2 OpenAiChatModelController.java
实现基于 ChatModel 的对话功能。
package com.alibaba.cloud.ai.example.chat.openai.controller;
import jakarta.servlet.http.HttpServletResponse;
import reactor.core.publisher.Flux;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.ai.openai.api.ResponseFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/openai/chat-model")
public class OpenAiChatModelController {
private static final String DEFAULT_PROMPT = "你好,介绍下你自己吧。";
private static final String JSON_OUTPUT_PROMPT = "how can I solve 8x + 7 = -23";
private final ChatModel openAiChatModel;
public OpenAiChatModelController(ChatModel chatModel) {
this.openAiChatModel = chatModel;
}
/**
* 最简单的使用方式,没有任何 LLMs 参数注入。
*
* @return String types.
*/
@GetMapping("/simple/chat")
public String simpleChat() {
return openAiChatModel.call(new Prompt(DEFAULT_PROMPT)).getResult().getOutput().getText();
}
/**
* Stream 流式调用。可以使大模型的输出信息实现打字机效果。
*
* @return Flux<String> types.
*/
@GetMapping("/stream/chat")
public Flux<String> streamChat(HttpServletResponse response) {
// 避免返回乱码
response.setCharacterEncoding("UTF-8");
Flux<ChatResponse> chatResponseFlux = openAiChatModel.stream(new Prompt(DEFAULT_PROMPT));
return chatResponseFlux.map(resp -> resp.getResult().getOutput().getText());
}
/**
* 使用编程方式自定义 LLMs ChatOptions 参数, {@link org.springframework.ai.openai.OpenAiChatOptions}
* 优先级高于在 application.yml 中配置的 LLMs 参数!
*/
@GetMapping("/custom/chat")
public String customChat() {
OpenAiChatOptions customOptions = OpenAiChatOptions.builder()
.topP(0.7)
.model("gpt-4o")
.maxTokens(1000)
.temperature(0.8)
.build();
return openAiChatModel.call(new Prompt(DEFAULT_PROMPT, customOptions)).getResult().getOutput().getText();
}
/**
* JSON mode:通过设置 response_format 参数为 JSON 类型,使大模型返回标准的 JSON 格式数据。
*
* @return JSON String.
*/
@GetMapping("/custom/chat/json-mode")
public String jsonChat() {
String jsonSchema = """
{
"type": "object",
"properties": {
"steps": {
"type": "array",
"items": {
"type": "object",
"properties": {
"explanation": { "type": "string" },
"output": { "type": "string" }
},
"required": ["explanation", "output"],
"additionalProperties": false
}
},
"final_answer": { "type": "string" }
},
"required": ["steps", "final_answer"],
"additionalProperties": false
}
""";
OpenAiChatOptions customOptions = OpenAiChatOptions.builder()
.topP(0.7)
.model("gpt-4o")
.temperature(0.4)
.maxTokens(4096)
.responseFormat(new ResponseFormat(ResponseFormat.Type.JSON_SCHEMA, jsonSchema))
.build();
return openAiChatModel.call(new Prompt(JSON_OUTPUT_PROMPT, customOptions)).getResult().getOutput().getText();
}
}
4.3 OpenAiChatClientController.java
实现基于 ChatClient 的对话功能。
package com.alibaba.cloud.ai.example.chat.openai.controller;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.RequestParam;
import reactor.core.publisher.Flux;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/openai/chat-client")
public class OpenAiChatClientController {
private static final String DEFAULT_PROMPT = "你好,介绍下你自己!";
private final ChatClient openAiChatClient;
private final ChatModel chatModel;
public OpenAiChatClientController(ChatModel chatModel) {
this.chatModel = chatModel;
// 构造时,可以设置 ChatClient 的参数
// {@link org.springframework.ai.chat.client.ChatClient};
this.openAiChatClient = ChatClient.builder(chatModel)
// 实现 Chat Memory 的 Advisor
// 在使用 Chat Memory 时,需要指定对话 ID,以便 Spring AI 处理上下文。
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder().build()).build()
)
// 实现 Logger 的 Advisor
.defaultAdvisors(
new SimpleLoggerAdvisor()
)
// 设置 ChatClient 中 ChatModel 的 Options 参数
.defaultOptions(
OpenAiChatOptions.builder()
.topP(0.7)
.build()
)
.build();
}
// 也可以使用如下的方式注入 ChatClient
// public OpenAIChatClientController(ChatClient.Builder chatClientBuilder) {
//
// this.openAiChatClient = chatClientBuilder.build();
// }
/**
* ChatClient 简单调用
*/
@GetMapping("/simple/chat")
public String simpleChat() {
return openAiChatClient.prompt(DEFAULT_PROMPT).call().content();
}
/**
* ChatClient 流式调用
*/
@GetMapping("/stream/chat")
public Flux<String> streamChat(HttpServletResponse response) {
response.setCharacterEncoding("UTF-8");
return openAiChatClient.prompt(DEFAULT_PROMPT).stream().content();
}
/**
* ChatClient 流式响应
*/
@GetMapping(value = "/stream/response", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<ServerSentEvent<String>> simpleChat(@RequestParam String message) {
return openAiChatClient.prompt()
.user(message)
.stream()
.content()
.map(content -> ServerSentEvent.<String>builder()
.data(content)
.build());
}
}
5. 运行与测试
- 启动应用:运行你的 Spring Boot 主程序。
- 使用浏览器或 API 工具(如 Postman, curl)进行测试。
测试 1:简单对话
访问以下 URL,进行最简单的对话测试。
http://localhost:10003/openai/chat-model/simple/chat
预期响应:
你好!我是一个由人工智能驱动的语言模型,旨在提供信息、回答问题和帮助解决各种问题。我的能力包括回答问题、提供解释、协助学习和创作内容等。如果你有任何问题或需要帮助,请随时告诉我!
测试 2:流式对话
访问以下 URL,体验流式输出的打字机效果。
http://localhost:10003/openai/chat-model/stream/chat
预期响应:流式文本输出,逐字显示响应内容。
测试 3:自定义参数对话
访问以下 URL,测试自定义参数的对话效果。
http://localhost:10003/openai/chat-model/custom/chat
预期响应:使用自定义参数(温度 0.8、topP 0.7、最大令牌数 1000、gpt-4o 模型)生成的响应。
测试 4:JSON 模式对话
访问以下 URL,测试 JSON 模式输出。
http://localhost:10003/openai/chat-model/custom/chat/json-mode
预期响应:
{
"steps": [
{
"explanation": "首先,我们需要解方程 8x + 7 = -23。第一步是将常数项移到等式右边。",
"output": "8x = -23 - 7"
},
{
"explanation": "计算右边的值:-23 - 7 = -30。",
"output": "8x = -30"
},
{
"explanation": "接下来,我们需要解出 x 的值。将等式两边同时除以 8。",
"output": "x = -30 / 8"
},
{
"explanation": "计算 -30 除以 8 的结果。",
"output": "x = -3.75"
}
],
"final_answer": "方程 8x + 7 = -23 的解是 x = -3.75"
}
测试 5:ChatClient 简单对话
访问以下 URL,测试基于 ChatClient 的简单对话。
http://localhost:10003/openai/chat-client/simple/chat
预期响应:使用 ChatClient API 生成的响应,与简单对话类似但内部实现不同。
测试 6:ChatClient 流式对话
访问以下 URL,测试基于 ChatClient 的流式对话。
http://localhost:10003/openai/chat-client/stream/chat
预期响应:使用 ChatClient API 实现的流式文本输出。
测试 7:ChatClient 流式响应
访问以下 URL,测试基于 ChatClient 的 SSE 格式流式响应。
http://localhost:10003/openai/chat-client/stream/response?message=你好,请介绍一下Spring AI
预期响应:以 SSE 格式返回的流式响应,适合前端直接使用。
6. 实现思路与扩展建议
实现思路
本案例展示了两种不同的 OpenAI 对话实现方式:
- ChatModel 方式:直接使用 Spring AI 的底层模型接口,提供更细粒度的控制,适合需要精确控制模型参数的场景。
- ChatClient 方式:使用 Spring AI 的高级客户端 API,提供了更简洁的编程模型和内置功能(如聊天记忆、日志记录等),适合大多数应用场景。
两种方式都支持:
- 简单对话:一次性返回完整响应。
- 流式对话:逐步返回响应内容,实现打字机效果。
- 自定义参数:通过编程方式设置模型参数,如温度、topP、最大令牌数等。
- 特殊模式:如 JSON 模式,强制模型返回结构化数据。
扩展建议
- 对话记忆增强:可以扩展 ChatClient 的记忆功能,实现更持久化的对话历史存储,如使用数据库或 Redis 存储对话历史。
- 多模型支持:通过配置不同的模型参数,实现同一应用中支持多种模型(如 GPT-3.5、GPT-4、Claude 等)的切换。
- 异步处理:对于耗时较长的对话请求,可以实现异步处理机制,避免阻塞主线程。
- 错误处理与重试:增加完善的错误处理和自动重试机制,提高应用稳定性。
- API 密钥管理:实现更安全的 API 密钥管理机制,如动态加载、轮换等。
- 请求限流:实现请求限流机制,防止 API 调用过于频繁导致超出配额。
- 成本监控:添加 API 调用成本监控功能,帮助控制使用成本。
- 内容过滤:实现内容安全过滤,防止不当内容的生成和传播。
更多推荐

所有评论(0)