Skip to content

SmartMed 智能医疗预约系统

一、项目概述

基于 LangChain4j 的 AI 智能医疗客服系统,通过自然语言对话实现预约挂号、取消挂号、就诊提醒等功能。

二、项目架构

┌─────────────────────────────────────────────────────────┐
│              SmartMed AI智能医疗客服 (端口8080)           │
│  ┌──────────────┐  ┌──────────────┐  ┌───────────────┐  │
│  │ LangChain4j  │  │ RAG知识检索   │  │ MongoDB聊天记忆│  │
│  │  AI对话引擎   │  │  (Pinecone)  │  │               │  │
│  └──────┬───────┘  └──────┬───────┘  └───────┬───────┘  │
│         └─────────────────┼──────────────────┘          │
│                    AppointmentTools                      │
│              (预约挂号/取消挂号/查询号源)                  │
└─────────────────────────────┬───────────────────────────┘
                              │ HTTP调用
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
        ┌──────────┐   ┌──────────┐    ┌──────────┐
        │ hosp服务  │   │ order服务 │    │  MySQL   │
        │ (8201)   │   │ (8207)   │    │ (3310)   │
        │ 排班查询  │   │ 订单处理  │    │ 预约记录  │
        └──────────┘   └──────────┘    └──────────┘

三、技术栈

分类技术用途
AI框架LangChain4j 1.4.0LLM应用开发框架
大模型通义千问 / DeepSeek对话生成
向量库PineconeRAG知识检索
后端Spring Boot 3.2.6基础框架
ORMMyBatis-Plus 3.5.11数据访问
数据库MySQL预约记录存储
数据库MongoDB对话历史存储
消息队列RabbitMQ就诊提醒异步通知
部署Docker容器化

四、核心模块

4.1 项目结构

src/main/java/com/xiaoxia/ai/langchain4j/
├── AiMedical.java              # 启动类
├── assistant/
│   └── XiaoXiaAssitant.java    # AI服务接口
├── config/
│   ├── XiaoXiaChatCongfigration.java  # 聊天记忆配置
│   └── EmbeddingStoreConfig.java      # 向量存储配置
├── controller/
│   └── XiaoXiaController.java  # REST接口
├── entity/
│   ├── Appointment.java        # 预约实体
│   └── ChatMessages.java       # 聊天记录实体
├── mapper/
│   └── AppointmentMapper.java  # 数据访问
├── service/
│   └── AppointmentService.java # 业务逻辑
├── store/
│   └── MongoChatMemoryStore.java # MongoDB聊天存储
└── tools/
    └── AppointmentTools.java   # 预约挂号工具

4.2 预约挂号 (AppointmentTools.java)

java
@Tool(name = "预约挂号")
public String bookAppointment(Appointment appointment) {
    // 1. 检查重复预约
    Appointment db = appointmentService.getOne(appointment);
    if (db != null) {
        return "您已预约过该科室,请勿重复预约";
    }

    // 2. 调用外部订单服务
    JSONObject result = executePost("http://localhost:8207",
        "/api/order/orderInfo/auth/AiSubmitOrder/", bodys);

    // 3. 保存本地记录
    appointmentService.save(appointment);
}

业务流程:

  1. AI通过对话收集用户信息(姓名、身份证、科室、日期、时段)
  2. 调用 queryDepartment 查询号源
  3. 用户确认后调用 bookAppointment 执行预约
  4. HTTP调用外部订单服务
  5. MySQL保存预约记录

4.3 取消挂号

java
@Tool(name = "取消预约挂号")
public String cancelAppointment(Appointment appointment) {
    // 1. 查询本地记录
    Appointment db = appointmentService.getOne(appointment);

    // 2. 调用外部服务取消
    executePost("http://localhost:8207",
        "/api/order/orderInfo/auth/AiCancelOrder/", bodys);

    // 3. 删除本地记录
    appointmentService.removeById(db.getId());
}

4.4 号源查询

java
@Tool(name = "查询是否有号源")
public Boolean queryDepartment(
    @P("科室名称") String name,
    @P("日期") String date,
    @P("时间,可选值:上午(0)、下午(1)") String time,
    @P(value = "医生名称", required = false) String doctorName) {

    // 调用医院服务查询排班
    JSONObject result = executePost("http://localhost:8201",
        "/api/hosp/selectSchedule", bodys);
}

五、MongoDB 聊天记忆

5.1 实现类 (MongoChatMemoryStore.java)

java
@Component
public class MongoChatMemoryStore implements ChatMemoryStore {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public List<ChatMessage> getMessages(Object memoryId) {
        // 根据memoryId查询聊天记录
        Criteria criteria = Criteria.where("memoryId").is(memoryId);
        ChatMessages chatMessages = mongoTemplate.findOne(query, ChatMessages.class);
        return ChatMessageDeserializer.messagesFromJson(chatMessages.getContent());
    }

    @Override
    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
        // 序列化并存储聊天记录
        update.set("content", ChatMessageSerializer.messagesToJson(messages));
        mongoTemplate.upsert(query, update, ChatMessages.class);
    }
}

5.2 数据结构

java
@Document("XiaoXiaChatMessages")
public class ChatMessages {
    private ObjectId id;
    private String memoryId;    // 会话ID
    private String content;     // JSON序列化的聊天记录
}

