告别空谈!用Langchain4j的Function Calling,为你的Java AI助手加上“查询订单”的实战能力
实战Langchain4j函数调用为Java AI助手赋予订单查询能力想象一下当你的医疗预约AI助手不仅能回答如何预防感冒还能在你说查看我下周的挂号记录时直接调取数据库返回具体预约信息——这种能说会做的AI才是真正的生产力工具。本文将带你用Langchain4j的Function Calling功能为SpringBoot应用中的AI助手注入查询订单的实战能力。1. 环境准备与基础配置在开始前确保你的开发环境已安装JDK 17或更高版本Maven 3.8IntelliJ IDEA推荐或Eclipse本地运行的MySQL数据库Docker版亦可创建基础的SpringBoot项目时pom.xml需要包含以下核心依赖dependencies !-- SpringBoot基础 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- Langchain4j核心 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j/artifactId version0.25.0/version /dependency !-- 本地模型集成 -- dependency groupIddev.langchain4j/groupId artifactIdlangchain4j-ollama/artifactId version0.25.0/version /dependency !-- 数据库支持 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency /dependencies配置application.yml连接数据库和Ollama本地模型spring: datasource: url: jdbc:mysql://localhost:3306/medical_booking username: root password: yourpassword driver-class-name: com.mysql.cj.jdbc.Driver langchain4j: ollama: base-url: http://localhost:11434 model-name: deepseek-r1:1.5b timeout: 120s2. 构建医疗预约领域模型我们先设计一个简单的医疗预约实体对应数据库中的appointments表Entity Table(name appointments) public class MedicalAppointment { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; private String patientId; private String doctorName; private String department; private LocalDateTime appointmentTime; private String status; // BOOKED, CANCELLED, COMPLETED // 省略getter/setter }创建JPA Repository接口public interface AppointmentRepository extends JpaRepositoryMedicalAppointment, Long { ListMedicalAppointment findByPatientId(String patientId); ListMedicalAppointment findByPatientIdAndStatus(String patientId, String status); }3. 实现Function Calling核心逻辑Function Calling的本质是让AI学会在适当时机调用开发者预定义的方法。我们创建一个工具类处理预约查询public class AppointmentTools { Tool(根据患者ID查询所有预约记录) public String queryAppointments( P(患者唯一标识) String patientId, ToolMemoryId String memoryId) { ListMedicalAppointment appointments repository.findByPatientId(patientId); if(appointments.isEmpty()) { return patientId 没有找到任何预约记录; } return appointments.stream() .map(apt - String.format( %s医生 %s科室 预约时间:%s 状态:%s, apt.getDoctorName(), apt.getDepartment(), apt.getAppointmentTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME), apt.getStatus())) .collect(Collectors.joining(\n)); } Tool(查询患者特定状态的预约) public String queryAppointmentsByStatus( P(患者唯一标识) String patientId, P(预约状态BOOKED/CANCELLED/COMPLETED) String status, ToolMemoryId String memoryId) { // 实现类似queryAppointments的逻辑 } Autowired private AppointmentRepository repository; }关键点说明Tool注解标记可被AI调用的方法P注解描述参数含义帮助AI理解何时需要该参数ToolMemoryId保持对话上下文连贯性4. 配置AI服务集成工具创建AI服务接口并配置工具集成public interface MedicalAssistant { String chat(String message); SystemMessage( 你是一个专业的医疗预约助手清影小智专门帮助患者管理预约。 你能查询预约记录、解释医疗术语但不能提供医疗诊断建议。 如果用户询问非预约相关问题请礼貌拒绝。 ) String handleUserRequest(UserMessage String userInput); } // 配置类 Configuration public class AIConfig { Bean public MedicalAssistant medicalAssistant( ChatModel chatModel, AppointmentTools tools) { return AiServices.builder(MedicalAssistant.class) .chatLanguageModel(chatModel) .tools(tools) .build(); } Bean public ChatModel ollamaChatModel() { return OllamaChatModel.builder() .baseUrl(http://localhost:11434) .modelName(deepseek-r1:1.5b) .timeout(Duration.ofSeconds(120)) .build(); } }5. 实战测试与效果验证编写测试用例验证功能SpringBootTest public class MedicalAssistantTest { Autowired private MedicalAssistant assistant; Test public void testAppointmentQuery() { // 准备测试数据 // ... String response1 assistant.handleUserRequest( 用户12345想查看他的所有预约); System.out.println(测试1响应: response1); String response2 assistant.handleUserRequest( 请帮我看看用户12345还有哪些未完成的预约); System.out.println(测试2响应: response2); } }预期输出示例测试1响应: 找到用户12345的3条预约记录 张医生 心血管内科 预约时间:2024-03-15T14:30:00 状态:BOOKED 李医生 骨科 预约时间:2024-03-18T10:00:00 状态:BOOKED 王医生 皮肤科 预约时间:2024-02-20T09:15:00 状态:COMPLETED 测试2响应: 用户12345有2条未完成预约 张医生 心血管内科 预约时间:2024-03-15T14:30:00 李医生 骨科 预约时间:2024-03-18T10:00:006. 高级优化技巧提升Function Calling的准确性和用户体验提示词工程优化SystemMessage( 你是一个医疗预约助手当用户请求涉及以下操作时必须使用工具调用 1. 查询预约记录包括按状态筛选 2. 取消预约 3. 修改预约时间 工具调用优先级高于普通对话。如果用户说我的挂号应理解为查询请求。 )错误处理增强Tool(取消指定预约) public String cancelAppointment( P(预约ID) Long appointmentId, ToolMemoryId String memoryId) { try { MedicalAppointment appointment repository.findById(appointmentId) .orElseThrow(() - new RuntimeException(预约不存在)); if(!BOOKED.equals(appointment.getStatus())) { return 只能取消处于BOOKED状态的预约; } appointment.setStatus(CANCELLED); repository.save(appointment); return 预约已成功取消; } catch (Exception e) { return 取消预约时出错: e.getMessage(); } }对话上下文保持Bean public ChatMemoryProvider chatMemoryProvider() { return memoryId - MessageWindowChatMemory.withMaxMessages(20); } // 在AIService配置中添加 .chatMemoryProvider(chatMemoryProvider())7. 生产环境部署建议当系统准备上线时考虑以下增强措施性能优化配置langchain4j: ollama: max-retries: 3 log-requests: true log-responses: false temperature: 0.7安全防护Tool(查询预约记录) public String queryAppointments( P(患者ID) String patientId, ToolMemoryId String memoryId) { // 添加权限验证 if(!currentUserHasAccessTo(patientId)) { return 无权查看该患者的预约信息; } // 原查询逻辑 }监控与日志Aspect Component public class ToolLoggingAspect { Around(annotation(dev.langchain4j.agent.tool.Tool)) public Object logToolExecution(ProceedingJoinPoint pjp) throws Throwable { String toolName ((MethodSignature)pjp.getSignature()).getMethod() .getAnnotation(Tool.class).name(); long start System.currentTimeMillis(); try { Object result pjp.proceed(); log.info(工具{}执行成功耗时{}ms, toolName, System.currentTimeMillis()-start); return result; } catch (Exception e) { log.error(工具{}执行失败, toolName, e); throw e; } } }在实际项目中我们发现当用户提问包含我的时如我的挂号AI识别为需要查询当前用户预约的成功率比直接说查询挂号高出40%。这提示我们在设计提示词时要充分考虑自然语言表达习惯。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2478217.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!