news 2026/9/4 8:05:45

Java 毕业设计:Spring Boot 接入 DeepSeek 实现中医药 AI 服务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java 毕业设计:Spring Boot 接入 DeepSeek 实现中医药 AI 服务

一、业务目标

杏林堂中医药服务平台集成了四项 AI 能力:

能力输入输出与展示
药性图谱分析单味药材资料性味、归经、功效及关系图
智能推荐症状、体质等信息平台在售药材范围内的辅助建议
药方检测药材、剂量、特殊人群风险等级、依据、调整建议
智能问答自由问题科普型自然语言回答

工程上的难点不是“调用一次 API”,而是让模型输出能够被程序稳定解析、阻止模型引用平台不存在的药材、保存调用记录,并在模型或网络异常时给出可控反馈。

医疗健康相关系统还必须明确边界:AI 输出只能作为科普与辅助参考,不能替代医师诊断和处方;出现急重症、过敏或不良反应时,应引导用户及时就医。

二、为什么选择 Java 17 HttpClient

项目没有引入大模型 SDK,而是直接使用 JDK 自带的java.net.http.HttpClient。优点是依赖少、请求结构透明、便于根据 API 文档调整参数。

客户端初始化如下:

privatestaticfinalStringAI_URL="https://api.deepseek.com/chat/completions";privatefinalObjectMapperobjectMapper=newObjectMapper();privatefinalHttpClienthttpClient=HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(20)).build();

API Key 不应写死在源码中。项目将ai_enableddeepseek_api_key保存在系统配置表,由超级管理员在后台维护:

publicvoidensureAiEnabled(){if(!"1".equals(getConfigValue("ai_enabled"))){thrownewBusinessException("AI功能已关闭");}}publicStringrequireApiKey(){StringapiKey=getConfigValue("deepseek_api_key");if(!StringUtils.hasText(apiKey)){thrownewBusinessException("DeepSeek API Key 未配置");}returnapiKey;}

正式环境中还应对 Key 加密存储或通过密钥管理服务注入,并确保接口、日志和异常信息都不会输出完整 Key。

三、构造 JSON Mode 请求

AI 结果需要直接映射为 Java 对象,因此请求中启用 JSON 输出模式:

ObjectNoderoot=objectMapper.createObjectNode();root.put("model","deepseek-chat");root.put("stream",false);ObjectNoderesponseFormat=objectMapper.createObjectNode();responseFormat.put("type","json_object");root.set("response_format",responseFormat);ArrayNodemessages=objectMapper.createArrayNode();ObjectNodesystemMsg=objectMapper.createObjectNode();systemMsg.put("role","system");systemMsg.put("content",systemPrompt);ObjectNodeuserMsg=objectMapper.createObjectNode();userMsg.put("role","user");userMsg.put("content",userPrompt);messages.add(systemMsg);messages.add(userMsg);root.set("messages",messages);

然后发送 HTTP 请求:

HttpRequestrequest=HttpRequest.newBuilder().uri(URI.create(AI_URL)).timeout(Duration.ofSeconds(90)).header("Authorization","Bearer "+apiKey).header("Content-Type","application/json").POST(HttpRequest.BodyPublishers.ofString(objectMapper.writeValueAsString(root))).build();HttpResponse<String>response=httpClient.send(request,HttpResponse.BodyHandlers.ofString());

除了设置response_format,提示词中仍需明确:“只输出一个合法 JSON 对象,不要输出解释文字,不要使用 Markdown 代码块”,并给出字段名称、类型和示例。JSON Mode 可以提高稳定性,但不能代替服务端校验。

四、解析失败自动重试与 JSON 清洗

模型偶尔仍可能返回 Markdown 围栏,或第一次输出字段不完整。项目封装统一入口,首次调用或解析失败后自动重试一次:

publicAiJsonResultcallJson(StringapiKey,StringsystemPrompt,StringuserPrompt){try{returndoCall(apiKey,systemPrompt,userPrompt);}catch(Exceptionfirst){try{returndoCall(apiKey,systemPrompt,userPrompt);}catch(Exceptionsecond){thrownewBusinessException("AI服务暂时不可用,请稍后重试");}}}

解析前对常见围栏进行清理:

privateStringcleanJson(Stringraw){if(raw==null){return"{}";}Stringtext=raw.trim();if(text.startsWith("```")){text=text.replaceFirst("^```json\\s*","").replaceFirst("^```\\s*","").replaceFirst("\\s*```$","");}returntext.trim();}

