基于RAG与知识图谱的微信小程序AI医疗问诊平台设计

发布时间:2026/8/31 4:30:05
基于RAG与知识图谱的微信小程序AI医疗问诊平台设计 今年毕设季我连续被好几个同学问同一个题目基于 LLM 的微信小程序 AI 医疗问诊平台技术栈还特别统一——RAG Spring AI Neo4j 知识图谱 SpringBoot Vue3。有人问我这题能不能做有人问我 RAG 和知识图谱到底怎么配合还有人直接卡在第一步Spring AI 到底怎么调通。先说结论这个项目能做但它的难点不在“接入大模型”而在“让医疗问答变得可靠”。你给用户一个聊天框很容易但用户问“头痛、发烧、咽喉痛是什么病”时模型不能靠感觉答它得能从知识库里找到依据能给出科室建议能规避“自己判断病情”的风险。能做到这一层你才真正理解了 RAG 和知识图谱为什么要同时出现。这篇文章我会按照自己设计这个项目时的思路把整体架构、知识库构建、RAG 与 Neo4j 的协作机制、小程序端注意事项、常见坑点和答辩准备路径完整拆一遍。文章里的代码片段是通用实现结构不是某个完整开源项目的搬运落地时要结合你的 Spring Boot 和 Spring AI 版本调整。1. 这个项目的核心难点不在 AI而在医疗问答的可靠性1.1 为什么普通聊天机器人方案不适合医疗场景如果只是做一个“能聊天”的问诊助手方案太简单了把大模型 API 接进来小程序端发消息后端转发返回流式文本。半天就能跑通。但这只能算 demo不能算医疗问诊平台。医疗场景有三层要求是普通聊天机器人扛不住的第一回答必须有依据。用户问“高血压日常要注意什么”模型如果凭训练数据答可能抓到过时信息甚至把养生偏方当医学建议。RAG 的逻辑是先从医学知识库里检索出相关内容再让模型基于这些内容生成答案。模型不自由发挥回答有出处这是医疗平台的底线。第二实体关系必须清晰。医疗知识不是孤立的文档而是大量实体之间的网络关系疾病对应哪些症状需要做哪些检查常用药物是什么应该挂哪个科室。这些关系用向量检索很吃力用知识图谱却很自然。第三风险边界必须可控。问诊平台不是医生不能给确定性诊断。系统必须能识别自己不适合回答的问题并引导用户去医院就诊。这类“拒答”和“安全提示”策略普通 chat 接口不会主动给你实现。所以这个题目的真正价值不是让模型学会看病而是设计一套“先检索、再组织、最后生成”的知识处理流程。这也是答辩时最值得展开的地方。1.2 这个项目里 RAG 和知识图谱分别扮演什么角色很多人把 RAG 和知识图谱搞成二选一其实在这个系统里它们负责的是两种完全不同的能力。RAG 处理的是非结构化知识。比如你好不容易找到的医学教材、临床指南、疾病科普文档这些是长篇文字适合切块后做向量化用语义相似度做召回。用户问“饭后血糖多少算正常”RAG 能把相关段落找出来。Neo4j 知识图谱处理的是结构化知识。症状、疾病、检查、药物、科室是节点它们之间的“属于”“建议检查”“常用药物”“就诊科室”是关系。用户问“持续干咳伴胸痛应该挂什么科”系统先在图谱里定位症状节点沿着关系找到可能疾病再映射到科室。这个过程是精确的、可解释的不是语义模糊的向量匹配。理想配合方式是RAG 负责提供大段解释性知识知识图谱负责提供精确的实体追溯和路径解释两者结果一起交给 LLM 去组织成用户能读懂的答案。一句话主判断这个项目拼的不是模型聪明不聪明而是知识组织得好不好、检索策略设计得对不对。2. 总体架构一条数据流把六个技术栈串起来2.1 先看懂请求从微信小程序到模型的完整链路整个系统可以看作一条生产线用户在微信小程序里输入问题。小程序把问题通过 HTTP 请求发给 Spring Boot 后端。Spring Boot 使用 Spring AI 的 ChatClient 与 LLM 建立对话但在此之前先做增强检索。RAG 模块把用户问题转为向量从向量数据库里检索相关医疗文档片段。Neo4j 查询模块把问题里的症状实体提取出来在图谱中查询关联疾病、科室、检查项目。把向量检索结果 图谱查询结果 用户问题拼装成 Prompt发送给 LLM。LLM 生成答案后端以流式方式返回给小程序逐字展示。这套链路里Spring AI 的核心价值不是“调用模型”这一个动作而是把模型调用、Prompt 模板、向量检索、结构化数据查询统一编排在一起。如果你只是在代码里硬编码 HTTP 调用大模型 API那 Spring AI 就没有体现出意义。2.2 Spring AI 在这套架构里到底负责什么先别急着写代码你要把 Spring AI 的角色理解成“AI 应用开发框架”不是“大模型客户端”。它主要负责三件事统一的模型接入层封装 OpenAI、通义千问、DeepSeek 等模型通过一个 ChatModel 接口调用切换模型时不用改业务代码。Prompt 与上下文管理支持模板化 Prompt、Message 组装、历史会话记录不用自己拼字符串。RAG 组件提供向量存储抽象、文档读取器、切分器、检索增强链等基础能力。你说的 Spring AI 2.0需要确认一下具体版本状态。按当前公开情况Spring AI 1.0 已经发布2.0 处于迭代期。如果标题写的是 2.0建议先查一下对应里程碑版本的 Maven 坐标和 API 差异不要照抄 1.0 教程避免版本不兼容。2.3 三层架构的职责边界可以按三层来拆层次技术组件主要职责前端展示层微信小程序、Vue3 管理后台问诊对话、历史记录、健康档案展示、后台知识库管理后端服务层Spring Boot、Spring AI用户接口、会话管理、RAG 编排、图谱查询、模型调用、权限控制数据与知识层MySQL、Neo4j、向量数据库用户数据、对话记录、知识图谱、医疗文档向量SpringBoot 4 和 Vue3 都代表了技术栈的“新”但你要注意SpringBoot 4 刚发布不久生态适配还不算完全稳定尤其是一些第三方 starter 可能还没有跟上。选型没有问题但毕设演示阶段要有备选方案至少保证 Spring AI 在目标 Spring Boot 版本上能正常初始化。这个问题放到第 5 部分细说。3. 医疗知识库构建这是项目质量的上限所在3.1 数据从哪来怎么清洗这个项目避不开一个问题医疗数据怎么获取。我用合法、稳妥的路径给你排序。首选是公开的医疗指南和科普文档。比如国家卫健委发布的临床路径、诊疗指南三甲医院官网的科普文章权威医学媒体公开的疾病百科内容。这些内容可以人工整理成文本数量不需要多500 到 1000 条高质量条目就足够支撑毕设演示。其次是结构化医学公开数据集。部分高校和科研机构开放了中文医学实体识别、关系抽取数据集可以用来构建图谱。但使用前要确认授权协议只用于学习研究。不建议直接爬取商业问诊平台的内容有版权和合规风险。毕设答辩也不会因为数据来源“全”而给你加分反而会因为来源不透明被追问。清洗时要注意去除页眉页脚、广告、联系方式统一医学术语表达保留来源链接和更新时间把专有名词如“高血压”统一成标准说法。数据质量直接决定后续向量检索的效果。3.2 RAG 切块策略不是切得越短越好RAG 的效果一大半取决于切块策略。医疗文档尤其讲究上下文完整性。我一般建议这样处理先按章节标题切大块保证同一个主题的内容不被打散。再按段落切块每一块控制在 300 到 800 个中文字符之间。切块时保留文档标题、来源、章节路径作为元数据。对包含症状列表、检查指标、药物用量的段落单独切出来不要混在长段落里。为什么不建议切得太短比如切成 100 字检索时可能召回语义相近但上下文断裂的碎片模型拼不出完整逻辑。为什么不建议切得太长因为向量检索的相似度计算会被大量无关信息稀释而且超出模型上下文窗口时还得做二次截断。注意切块没有一劳永逸的参数。切完之后用 20 个真实医疗问题做一轮召回测试看检索结果里前 5 条是否包含正确答案再决定调大还是调小。3.3 Neo4j 知识图谱怎么设计实体和关系知识图谱不是把文档塞进 Neo4j 就完了你需要先设计本体Ontology。对于医疗问诊场景我建议先从这五类实体和五类关系起步实体类型示例关系类型示例疾病高血压、2型糖尿病疾病 - 症状高血压 - 头晕症状头痛、心悸、多饮疾病 - 检查高血压 - 血压测量检查血常规、糖化血红蛋白疾病 - 药物2型糖尿病 - 二甲双胍药物硝苯地平、阿卡波糖疾病 - 科室高血压 - 心血管内科科室心血管内科、内分泌科症状 - 可能疾病心悸 - 心律失常先建这么多就够支撑问诊的常见路径。Neo4j 的 Cypher 查询核心是// 根据症状查可能疾病和对应科室 MATCH (s:Symptom {name: 干咳})-[r:POSSIBLE_DISEASE]-(d:Disease) MATCH (d)-[:DEPARTMENT]-(dept:Department) RETURN d.name, dept.name, r.weight关键在于图谱里的关系必须有来源或权重。比如“干咳”可能是感冒症状也可能是支气管炎症状。你在关系上设置一个 weight 字段表示这种关联的常见程度或来源权威度检索时要排序不能让模型把所有可能性都当等概率输出。3.4 文档型知识和结构化知识如何并存最常见的错误是把文档切块后向量化又把这些块复制到 Neo4j 里结果两边数据冗余查询结果互相矛盾。更合理的方式是文档型知识进向量数据库用于生成答案时的参考内容。结构化关系进 Neo4j用于精确实体定位和路径解释。两者通过“疾病名称”或“标准实体名”产生交集。举个例子用户问“高血压不能吃哪些食物”。RAG 可能检索到一段“高血压饮食建议”的文档含有低盐、低脂、多果蔬等具体描述图谱查询则找到“高血压”这个疾病节点顺着“推荐饮食”和“避免饮食”关系返回一些结构化条目。两条路径的结果都可以塞进 Prompt让模型综合回答。一种是内容补充一种是逻辑约束缺一不可。4. 从 Demo 到可演示项目四个关键技术实现点4.1 Spring AI 的调用链怎么搭在 Spring Boot 项目里引入 Spring AI 之后通常会有这样一条调用链用户消息进入 Controller。Service 层先调用 RAG API 做向量检索。Service 层再调用 Neo4jService 做图谱查询。把检索结果组装成 Prompt。调用 ChatModel 流式生成回答。通过 SSE 或 WebSocket 推送给小程序。代码结构可以参考Service public class ConsultationService { private final ChatModel chatModel; private final VectorStore vectorStore; private final Neo4jKnowledgeService knowledgeService; public FluxString ask(String userId, String question) { ListDocument docs vectorStore.similaritySearch(question); GraphQueryResult graphResult knowledgeService.queryBySymptom(question); Prompt prompt buildMedicalPrompt(question, docs, graphResult); return chatModel.stream(prompt.getContents()); } }这只是显示调用顺序具体 API 名称和参数在不同版本里有差异。引用方式以 Spring AI 官方文档和你引入的版本为准。4.2 RAG 与图谱的检索策略向量先召回图谱再约束这里有一个很值得写进论文的策略不把所有知识一次性塞给模型而是分阶段召回。比如用户问题“我最近经常头痛有时候还感到恶心应该挂什么科”第一阶段从问题里抽取症状实体“头痛”“恶心”。可以用 LLM 做轻量实体抽取也可以用规则匹配。毕设场景建议先用规则匹配 预置症状词表简单可控如果效果不够再引入 LLM 抽取。第二阶段把症状实体带去 Neo4j 查询。找到关联疾病后按 weight 排序再映射到科室。第三阶段把疾病名和科室名作为查询词去向量数据库检索相关科普文档获得更完整的背景知识。第四阶段组合这三个结果送入模型。这个策略是“先精确定位再补充扩展”。如果反过来先做向量召回模型可能被大段相似但不精确的文献带偏。4.3 微信小程序端的技术选型和展示细节项目标题里同时写“微信小程序”和“Vue3”这里有一个常见混淆需要澄清微信小程序原生开发用的是 WXML/WXSS/JS不是 Vue3 语法。如果你写 Vue3通常指的是用 uni-app 或 Taro 这类跨端框架来生成小程序或者 Vue3 用于后台管理端。我建议把定位拆清楚用户问诊端用微信小程序不管是用原生还是 uni-app都要做聊天式界面。管理后台用 Vue3 Element Plus统一管理用户、对话日志、知识库文档、图谱数据。小程序端最影响体验的不是 UI 动画而是流式响应。你发一句话等 10 秒才看到完整回答用户会觉得系统很慢。要优先实现字级或句级流式展示让用户看到模型“正在生成”。这个功能后端用 SSE 或 WebSocket小程序端用wx.request的 enableChunked 能力或 WebSocket 接收分片逐段追加到消息气泡里。建议用微信开发者工具的真机预览模式调试流式效果。开发工具模拟器和真机在网络行为上经常不一致不要等到答辩前一天才发现。4.4 会话上下文和用户意图识别按最小可用设计第一次做这个项目别急着把上下文管理做得很复杂。两个原则足够第一只保留最近 5 到 8 轮对话。把历史摘要和当前问题一起拼到 Prompt 里。对话超过窗口就丢弃最早的消息避免 Token 过长。第二区分问诊意图和非问诊意图。比如用户发“你好”“谢谢”“你是谁”不需要走 RAG 和知识图谱直接由模型回答即可。可以通过关键词或轻量分类识别。如果用户问“吃什么能治癌症”这类高风险问题要触发安全回复模板提示“不能替代医生诊断请及时就医”。这些边界规则看着不复杂但它们是医疗问诊平台区别于普通聊天机器人的关键所在。5. 最容易翻车的四个场景和排查路径5.1 检索结果为空或相关性差现象用户问题很明确但 RAG 返回的文档片段完全不相关或者 Neo4j 查询结果为空。排查顺序先检查文本是否进入向量库。常见问题是已经执行了切块和向量化但没有调用 store 保存或者向量数据库服务没启动。检查问题与文档片段的语言一致性。用户用口语文档用书面语可能导致语义相似度偏低。检查知识图谱里的实体名称和用户问题里的症状名是否一致。比如用户说“头晕”图谱里只有“眩晕”匹配不到。检查 Neo4j 服务地址、账号密码、数据库名称是否对得上。开发环境最容易忽略 Neo4j 默认数据库是neo4j如果你新建了medical.db又没切换查不到任何数据。对于匹配不到的问题最实用的解决办法是维护一个“同义词表”或“别名表”把口语化表达映射到标准术语。比如“脑袋疼”映射到“头痛”。5.2 模型幻觉回答与检索内容不一致现象检索结果明明说“高血压患者每日盐摄入量应低于 5 克”模型生成时却写成“可以不限盐”。排查路径检查 Prompt 是否明确约束了“只能基于给定知识库内容回答”。Spring AI 的 System Prompt 可以写成固定模板去掉模型自由发挥的空间。检查是不是检索到的内容太多了模型抓不住重点。适当减少 Top-K 返回数量比如从 10 条降到 5 条。检查模型温度参数。医疗场景建议把 temperature 调低到 0.2 以下或直接设置为 0。温度越高回答随机性越强不适合医疗场景。检查是否有多个矛盾来源同时被召回。比如一篇文档说“高血压标准是 140/90”另一篇说“新版标准是 130/80”模型可能综合出错误结论。这需要在数据清洗时统一标准或在 Prompt 里要求“如果存在矛盾提示信息需要进一步确认”。5.3 版本不兼容Spring AI、Spring Boot、Neo4j 驱动互相打架这个项目最容易卡住的地方不是业务逻辑而是启动阶段报错。排查顺序先确认 Spring Boot 版本和 Spring AI 版本的兼容关系。Spring AI 官方文档通常会在 Release Notes 里标明支持的 Spring Boot 版本范围。Neo4j 驱动版本要和 Neo4j 服务端版本匹配。比如 Neo4j 4.x 对应旧驱动Neo4j 5.x 需要更新驱动这个不能混。向量数据库组件选型要提前确认。Spring AI 提供了多种向量存储适配器本地开发建议先用轻量级实现比如基于内存的 SimpleVectorStore避免一开始就引入复杂中间件。如果使用 Docker 安装 Neo4j要确认容器内部端口和宿主机端口的映射关系连接失败常常是端口没映射对。# 常见 Docker 启动 Neo4j 的命令结构 docker run -d \ --name neo4j-medical \ -p 7474:7474 -p 7687:7687 \ -e NEO4J_AUTHneo4j/yourpassword \ neo4j:5.26不同 Neo4j 版本的镜像 tag 不一样启动前用docker images和docker ps检查容器状态。5.4 小程序端白屏、报错、无法访问接口排查顺序先看微信开发者工具的 Network 面板确认请求是否发出、响应码是多少。注意开发环境中关闭“不校验合法域名”前要确认你只是本地调试。检查本地开发服务器是否监听在小程序可访问的地址上。不能只监听 127.0.0.1真机调试时手机访问不到本机 localhost。检查小程序端是不是用了未编译的 npm 包。小程序不支持直接 require 所有 Node.js 包需要先构建 npm。检查页面栈。微信小程序页面跳转层级过深时用wx.navigateTo会失效需要改用wx.redirectTo或wx.reLaunch这是关键词里出现pageindex和“分包异步化”时最常关联的问题。问诊对话页要考虑分包加载避免主包体积超限。6. 从毕设题目到能演示的项目还需要走完哪几段路6.1 第一优先级先把最小闭环跑通不要一上来就想着做完整平台。推荐顺序是后端先写一个最简单接口直接调用 ChatModel 返回一句话。小程序端展示这句话确认网络通路正常。引入 Spring AI 的向量能力手动放入 20 篇医疗文档做一次检索测试。在 Neo4j 里建 50 个疾病节点和 200 条关系手工写 Cypher 查询确认能查到科室。把检索结果拼进 Prompt让模型说出答案和参考来源。最后再做流式、历史记录、后台管理。每完成一步都保留一个可演示的截图或录屏写论文和答辩 PPT 时都需要这些过程材料。6.2 第二优先级在“玩具”和“毕设系统”之间补齐差距演示时很多人一眼就能看出项目是纯 demo 还是完整系统。差距通常体现在用户登录和会话隔离。至少要有 openId 绑定、会话表、历史记录表。知识库管理页面。允许管理员上传文档进行切割、向量化并查看状态。对话日志。记录用户的每次提问、系统回答、检索命中的文档 ID。这个记录既是调试工具也是论文里的测试数据来源。错误兜底。模型调用失败时返回固定提示而不是空白或报错。6.3 答辩时最可能被追问的几个问题提前准备好这几个问题的答案比背稿更有用为什么用 RAG 而不是微调模型答医疗知识更新快RAG 可以随时更新知识库而无需重新训练模型且 RAG 能附来源可解释性更强。为什么还需要知识图谱答很多问诊问题本质上是实体关系查询图谱路径清晰可解释能纠正纯语义检索的模糊性。如果用户问的问题在知识库里查不到怎么办答先触发拒答模板告知无法提供确定性建议引导前往正规医疗渠道。如何评估回答质量答建立了测试集包含 50 个常见医疗问题分别评估检索召回率和回答正确率。虽然不够完整但能证明系统具备效果验证能力。6.4 对毕设项目使用 LLM 的几条实在建议第一模型选择没必要追求最大最强。用国内大模型 API 或开源模型部署都能完成项目优先选文档完善、接入方便的。毕设评分看的是系统设计、工程完整度和对问题理解的深度不是模型推理分数。第二本地部署大模型不是必选项。如果你的机器不支持就老老实实走 API 方案。需要展示“本地化”能力时可以说明模型层被 Spring AI 抽象后续可无缝切换到本地部署模型。第三所有外部服务和数据集都要在论文里注明来源。既体现学术规范也避免答辩评审追问来源时语焉不详。收尾先解决知识组织再谈模型强弱这个题目很容易让人误以为“AI 医疗问诊 接入大模型 聊天气泡”但真正把系统做完后你会发现大模型只是最后一步的生成器前面还有知识清洗、切块、向量化、图谱建模、检索策略、安全兜底、流式链路。项目质量的高下不取决于模型多聪明而取决于你让模型站在多少真实、可靠、有结构的医学知识之上。再提醒一句开工时别急着调参数、写炫酷界面。先把一条最简单的问题问答链路完整打通再逐步叠加 RAG 和图谱。链路畅通了后面所有优化才有意义。