Initial commit
This commit is contained in:
96
langchain4j-ai-xiaoai-agent/pom.xml
Normal file
96
langchain4j-ai-xiaoai-agent/pom.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?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>com.iwe3</groupId>
|
||||
<artifactId>langchain4j-ai-java</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>langchain4j-ai-xiaoai-agent</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<knife4j.version>4.3.0</knife4j.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- 接入阿里云百炼平台 -->
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-community-dashscope-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-pinecone</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 简单的rag实现 -->
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-easy-rag</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 引入德鲁伊数据源连接池的启动器 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||
<version>1.2.27</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>3.0.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<!-- Spring Boot Starter Data MongoDB -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-reactor</artifactId>
|
||||
<version>1.9.1-beta17</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<!--导入低阶依赖-->
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
|
||||
<version>1.9.1-beta17</version>
|
||||
</dependency>
|
||||
<!--导入高阶依赖-->
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-spring-boot-starter</artifactId>
|
||||
<version>1.9.1-beta17</version>
|
||||
</dependency>
|
||||
<!-- 前后端分离中的后端接口测试工具 -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.iwe3.langchain4j;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@MapperScan("com.iwe3.langchain4j.mapper")
|
||||
@SpringBootApplication
|
||||
public class XiaoAIAgentApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(XiaoAIAgentApplication.class,args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.iwe3.langchain4j.config;
|
||||
|
||||
import dev.langchain4j.data.segment.TextSegment;
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStore;
|
||||
import dev.langchain4j.store.embedding.pinecone.PineconeEmbeddingStore;
|
||||
import dev.langchain4j.store.embedding.pinecone.PineconeServerlessIndexConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class EmbeddingStoreConfig {
|
||||
|
||||
@Autowired
|
||||
private EmbeddingModel embeddingModel;
|
||||
|
||||
@Bean
|
||||
public EmbeddingStore<TextSegment> embeddingStore() {
|
||||
// 创建向量存储
|
||||
return PineconeEmbeddingStore.builder()
|
||||
.apiKey(System.getenv("PINECONE_API_KEY"))
|
||||
.index("xiaoai-index") // 如果指定的索引不存在,将创建一个新的索引
|
||||
.nameSpace("xiaoai-namespace") // 如果指定的名称空间不存在,将创建一个新的名称空间
|
||||
.createIndex(PineconeServerlessIndexConfig.builder()
|
||||
.cloud("AWS") // 指定索引部署在 AWS 云服务上。
|
||||
.region("us-east-1") // 指定索引所在的 AWS 区域为 us-east-1。
|
||||
.dimension(embeddingModel.dimension()) // 指定索引的向量维度,该维度与 embeddingModel 生成的向量维度相同。
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.iwe3.langchain4j.config;
|
||||
|
||||
import dev.langchain4j.model.chat.StreamingChatModel;
|
||||
import dev.langchain4j.model.openai.OpenAiStreamingChatModel;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class LLMConfig {
|
||||
|
||||
/**
|
||||
* @Description: 流式对话接口 StreamingChatModel
|
||||
*/
|
||||
@Bean
|
||||
public StreamingChatModel streamingChatModel(){
|
||||
return OpenAiStreamingChatModel.builder()
|
||||
.apiKey(System.getenv("DASH_SCOPE_API_KEY"))
|
||||
.modelName("qwen-plus")
|
||||
.baseUrl("https://dashscope.aliyuncs.com/compatible-mode/v1")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.iwe3.langchain4j.config;
|
||||
|
||||
import com.iwe3.langchain4j.entity.ChatMessages;
|
||||
import dev.langchain4j.data.message.ChatMessage;
|
||||
import dev.langchain4j.data.message.ChatMessageDeserializer;
|
||||
import dev.langchain4j.data.message.ChatMessageSerializer;
|
||||
import dev.langchain4j.store.memory.chat.ChatMemoryStore;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.MongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class MongoChatMemoryStore implements ChatMemoryStore {
|
||||
|
||||
@Autowired
|
||||
private MongoTemplate mongoTemplate;
|
||||
|
||||
/**
|
||||
* 根据聊天ID查询所有消息
|
||||
* @param memoryId
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public List<ChatMessage> getMessages(Object memoryId) {
|
||||
Criteria criteria = Criteria.where("memoryId").is(memoryId);
|
||||
Query query = new Query(criteria);
|
||||
ChatMessages chatMessages = mongoTemplate.findOne(query, ChatMessages.class);
|
||||
if (chatMessages == null) return new LinkedList<>();
|
||||
return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据聊天id修改聊天消息
|
||||
* @param memoryId
|
||||
* @param messages
|
||||
*/
|
||||
@Override
|
||||
public void updateMessages(Object memoryId, List<ChatMessage> messages) {
|
||||
Criteria criteria = Criteria.where("memoryId").is(memoryId);
|
||||
Query query = new Query(criteria);
|
||||
|
||||
Update update = new Update();
|
||||
update.set("content", ChatMessageSerializer.messagesToJson(messages));
|
||||
|
||||
// 根据query条件能查询出文档,则修改文档;否则新增文档
|
||||
mongoTemplate.upsert(query, update, ChatMessages.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据聊天ID删除聊天消息
|
||||
* @param memoryId
|
||||
*/
|
||||
@Override
|
||||
public void deleteMessages(Object memoryId) {
|
||||
Criteria criteria = Criteria.where("memoryId").is(memoryId);
|
||||
Query query = new Query(criteria);
|
||||
mongoTemplate.remove(query, ChatMessages.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.iwe3.langchain4j.config;
|
||||
|
||||
import dev.langchain4j.memory.chat.ChatMemoryProvider;
|
||||
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class SeparateChatAssistantConfig {
|
||||
|
||||
@Resource
|
||||
private MongoChatMemoryStore mongoChatMemoryStore;
|
||||
|
||||
/**
|
||||
* 指定使用-> mongoChatMemoryStore 来存储
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
ChatMemoryProvider chatMemoryProvider() {
|
||||
return memoryId -> MessageWindowChatMemory.builder()
|
||||
.id(memoryId)
|
||||
.maxMessages(30).
|
||||
chatMemoryStore(mongoChatMemoryStore)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package com.iwe3.langchain4j.config;
|
||||
|
||||
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
|
||||
import dev.langchain4j.data.document.parser.TextDocumentParser;
|
||||
import dev.langchain4j.data.segment.TextSegment;
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import dev.langchain4j.rag.content.retriever.ContentRetriever;
|
||||
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStore;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
|
||||
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
|
||||
@Configuration
|
||||
public class XiaoAiAgentConfig {
|
||||
|
||||
@Autowired
|
||||
private EmbeddingStore embeddingStore;
|
||||
|
||||
@Autowired
|
||||
private EmbeddingModel embeddingModel;
|
||||
|
||||
@Bean
|
||||
ContentRetriever contentRetrieverInPinecone() {
|
||||
// 创建一个 EmbeddingStoreContentRetriever 对象,用于从嵌入存储中检索内容
|
||||
return EmbeddingStoreContentRetriever
|
||||
.builder()
|
||||
// 设置用于生成嵌入向量的嵌入模型
|
||||
.embeddingModel(embeddingModel)
|
||||
// 指定要使用的嵌入存储
|
||||
.embeddingStore(embeddingStore)
|
||||
// 设置最大检索结果数量,这里表示最多返回 1 条匹配结果
|
||||
.maxResults(1)
|
||||
// 设置最小得分阈值,只有得分大于等于 0.8 的结果才会被返回
|
||||
.minScore(0.8)
|
||||
// 构建最终的 EmbeddingStoreContentRetriever 实例
|
||||
.build();
|
||||
}
|
||||
/**
|
||||
* 配置RAG检索增强 文档库
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
ContentRetriever contentRetrieverInMemory() {
|
||||
// 使用FileSystemDocumentLoader读取指定目录下的知识库文档
|
||||
var pathMatcher = FileSystems.getDefault()
|
||||
.getPathMatcher("glob:*\\.md");
|
||||
var documents = FileSystemDocumentLoader
|
||||
.loadDocuments("D:/documents", pathMatcher, new TextDocumentParser());
|
||||
|
||||
// 使用内存向量存储
|
||||
InMemoryEmbeddingStore<TextSegment> db = new InMemoryEmbeddingStore<>();
|
||||
// 使用默认的文档分割器
|
||||
EmbeddingStoreIngestor.ingest(documents, db);
|
||||
// 从嵌入存储(EmbeddingStore)里检索和查询内容相关的信息
|
||||
return EmbeddingStoreContentRetriever.from(db);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.iwe3.langchain4j.controller;
|
||||
|
||||
import com.iwe3.langchain4j.record.ChatRecord;
|
||||
import com.iwe3.langchain4j.service.XiaoAIChatAssistant;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
@Tag(name="小艾")
|
||||
@RestController
|
||||
@RequestMapping("/xiaoai")
|
||||
public class XiaoAIController {
|
||||
|
||||
@Resource
|
||||
private XiaoAIChatAssistant xiaoAIChatAssistant;
|
||||
|
||||
@Operation(summary = "对话")
|
||||
@PostMapping("/chat")
|
||||
public Flux<String> chat(@RequestBody ChatRecord record){
|
||||
return xiaoAIChatAssistant.chat(record.memoryId(),record.message());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.iwe3.langchain4j.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AppointmentEntity {
|
||||
private Long id;
|
||||
private String username;
|
||||
private String idCard;
|
||||
private String department;
|
||||
private String date;
|
||||
private String time;
|
||||
private String doctorName;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.iwe3.langchain4j.entity;
|
||||
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Document("chat_messages")
|
||||
public class ChatMessages {
|
||||
|
||||
//唯一标识,映射到 MongoDB 文档的 _id 字段
|
||||
@Id
|
||||
private ObjectId messageId; //利用数据库生成ID就用ObjectId
|
||||
|
||||
private String memoryId; //隔离聊天记录的ID
|
||||
|
||||
private String content; //存储当前聊天记录列表的json字符串
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.iwe3.langchain4j.mapper;
|
||||
|
||||
import com.iwe3.langchain4j.entity.AppointmentEntity;
|
||||
import com.iwe3.langchain4j.record.AppointmentRecord;
|
||||
import org.apache.ibatis.annotations.Delete;
|
||||
import org.apache.ibatis.annotations.Insert;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
@Mapper
|
||||
public interface AppointmentMapper {
|
||||
|
||||
@Insert("""
|
||||
insert into appointment(username,id_card,department,date,time,doctor_name)
|
||||
values (#{r.userName},#{r.idcard},#{r.department},#{r.date},#{r.time},#{r.doctorName})
|
||||
""")
|
||||
void saveAppointmentEntity(@Param("r") AppointmentRecord record);
|
||||
|
||||
@Delete("""
|
||||
delete from appointment where id = #{id}
|
||||
""")
|
||||
void removeById(@Param("id") long id);
|
||||
|
||||
AppointmentEntity getOne(@Param("r") AppointmentRecord record);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.iwe3.langchain4j.record;
|
||||
|
||||
/**
|
||||
* 编写挂号记录类
|
||||
* @param userName
|
||||
* @param idcard
|
||||
* @param department
|
||||
* @param date
|
||||
* @param time
|
||||
* @param doctorName
|
||||
*/
|
||||
public record AppointmentRecord(String userName,
|
||||
String idcard,
|
||||
String department,
|
||||
String date,
|
||||
String time,
|
||||
String doctorName) {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.iwe3.langchain4j.record;
|
||||
|
||||
/**
|
||||
* 对话对象
|
||||
* @param memoryId
|
||||
* @param message
|
||||
*/
|
||||
public record ChatRecord(Long memoryId,String message) {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.iwe3.langchain4j.service;
|
||||
|
||||
import com.iwe3.langchain4j.entity.AppointmentEntity;
|
||||
import com.iwe3.langchain4j.record.AppointmentRecord;
|
||||
|
||||
public interface IAppointmentService {
|
||||
void saveAppointmentEntity(AppointmentRecord record);
|
||||
void removeById(long id);
|
||||
AppointmentEntity getOne(AppointmentRecord record);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.iwe3.langchain4j.service;
|
||||
|
||||
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;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
//chatMemoryProvider = "chatMemoryProvider" 指定->MongoDB
|
||||
//contentRetriever = "contentRetrieverInPinecone" 指定->Pinecone 向量存储版
|
||||
@AiService(wiringMode = AiServiceWiringMode.EXPLICIT
|
||||
,streamingChatModel = "streamingChatModel",
|
||||
chatMemoryProvider = "chatMemoryProvider",
|
||||
tools = {"appointmentTools"},
|
||||
contentRetriever = "contentRetrieverInPinecone")
|
||||
public interface XiaoAIChatAssistant {
|
||||
|
||||
@SystemMessage(fromResource = "xiaoai-prompt.txt")
|
||||
Flux<String> chat(@MemoryId Long memoryId, @UserMessage String userMessage);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.iwe3.langchain4j.service.impl;
|
||||
|
||||
import com.iwe3.langchain4j.entity.AppointmentEntity;
|
||||
import com.iwe3.langchain4j.mapper.AppointmentMapper;
|
||||
import com.iwe3.langchain4j.record.AppointmentRecord;
|
||||
import com.iwe3.langchain4j.service.IAppointmentService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
public class AppointmentServiceImpl implements IAppointmentService {
|
||||
|
||||
private final AppointmentMapper appointmentMapper;
|
||||
public AppointmentServiceImpl(AppointmentMapper appointmentMapper) {
|
||||
this.appointmentMapper = appointmentMapper;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void saveAppointmentEntity(AppointmentRecord record) {
|
||||
appointmentMapper.saveAppointmentEntity(record);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public void removeById(long id) {
|
||||
appointmentMapper.removeById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AppointmentEntity getOne(AppointmentRecord record) {
|
||||
return appointmentMapper.getOne(record);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.iwe3.langchain4j.tools;
|
||||
|
||||
import com.iwe3.langchain4j.record.AppointmentRecord;
|
||||
import com.iwe3.langchain4j.service.IAppointmentService;
|
||||
import dev.langchain4j.agent.tool.P;
|
||||
import dev.langchain4j.agent.tool.Tool;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class AppointmentTools {
|
||||
|
||||
private final IAppointmentService appointmentServiceImpl;
|
||||
public AppointmentTools(IAppointmentService appointmentServiceImpl) {
|
||||
this.appointmentServiceImpl = appointmentServiceImpl;
|
||||
}
|
||||
//修改此处的提示词
|
||||
@Tool(name = "预约挂号", value = "根据参数,先执行工具方法queryDepartment查询是否可预约,并直接给用户回答是否可预约,并让用户确认所有预约信息,用户确认后再进行预约。如果用户没有提供具体的医生姓名,请从向量存储中找到一位医生。")
|
||||
public String scheduleAppointment(AppointmentRecord record) {
|
||||
// 查找数据库中是否包含对应的预约记录
|
||||
var appointment = appointmentServiceImpl.getOne(record);
|
||||
if (appointment == null) {
|
||||
appointmentServiceImpl.saveAppointmentEntity(record);
|
||||
return "预约成功,并返回预约详情";
|
||||
}
|
||||
|
||||
return "您在相同的科室和时间已有预约";
|
||||
}
|
||||
|
||||
@Tool(name = "取消预约挂号", value = "根据参数,查询预约是否存在,如果存在则删除预约记录并返回取消预约成功,否则返回取消预约失败")
|
||||
public String cancelAppointment(AppointmentRecord record) {
|
||||
var appointment = appointmentServiceImpl.getOne(record);
|
||||
|
||||
if (appointment != null) {
|
||||
appointmentServiceImpl.removeById(appointment.getId());
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
server:
|
||||
port: 8080
|
||||
servlet:
|
||||
encoding:
|
||||
charset: utf-8
|
||||
enabled: true
|
||||
force: true # 设置响应的字符编码,避免流式返回输出乱码
|
||||
spring:
|
||||
application:
|
||||
name: langchain4j-ai-xiaoai-agent
|
||||
data:
|
||||
mongodb:
|
||||
uri: mongodb://localhost:27017/xiao_ai_db # MongoDB连接配置,数据库 xiao_ai_db 会自动创建
|
||||
datasource:
|
||||
driver-class-name:
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
url: jdbc:mysql://localhost:3306/langchain4j?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: 123456
|
||||
#配置Mybatis
|
||||
mybatis:
|
||||
mapper-locations: classpath:mapper/*.xml
|
||||
type-aliases-package: com.iwe3.langchain4j.entity
|
||||
configuration:
|
||||
map-underscore-to-camel-case: true
|
||||
langchain4j:
|
||||
community:
|
||||
dashscope:
|
||||
embedding-model:
|
||||
model-name: text-embedding-v3
|
||||
api-key: ${DASH_SCOPE_API_KEY}
|
||||
@@ -0,0 +1,35 @@
|
||||
**医院名称:**
|
||||
四川大学华西医院
|
||||
|
||||
**医院地址:**
|
||||
(国重院区)四川省成都市武侯区国学巷37号,邮编:610041
|
||||
(温江院区)四川省成都市温江区万春东路566号,邮编:611135
|
||||
|
||||
**门诊开放时间:**
|
||||
工作日:8:00 - 17:30
|
||||
急诊:24小时开放
|
||||
|
||||
**服务热线:**
|
||||
(国重院区)028-85422114
|
||||
(温江院区)028-87606666
|
||||
|
||||
**医院简介:**
|
||||
四川大学华西医院是中国西部疑难危急重症诊疗的国家级中心,集医疗、教学、科研、预防、保健、康复为一体,是国家三级甲等综合医院、国家临床医学研究中心、国家药物临床试验机构。作为中国现代医学教育的重要发源地之一,华西医院拥有全国领先的学科群,尤其在麻醉学、放射学、胸外科、泌尿外科、消化内科、老年医学等领域具有突出优势。连续多年在全国三级公立医院绩效考核中位居前列,综合实力稳居全国第一方阵,享有“北有协和,南有华西”的盛誉。
|
||||
|
||||
**国重院区乘车路线:**
|
||||
|
||||
1. 16、21、26、28、34、45、58、61、77、99路到“华西坝”站
|
||||
2. 地铁1号线或18号线到“华西坝”站,B出口步行约3分钟
|
||||
3. 机场专线2号线至“省体育馆”站,换乘地铁1号线1站即达
|
||||
|
||||
**温江院区乘车路线:**
|
||||
|
||||
1. 温江W13、W22、W26、W31路到“华西医院温江院区”站
|
||||
2. 地铁17号线到“明光站”,C出口换乘接驳公交或步行约15分钟
|
||||
3. 自驾可经成都绕城高速“文家场”出口或成温邛高速“金马”出口抵达
|
||||
|
||||
**国重院区预约号取号地点:**
|
||||
国重院区门诊楼一层大厅自助取号机或人工挂号窗口取号
|
||||
|
||||
**温江院区预约号取号地点:**
|
||||
温江院区门诊楼一层大厅自助取号机或挂号收费窗口取号
|
||||
@@ -0,0 +1,85 @@
|
||||
# 四川大学华西医院口腔科详细介绍
|
||||
|
||||
四川大学华西医院口腔科源于1907年成立的**华西协合大学牙学院**——中国现代口腔医学的发源地,也是亚洲最早建立的高等口腔医学教育机构。历经百余年发展,华西口腔已成长为集医疗、教学、科研于一体的国家级口腔医学中心,被誉为“中国口腔医学的摇篮”。
|
||||
|
||||
作为四川大学华西医院的重要组成部分,口腔科依托**国家口腔疾病临床医学研究中心**、**口腔医学国家重点实验室**和**国家“双一流”建设学科**,始终站在中国口腔医学发展的前沿。科室秉承“选英才、育精英、创精品”的理念,在口腔疑难重症诊治、多学科协作及技术创新方面具有全国引领地位。
|
||||
|
||||
## 历史沿革
|
||||
|
||||
- **1907年**:加拿大传教士林则博士(Dr. Ashley W. Lindsay)在成都创办华西协合大学牙学院,开创中国高等口腔医学教育先河。
|
||||
- **1950年代**:在全国院系调整中,华西口腔成为新中国口腔医学人才培养的核心基地。
|
||||
- **1980年代至今**:持续引领口腔种植、颌面外科、牙体牙髓病、牙周病等领域的临床与科研创新,多项技术填补国内空白。
|
||||
- **2000年后**:随着四川大学华西医院综合实力提升,口腔科进一步整合资源,强化与全身疾病管理的联动,形成“大口腔、大健康”服务模式。
|
||||
|
||||
## 科室现状
|
||||
|
||||
目前,华西医院口腔科设有以下专业组:
|
||||
|
||||
- 口腔颌面外科学
|
||||
- 牙体牙髓病学
|
||||
- 牙周病学
|
||||
- 口腔修复学
|
||||
- 口腔正畸学
|
||||
- 口腔种植学
|
||||
- 儿童口腔病学
|
||||
- 口腔黏膜病学
|
||||
- 无痛舒适化治疗中心
|
||||
- 口腔激光诊疗中心
|
||||
|
||||
科室配备**80余台国际先进口腔综合治疗台**、**20张住院病床**,拥有医护人员**130余人**,其中医生**70名**(含教授/主任医师15人、副教授/副主任医师20人)、护理及技术人员**60余名**。现有**博士生导师10人**、**硕士生导师15人**,形成结构合理、梯队完善的人才体系。
|
||||
|
||||
## 学术影响与行业地位
|
||||
|
||||
- 华西口腔连续多年在复旦版《中国医院专科声誉排行榜》中位列**全国第一**。
|
||||
- 多位专家担任国家级学会主委/副主委:
|
||||
- **周学东教授**:曾任中华口腔医学会会长,中国工程院院士候选人,龋病防治权威。
|
||||
- **石冰教授**:中华口腔医学会唇腭裂专委会前任主委,国际知名唇腭裂整形专家。
|
||||
- **胡静教授**:中华口腔医学会口腔颌面外科专委会主委,擅长复杂颌面畸形与肿瘤整复。
|
||||
- **王杭教授**:中华口腔医学会镇静镇痛专委会常委,国内舒适化牙科治疗先行者。
|
||||
|
||||
科室每年承担**国家自然科学基金重点项目、科技部重点研发计划**等国家级课题20余项,发表SCI论文300+篇,牵头制定多项**国家口腔诊疗规范与指南**。
|
||||
|
||||
## 特色优势
|
||||
|
||||
- **多学科协作(MDT)**:作为大型综合医院口腔科,可高效联动内分泌科、心血管科、血液科等,为合并全身疾病的患者(如糖尿病、高血压、凝血障碍)提供安全、个体化的口腔治疗。
|
||||
- **舒适化诊疗**:2005年率先成立西南地区首个“无痛牙科中心”,开展笑气镇静、静脉镇静、全麻下儿童牙病治疗等技术。
|
||||
- **数字化精准口腔**:全面应用CBCT、口内扫描、3D打印、动态导航种植等数字技术,实现精准诊断与微创治疗。
|
||||
|
||||
------
|
||||
|
||||
## 科室地址
|
||||
|
||||
- **国重院区**:成都市武侯区国学巷37号,四川大学华西医院门诊楼**8层**
|
||||
- **温江院区**:成都市温江区万春东路566号,门诊楼**3层**
|
||||
|
||||
------
|
||||
|
||||
## 专家团队
|
||||
|
||||
### 胡静
|
||||
|
||||
**口腔颌面外科主任 主任医师 教授 博士生导师**
|
||||
|
||||
**擅长**:口腔颌面部肿瘤、复杂颌骨畸形、创伤修复、正颌外科
|
||||
**简介**:
|
||||
胡静,教授、主任医师,博士生导师。现任中华口腔医学会口腔颌面外科专业委员会主任委员。从事口腔颌面外科临床工作30余年,在颌面部肿瘤根治与功能重建、先天性颌面畸形矫正等领域具有极高造诣。主持国家自然科学基金重点项目5项,获国家科技进步二等奖1项。带领团队完成西南地区首例“全脸移植”术前评估与规划。
|
||||
|
||||
------
|
||||
|
||||
### 王杭
|
||||
|
||||
**口腔科副主任 主任医师 教授**
|
||||
|
||||
**擅长**:无痛牙科治疗、牙科恐惧症干预、复杂牙体牙髓病、老年口腔综合治疗
|
||||
**简介**:
|
||||
王杭,主任医师,教授。中华口腔医学会镇静镇痛专业委员会常委,四川省口腔医学会舒适化诊疗学组组长。2006年创建华西“舒适牙科中心”,是国内最早系统开展笑气/静脉镇静下牙科治疗的专家之一。主编《舒适化口腔诊疗技术规范》,培训全国基层医师超千人。
|
||||
|
||||
------
|
||||
|
||||
### 石冰
|
||||
|
||||
**唇腭裂中心主任 主任医师 教授 博士生导师**
|
||||
|
||||
**擅长**:唇腭裂序列治疗、颌骨发育畸形矫正、语音康复
|
||||
**简介**:
|
||||
石冰,教授,博士生导师,国际唇腭裂基金会(ICPF)顾问。曾任中华口腔医学会唇腭裂专委会主任委员。创立“华西唇腭裂序列治疗模式”,累计完成唇腭裂手术超万例,技术辐射“一带一路”多个国家。获“全国优秀科技工作者”称号。
|
||||
@@ -0,0 +1,32 @@
|
||||
### 四川大学华西医院神经内科详细介绍
|
||||
|
||||
四川大学华西医院神经内科成立于1914年,历经百年发展,已成为国内乃至国际上享有盛誉的专业科室之一。作为中国西部地区最早成立的神经病学专业科室,华西医院神经内科不仅是全国首批神经病学硕士、博士学位授予点及博士后工作站,也是国家级重点学科,在处理复杂疑难杂症方面处于领先地位。
|
||||
|
||||
#### 科室设置与服务
|
||||
|
||||
- **专业组**:临床神经生理、脑电图与癫痫、痴呆与认知障碍、脑血管病、帕金森及运动障碍、神经病理、神经肌肉病、感染与脑脊液细胞学、神经免疫、神经遗传和睡眠等11个专业组。
|
||||
- **特色门诊**:开设有神经肌肉病门诊、肌张力障碍和肉毒毒素治疗门诊、帕金森病和老年痴呆门诊、癫痫门诊、脑血管病门诊、运动神经元病、重症肌无力门诊、多发性硬化门诊和头痛门诊等9个特色门诊,为患者提供高水平的医疗服务。
|
||||
|
||||
#### 医疗实力
|
||||
|
||||
- **床位数**:拥有超过100张床位,每年门急诊接诊量超过20万人次,住院患者超过2000人次。
|
||||
- **实验室设施**:配备了先进的肌电图与脑诱发电位、神经病理、脑电图、经颅超声多普勒、神经生化和免疫、分子生物学实验室,为临床诊断提供了强有力的支持。
|
||||
|
||||
#### 科研与教学
|
||||
|
||||
- **科研成就**:近五年来承担了超过50项科研课题,包括多项国家级重点项目,累计科研经费超过5000万元,并获得了包括国家科技进步奖在内的多个重要奖项。
|
||||
- **教学任务**:承担四川大学华西临床医学院本科生、研究生、进修医师的教学工作,是四川省住院医师规范化培训基地。每年举办多个国家级继续教育学习班,如神经系统疾病高级进展学习班、经颅多普勒超声学习班等,为全国输送大量神经内科专科人才。
|
||||
|
||||
#### 专家团队
|
||||
|
||||
- **现有医生**:共有60余名医生,其中包括教授12人、副教授18人、主治医生20人、住院医生10人,其中博士生导师8人,硕士生导师10人。
|
||||
|
||||
- 知名专家:
|
||||
|
||||
- **李为民**:主任医师,教授,博士研究生导师。擅长脑血管病及神经系统危重疾病的诊治,在国内外发表学术论文150余篇。
|
||||
- **王莉**:现任神经内科主任,教授,博士研究生导师。专注于运动神经元病、周围神经病、肌肉病等神经系统的各种疑难杂症的研究与治疗,发表了超过300篇学术论文,并著书20余本。
|
||||
|
||||
#### 地址与联系方式
|
||||
|
||||
- **地址**:成都市武侯区国学巷37号,四川大学华西医院门诊楼6层。
|
||||
- **电话**:028-85422114(总机)
|
||||
@@ -0,0 +1,13 @@
|
||||
### 四川大学华西医院科室详细介绍
|
||||
|
||||
#### 1、内科学系
|
||||
|
||||
心内科、呼吸与危重症医学科、消化内科、肾内科、血液内科、风湿免疫科、感染性疾病中心、全科医学科(普通内科)、肿瘤中心(含肿瘤内科、放疗科)、老年医学科、内分泌代谢科、重症医学科(ICU/MICU)、儿科、神经内科、心理卫生中心、皮肤性病科、变态反应(过敏)科、急诊科、中医科、康复医学科、临床营养科、罕见病诊治中心。
|
||||
|
||||
#### 2、外科学系
|
||||
|
||||
普外科(含胃肠外科、结直肠外科、胰腺外科、甲状腺外科等亚专业)、骨科、心脏大血管外科、胸外科、泌尿外科、神经外科、血管外科、整形外科/烧伤科、乳腺疾病中心、肝脏外科/肝移植中心、麻醉科、手术室。
|
||||
|
||||
#### 3、其他科室
|
||||
|
||||
妇产科(含妇科、产科、生殖医学中心)、眼科、耳鼻咽喉头颈外科、口腔科(依托华西口腔医学院,全国顶尖)、超声医学科、病理科、检验科、放射科(医学影像中心)、放射治疗科(肿瘤放疗中心)、核医学科、输血科、药剂科、病案管理科、国际医疗部、健康管理中心(体检中心)、临床药理研究中心、转化医学中心、护理部、医务部、医院感染管理部。
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<!--namespace 命名空间:1、与Java接口发生关联 2、为XML中内容提供一个唯一的路径-->
|
||||
<mapper namespace="com.iwe3.langchain4j.mapper.AppointmentMapper">
|
||||
<resultMap id="appmap" type="AppointmentEntity" autoMapping="true">
|
||||
<result column="id_card" property="idCard"/>
|
||||
<result column="doctor_name" property="doctorName"/>
|
||||
</resultMap>
|
||||
<select id="getOne" resultMap="appmap">
|
||||
select * from appointment
|
||||
<where>
|
||||
<if test="r.userName != null">
|
||||
and username = #{r.userName}
|
||||
</if>
|
||||
<if test="r.idcard != null">
|
||||
and id_card = #{r.idcard}
|
||||
</if>
|
||||
<if test="r.department != null">
|
||||
and department = #{r.department}
|
||||
</if>
|
||||
<if test="r.date != null">
|
||||
and date = #{r.date}
|
||||
</if>
|
||||
<if test="r.time != null">
|
||||
and time = #{r.time}
|
||||
</if>
|
||||
<if test="r.doctorName != null">
|
||||
and doctor_name = #{r.doctorName}
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,18 @@
|
||||
你的名字是“小艾”,你是一家名为“四川大学华西医院”的智能客服。
|
||||
你是一个训练有素的医疗顾问和医疗伴诊助手。
|
||||
你态度友好、礼貌且言辞简洁。
|
||||
1、请仅在用户发起第一次会话时,和用户打个招呼,并介绍你是谁。
|
||||
2、作为一个训练有素的医疗顾问:
|
||||
请基于当前临床实践和研究,针对患者提出的特定健康问题,提供详细、准确且实用的医疗建议。请同时考虑可能的病
|
||||
因、诊断流程、治疗方案以及预防措施,并给出在不同情境下的应对策略。对于药物治疗,请特别指明适用的药品名
|
||||
称、剂量和疗程。如果需要进一步的检查或就医,也请明确指示。
|
||||
3、作为医疗伴诊助手,你可以回答用户就医流程中的相关问题,主要包含以下功能:
|
||||
AI分导诊:根据患者的病情和就医需求,智能推荐最合适的科室。
|
||||
AI挂号助手:实现智能查询是否有挂号号源服务;实现智能预约挂号服务;实现智能取消挂号服务。
|
||||
4、你必须遵守的规则如下:
|
||||
在获取挂号预约详情或取消挂号预约之前,你必须确保自己知晓用户的姓名(必选)、身份证号(必选)、预约科室
|
||||
(必选)、预约日期(必选,格式举例:2025-12-12)、预约时间(必选,格式:上午 或 下午)、预约医生(可
|
||||
选)。
|
||||
当被问到其他领域的咨询时,要表示歉意并说明你无法在这方面提供帮助。
|
||||
5、请在回答的结果中适当包含一些轻松可爱的图标和表情。
|
||||
6、今天是 {{current_date}}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.iwe3.langchain4j;
|
||||
|
||||
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
|
||||
import dev.langchain4j.data.document.parser.TextDocumentParser;
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStore;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.nio.file.FileSystems;
|
||||
|
||||
@SpringBootTest
|
||||
public class RagUploadTest {
|
||||
|
||||
@Autowired
|
||||
private EmbeddingStore embeddingStore;
|
||||
|
||||
@Autowired
|
||||
private EmbeddingModel embeddingModel;
|
||||
|
||||
@Test
|
||||
public void testUploadKnowledgeLibrary() {
|
||||
// 使用FileSystemDocumentLoader读取指定目录下的知识库文档
|
||||
var pathMatcher = FileSystems.getDefault()
|
||||
.getPathMatcher("glob:*\\.md");
|
||||
var documents = FileSystemDocumentLoader
|
||||
.loadDocuments("D:/documents", pathMatcher,
|
||||
new TextDocumentParser());
|
||||
|
||||
// 文本向量化并存入向量数据库:将每个片段进行向量化,得到一个嵌入向量
|
||||
EmbeddingStoreIngestor
|
||||
.builder()
|
||||
.embeddingStore(embeddingStore)
|
||||
.embeddingModel(embeddingModel)
|
||||
.build()
|
||||
.ingest(documents);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.iwe3.langchain4j;
|
||||
|
||||
import com.iwe3.langchain4j.record.AppointmentRecord;
|
||||
import com.iwe3.langchain4j.service.IAppointmentService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class XiaoAIAgentApplicationTest {
|
||||
|
||||
@Autowired
|
||||
private IAppointmentService appointmentServiceImpl;
|
||||
|
||||
|
||||
@Test
|
||||
void saveAppointmentEntity() {
|
||||
var record = new AppointmentRecord("贝利亚",
|
||||
"123456789012345678",
|
||||
"内科",
|
||||
"2025-12-12","上午08.30","李娜");
|
||||
appointmentServiceImpl.saveAppointmentEntity(record);
|
||||
}
|
||||
|
||||
@Test
|
||||
void removeById() {
|
||||
appointmentServiceImpl.removeById(1L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOne() {
|
||||
var record = new AppointmentRecord("贝利亚",
|
||||
"123456789012345678",
|
||||
"内科",
|
||||
"2025-12-12","上午08.30","李娜");
|
||||
var entity = appointmentServiceImpl.getOne(record);
|
||||
System.out.println("entity = " + entity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user