5.3 为什么用MongoDB?

  • 文档型存储天然适合JSON格式的对话历史
  • Schema灵活,易于扩展
  • 读写性能高

六、RAG 知识检索

6.1 向量存储配置

java
@Bean
EmbeddingStore<TextSegment> embeddingStore() {
    return PineconeEmbeddingStore.builder()
        .apiKey("xxx")
        .nameSpace("default")
        .index("llama-text-embed-v2-index")
        .build();
}

6.2 知识库加载

java
// 加载医院相关文档
Document doc1 = FileSystemDocumentLoader.loadDocument("医院信息.md");
Document doc2 = FileSystemDocumentLoader.loadDocument("科室信息.md");

// 向量化并存储
EmbeddingStoreIngestor.builder()
    .embeddingStore(embeddingStore)
    .embeddingModel(embeddingModel)  // 阿里云text-embedding-v3
    .build()
    .ingest(documents);

6.3 RAG工作流程

  1. 用户提问 → 文本向量化
  2. 在Pinecone中搜索相似向量
  3. 返回相关的医院/科室信息
  4. 将检索结果注入到AI提示词中
  5. AI基于检索内容生成回答

七、AI服务配置

7.1 XiaoXiaAssitant 接口

java
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "qwenStreamingChatModel",  // 流式模型
    chatMemoryProvider = "xiaoXiaChatMemoryProvider", // MongoDB记忆
    tools = "appointmentTools",  // 预约挂号工具
    contentRetriever = "xiaoxiaContentRetriever"  // RAG检索器
)
public interface XiaoXiaAssitant {
    @SystemMessage(fromResource = "xiaoxia-prompt-template.txt")
    Flux<String> chat(@MemoryId Long memoryId, @UserMessage String message);
}

7.2 关键特性

  • 流式输出Flux<String> 实现SSE
  • 多轮对话:MongoDB持久化聊天记忆
  • Function Calling:AI自动调用预约工具
  • RAG知识检索:Pinecone向量库

八、API接口

java
@PostMapping(value = "/chat", produces = "text/stream;charset=utf-8")
public Flux<String> chat(@RequestBody ChatForm chatForm) {
    return xiaoXiaAssitant.chat(chatForm.getMemoryId(), chatForm.getMessage());
}

请求示例:

json
POST /xiaozhi/chat
{
    "memoryId": 12345,
    "message": "我想预约明天上午的神经内科"
}

九、Docker部署

项目依赖的服务通过Docker容器运行:

  • MySQL (端口3310)
  • MongoDB
  • RabbitMQ

十、面试问答

Q1: 为什么用MongoDB存聊天记录?

聊天记录是JSON格式,MongoDB文档型存储天然适合;Schema灵活易扩展;读写性能高。

Q2: RabbitMQ在项目中怎么用的?

用于就诊提醒的异步通知。预约成功后发消息到队列,消费者处理短信/推送通知,实现服务解耦。

Q3: 预约挂号的业务流程?

AI收集信息 → 查询号源 → 用户确认 → 调用订单服务 → 保存本地记录 → 返回结果。

Q4: 如何保证不重复预约?

预约前先查本地MySQL,检查同一用户+科室+日期是否已存在记录。

Q5: Function Calling如何实现?

使用@Tool注解定义工具方法,AI根据用户意图自动选择调用,工具返回结果后AI继续生成回复。

Q6: 流式输出的优势?

用户体验好,实时看到回复;减少等待时间感知;适合长文本生成场景。

Q7: RAG的工作原理?

文档分块 → 向量化 → 存储到Pinecone → 查询时问题向量化 → 相似度搜索 → 注入上下文。

Q8: 微服务之间如何通信?

通过HTTP调用,本项目调用医院服务(8201)查询排班,调用订单服务(8207)处理预约。

十一、简历写法

项目名称:SmartMed 智能医疗预约系统

项目描述:
基于LangChain4j的AI智能医疗客服系统,通过自然语言对话实现预约挂号、
取消挂号、就诊提醒等功能,调用后端微服务完成业务处理。

技术栈:
- AI框架:LangChain4j + 通义千问/DeepSeek
- 后端:Spring Boot 3.x + Spring Cloud(微服务调用)
- 数据库:MySQL(预约记录)+ MongoDB(对话历史)
- 消息队列:RabbitMQ(就诊提醒异步通知)
- 向量库:Pinecone(RAG知识检索)
- 部署:Docker容器化

核心职责:
1. 实现AI对话引擎,支持Function Calling自动调用预约工具
2. 设计MongoDB聊天记忆存储,支持多轮对话上下文
3. 集成RabbitMQ实现就诊提醒异步推送
4. 通过HTTP调用医院排班、订单等微服务接口

十二、项目亮点

  1. AI + 传统业务结合 - 用LLM理解用户意图,自动调用业务工具
  2. RAG知识检索 - Pinecone向量库存储医院/科室信息
  3. 流式输出 - WebFlux实现SSE,用户体验好
  4. 多轮对话记忆 - MongoDB持久化,支持上下文理解
  5. 微服务架构 - AI层与业务层解耦,通过HTTP通信

贡献者

The avatar of contributor named as 四季夏目 四季夏目
The avatar of contributor named as Claude Opus 4.5 Claude Opus 4.5

页面历史

最近更新

基于 VitePress 搭建