news 2026/7/17 17:57:43

中医方剂推荐系统的设计:知识图谱 + 大模型混合架构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
中医方剂推荐系统的设计:知识图谱 + 大模型混合架构

中医方剂推荐系统的设计:知识图谱 + 大模型混合架构

一、个性化深度引言

传统中医方剂推荐的核心痛点:症状组合太多、方剂配伍规则复杂、医生经验高度个人化。一个简单的"头痛 + 咳嗽 + 舌苔白"组合,在《伤寒论》《金匮要略》《温病条辨》三本书中对应至少 5 种不同的证型和方剂。

纯大模型方案做了一版。输入症状,GPT 输出方剂。结果不可控:同样的问题问三次,出了三个不同的方子。原因是大模型在缺乏结构约束时,输出的不是"最优推荐",而是"概率最高的字符串续写"。

见证奇迹的时刻:把知识图谱用于约束推理路径,大模型用于自然语言交互和解释生成。知识图谱保证推荐的医学合理性,大模型保证交互的灵活性——不是"中医 + AI"简单的拼接,而是让两类技术各自做自己擅长的事。

二、个性化原理剖析

中医方剂推荐系统的混合架构:

架构核心:

知识图谱负责确定性推理:症状→证型→治法→方剂,这条推理链是中医辨证论治的标准路径,适合用知识图谱的图遍历和规则推理。

大模型负责自然语言交互:症状提取、用户对话、方义解释。这些任务需要语言理解和生成能力,是 LLM 的强项。

置信度分诊:知识图谱推理置信度高时直接用图谱结果,低置信度时才让 LLM 参与——既保证稳定性,又不失灵活性。

三、个性化代码实践

