本仓库是论文 Personalized multi-source retrieval-augmented large language model improves guideline-aligned decision accuracy, safety and efficiency for type 2 diabetes in primary care 中两大核心算法 —— PMS-RAG(Personal Multi-Source Retrieval-Augmented Generation) 与 Action-LLM(带 Token-Filter + Re-Softmax 的约束生成) 的代码骨架(skeleton)。
Qwen3、SentenceTransformer、VF2、BGE-Reranker 等具体模型逐个插入。 所有需要真实模型调用的位置均已标注
TODO。
PMS-RAG 在严格的 Recall@5 约束下,把三路证据流动态融合进 LLM 的上下文:
- 个性化病人信息索引
PGraph—— 病史知识图谱,三元组(E_i, R_n, E_j)PQuery—— 个人信息摘要(由 LLM 推理总结生成)PDense—— 文档切片的稠密向量P_w—— 基于词频的个性化关键词权重
- 机构医疗资源图
MGraph—— 用 Graph-RAG 从药品说明书 + 可用化验 项目构建,按语义分类成多个社区。 - T2DM 指南索引
D_vector = {C1, …, Cn}—— 按章节→滑窗切片组织成树形 结构;章节摘要用稠密嵌入,块使用稀疏(词频)嵌入。 - 双搜索器 + 融合
- Vector Searcher:
cos(PDense, DDense)取 Top-K + 修改版 BM25 (注入P_w权重) - Graph Searcher:CLF(core-forest-leaf)子图同构匹配,
Score_G = N_sim · P_w,沿匹配社区 DFS 展开 - Reranker:把 dense + sparse 合并后用 cross-encoder 精排
- RAG Fusion Model:改进 DSSM 双塔,
u = f_θu(Q, PersonalInfo),v = g_θv(Document), 相似度按 cosine / dot,带动态温度 τ(dosage/contraindication 用小 τ 更"锐",education/comprehensive 用大 τ 更"平"); 训练采用 in-batch NLL 对比损失。
- Vector Searcher:
-
以 Qwen3-1.7B 为底座,SFT 学习
(patient ⊕ drug ⊕ guideline) → ADA的映射。 -
显式离散化 5 大临床维度的 Auxiliary Diagnostic Actions(ADA)为单 token 符号,构造 Action 词表
A,例如:ADA Token 类别 Metformin [MET]drug Sitagliptin [SITA]drug Dapagliflozin [DAPA]drug HbA1c [HBA1C]auxiliary_exam ... ... ... 扩展词表
V' = V ∪ A,Custom Tokenizer 保证每个a ∈ A只占 1 个 token。 -
Token Filter:对 logits 做掩码(非动作位置置为
-∞); -
Re-Softmax:只在动作子空间上归一化,得到每个 ADA 的置信度
p(v | x, v ∈ A); -
生成结果严格落在 ADA 集合,彻底抑制"幻觉"式开放文本输出。
在实际问诊时:
患者到诊
└── PMS-RAG 检索本地化证据(病人 + 机构资源 + 指南)
└── RAG Fusion 输出 Top-K 最相关、安全、合规文档
└── Action-LLM 在 Action 子空间做约束解码
└── 输出结构化 ADA(药品/体检/化验/生活方式/特殊人群)
LLM_PMS/
├── __init__.py
├── config.py # 全局配置(Qwen3-1.7B、Recall@5 …)
├── data_schema.py # 数据结构 PGraph/PQuery/PDense/ADA 等
├── indexing/
│ ├── personal_index.py # §Methods §个性化病人信息索引
│ ├── resource_graph.py # §Methods §医疗资源图 (MGraph)
│ └── guideline_index.py # §Methods §T2DM 指南向量化
├── retrieval/
│ ├── vector_searcher.py # Dense + 修改版 BM25
│ ├── graph_searcher.py # CLF 子图匹配
│ └── reranker.py # cross-encoder 精排
├── fusion/
│ └── rag_fusion_model.py # DSSM 双塔 + 动态 τ + 对比损失
├── action_llm/
│ ├── action_vocab.py # Action 词表 / Custom Tokenizer
│ ├── token_filter.py # Token Filter + Re-Softmax
│ ├── sft_trainer.py # SFT 训练接口
│ └── action_llm.py # Action-LLM 主类
├── agent/
│ └── phc_agent.py # 端到端编排:PMS-RAG → Action-LLM
├── evaluation/
│ └── ada_scorer.py # Appendix 2 评分 + Appendix 3 ARR/NNT
└── examples/
└── run_demo.py # 端到端演示脚本
| 接口 / 类 | 功能 | 对应论文位置 |
|---|---|---|
indexing.personal_index.build_patient_index |
生成 PGraph / PQuery / PDense / P_w |
Methods - Construction of personalized patient information indices |
indexing.resource_graph.build_resource_graph |
构造 MGraph(药 + 化验) |
Methods - Knowledge graph construction for institutional medical resources |
indexing.guideline_index.build_guideline_index |
构造 D_vector 指南树 |
Methods - Vectorization and indexing of clinical guidelines |
retrieval.vector_searcher.VectorSearcher |
Dense + 修改版 BM25 | Methods - Architecture of PMS-RAG |
retrieval.graph_searcher.GraphSearcher |
CLF 子图匹配 + DFS 展开 | Methods - Architecture of PMS-RAG |
retrieval.reranker.Reranker |
双路召回结果交叉编码精排 | Methods - Architecture of PMS-RAG |
fusion.rag_fusion_model.RAGFusionModel |
DSSM 双塔 + 动态 τ + in-batch NLL 对比损失 | Methods - multi-path RAG fusion |
action_llm.action_vocab.ActionVocabulary |
动作词表 A;扩展词表 V' = V ∪ A |
Methods - Action-LLM |
action_llm.token_filter.ActionTokenConstraintDecoder |
Token-Filter + Re-Softmax |
Methods - Action-LLM |
action_llm.sft_trainer.SFTTrainer |
Qwen3-1.7B 的 SFT 接口 | Methods - Action-LLM |
action_llm.action_llm.ActionLLM |
约束生成 ADA | Methods - Action-LLM |
agent.phc_agent.PHCAgent |
端到端编排 | Fig.2 Architectural framework |
evaluation.ada_scorer |
5 维零容忍评分 + ARR / NNT | Supplementary Appendix 2 & 3 |
# 1. (可选)建议在虚拟环境中安装后续真实依赖:
# pip install torch transformers sentence-transformers networkx
# 2. 直接运行骨架版 demo
python -m LLM_PMS.examples.run_demorun_demo.py 会走一遍 建索引 → PMS-RAG 检索 → Action-LLM 约束生成
的完整调用链,但因底层模型是占位实现,打印出的 ADA 列表可能为空;
这是预期行为 —— 它证明数据在模块之间流动的"通路"已经打通。
下表列出了 TODO 最关键的几处;把它们换成真实调用即可得到可训练/可推理
的完整系统:
| 文件 | 需要替换的 TODO |
|---|---|
indexing/personal_index.py |
llm_extract_kg, llm_summarize, text_encoder_embed, build_term_weights |
indexing/resource_graph.py |
extract_drug_triples, detect_communities |
indexing/guideline_index.py |
split_into_chapters, summarize_chapter, dense_encode, sparse_encode |
retrieval/graph_searcher.py |
find_isomorphic_subgraphs, dfs_expand |
retrieval/reranker.py |
cross_encoder_score |
fusion/rag_fusion_model.py |
UserTower.encode, DocTower.encode |
action_llm/action_vocab.py |
CustomTokenizer._inject_action_tokens/encode/decode |
action_llm/action_llm.py |
ActionLLM._forward_logits |
action_llm/sft_trainer.py |
SFTTrainer.collate / train 循环 |
from LLM_PMS.evaluation.ada_scorer import score_sample, aggregate_scores, error_rate
per_physician = [
score_sample(predicted_adas, gold_pos_by_cat, gold_forb_by_cat)
for _ in range(3) # 3 位独立医生
]
domain_scores = aggregate_scores(per_physician)
err_rate = error_rate(per_physician)from LLM_PMS.evaluation.ada_scorer import clinical_benefit_report
report = clinical_benefit_report(err_baseline=0.248, err_phc=0.105)
# report = {'error_rate_baseline': 0.248,
# 'error_rate_phc_agent': 0.105,
# 'ARR': 0.143, 'NNT': ~7}Action-LLM 解码核心(与 §Methods-Action-LLM 完全对齐):
action mask: m ∈ {0, 1}^|V'|, m[v] = 1 ⇔ v ∈ A
filtered: logits'[v] = logits[v] if m[v]=1, else -∞
Re-Softmax: p(v | x, v ∈ A) = exp(logits'[v]) / Σ_{v' ∈ A} exp(logits'[v'])
RAG Fusion 训练损失(in-batch contrastive NLL):
sim(u, v) = cos(u, v) # u = f_θu(Q, PersonalInfo); v = g_θv(Doc)
p(d | Q) = exp(sim/τ) / Σ_{d' ∈ B} exp(sim/τ)
L = -(1/N) Σ_i log p(d_i⁺ | Q_i)
τ = dynamic_temperature(query_type) # dosage/contraindication → 小
# education/comprehensive → 大
仅用于学术研究与算法复现。生产部署时请遵守论文作者 / 医院伦理委员会的 数据使用约束(见论文 Data availability 节)。