一、项目背景与核心目标

基于 LangChain4j 实现北京协和医院智能客服(硅谷小智),核心功能包括:

  • 医疗咨询:提供病因、诊断、治疗、预防等医疗建议;
  • 就医伴诊:AI 分导诊、挂号查询 / 预约 / 取消;
  • 会话能力:聊天记忆(上下文)、记忆持久化(MongoDB)、个性化提示词;
  • 交互规范:友好礼貌、仅首次会话打招呼、跨领域咨询致歉、带可爱表情。

二、核心组件实现

2.1 1. 定义小智助手接口(XiaozhiAgent)

通过 @AiService 注解声明 AI 服务,指定聊天模型、记忆提供者,结合 @SystemMessage/@MemoryId/@UserMessage 实现提示词和会话控制。

package com.atguigu.java.ai.langchain4j.assistant;

import dev.langchain4j.service.*;
import dev.langchain4j.service.spring.AiService;
import static dev.langchain4j.service.spring.AiServiceWiringMode.EXPLICIT;

/**
 * 硅谷小智(北京协和医院智能客服)核心接口
 */
@AiService(
    wiringMode = EXPLICIT,          // 显式绑定模式(精准控制依赖)
    chatModel = "qwenChatModel",    // 指定使用的大模型(如通义千问)
    chatMemoryProvider = "chatMemoryProviderXiaozhi" // 绑定自定义的聊天记忆提供者
)
public interface XiaozhiAgent {

    /**
     * 核心聊天方法
     * @param memoryId 会话记忆ID(用于隔离不同用户的上下文)
     * @param userMessage 用户输入的问题
     * @return 小智的回复
     */
    @SystemMessage(fromResource = "zhaozhi-prompt-template.txt") // 从资源文件加载系统提示词
    String chat(@MemoryId Long memoryId, @UserMessage String userMessage);
}

2.2 2. 系统提示词模板(zhaozhi-prompt-template.txt)

放置在 resources 根目录,定义小智的角色、规则、回复风格,包含 {{current_date}} 动态占位符(自动填充当前日期)。

txt

你的名字是“硅谷小智”,你是一家名为“北京协和医院”的智能客服。
你是一个训练有素的医疗顾问和医疗伴诊助手。
你态度友好、礼貌且言辞简洁。

### 核心规则
1. 仅在用户发起第一次会话时,和用户打个招呼,并介绍你是谁。
2. 作为医疗顾问:
   请基于当前临床实践和研究,针对患者提出的特定健康问题,提供详细、准确且实用的医疗建议。
   需包含可能的病因、诊断流程、治疗方案以及预防措施,并给出不同情境下的应对策略。
   涉及药物治疗时,明确药品名称、剂量和疗程;需要就医/检查时,明确指示。
3. 作为医疗伴诊助手(挂号相关):
   - AI分导诊:根据病情/需求推荐最合适的科室;
   - AI挂号助手:支持查询号源、预约挂号、取消挂号;
   - 操作挂号/取消挂号前,必须确认用户的姓名(必选)、身份证号(必选)、预约科室(必选)、预约日期(格式:2025-04-14,必选)、预约时间(上午/下午,必选)、预约医生(可选)。
4. 跨领域咨询:被问到医疗/挂号以外的问题时,致歉并说明无法提供帮助。
5. 回复风格:适当添加轻松可爱的图标和表情(如😊、💊、🏥)。

### 补充信息
今天是 {{current_date}}。

2.3 3. 配置聊天记忆(持久化 + 隔离)

通过 @Configuration 配置类创建 ChatMemoryProvider,实现会话记忆的持久化(MongoDB)和隔离(按 memoryId 区分用户),控制最大记忆消息数。

package com.atguigu.java.ai.langchain4j.config;

import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.memory.store.MongoChatMemoryStore;
import dev.langchain4j.service.ChatMemoryProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 硅谷小智的聊天记忆配置
 */
@Configuration
public class XiaozhiAgentConfig {

    // 注入MongoDB持久化存储对象(需提前配置MongoDB连接)
    @Autowired
    private MongoChatMemoryStore mongoChatMemoryStore;

    /**
     * 创建小智专属的聊天记忆提供者
     * @return 按memoryId隔离的聊天记忆
     */
    @Bean
    ChatMemoryProvider chatMemoryProviderXiaozhi() {
        // 为每个memoryId创建独立的MessageWindowChatMemory
        return memoryId -> MessageWindowChatMemory.builder()
                .id(memoryId)               // 会话ID(用户唯一标识)
                .maxMessages(20)            // 最大记忆20条消息(控制上下文长度)
                .chatMemoryStore(mongoChatMemoryStore) // 持久化到MongoDB
                .build();
    }
}

2.4 4. 封装对话请求对象(ChatForm)

统一接收前端 / 测试端的对话请求参数,包含会话 ID 和用户消息。

package com.atguigu.java.ai.langchain4j.bean;

import lombok.Data;

/**
 * 聊天请求表单对象
 */
@Data // Lombok注解,自动生成get/set/toString等方法
public class ChatForm {
    private Long memoryId; // 对话ID(用户唯一标识,用于记忆隔离)
    private String message;// 用户输入的问题/指令
}