""" 中医方剂推荐系统——知识图谱 + 大模型混合架构。 设计理念:图谱做结构化推理(确定性),LLM 做自然语言(灵活性)。 """ from dataclasses import dataclass, field from typing import Any, Dict, List, Optional, Set, Tuple @dataclass class Symptom: """设计原因:症状实体——知识图谱的入口节点。""" name: str category: str # 主诉/兼症/舌诊/脉诊 severity: int = 5 # 1-10 程度 @dataclass class Syndrome: """设计原因:证型——中医辨证的核心概念。""" name: str # 如"风寒束表" confidence: float # 推理置信度 evidence: List[str] # 支持此证型的症状依据 @dataclass class Prescription: """设计原因:方剂——最终推荐结果。""" name: str # 方剂名称 herbs: List[Dict] # [{name, dosage, role}] indications: List[str] # 适应症 source: str # 出处 confidence: float modifications: List[str] # 加减建议 class TCMKnowledgeGraph: """ 设计原因:中医知识图谱。 存储症状、证型、治法、方剂、中药实体及它们之间的关系。 使用邻接表 + 规则引擎做推理。 """ def __init__(self): # 设计原因:核心关系表——中医辨证论治的四层映射。 # symptom_to_syndrome: {症状名: {证型名: 权重}} self.symptom_to_syndrome: Dict[str, Dict[str, float]] = { "恶寒": {"风寒束表": 0.9, "阳虚": 0.5}, "发热": {"风寒束表": 0.8, "风热犯肺": 0.9, "阳明腑实": 0.6}, "头痛": {"风寒束表": 0.7, "风热犯肺": 0.6, "肝阳上亢": 0.8}, "咳嗽": {"风寒束表": 0.5, "风热犯肺": 0.8, "痰湿阻肺": 0.7}, "舌苔白": {"风寒束表": 0.9, "寒湿困脾": 0.7}, "脉浮": {"风寒束表": 0.9, "风热犯肺": 0.8}, } # 设计原因:证型到方剂的映射。 self.syndrome_to_prescription: Dict[str, List[Dict]] = { "风寒束表": [ { "name": "麻黄汤", "herbs": [ {"name": "麻黄", "dosage": "9g", "role": "君"}, {"name": "桂枝", "dosage": "6g", "role": "臣"}, {"name": "杏仁", "dosage": "9g", "role": "佐"}, {"name": "甘草", "dosage": "3g", "role": "使"}, ], "source": "《伤寒论》", "modifications": [ "无汗重者麻黄可加至12g", "体虚者加黄芪15g", ], }, { "name": "桂枝汤", "herbs": [ {"name": "桂枝", "dosage": "9g", "role": "君"}, {"name": "白芍", "dosage": "9g", "role": "臣"}, {"name": "生姜", "dosage": "9g", "role": "佐"}, {"name": "大枣", "dosage": "4枚", "role": "佐"}, {"name": "甘草", "dosage": "6g", "role": "使"}, ], "source": "《伤寒论》", "modifications": [ "有汗者适用", "恶风明显加防风9g", ], }, ], "风热犯肺": [ { "name": "银翘散", "herbs": [ {"name": "金银花", "dosage": "15g", "role": "君"}, {"name": "连翘", "dosage": "15g", "role": "君"}, {"name": "薄荷", "dosage": "6g", "role": "臣"}, {"name": "牛蒡子", "dosage": "9g", "role": "臣"}, ], "source": "《温病条辨》", "modifications": [ "咽喉痛加板蓝根12g", "咳嗽重加前胡9g", ], }, ], } def differential_diagnosis( self, symptoms: List[Symptom] ) -> List[Syndrome]: """ 设计原因:辨证论治——从症状集合推断最可能的证型。 使用加权投票机制(症状匹配度 × 症状权重)。 """ syndrome_scores: Dict[str, float] = {} for symptom in symptoms: candidates = self.symptom_to_syndrome.get( symptom.name, {} ) # 设计原因:每个症状对所有可能证型进行"投票"。 # 权重 = 关系的先验概率 × 症状的严重程度归一化值。 symptom_weight = symptom.severity / 10.0 for syndrome_name, prior_weight in candidates.items(): score = prior_weight * symptom_weight syndrome_scores[syndrome_name] = ( syndrome_scores.get(syndrome_name, 0) + score ) # 设计原因:按得分排序,取 Top-3 证型。 sorted_syndromes = sorted( syndrome_scores.items(), key=lambda x: x[1], reverse=True, ) # 设计原因:归一化得分到 [0, 1] 区间作为置信度。 max_score = sorted_syndromes[0][1] if sorted_syndromes else 1 results = [] for name, score in sorted_syndromes[:3]: # 设计原因:收集支持该证型的证据(症状名列表)。 evidence = [ s.name for s in symptoms if name in self.symptom_to_syndrome.get(s.name, {}) ] results.append(Syndrome( name=name, confidence=round(score / max(max_score, 0.01), 2), evidence=evidence, )) return results def prescribe( self, syndrome: Syndrome, top_k: int = 3 ) -> List[Prescription]: """ 设计原因:根据证型推荐方剂。 每个证型可能有多个可选方剂(如麻黄汤、桂枝汤都治风寒表证)。 """ candidates = self.syndrome_to_prescription.get( syndrome.name, [] ) prescriptions = [] for cand in candidates[:top_k]: prescriptions.append(Prescription( name=cand["name"], herbs=cand["herbs"], indications=[syndrome.name], source=cand["source"], confidence=syndrome.confidence * 0.95, # 传递置信度 modifications=cand.get("modifications", []), )) return prescriptions class TCMPrescriptionSystem: """ 设计原因:中医方剂推荐系统——知识图谱 + LLM 混合架构。 图谱负责确定性推理,LLM 负责交互和解释。 """ def __init__(self): self.kg = TCMKnowledgeGraph() self.confidence_threshold = 0.8 def recommend( self, symptoms: List[Symptom] ) -> Dict[str, Any]: """ 设计原因:完整的推荐流程。 图谱推理 → 置信度判断 → 可能需要 LLM 增强。 """ # 第一步:知识图谱辨证论治 syndromes = self.kg.differential_diagnosis(symptoms) if not syndromes: return { "status": "no_match", "message": "症状组合未能匹配到已知证型,建议面诊。", } top_syndrome = syndromes[0] # 第二步:置信度分诊 if top_syndrome.confidence >= self.confidence_threshold: # 设计原因:高置信度 → 纯图谱推理,保证确定性。 prescriptions = self.kg.prescribe(top_syndrome) reasoning_method = "knowledge_graph" else: # 设计原因:低置信度 → 联合 LLM 做辅助推理。 prescriptions = self._llm_enhanced_prescribe( symptoms, syndromes ) reasoning_method = "kg_plus_llm" # 第三步:LLM 生成解释 explanations = self._generate_explanations( symptoms, top_syndrome, prescriptions ) return { "status": "success", "symptoms": [s.name for s in symptoms], "syndrome": { "name": top_syndrome.name, "confidence": top_syndrome.confidence, "evidence": top_syndrome.evidence, }, "prescriptions": [ { "name": p.name, "herbs": p.herbs, "source": p.source, "confidence": p.confidence, "modifications": p.modifications, } for p in prescriptions ], "explanations": explanations, "reasoning_method": reasoning_method, "disclaimer": ( "本推荐仅供参考,不构成医疗处方。" "具体用药请咨询执业中医师。" ), } def _llm_enhanced_prescribe( self, symptoms: List[Symptom], syndromes: List[Syndrome], ) -> List[Prescription]: """ 设计原因:LLM 增强的方剂推荐。 当图谱推理置信度不足时,基于古籍语料做补充推理。 """ # 设计原因:把症状和候选证型传给 LLM, # 让 LLM 基于《伤寒论》等古籍知识做补充推荐。 prompt = self._build_syndrome_prompt(symptoms, syndromes) # llm_response = call_llm(prompt) 实际调用 LLM # prescriptions = parse_prescriptions(llm_response) # 设计原因:LLM 返回的结果标记置信度, # LLM 推荐置信度 < 图谱推荐置信度。 return self.kg.prescribe(syndromes[0]) def _build_syndrome_prompt( self, symptoms: List[Symptom], syndromes: List[Syndrome], ) -> str: """设计原因:构建传给 LLM 的辨证提示词。""" symptom_text = "、".join( f"{s.name}({s.category}, 程度{s.severity}/10)" for s in symptoms ) syndrome_text = "、".join( f"{s.name}(置信度{s.confidence:.2f})" for s in syndromes ) return ( f"患者症状:{symptom_text}。\n" f"知识图谱推理的候选证型:{syndrome_text}。\n" f"请基于《伤寒论》和《金匮要略》理论," f"判断最可能的证型并推荐对应方剂。" ) def _generate_explanations( self, symptoms: List[Symptom], syndrome: Syndrome, prescriptions: List[Prescription], ) -> Dict[str, str]: """ 设计原因:LLM 生成可读的解释文本。 方义分析、加减建议——这些是需要自然语言生成的任务。 """ # 设计原因:构建解释提示词,让 LLM 生成三部分解释。 prompt = ( f"证型:{syndrome.name},置信度{syndrome.confidence:.2f}。\n" f"症状依据:{'、'.join(syndrome.evidence)}。\n" f"推荐方剂:{prescriptions[0].name if prescriptions else '无'}。\n" f"出处:{prescriptions[0].source if prescriptions else '无'}。\n\n" f"请生成以下三段解释:\n" f"1. 方义解释:君臣佐使配伍原理\n" f"2. 加减建议:根据具体症状调整\n" f"3. 注意事项:剂量禁忌和特殊人群注意" ) # llm_response = call_llm(prompt) # 实际使用时替换为 LLM 调用 return { "方义解释": ( f"{prescriptions[0].name}以" f"{'、'.join(h['name'] for h in prescriptions[0].herbs)}" f"组成,遵循君臣佐使配伍原则。" ), "加减建议": ( f"体质偏寒者加干姜6g;" f"湿重者加茯苓12g。" ), "注意事项": ( f"孕妇禁用麻黄;" f"高血压患者慎用桂枝;" f"服用期间忌食生冷。" ), } # ── 使用示例 ── def demo_tcm_system(): """设计原因:演示完整的中医方剂推荐流程。""" system = TCMPrescriptionSystem() # 模拟用户输入的症状 symptoms = [ Symptom(name="恶寒", category="主诉", severity=7), Symptom(name="发热", category="主诉", severity=6), Symptom(name="头痛", category="兼症", severity=5), Symptom(name="脉浮", category="脉诊", severity=8), ] result = system.recommend(symptoms) print(f"辨证结果: {result['syndrome']['name']}") print(f"置信度: {result['syndrome']['confidence']}") print(f"推理方式: {result['reasoning_method']}") print(f"推荐方剂: {result['prescriptions'][0]['name']}") print(f"出处: {result['prescriptions'][0]['source']}") print(f"\n{result['disclaimer']}") return result

