|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?注册
×
作者:微信文章
说明:该实战项目是基于前面几篇文章的基础下进行的,一些基础知识不懂可以看看前面几篇AI相关的文章。
其中比较核心的,一个是记忆聊天,二个是Aiservice使用,三个是Tool的使用
其中涉及到Tool的使用中,提示模版的章节未补充,后面慢慢完善~~
一、新建数据库和表
CREATE TABLE `appointment` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL, `id_card` varchar(18) NOT NULL, `department` varchar(50) NOT NULL, `date` varchar(10) NOT NULL, `time` varchar(10) NOT NULL, `doctor_name` varchar(50) DEFAULT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
二、添加POM依赖
<mybatis-plus.version>3.5.11</mybatis-plus.version><!-- Mysql Connector --><dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId></dependency><!--mybatis-plus 持久层--><dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-spring-boot3-starter</artifactId> <version>${mybatis-plus.version}</version></dependency> 三、配置文件
spring: data: mongodb: uri: mongodb://admin:123456@192.168.10.109:27017/chat_memory_db?authSource=admin datasource: url: jdbc:mysql://192.168.10.109:3306/xuewei?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false driver-class-name: com.mysql.cj.jdbc.Driver username: root password: rootmybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpllangchain4j: open-ai: chat-model: # api-key: demo # base-url: http://langchain4j.dev/demo/openai/v1 # model-name: gpt-4o-mini
# deepseek #base-url: https://api.deepseek.com #api-key: sk-851e968414c947c6be86427b1014xxxx #model-name: deepseek-chat #model-name: =deepseek-reasoner
# 阿里白练通义千问 base-url: https://dashscope.aliyuncs.com/compatible-mode/v1 api-key: sk-09c7b571687b46d5a2e25a03fbddxxxx model-name: deepseek-v3 log-requests: true log-responses: true # 阿里白练通义千问 community: dashscope: chat-model: api-key: sk-09c7b571687b46d5a2e25a03fbddxxxx model-name: qwen-maxlogging: level: root: info四、MP代码生成
1.entity
package com.zhan.chat.entity;
import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.TableId;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;
/** * @author zhanxuewei */@Data@AllArgsConstructor@NoArgsConstructorpublic class Appointment { @TableId(type = IdType.AUTO) private Long id; private String username; private String idCard; private String department; private String date; private String time; private String doctorName;}2.mapper
package com.zhan.chat.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.zhan.chat.entity.Appointment;import org.apache.ibatis.annotations.Mapper;
@Mapperpublic interface AppointmentMapper extends BaseMapper<Appointment> {}3.service
package com.zhan.chat.service;
import com.baomidou.mybatisplus.extension.service.IService;import com.zhan.chat.entity.Appointment;
/** * @author zhanxuewei */public interface AppointmentService extends IService<Appointment> {
Appointment getOne(Appointment appointment);
}package com.zhan.chat.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.zhan.chat.entity.Appointment;import com.zhan.chat.mapper.AppointmentMapper;import com.zhan.chat.service.AppointmentService;import org.springframework.stereotype.Service;
/** * @author zhanxuewei */@Servicepublic class AppointmentServiceImpl extends ServiceImpl<AppointmentMapper, Appointment> implements AppointmentService { @Override public Appointment getOne(Appointment appointment) { return baseMapper.selectOne(new LambdaQueryWrapper<Appointment>() .eq(Appointment::getUsername, appointment.getUsername()) .eq(Appointment::getIdCard, appointment.getIdCard()) .eq(Appointment::getDepartment, appointment.getDepartment()) .eq(Appointment::getDate, appointment.getDate()) .eq(Appointment::getTime, appointment.getTime())); }}
4.controller
package com.zhan.chat.controller;
import com.zhan.chat.assistant.XueweiAgent;import com.zhan.chat.bean.ChatForm;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.tags.Tag;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
@Tag(name = "智能医生助手")@RestController@RequestMapping("/doctor/assistant")public class XueweiController {
@Autowired private XueweiAgent xueweiAgent;
@Operation(summary = "对话") @PostMapping("/chat") public String chat(@RequestBody ChatForm chatForm) { return xueweiAgent.chat(chatForm.getMemoryId(), chatForm.getMessage()); }}
五、测试CRUD
package com.zhan.chat;
import com.zhan.chat.entity.Appointment;import com.zhan.chat.service.AppointmentService;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTestpublic class AppointmentServiceTest {
@Autowired private AppointmentService appointmentService;
@Test void testGetOne() { Appointment appointment = new Appointment(); appointment.setUsername("张三"); appointment.setIdCard("123456789012345678"); appointment.setDepartment("内科"); appointment.setDate("2025-06-07"); appointment.setTime("上午"); Appointment appointmentDB = appointmentService.getOne(appointment); System.out.println(appointmentDB); }
@Test void testSave() { Appointment appointment = new Appointment(); appointment.setUsername("张三"); appointment.setIdCard("123456789012345678"); appointment.setDepartment("内科"); appointment.setDate("2025-06-07"); appointment.setTime("上午"); appointment.setDoctorName("詹医生"); appointmentService.save(appointment); }
@Test void testRemoveById() { appointmentService.removeById(1L); }}
六、编写智能体
package com.zhan.chat.assistant;
import dev.langchain4j.service.MemoryId;import dev.langchain4j.service.SystemMessage;import dev.langchain4j.service.UserMessage;import dev.langchain4j.service.spring.AiService;import dev.langchain4j.service.spring.AiServiceWiringMode;
/** * @author zhanxuewei */@AiService( wiringMode = AiServiceWiringMode.EXPLICIT, chatModel = "qwenChatModel", chatMemory = "chatMemory", chatMemoryProvider = "chatMemoryProviderXuewei", tools = "appointmentTools")public interface XueweiAgent {
@SystemMessage(fromResource = "xuewei-prompt-template.txt") String chat(@MemoryId Long memoryId, @UserMessage String userMessage);}
消息模版:
七、编写ChatMemoryProvider
package com.zhan.chat.config;
import com.zhan.chat.store.MongoChatMemoryStore;import dev.langchain4j.memory.chat.ChatMemoryProvider;import dev.langchain4j.memory.chat.MessageWindowChatMemory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
/** * @author zhanxuewei */@Configurationpublic class XueweiAgentConfig {
@Autowired private MongoChatMemoryStore mongoChatMemoryStore;
@Bean ChatMemoryProvider chatMemoryProviderXuewei() { return memoryId -> MessageWindowChatMemory.builder() .id(memoryId) .maxMessages(20) .chatMemoryStore(mongoChatMemoryStore) .build(); }}
八、编写AppointmentTools
package com.zhan.chat.tools;
import com.zhan.chat.entity.Appointment;import com.zhan.chat.service.AppointmentService;import dev.langchain4j.agent.tool.P;import dev.langchain4j.agent.tool.Tool;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;
/** * @author zhanxuewei */@Componentpublic class AppointmentTools {
@Autowired private AppointmentService appointmentService;
@Tool(name = "预约挂号", value = "根据参数,先执行工具方法queryDepartment查询是否可预约,并直 接给用户回答是否可预约,并让用户确认所有预约信息,用户确认后再进行预约。") public String bookAppointment(Appointment appointment) { //查找数据库中是否包含对应的预约记录 Appointment existAppointment = appointmentService.getOne(appointment); if (existAppointment == null) { appointment.setId(null); if (appointmentService.save(appointment)) { return "预约成功,并返回预约详情"; } else { return "预约失败"; } } return "您在相同的科室和时间已有预约"; }
@Tool(name = "取消预约挂号", value = "根据参数,查询预约是否存在,如果存在则删除预约记录并返回取 消预约成功,否则返回取消预约失败") public String cancelAppointment(Appointment appointment) { Appointment one = appointmentService.getOne(appointment); if (one != null) { //删除预约记录 if (appointmentService.removeById(one.getId())) { return "取消预约成功"; } else { return "取消预约失败"; } } //取消失败 return "您没有预约记录,请核对预约科室和时间"; }
@Tool(name = "查询是否有号源", value = "根据科室名称,日期,时间和医生查询是否有号源,并返回给用户") public boolean queryDepartment(@P(value = "科室名称") String name, @P(value = "日期") String date, @P(value = "时间,可选值:上午、下午") String time, @P(value = "医生名称", required = false) String doctorName) { System.out.println("查询是否有号源"); System.out.println("科室名称:" + name); System.out.println("日期:" + date); System.out.println("时间:" + time); System.out.println("医生名称:" + doctorName); //TODO 维护医生的排班信息: //如果没有指定医生名字,则根据其他条件查询是否有可以预约的医生(有返回true,否则返回false; //如果指定了医生名字,则判断医生是否有排班(没有排版返回false) //如果有排班,则判断医生排班时间段是否已约满(约满返回false,有空闲时间返回true) return true; }}
九、测试智能挂号
第一轮对话:
第二轮对话:
第三轮对话:
第四轮对话:
第五轮对话:
第六轮对话:
十、结果
六轮对话完成后,挂号成功,看数据库:
|
|