1、pom
<properties>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>3.2.0</spring-boot.version>
<spring-ai.version>1.0.0</spring-ai.version>
<spring-ai-alibaba.version>1.0.0.2</spring-ai-alibaba.version>
<jedis.version>5.2.0</jedis.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 阿里云通义千问(DashScope)starter -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!--对话记忆 chat-memory-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-autoconfigure-model-chat-memory</artifactId>
</dependency>
<!-- Spring AI JDBC 聊天记忆核心依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>
<!-- Spring Boot JDBC Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Spring AI Alibaba Redis 记忆 Starter -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-memory-redis</artifactId>
</dependency>
<!-- Jedis 客户端依赖 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 统一管理Spring AI依赖版本 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>${spring-ai-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- Spring AI 里程碑/快照仓库(必须配置,否则依赖无法下载) -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<releases>
<enabled>false</enabled>
</releases>
</repository>
</repositories>
2、yml
server:
port: 18081
spring:
ai:
dashscope:
api-key: sk-8718a83408d7443b9544cXXXXXXXX
chat:
memory:
repository:
jdbc:
initialize-schema: always
schema: classpath:/sql/schema-mysql.sql
memory:
# Redis 配置必须放在 spring.ai 下,层级要和你的 @Value 匹配
redis:
host: 192.168.91.165 # 你的 Redis 地址
port: 6379
timeout: 5000
# password: 123456 # 有密码再打开
datasource:
url: jdbc:mysql://192.168.91.165:3306/springai?useSSL=false&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
logging:
level:
org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor: debug
#org.springframework.ai.chat.client.advisor: debug
3、pojo
public record Address(
String name, // 收件人姓名
String phone, // 联系电话
String province, // 省
String city, // 市
String district, // 区/县
String detail // 详细地址
) {}
4、controller
import com.sb.dashscope18081.pojo.Address;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@RequestMapping("/openai")
@ResponseBody
@Controller
public class ChatclientStructuredOutputController {
@Autowired
private ChatClient.Builder chatClientBuilder;
/**
* 以Boolean为例,在agent中可以用于判定用于的内容2个分支,不同的分支走不同的逻辑
* @return
*/
@GetMapping("/simple/chatclientsoutput")
public String chatclient () {
// 构建ChatClient并调用
ChatClient chatClient = chatClientBuilder
.build();
String content ="";
Boolean isComplain = chatClient
.prompt()
.system("""
请判断用户信息是否表达了投诉意图?
只能用 true 或 false 回答,不要输出多余内容
""")
.user("你们家的快递迟迟不到,我要退货!")
.call()
.entity(Boolean.class);
// 分支逻辑
if (Boolean.TRUE.equals(isComplain)) {
content="用户是投诉, 转接人工客服!";
System.out.println(content);
} else {
content="用户不是投诉, 自动流转客服机器人。";
System.out.println(content);
// todo 继续调用 客服ChatClient进行对话
}
return "【以Boolean为例】"+content;
}
/**
* 以Boolean为例,在agent中可以用于判定用于的内容2个分支,不同的分支走不同的逻辑
* @return
*/
@GetMapping("/simple/chatclientsoutput2")
public String chatclient2 () {
// 构建ChatClient并调用
ChatClient chatClient = chatClientBuilder
.build();
String content ="";
Boolean isComplain = chatClient
.prompt()
.system("""
请判断用户信息是否表达了投诉意图?
只能用 true 或 false 回答,不要输出多余内容
""")
.user("你好!")
.call()
.entity(Boolean.class);
// 分支逻辑
if (Boolean.TRUE.equals(isComplain)) {
content="用户是投诉, 转接人工客服!";
System.out.println(content);
} else {
content="用户不是投诉, 自动流转客服机器人。";
System.out.println(content);
// todo 继续调用 客服ChatClient进行对话
}
return "【以Boolean为例】"+content;
}
/**
* 从文本提取地址信息address
* @return
*/
@GetMapping("/simple/chatclientaddress")
public String chatclientaddress () {
// 构建ChatClient并调用
ChatClient chatClient = chatClientBuilder
.build();
String content ="";
Address address = chatClient.prompt()
.system("""
请从下面这条文本中提取收货信息
""")
.user("收货人:张三,电话13588888888,地址:浙江省杭州市西湖区文一西路100号8幢202室")
.call()
.entity(Address.class);
content=address.toString();
System.out.println(content);
return "【从文本提取地址信息address】"+content;
}
}
5、
5.1
http://localhost:18081/openai/simple/chatclientsoutput


5.2
http://localhost:18081/openai/simple/chatclientsoutput2


5.3


http://localhost:18081/openai/simple/chatclientaddress



浙公网安备 33010602011771号