四、个性化边界权衡

1. 知识图谱推理 vs LLM 推理

知识图谱推理确定性强,可解释性好,每个推理步骤有据可查。LLM 推理灵活,能处理图谱未覆盖的边缘情况,但可解释性差。推荐:80% 的常见辨证用图谱推理,20% 的边缘情况用 LLM 补充。

2. 图谱知识覆盖度:经典 vs 现代

经典医学文献(《伤寒论》《金匮要略》)覆盖 30% 的临床场景,结构化程度高。现代临床经验覆盖更广但难以结构化。建议:以经典为基础构建核心图谱,现代经验用 LLM 的 Context 注入。

3. 置信度阈值:高阈值 vs 低阈值

高阈值(>0.9)保证推荐安全性但可能拒绝很多有效推理。低阈值(>0.6)覆盖面广但假阳性增加。推荐:非处方场景阈值 0.8,处方辅助场景阈值 0.9。

4. 方剂推荐:单一推荐 vs Top-K

单一推荐简洁但可能忽略个体差异。Top-K 推荐给医生多个选择但增加决策负担。推荐:默认展示 Top-3,标注置信度和适用条件差异。

5. 安全性:免责声明 vs 硬约束

免责声明法务上必要但用户常忽略。硬约束(拒绝推荐危险方剂、提醒致命禁忌)才是真正的安全网。建议:硬约束是第一道防线(代码层面的安全过滤),免责声明是第二道(法务层面的风险转移)。

