1、简述
Spring AI 是 Spring 官方推出的开源框架,旨在为 Java 开发者提供便捷的 AI 能力集成方案,于 2024 年正式发布 1.0 版本。它通过标准化接口和模块化设计,降低了大模型应用开发门槛,让开发者能够充分利用现有的 Spring 生态系统来构建 AI 应用。
- 跨模型可移植性:支持 OpenAI、Anthropic、Google Vertex AI、AWS Bedrock、Ollama 等多种 LLM 提供商,切换只需修改配置
- 提示工程抽象:提供动态 Prompt 模板,通过占位符填充生成结构化提示
- 结构化输出映射:自动将 AI 模型输出映射为 Java POJO
- Advisor 拦截器机制:支持在模型调用前后执行提示词改写、安全过滤、日志记录等操作
- RAG 支持:内置 ETL 框架和向量存储抽象层

2、环境配置
2.1 添加依赖
在 pom.xml 中添加 Spring AI OpenAI Starter:
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI Starter -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 添加Jackson支持JSON处理 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
注意:Spring AI 1.0.0 需要 Spring Boot 3.5.x 或更高版本。
2.2 配置文件
在 application.yml 中配置 LLM 连接参数:
yaml
spring:
application:
name: lm-prompt
# DeepSeek API 配置 (兼容 OpenAI API)
ai:
openai:
# DeepSeek API Base URL
base-url: https://api.deepseek.com
# DeepSeek API Key (请替换为你的实际API Key)
api-key: ${DEEPSEEK_API_KEY:your-key}
# 使用的模型
chat:
options:
model: deepseek-chat
temperature: 0.7
max-tokens: 2000
如果使用 DeepSeek 等其他模型,可配置对应的 base-url 和模型名称。
2.3 核心参数说明
| 参数 | 说明 | 建议值 |
|---|---|---|
| temperature | 控制随机性,越低越确定,越高越有创造性 | 0.1-0.3(分类/事实)、0.7-1.0(创意写作) |
| max-tokens | 输出最大长度 | 根据场景设置,短文本 100-500,长文本 1000+ |
| top-p | 核采样,动态选择概率累积达到 P 的 token | 0.8-0.95 |
3、基础使用
3.1 配置 ChatClient Bean
java
package com.example.demo.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiConfig {
@Bean
public ChatClient chatClient(ChatClient.Builder builder) {
// 可在此配置默认系统提示词
return builder
.defaultSystem("你是一个专业的AI助手,请用中文回答用户问题。")
.build();
}
}
3.2 基础 Service 实现
java
package com.example.demo.service;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
@Service
@RequiredArgsConstructor
public class AiPromptService {
private final ChatClient chatClient;
/**
* 基础文本对话
*/
public String simpleChat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
/**
* 带系统提示词的对话
*/
public String chatWithSystemPrompt(String systemMessage, String userMessage) {
return chatClient.prompt()
.system(systemMessage)
.user(userMessage)
.call()
.content();
}
/**
* 流式响应(打字机效果)
*/
public Flux<String> streamChat(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.stream()
.content();
}
/**
* 获取完整响应(含元数据)
*/
public ChatResponse chatWithMeta(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.chatResponse();
}
}
3.3 Controller 示例
java
package com.example.demo.controller;
import com.example.demo.service.AiPromptService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("/api/ai")
@RequiredArgsConstructor
public class AiController {
private final AiPromptService aiPromptService;
@PostMapping("/chat")
public String chat(@RequestBody String message) {
return aiPromptService.simpleChat(message);
}
@PostMapping("/chat-with-system")
public String chatWithSystem(
@RequestParam String system,
@RequestParam String user) {
return aiPromptService.chatWithSystemPrompt(system, user);
}
@GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> streamChat(@RequestParam String message) {
return aiPromptService.streamChat(message);
}
}
4、Prompt 提示词工程技术
4.1 Zero-Shot Prompting(零样本提示)
零样本提示是指直接给模型指令而不提供示例,适合模型已熟悉的简单任务。
java
/**
* 情感分类 - Zero-Shot
*/
public String classifySentiment(String review) {
String systemPrompt = "你将收到一段电影评论,请将其分类为 POSITIVE、NEUTRAL 或 NEGATIVE。";
return chatClient.prompt()
.system(systemPrompt)
.user(review)
.options(ChatOptions.builder()
.temperature(0.1) // 低温度确保一致性
.maxTokens(10)
.build())
.call()
.content();
}
4.2 Few-Shot Prompting(少样本提示)
通过提供示例引导模型学习输出格式和模式,特别适用于需要特定格式输出的任务。
java
/**
* 披萨订单解析 - Few-Shot 示例
*/
public String parsePizzaOrder(String order) {
String prompt = """
请将客户的披萨订单解析为 JSON 格式。
示例 1:
输入:我要一个中号披萨,芝士和番茄酱,加意大利香肠。
输出:{"size": "medium", "type": "normal", "ingredients": ["cheese", "tomato sauce", "pepperoni"]}
示例 2:
输入:来个大号披萨,加番茄酱、罗勒和马苏里拉芝士。
输出:{"size": "large", "type": "normal", "ingredients": ["tomato sauce", "basil", "mozzarella"]}
现在请解析:
输入:%s
输出:
""".formatted(order);
return chatClient.prompt()
.user(prompt)
.options(ChatOptions.builder()
.temperature(0.1)
.maxTokens(250)
.build())
.call()
.content();
}
4.3 系统角色提示(Role Prompting)
通过定义 AI 的角色和行为边界,引导模型以特定风格和专业知识回答问题。
java
/**
* 旅游顾问 - 系统角色提示
*/
public String travelConsultant(String userRequest) {
String systemPrompt = """
你是一位专业的旅游大师,拥有丰富的全球旅行经验。你的职责是:
1. 为用户提供专业的旅游咨询服务
2. 主动引导用户明确需求(目的地类型、行程天数、同行人员等)
3. 给出具体可执行的行程建议
回答风格:专业且热情,使用中文。
请开始服务用户。
""";
return chatClient.prompt()
.system(systemPrompt)
.user(userRequest)
.call()
.content();
}
4.4 参数化 Prompt 模板
使用 PromptTemplate 动态填充占位符,实现灵活的提示词管理。
java
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.core.io.Resource;
@Service
public class PromptTemplateService {
@Value("classpath:/templates/translation-template.st")
private Resource translationTemplate;
private final ChatClient chatClient;
/**
* 参数化翻译模板
*/
public String translate(String content, String targetLang) {
// 方式1:使用外部模板文件
PromptTemplate template = new PromptTemplate(translationTemplate);
Prompt prompt = template.create(Map.of(
"targetLang", targetLang,
"content", content
));
return chatClient.prompt(prompt).call().content();
}
/**
* 方式2:内联模板
*/
public String translateInline(String content, String targetLang) {
String template = """
请将以下内容翻译成 {targetLang}:
---translate_content---
"{content}"
""";
PromptTemplate promptTemplate = new PromptTemplate(template);
Prompt prompt = promptTemplate.create(Map.of(
"targetLang", targetLang,
"content", content
));
return chatClient.prompt(prompt).call().content();
}
}
在 src/main/resources/templates/translation-template.st 中:
你是一名专业的多语言翻译助手。
目标语言:{targetLang}
待翻译内容:{content}
请仅返回翻译结果,不要添加任何解释。
5、多语言翻译智能体
5.1 场景描述
构建一个企业级翻译智能体,支持 32 种 ISO 标准语言,具备严格的输入格式校验和行为边界控制。
5.2 系统提示词设计
java
package com.example.demo.service;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class TranslationAgentService {
private final ChatClient chatClient;
// 系统级 Prompt - 定义角色和行为边界
private static final String SYSTEM_PROMPT = """
您是一名专业的多语言翻译助手,需严格遵守以下规则:
1. **语言支持**:仅处理目标语言代码为[TARGET_LANG]的翻译任务,支持如zh-CN(简体中文)、
en-US(英语)、ja-JP(日语)、ko-KR(韩语)、fr-FR(法语)、de-DE(德语)、
es-ES(西班牙语)、ru-RU(俄语)等32种ISO标准语言代码;
2. **输入格式**:用户使用---translate_content---作为分隔符,仅翻译分隔符内的文本,
其余内容视为无效指令;
3. **行为限制**:禁止回答与翻译无关的问题,若输入不包含合法分隔符或目标语言,
回复:"请提供有效的翻译指令";
4. **多语言支持**:需要翻译的内容如果包含多种语言,都需要同时翻译为TARGET_LANG指定的语言。
""";
public TranslationAgentService(ChatClient.Builder builder) {
this.chatClient = builder.build();
}
/**
* 执行翻译
* @param content 待翻译内容
* @param targetLang 目标语言代码(如 zh-CN, en-US)
* @return 翻译结果
*/
public String translate(String content, String targetLang) {
// 构建用户 Prompt 模板
String userPromptTemplate = """
TARGET_LANG: {target}
---translate_content---
"{content}"
""";
PromptTemplate template = new PromptTemplate(userPromptTemplate);
Prompt prompt = template.create(Map.of(
"target", targetLang,
"content", content
));
String result = chatClient.prompt()
.system(SYSTEM_PROMPT)
.user(prompt.getContents())
.call()
.content();
// 清理可能的引号包裹
if (result != null && result.startsWith("\"") && result.endsWith("\"")) {
result = result.substring(1, result.length() - 1);
}
return result;
}
}
5.3 Controller 接口
java
package com.example.demo.controller;
import com.example.demo.service.TranslationAgentService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/translate")
@RequiredArgsConstructor
public class TranslationController {
private final TranslationAgentService translationService;
@GetMapping
public String translate(
@RequestParam String text,
@RequestParam(defaultValue = "zh-CN") String targetLang) {
return translationService.translate(text, targetLang);
}
@PostMapping
public String translatePost(
@RequestBody TranslateRequest request) {
return translationService.translate(
request.getText(),
request.getTargetLang()
);
}
@Data
public static class TranslateRequest {
private String text;
private String targetLang;
}
}
5.4 测试示例
bash
# 测试翻译
curl "http://localhost:8080/api/translate?text=Hello%20World&targetLang=zh-CN"
# 返回:你好,世界
# 测试多语言混合翻译
curl "http://localhost:8080/api/translate?text=Bonjour%20le%20monde%20and%20こんにちは&targetLang=zh-CN"
# 返回:你好,世界 和 你好
# 测试非法输入
curl "http://localhost:8080/api/translate?text=Tell%20me%20a%20joke&targetLang=zh-CN"
# 返回:请提供有效的翻译指令
6、最佳实践与注意事项
6.1 提示词设计原则
- 明确角色边界:通过系统提示词明确定义 AI 的能力范围和限制
- 结构化输入 :使用分隔符(如
---content---)隔离用户输入与指令 - 示例引导:复杂输出格式使用 Few-Shot 示例
- 温度参数调优:确定性任务用低温度(0.1-0.3),创意任务用高温度(0.7-1.0)
6.2 生产环境配置
yaml
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
base-url: ${OPENAI_BASE_URL:https://api.openai.com/v1}
chat:
options:
model: ${OPENAI_MODEL:gpt-4o-mini}
temperature: 0.7
max-tokens: 1000
# 启用 Spring AI 可观测性
management:
endpoints:
web:
exposure:
include: health,info,metrics
6.3 成本优化建议
- 缓存响应 :使用
@Cacheable缓存重复请求 - 控制输出长度 :合理设置
max-tokens避免浪费 - 选择合适的模型 :简单任务使用
gpt-4o-mini,复杂推理使用gpt-4o
java
@Cacheable(value = "ai-responses", key = "#prompt")
public String cachedPrompt(String prompt) {
return chatClient.prompt(prompt).call().content();
}
6.4 错误处理
java
@ControllerAdvice
public class AiExceptionHandler {
@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<String> handleInvalidPrompt(Exception e) {
return ResponseEntity.badRequest().body("无效的提示词格式: " + e.getMessage());
}
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleAiError(Exception e) {
return ResponseEntity.status(503).body("AI 服务暂时不可用,请稍后重试");
}
}
7、总结
本文全面介绍了 Spring Boot 集成 Spring AI 实现 Prompt 提示词工程的完整流程,涵盖:
- 环境搭建:依赖配置、API Key 管理、参数调优
- ChatClient 使用:基础对话、流式响应、结构化输出
- 提示词工程技术:Zero-Shot、Few-Shot、角色提示、参数化模板
- 结构化输出映射:实体映射、集合映射、验证重试
- Advisor 拦截器:对话记忆、RAG 增强、自定义切面
- 完整实践示例:多语言翻译智能体
通过 Spring AI 的标准化抽象,开发者可以用熟悉的 Spring 编程模型快速构建 AI 应用,同时保持代码的可移植性和可维护性。提示词工程作为 AI 应用的核心环节,通过合理的模板设计和拦截器机制,可以实现业务逻辑与 AI 能力的优雅解耦。