重试次数不能无限增加。模型输出结构错误时,盲目重试会放大费用和接口延迟。更合理的做法是有限重试、记录错误摘要,并向前端返回可理解的降级提示。

五、智能推荐中的“药材白名单”

大模型可能生成平台数据库中不存在或已经下架的药材。若前端直接根据模型返回的medicineId跳转,会出现空页面,甚至把不受平台管理的内容包装成可购买商品。

项目采用“两层约束”:

第一层:将数据库药材目录注入 Prompt

publicStringbuildCatalogText(){List<MedicineInfo>list=medicineInfoMapper.selectList(newLambdaQueryWrapper<MedicineInfo>().eq(MedicineInfo::getStatus,1));returnlist.stream().map(m->String.join("|",String.valueOf(m.getId()),nullToEmpty(m.getMedicineName()),nullToEmpty(m.getNature()),nullToEmpty(m.getMeridian()),nullToEmpty(m.getEffect()))).collect(Collectors.joining("\n"));}

紧凑的id|名称|性味|归经|功效格式比完整 JSON 更节省 Token。提示词要求模型只能从目录中选择medicineId

第二层:后端二次过滤

publicSet<Long>validMedicineIds(){returnmedicineInfoMapper.selectList(newLambdaQueryWrapper<MedicineInfo>().eq(MedicineInfo::getStatus,1)).stream().map(MedicineInfo::getId).collect(Collectors.toSet());}

解析模型结果后,将返回 ID 与合法集合求交集,不在白名单中的 ID 一律剔除。这里体现了一条重要原则:Prompt 约束属于“软约束”,服务端校验才是“硬约束”。

当在售药材很多时,不宜把整个目录都塞进 Prompt。可以先使用关键词、向量检索或数据库规则召回候选药材,再让模型只在候选集内分析。

六、四项能力如何分别落地

1. 药性图谱分析

后端把药材名称、性味、归经、功效、禁忌等字段传给模型,要求返回节点与关系。结果写入ai_medicine_analysis,一味药材对应一条缓存记录。前端使用 EChartsgraph力导向图,将药材放在中心,把性味、归经、功效和配伍关系作为周边节点。

缓存可以减少相同药材的重复调用。管理员更新药材资料后,可通过“强制重新生成”刷新分析结果。

2. 智能推荐

用户输入症状和体质,系统拼接在售药材目录,请模型返回建议药材、推荐理由和注意事项。返回结果先经过 ID 白名单过滤,再写入ai_recommend

这里应避免使用“自动开方”“确诊”等表述。更稳妥的产品定位是健康知识推荐,并持续显示“请咨询专业医师”的提示。

3. 药方检测

用户添加药材和剂量,并选择是否为儿童或妊娠人群。模型检查十八反、十九畏、剂量异常和特殊人群风险,返回safewarndanger,同时给出风险条目、依据和调整建议,记录写入ai_prescription_check

高风险规则不能只依赖大模型。正式医疗系统应把明确、稳定的禁忌和剂量规则沉淀为可审计的规则库,模型负责解释和补充,最终仍由药师或医师审核。

4. 智能问答

智能问答允许匿名访问,前端左侧展示分组常见问题,右侧进行对话。问答记录写入ai_chat,可统计热门关键词和调用成本。匿名访问也应设置频率限制、敏感内容过滤和单次输入长度限制,避免接口被滥用。

七、结果落库的价值

AI 接口返回后立即丢弃结果,看似简单,实际上不利于维护。将结果落库可以获得:

  • 相同药材分析直接命中缓存,减少费用和等待时间;
  • 追踪模型、Token 数与生成时间;
  • 后台审计风险内容;
  • 统计用户关注的症状与药材;
  • Prompt 或模型升级后对比新旧结果;
  • 出现争议时保留必要的调用记录。

数据库中不应保存不必要的敏感健康信息。需要明确数据保留周期、访问权限、脱敏方式和删除机制。

八、前端悬浮 AI 面板设计

四项能力统一放入右下角悬浮入口,并复用固定尺寸的面板壳。业务页面通过 Pinia 保存待打开的面板类型和预填参数。例如用户在药材详情页点击“加入药方检测”,系统先把药材写入暂存篮,再打开检测面板。