五、总结

中医方剂推荐系统的混合架构,通过知识图谱处理确定性的辨证推理(症状→证型→治法→方剂),通过大模型处理自然语言交互和解释生成,实现了医学确定性与交互灵活性的互补。知识图谱提供结构化推理和可追溯的决策依据,大模型提供灵活的症状理解和方义解释。工程实践中需要在推理分工、置信度阈值、安全性约束上做权衡,核心原则是:图谱保证"对"的底线,LLM 扩展"好"的上限,硬约束守住"安全"的生命线。

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

计算机毕业设计之基于springboot的医疗预约挂号系统小程序

本医疗预约挂号系统小程序是基于Spring Boot框架与Java语言开发的后端服务&#xff0c;结合uniapp框架实现的前端界面&#xff0c;采用MySQL数据库作为数据存储支持&#xff0c;构建了一个完整的C/S架构应用系统。在当前医疗资源分配不均、患者就医难等背景下&#xff0c;该系统…

作者头像 李华
网站建设 2026/7/17 17:50:34

小程序毕设选题推荐:猫咖饮品撸宠预约平台的设计与实现 基于 SpringBoot + 微信小程序的宠物主题小店服务管理小程序【附源码、mysql、文档、调试+代码讲解+全bao等】

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/7/17 17:48:28

乌兹别克斯坦名义雇主EOR为中国企业出海提供创新支持

在全球化的背景下、乌兹别克斯坦的名义雇主公司EOR为中国企业出海提供了创新支持。这种雇佣模式使企业能够在不建立海外实体的情况下市场。这除了简化了劳动合同的执行流程&#xff0c;还确保了企业合规运营&#xff0c;减少法律风险。通过提供本地化服务&#xff0c;EOR可以帮…

作者头像 李华