1. 项目概述
这个项目实现了一个志愿填报系统的AI智能客服功能,核心目标是让AI客服能够主动询问用户是否需要预约一对一指导服务,并完成预约信息的收集和存储。整个方案基于Spring Boot后端框架,结合大模型的Tools工具(原Function Calling功能)实现自然语言交互与业务逻辑的无缝对接。
作为一名有多年全栈开发经验的工程师,我认为这种AI与传统业务系统结合的方案特别适合需要自然语言交互的场景。志愿填报本身就是个信息密集、决策复杂的领域,家长和学生往往需要反复咨询。通过AI客服自动处理常规咨询和预约,可以大幅减轻人工客服压力。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 准备工作
2.1 数据库设计
首先需要创建预约表,这是整个功能的数据基础。表结构设计考虑了志愿填报咨询的核心要素:
sql复制CREATE TABLE reservation (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL COMMENT '预约人姓名',
gender VARCHAR(10) NOT NULL COMMENT '预约人性别',
phone VARCHAR(20) NOT NULL COMMENT '预约人手机号',
time DATETIME NOT NULL COMMENT '预计沟通时间',
province VARCHAR(50) NOT NULL COMMENT '省份',
score INT NOT NULL COMMENT '预估分数'
);
这个设计有几个关键点:
- 手机号设为NOT NULL,因为它是查询的主要依据
- 预估分数用INT类型,方便后续分数段统计
- 沟通时间精确到秒,避免预约冲突
2.2 实体类定义
实体类与数据库表严格对应,使用了Lombok简化代码:
java复制@Data
@NoArgsConstructor
@AllArgsConstructor
public class Reservation {
private Integer id;
private String name;
private String gender;
private String phone;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time;
private String province;
private Integer score;
}
特别要注意时间字段的@JsonFormat注解,这确保了前后端时间格式的统一。在实际项目中,我建议同时配置全局的日期格式化,避免每个字段单独声明。
2.3 三层架构实现
2.3.1 Mapper层
使用MyBatis注解方式实现SQL映射:
java复制@Mapper
public interface ReservationMapper {
@Insert("insert into reservation values (null, #{name}, #{gender}, #{phone}, #{time}, #{province}, #{score})")
int addOneReservation(Reservation reservation);
@Select("select * from reservation where phone = #{phone}")
Reservation queryOneReservationByPhone(String phone);
}
这里有两个优化建议:
- 生产环境应该添加手机号的唯一索引,避免重复预约
- 查询接口应考虑分页,虽然本例中单个用户预约次数有限
2.3.2 Service层
业务逻辑层封装了数据库操作,并处理异常情况:
java复制@Service
public class ReservationServiceImpl implements ReservationService {
@Autowired
private ReservationMapper reservationMapper;
public Result addOneReservation(Reservation reservation) {
try {
int i = reservationMapper.addOneReservation(reservation);
return new Result(200, "成功添加"+i+"条预约信息~");
} catch(Exception e) {
return new Result(500, "添加失败,错误信息:"+e.getMessage());
}
}
public Result queryOneReservationByPhone(String phone) {
try {
Reservation reservation = reservationMapper.queryOneReservationByPhone(phone);
return new Result(200, "查询成功", reservation);
} catch(Exception e) {
return new Result(500, "查询失败,错误信息:"+e.getMessage());
}
}
}
在实际项目中,我通常会:
- 对手机号格式进行校验
- 对预约时间做冲突检查
- 添加日志记录关键操作
2.3.3 Controller层
提供RESTful API接口:
java复制@RestController
@RequestMapping("/api/reservation")
public class ReservationController {
@Autowired
private ReservationService reservationService;
@PostMapping("/addOneReservation")
public Result addOneReservation(@RequestBody Reservation reservation) {
return reservationService.addOneReservation(reservation);
}
@GetMapping("/queryReservationByPhone")
public Result queryOneReservationByPhone(String phone) {
return reservationService.queryOneReservationByPhone(phone);
}
}
建议添加Swagger文档注解,方便前端对接。同时应该考虑:
- 接口权限控制
- 请求参数校验
- 防刷限流措施
3. Tools工具集成原理
Tools工具(原Function Calling)的工作原理可以用以下流程描述:
- 用户向AI客服提出问题
- 大模型判断是否需要调用工具
- 如需调用,大模型生成工具调用请求
- 系统执行具体工具方法
- 将执行结果返回给大模型
- 大模型组织自然语言回复用户
在这个过程中,开发者只需要:
- 定义工具方法
- 配置系统提示词
- 处理工具执行结果
LangChain4j等框架会处理中间的复杂流程,包括:
- 工具描述的自动生成
- 参数类型的转换
- 调用结果的格式化
4. 具体实现细节
4.1 系统提示词配置
好的提示词是AI客服表现的关键。本例中的提示词实现了:
- 身份设定:志愿填报助手
- 业务引导:主动询问预约需求
- 信息收集:明确需要哪些字段
java复制String systemPrompt = """
你是一个专业的AI智能志愿填报助手,负责解答高考志愿填报相关问题。
在每次回答完问题后,你都需要主动询问:
"您是否需要预约一对一志愿填报指导服务?如需预约请提供以下信息:
- 考生姓名
- 考生性别
- 考生手机号
- 期望沟通时间(格式:yyyy-MM-dd HH:mm:ss)
- 所在省份
- 预估高考分数"
""";
提示词设计经验:
- 用明确的分隔符(如引号)界定提示词范围
- 重要信息放在前面
- 给出具体的格式要求
- 避免歧义表述
4.2 工具方法实现
工具类使用@Tool和@P注解:
java复制@Component
public class ReservationTool {
@Autowired
private ReservationService reservationService;
@Tool("预约志愿填报服务")
public Result addReservation(
@P("考生姓名") String name,
@P("考生性别") String gender,
@P("考生手机号") String phone,
@P("预约沟通时间,格式为:yyyy-MM-dd HH:mm:ss") String time,
@P("考生所在省份") String province,
@P("考生预估分数") Integer score) {
Reservation reservation = new Reservation(null, name, gender, phone, LocalDateTime.parse(time), province, score);
return reservationService.addOneReservation(reservation);
}
@Tool("根据手机号查询预约报考服务单")
public Result queryReservationByPhone(@P("考生手机号") String phone) {
return reservationService.queryOneReservationByPhone(phone);
}
}
工具方法设计的几个要点:
- 方法名要有意义,便于调试
- 参数描述要详细准确
- 保持方法单一职责
- 处理好参数类型转换
4.3 工具配置
将工具注入AI服务:
java复制@Bean
public AiServices<AiAssistant> aiServices(ReservationTool reservationTool) {
return AiServices.builder(AiAssistant.class)
.tools(reservationTool)
.chatLanguageModel(chatLanguageModel)
.build();
}
配置时的注意事项:
- 确保工具类被Spring管理
- 检查模型参数设置
- 考虑添加监控和日志
- 测试工具发现机制
5. 测试与优化
5.1 添加预约测试
测试流程:
- 用户发起咨询
- AI回复后询问是否需要预约
- 用户提供预约信息
- AI调用工具完成预约
- 返回成功提示
关键检查点:
- 数据库记录是否正确
- 特殊字符处理
- 时间格式兼容性
- 错误信息友好度
5.2 查询功能测试
验证场景:
- 已预约用户查询
- 未预约用户查询
- 错误手机号格式
- 并发查询测试
测试技巧:
- 使用真实手机号段测试
- 验证敏感信息脱敏
- 检查响应时间
- 模拟网络异常
6. 生产环境建议
基于实际项目经验,给出以下优化建议:
-
性能优化
- 添加缓存层,减少数据库查询
- 异步处理非关键日志
- 批量处理预约冲突检查
-
安全加固
- 手机号加密存储
- 接口访问频率限制
- 敏感操作二次确认
-
体验提升
- 添加预约时间推荐
- 支持预约修改取消
- 短信通知确认
-
监控运维
- 关键指标监控(成功率、响应时间)
- 异常请求告警
- 定期数据备份
7. 扩展思考
这个方案可以进一步扩展:
-
多工具协作
- 结合成绩分析工具
- 对接院校数据库
- 集成支付能力
-
流程优化
- 智能分时段预约
- 顾问智能匹配
- 自动生成填报建议
-
数据分析
- 热门专业分析
- 分数段统计
- 地域偏好分析
在实际开发中,我发现Tools工具最适合处理那些:
- 有明确输入输出
- 需要精准执行
- 结果可结构化的场景
对于开放性的咨询问题,还是应该让大模型直接生成回答。关键在于找到业务场景与AI能力的平衡点。