这种pending-key模式避免了页面组件直接操作远处的弹窗实例:

药材详情页 -> 写入 Pinia 待办状态 -> 全局 Dock 监听 -> 打开指定面板并预填

所有面板共享标题栏、遮罩、关闭行为和尺寸规范,业务组件只负责输入表单与结果展示,能够显著减少重复代码。

九、生产化还需要补充什么

课程设计中的实现已经形成完整链路,但若进入真实生产环境,还应补充:

  1. 对 API Key 加密存储并定期轮换;
  2. 增加限流、超时、熔断、监控和调用费用告警;
  3. 使用 JSON Schema 或 DTO 校验每个返回字段;
  4. 对危险医学内容设置规则库与人工审核;
  5. 对 Prompt 版本化,保存模型名和提示词版本;
  6. 对个人健康信息进行最小化收集、脱敏和权限隔离;
  7. 对药材目录使用检索召回,避免 Prompt 随数据量无限增长;
  8. 设计清晰的免责声明、急症提示和转人工入口。

十、总结

大模型接入业务系统不能停留在“请求 API,然后把文本显示出来”。一个可维护的 AI 功能至少包含配置开关、密钥管理、结构化输出、有限重试、服务端校验、白名单约束、结果缓存、审计记录、前端状态编排和安全提示。尤其在中医药与健康场景中,应让规则和专业审核掌握最终决定权,把模型定位为解释、整理和辅助工具。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 8:05:22

Unity钓鱼系统架构:状态机+事件总线+C#数据驱动实现

简介&#xff1a;这是一套基于Unity引擎开发的钓鱼模拟挂机游戏完整项目源码&#xff0c;面向Unity初学者与C#游戏开发实践者&#xff0c;适用于学习状态管理、资源加载、动画控制及轻量级挂机逻辑实现等核心技能。项目采用URP高清渲染管线&#xff0c;包含505个文件&#xff0…

作者头像 李华
网站建设 2026/9/4 8:03:42

【多智能体】AI 教学代理团队案例讲解

目录 案例简介 案例目标 技术栈与核心依赖 核心技术 关键依赖库 外部服务集成 项目结构 核心设计理念 1. 代理角色分工 2. 工具集成架构 3. 协作流程 核心代码实现 1. 初始化 Composio 工具集 2. 创建教授代理 3. 创建学术顾问代理 4. 创建研究图书管理员代理 …

作者头像 李华
网站建设 2026/9/4 8:01:54

纯原生PHP实现高可靠实时聊天室

简介&#xff1a;这是一套轻量级PHP实时聊天室源码&#xff0c;面向Web开发初学者与小型项目开发者&#xff0c;解决无需数据库和后台即可快速部署多人在线聊天场景的需求&#xff0c;适用于社区交流、教学互动、临时协作等轻量沟通场景。资源共70个文件&#xff0c;包含4个核心…

作者头像 李华
网站建设 2026/9/4 8:01:23

FPGA在彩超成像中的核心作用:前置处理与波束形成技术详解

简介&#xff1a;本资源是一套面向医学超声设备研发工程师与FPGA信号处理学习者的实战代码集&#xff0c;聚焦B型超声系统中前端信号调理与波束形成滤波两大核心环节&#xff0c;解决实时、高并行数字信号处理在彩超硬件平台上的落地难题。压缩包共344个文件&#xff0c;主体为…

作者头像 李华
网站建设 2026/9/4 8:01:03

Linux 五种 I/O 模型与多路复用详解

1 引言&#xff1a;I/O 的两个阶段纵观我们学习计算机知识到现在&#xff0c;I/O 一直相伴左右&#xff0c;可我们还没有系统性地了解过总共有哪些类型的 I/O。要理解这些类型&#xff0c;先把一次 I/O 拆成两个阶段&#xff1a;等待&#xff1a;数据从设备到达内核缓冲区&…

作者头像 李华
网站建设 2026/9/4 8:00:33

基于形状匹配金石为开的智慧(一)

opencv 的相关系数模板匹配勾起了我打算总结一下自己的形状匹配&#xff1a;这一节讲第一个&#xff1a;使用高斯平滑后的金字塔图像学习和匹配所以你必须学会高斯平滑以及学会速度极快的高斯平滑然后获取金字塔图像代码如下&#xff1a;IM_BoxBlur_C(pm->zoomimg, output加…

作者头像 李华