中医方剂推荐系统的设计:知识图谱 + 大模型混合架构 中医方剂推荐系统的设计知识图谱 大模型混合架构一、个性化深度引言传统中医方剂推荐的核心痛点症状组合太多、方剂配伍规则复杂、医生经验高度个人化。一个简单的头痛 咳嗽 舌苔白组合在《伤寒论》《金匮要略》《温病条辨》三本书中对应至少 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(), keylambda x: x[1], reverseTrue, ) # 设计原因归一化得分到 [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( namename, confidenceround(score / max(max_score, 0.01), 2), evidenceevidence, )) 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( namecand[name], herbscand[herbs], indications[syndrome.name], sourcecand[source], confidencesyndrome.confidence * 0.95, # 传递置信度 modificationscand.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 f1. 方义解释君臣佐使配伍原理\n f2. 加减建议根据具体症状调整\n f3. 注意事项剂量禁忌和特殊人群注意 ) # 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主诉, severity7), Symptom(name发热, category主诉, severity6), Symptom(name头痛, category兼症, severity5), Symptom(name脉浮, category脉诊, severity8), ] 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 扩展好的上限硬约束守住安全的生命线。