架构手记(三):告别大模型幻觉——面向用药冲突的轻量级知识图谱(Graph RAG)设计与实现
一、 架构抉择:为什么抛弃了最火的“向量数据库”?
在明确了上一篇博客提到的 API 契约后,后端需要提供一个极其稳定的 check_drug_interaction(用药冲突检测)服务。
最初,团队有人提议采用市面上最火的 RAG 方案:把所有的药理学说明书切片(Chunk),扔进向量数据库(Vector DB),然后让大模型去检索相似度。作为架构师,我经过沙盘推演后,坚决否决了这个方案。
原因很简单:在医疗领域,向量检索(语义相似度)是致命的。
例如,“布洛芬”和“阿司匹林”在语义上极度相似(都是非甾体抗炎药,常用于解热镇痛)。如果用向量检索,它们会被认为是“高度相关的同类词”。但在真实的药理学中,这两种药绝对不能同时服用,叠加会引发严重的胃出血!
医疗冲突不是“语义相似”,而是“规则互斥”。因此,我们必须放弃 Vector RAG,转向构建一个基于确切节点和边的 知识图谱(Graph RAG)。
二、 极简主义:轻量级内存图谱(Adjacency List)的设计
考虑到我们是一个敏捷开发团队,如果为了这个功能去额外部署一套 Neo4j 图数据库,不仅会拉长运维战线,还会导致接口响应变慢。我们需要的是“轻量、极速”。
在《数据结构》课程的启发下,我决定直接在 FastAPI 后端的内存中,使用邻接表(Adjacency List)的数据结构来模拟图谱。
1. 节点(Nodes)的定义
在我们的图谱中,节点分为三类:
-
Drug(药物):如布洛芬、利巴韦林。 -
Patient_Tag(患者生理标签):如孕妇、消化道溃疡史。 -
Food/LifeStyle(食物/生活方式):如西柚汁、饮酒。
2. 边(Edges)的定义
边代表冲突。我在 Python 中利用嵌套字典(Dict of Dicts)设计了如下结构的哈希图:
Python
# 轻量级图谱的 JSON/Dict 表达 (截取部分)
medical_graph = {
"布洛芬": {
"阿司匹林": {
"risk_level": "High",
"conflict_type": "Drug-Drug",
"reason": "同属NSAIDs,叠加使用成倍增加消化道出血风险。"
},
"消化道溃疡史": {
"risk_level": "High",
"conflict_type": "Drug-History",
"reason": "非甾体抗炎药易破坏胃黏膜,溃疡患者绝对禁用。"
}
},
"利巴韦林": {
"孕妇": {
"risk_level": "High",
"conflict_type": "Drug-History",
"reason": "具有极强致畸性,孕妇及备孕期绝对禁用。"
}
}
}
三、 降维打击:$O(1)$ 复杂度的图碰撞算法
有了上述的图结构,当 Agent 提取出患者的特征和用药清单后,我们不需要让 Agent 自己去“思考”会不会死人,而是直接调用后端的图碰撞算法。
假设前端传入的提取结果是:["布洛芬", "阿莫西林", "消化道溃疡史"]。
我利用 Python 的组合数学库 itertools.combinations,对传入的实体数组进行两两组合,然后在哈希图谱中进行精确的 Key-Value 寻址:
Python
import itertools
def check_graph_collisions(entities: list) -> list:
collisions = []
# 两两组合遍历,例如 (布洛芬, 阿莫西林), (布洛芬, 消化道溃疡史)...
for node_a, node_b in itertools.combinations(entities, 2):
# O(1) 的图路径寻址
if node_a in medical_graph and node_b in medical_graph[node_a]:
collisions.append({
"nodes": [node_a, node_b],
"rule": medical_graph[node_a][node_b]
})
elif node_b in medical_graph and node_a in medical_graph[node_b]:
collisions.append({
"nodes": [node_a, node_b],
"rule": medical_graph[node_b][node_a]
})
return collisions
工程收益:
这个算法的时间复杂度接近 $O(1)$(取决于常数级的实体数量)。这意味着我们的 Graph RAG 检索耗时几乎为 0 毫秒!大模型(Agent)只需等待自己生成的 API 响应,极大降低了整个链路的延迟(Latency)。
四、 形成闭环:把图谱的“真理”喂给 Agent
当算法检测到 ["布洛芬", "消化道溃疡史"] 存在边(Edge)时,后端会将提取到的 reason(非甾体抗炎药易破坏胃黏膜...)组装成一段系统级提示词(System Context),反向注入给 Agent。
Agent 接收到这个“不可违背的事实”后,就会乖乖地按照我们在第二篇博客中定义的 JSON Schema,输出 action_type: "BLOCK",并生成基于图谱规则的友好解释。
至此,大模型可怕的“幻觉”被我们的轻量级图谱彻底锁死在了笼子里。
五、 结语
不要为了用新技术而用新技术。在医疗这种高敏感领域,用最朴素的数据结构(哈希邻接表)解决最前沿的痛点(大模型幻觉),才是一个架构师应有的 Trade-off(权衡)思维。
更多推荐


所有评论(0)