本文目录导读:

我将为您提供一个完整的Java Spring AI案例,展示如何使用Spring AI框架集成AI功能。
项目结构
spring-ai-demo/
├── pom.xml
├── src/main/java/com/example/springaidemo/
│ ├── SpringAiDemoApplication.java
│ ├── controller/
│ │ ├── ChatController.java
│ │ └── ImageController.java
│ ├── service/
│ │ ├── AIService.java
│ │ └── AIServiceImpl.java
│ └── config/
│ └── AiConfig.java
└── src/main/resources/
└── application.yml
pom.xml 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-ai-demo</artifactId>
<version>1.0.0</version>
<name>spring-ai-demo</name>
<description>Spring AI Demo Project</description>
<properties>
<java.version>17</java.version>
<spring-ai.version>0.8.1</spring-ai.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI OpenAI -->
<dependency>
<groupId>org.springframework.experimental.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- Spring AI Azure OpenAI -->
<dependency>
<groupId>org.springframework.experimental.ai</groupId>
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
<version>${spring-ai.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</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>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
主应用类
package com.example.springaidemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringAiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringAiDemoApplication.class, args);
}
}
配置文件 application.yml
server:
port: 8080
spring:
application:
name: spring-ai-demo
# OpenAI 配置
ai:
openai:
api-key: ${OPENAI_API_KEY:your-api-key-here}
chat:
options:
model: gpt-3.5-turbo
temperature: 0.7
max-tokens: 1000
# Azure OpenAI 配置(可选)
azure:
openai:
endpoint: ${AZURE_OPENAI_ENDPOINT:}
api-key: ${AZURE_OPENAI_API_KEY:}
chat:
options:
deployment-name: gpt-35-turbo
temperature: 0.7
max-tokens: 1000
# 日志配置
logging:
level:
com.example: DEBUG
org.springframework.ai: DEBUG
AI配置类
package com.example.springaidemo.config;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.image.ImageClient;
import org.springframework.ai.openai.OpenAiChatClient;
import org.springframework.ai.openai.OpenAiImageClient;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AiConfig {
@Value("${spring.ai.openai.api-key}")
private String openAiApiKey;
@Bean
public OpenAiApi openAiApi() {
return new OpenAiApi(openAiApiKey);
}
@Bean
public ChatClient chatClient(OpenAiApi openAiApi) {
return new OpenAiChatClient(openAiApi);
}
@Bean
public ImageClient imageClient(OpenAiApi openAiApi) {
return new OpenAiImageClient(openAiApi);
}
}
AI服务接口
package com.example.springaidemo.service;
import java.util.List;
import java.util.Map;
public interface AIService {
/**
* 发送聊天消息
*/
String chat(String message);
/**
* 带上下文的聊天
*/
String chatWithContext(String userMessage, String conversationId);
/**
* 生成代码
*/
String generateCode(String description, String language);
/**
* 文本分析
*/
Map<String, Object> analyzeText(String text);
/**
* 生成图片描述
*/
String generateImageDescription(String prompt);
/**
* 多轮对话
*/
List<String> multiTurnChat(List<String> messages);
}
AI服务实现类
package com.example.springaidemo.service.impl;
import com.example.springaidemo.service.AIService;
import org.springframework.ai.chat.ChatClient;
import org.springframework.ai.chat.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.system.SystemPromptTemplate;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@Service
public class AIServiceImpl implements AIService {
@Autowired
private ChatClient chatClient;
// 存储对话上下文
private final Map<String, List<Message>> conversationContexts = new ConcurrentHashMap<>();
@Override
public String chat(String message) {
try {
Prompt prompt = new Prompt(new UserMessage(message));
ChatResponse response = chatClient.call(prompt);
return response.getResult().getOutput().getContent();
} catch (Exception e) {
return "抱歉,处理您的请求时出现错误: " + e.getMessage();
}
}
@Override
public String chatWithContext(String userMessage, String conversationId) {
List<Message> messages = conversationContexts
.computeIfAbsent(conversationId, k -> new ArrayList<>());
// 添加用户消息
messages.add(new UserMessage(userMessage));
// 保持上下文在合理范围内
if (messages.size() > 10) {
messages = messages.subList(messages.size() - 10, messages.size());
}
Prompt prompt = new Prompt(messages);
ChatResponse response = chatClient.call(prompt);
// 添加AI响应到上下文
String aiResponse = response.getResult().getOutput().getContent();
messages.add(new AssistantMessage(aiResponse));
conversationContexts.put(conversationId, messages);
return aiResponse;
}
@Override
public String generateCode(String description, String language) {
String systemPrompt = String.format(
"你是一个专业的%s程序员,请根据描述生成高质量的代码,包含必要的注释和错误处理。",
language
);
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);
Message systemMessage = systemPromptTemplate.createMessage();
Prompt prompt = new Prompt(List.of(systemMessage, new UserMessage(description)));
ChatResponse response = chatClient.call(prompt);
return response.getResult().getOutput().getContent();
}
@Override
public Map<String, Object> analyzeText(String text) {
String analysisPrompt = """
请分析以下文本,并以JSON格式返回分析结果,包含:
1. 情感分析(正面/负面/中性)
2. 关键词
3. 文本摘要
4. 语言风格
文本:%s
""".formatted(text);
Prompt prompt = new Prompt(new UserMessage(analysisPrompt));
ChatResponse response = chatClient.call(prompt);
Map<String, Object> result = new HashMap<>();
result.put("analysis", response.getResult().getOutput().getContent());
result.put("originalText", text);
result.put("timestamp", System.currentTimeMillis());
return result;
}
@Override
public String generateImageDescription(String prompt) {
String imagePrompt = String.format(
"请为以下主题生成详细的图片描述,用于AI图片生成:%s\n" +
"包含:场景、色彩、构图、风格等详细信息",
prompt
);
Prompt aiPrompt = new Prompt(new UserMessage(imagePrompt));
ChatResponse response = chatClient.call(aiPrompt);
return response.getResult().getOutput().getContent();
}
@Override
public List<String> multiTurnChat(List<String> messages) {
List<Message> chatMessages = new ArrayList<>();
for (String message : messages) {
chatMessages.add(new UserMessage(message));
}
Prompt prompt = new Prompt(chatMessages);
ChatResponse response = chatClient.call(prompt);
List<String> responses = new ArrayList<>();
responses.add(response.getResult().getOutput().getContent());
return responses;
}
}
聊天控制器
package com.example.springaidemo.controller;
import com.example.springaidemo.service.AIService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/ai")
public class ChatController {
@Autowired
private AIService aiService;
/**
* 简单聊天
*/
@PostMapping("/chat")
public ResponseEntity<String> chat(@RequestBody Map<String, String> request) {
String message = request.get("message");
if (message == null || message.isEmpty()) {
return ResponseEntity.badRequest().body("消息不能为空");
}
String response = aiService.chat(message);
return ResponseEntity.ok(response);
}
/**
* 带上下文的对话
*/
@PostMapping("/chat/context")
public ResponseEntity<String> chatWithContext(@RequestBody Map<String, String> request) {
String message = request.get("message");
String conversationId = request.getOrDefault("conversationId", "default");
if (message == null || message.isEmpty()) {
return ResponseEntity.badRequest().body("消息不能为空");
}
String response = aiService.chatWithContext(message, conversationId);
return ResponseEntity.ok(response);
}
/**
* 代码生成
*/
@PostMapping("/code")
public ResponseEntity<String> generateCode(@RequestBody Map<String, String> request) {
String description = request.get("description");
String language = request.getOrDefault("language", "Java");
if (description == null || description.isEmpty()) {
return ResponseEntity.badRequest().body("描述不能为空");
}
String code = aiService.generateCode(description, language);
return ResponseEntity.ok(code);
}
/**
* 文本分析
*/
@PostMapping("/analyze")
public ResponseEntity<Map<String, Object>> analyzeText(@RequestBody Map<String, String> request) {
String text = request.get("text");
if (text == null || text.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of("error", "文本不能为空"));
}
Map<String, Object> analysis = aiService.analyzeText(text);
return ResponseEntity.ok(analysis);
}
/**
* 图片描述生成
*/
@PostMapping("/image-description")
public ResponseEntity<String> generateImageDescription(@RequestBody Map<String, String> request) {
String prompt = request.get("prompt");
if (prompt == null || prompt.isEmpty()) {
return ResponseEntity.badRequest().body("提示词不能为空");
}
String description = aiService.generateImageDescription(prompt);
return ResponseEntity.ok(description);
}
/**
* 多轮对话
*/
@PostMapping("/multi-turn")
public ResponseEntity<List<String>> multiTurnChat(@RequestBody Map<String, Object> request) {
@SuppressWarnings("unchecked")
List<String> messages = (List<String>) request.get("messages");
if (messages == null || messages.isEmpty()) {
return ResponseEntity.badRequest().body(List.of("消息列表不能为空"));
}
List<String> responses = aiService.multiTurnChat(messages);
return ResponseEntity.ok(responses);
}
/**
* 健康检查
*/
@GetMapping("/health")
public ResponseEntity<String> health() {
return ResponseEntity.ok("AI Service is running!");
}
}
图片生成控制器
package com.example.springaidemo.controller;
import org.springframework.ai.image.ImageClient;
import org.springframework.ai.image.ImageGeneration;
import org.springframework.ai.image.ImagePrompt;
import org.springframework.ai.image.ImageResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/ai/image")
public class ImageController {
@Autowired
private ImageClient imageClient;
/**
* 生成图片
*/
@PostMapping("/generate")
public ResponseEntity<Map<String, Object>> generateImage(@RequestBody Map<String, String> request) {
String prompt = request.get("prompt");
String size = request.getOrDefault("size", "1024x1024");
int n = Integer.parseInt(request.getOrDefault("n", "1"));
if (prompt == null || prompt.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of("error", "提示词不能为空"));
}
try {
ImagePrompt imagePrompt = new ImagePrompt(prompt, size, n);
ImageResponse response = imageClient.call(imagePrompt);
Map<String, Object> result = Map.of(
"success", true,
"images", response.getResults().stream()
.map(ImageGeneration::getOutput)
.toList()
);
return ResponseEntity.ok(result);
} catch (Exception e) {
return ResponseEntity.internalServerError()
.body(Map.of("error", "图片生成失败: " + e.getMessage()));
}
}
}
测试类
package com.example.springaidemo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import java.util.Map;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class SpringAiDemoApplicationTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
void testChatEndpoint() {
Map<String, String> request = Map.of("message", "你好,请介绍一下你自己");
ResponseEntity<String> response = restTemplate.postForEntity(
"/api/ai/chat",
request,
String.class
);
System.out.println("Chat Response: " + response.getBody());
}
@Test
void testCodeGeneration() {
Map<String, String> request = Map.of(
"description", "请生成一个Spring Boot的Hello World控制器",
"language", "Java"
);
ResponseEntity<String> response = restTemplate.postForEntity(
"/api/ai/code",
request,
String.class
);
System.out.println("Generated Code: " + response.getBody());
}
@Test
void testHealthCheck() {
ResponseEntity<String> response = restTemplate.getForEntity(
"/api/ai/health",
String.class
);
System.out.println("Health: " + response.getBody());
}
}
使用说明
配置API密钥
在 application.yml 中设置您的OpenAI API密钥:
spring:
ai:
openai:
api-key: your-actual-api-key-here
或者在启动时设置环境变量:
export OPENAI_API_KEY=your-actual-api-key-here
启动应用
mvn spring-boot:run
API测试示例
# 聊天
curl -X POST http://localhost:8080/api/ai/chat \
-H "Content-Type: application/json" \
-d '{"message": "请用中文回答:什么是Spring框架?"}'
# 代码生成
curl -X POST http://localhost:8080/api/ai/code \
-H "Content-Type: application/json" \
-d '{"description": "创建REST API控制器", "language": "Java"}'
# 文本分析
curl -X POST http://localhost:8080/api/ai/analyze \
-H "Content-Type: application/json" \
-d '{"text": "今天的天气真好,适合出去散步!"}'
# 带上下文的对话
curl -X POST http://localhost:8080/api/ai/chat/context \
-H "Content-Type: application/json" \
-d '{"message": "我的名字是张三", "conversationId": "user123"}'
curl -X POST http://localhost:8080/api/ai/chat/context \
-H "Content-Type: application/json" \
-d '{"message": "你还记得我的名字吗?", "conversationId": "user123"}'
这个案例展示了Spring AI的核心功能,包括:
- 聊天对话:支持简单对话和带上下文的对话
- 代码生成:根据描述生成指定语言的代码
- 文本分析:情感分析、关键词提取等
- 图片相关:生成图片描述和实际图片
- 多轮对话:支持连续的对话管理
- 错误处理:完善的异常处理和响应
您可以根据实际需求扩展更多功能,如流式输出、本地模型支持、向量数据库集成等。