2.5 5. 控制器层(Controller)

暴露接口供外部调用,接收用户请求并转发给 XiaozhiAgent

package com.atguigu.java.ai.langchain4j.controller;

import com.atguigu.java.ai.langchain4j.assistant.XiaozhiAgent;
import com.atgu.java.ai.langchain4j.bean.ChatForm;
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.RestController;

/**
 * 硅谷小智前端交互接口
 */
@RestController
public class XiaozhiController {

    @Autowired
    private XiaozhiAgent xiaozhiAgent;

    /**
     * 聊天接口
     * @param chatForm 聊天请求参数(memoryId + message)
     * @return 小智的回复
     */
    @PostMapping("/xiaozhi/chat")
    public String chat(@RequestBody ChatForm chatForm) {
        // 调用小智核心方法
        return xiaozhiAgent.chat(chatForm.getMemoryId(), chatForm.getMessage());
    }
}

2.6 6. 测试方法

package com.atguigu.java.ai.langchain4j;

import com.atguigu.java.ai.langchain4j.assistant.XiaozhiAgent;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class XiaozhiAgentTest {

    @Autowired
    private XiaozhiAgent xiaozhiAgent;

    /**
     * 测试小智核心功能
     */
    @Test
    public void testXiaozhiChat() {
        // 第一次会话(memoryId=1,用户首次提问)
        String answer1 = xiaozhiAgent.chat(1L, "我最近胃疼,该怎么办?");
        System.out.println("小智回复1:" + answer1);
        // 预期回复:打招呼+医疗建议(如“你好呀😊!我是硅谷小智,协和医院的智能客服~胃疼可能是胃炎/胃溃疡等原因💊,建议先做胃镜检查🏥,日常避免辛辣饮食...)

        // 第二次会话(同一memoryId,上下文连续)
        String answer2 = xiaozhiAgent.chat(1L, "那我该挂哪个科室?");
        System.out.println("小智回复2:" + answer2);
        // 预期回复:基于上文推荐科室(如“胃疼建议挂消化内科哦😜,消化内科主要处理胃肠相关疾病~”)

        // 跨领域咨询测试
        String answer3 = xiaozhiAgent.chat(1L, "怎么订机票?");
        System.out.println("小智回复3:" + answer3);
        // 预期回复:致歉(如“抱歉呀😅,我是协和医院的智能客服,暂时无法解答订机票的问题哦~”)
    }
}

三、待优化与扩展方向

3.1 1. 信息查询能力增强(RAG 检索增强生成)

当前提示词仅定义规则,但缺乏医院 / 科室 / 医生的真实数据,需结合 RAG 实现精准信息查询:

  • 数据准备:将协和医院的位置、营业时间、科室列表、医生信息(职称、擅长领域、出诊时间)存入向量数据库(如 Milvus/PGVector);
  • RAG 集成:在 XiaozhiAgent 中添加 RAG 检索逻辑,用户询问 “协和医院在哪”“消化内科有哪些医生” 时,从向量库检索真实数据并生成回复;
  • 优势:避免大模型 “幻觉”,保证信息准确。

3.2 2. 业务功能落地(Function Calling 函数调用)

当前仅定义了挂号 / 取消挂号的规则,需通过 Function Calling 对接真实业务系统:

  • 步骤 1:定义业务函数(如查询号源、预约挂号、取消挂号):

    // 挂号服务接口
    public interface RegistrationService {
        // 查询科室号源
        String queryRegistrationSource(String department, String date);
        // 预约挂号
        String register(String name, String idCard, String department, String date, String time, String doctor);
        // 取消挂号
        String cancelRegistration(String name, String idCard, String department, String date);
    }
    
  • 步骤 2:在 LangChain4j 中配置 Function Calling,让大模型根据用户指令自动调用上述函数;
  • 步骤 3:函数执行结果返回给大模型,由大模型整理成自然语言回复用户(如 “已为你预约 2025-04-14 上午消化内科张医生的号😘,请携带身份证前往就诊~”)。

3.3 3. 其他优化点

  • 参数校验:在 Controller 层校验 ChatFormmemoryIdmessage 非空,挂号相关指令校验姓名 / 身份证等必填参数;
  • 异常处理:添加全局异常处理器,捕获大模型调用 / 数据库 / 业务系统异常,返回友好提示;
  • 多轮会话优化:调整 maxMessages 数量,平衡上下文长度和性能;
  • 表情 / 格式标准化:定义固定的表情库,避免回复风格混乱。

四、核心总结

  1. 硅谷小智的核心是 @AiService 注解的 XiaozhiAgent 接口,通过 @SystemMessage 定义角色 / 规则,@MemoryId 实现会话隔离;
  2. 聊天记忆通过 ChatMemoryProvider 配置,结合 MongoChatMemoryStore 实现持久化,maxMessages 控制上下文长度;
  3. 现阶段实现了基础的医疗咨询 / 伴诊规则,后续需通过 RAG 补充真实信息、Function Calling 对接业务系统,完成功能落地。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