微信扫码
添加专属顾问
我要投稿
企业级AI协作系统的核心突破:基于本体Ontology的记忆系统如何解决大模型在专业领域的精准记忆难题。核心内容: 1. 生产环境中大模型记忆结构化知识的痛点与现有方案缺陷 2. 本体记忆系统的架构设计与医疗行业应用实例 3. 将静态本体转化为动态记忆层的技术实现路径(Neo4j+LangGraph)
很久没写公众号了, 最近在做企业级别智能体协作系统,以便行业专家能够在AI的加持下协作高效完成价值创造,过程中天天和本体/Ontology这个概念打交道,以下这篇就和本体/Ontology强相关,供大家参考
基于大模型的记忆,一直是影响大模型Agent效果的重点环节之一, 在对信息准确度要求较高的生产环境中, 这个问题更加明显。
本文介绍了一种基于本体Ontology的记忆实现及评估系统, 以便在医疗, 法律, 金融等准确度要求较高的应用环境中, 保证领域相关的精准行业记忆的有效使用。
P.S. 本文以医疗行业为例, 会出现较多医疗行业相关名词; 另外最近的一个感悟, 就是传统行业中有太多能够使用AI提效的地方, 所以做AI的一定要深入行业, 行业领域知识及业务, 才是真正有价值的地方。
在生产环境, 大型语言模型在推理、总结和生成文本方面表现很好,但当涉及记忆结构化知识时,它们会以非常微妙,且危险的方式出问题。
如果你向一个LLM询问一个本体(或者叫Ontology)驱动的领域的问题,我们经常会看到矛盾、定义漂移,或者那些看似大模型很自信却悄悄违反底层逻辑或者事实的答案。
模型知道这些词,但它并不能可靠地记住赋予这些词意义的结构。
大多数现代系统试通过检索来解决这个问题:用本体片段提示LLM,注入Graph上下文,或在查询时重新加载模式。这种模式一般能产生短暂的正向效果,但很快就会出错。
检索是无状态的,Prompt是脆弱不稳定的,两者都无法让系统持久地感知它已经学习、验证或认定为真正的内容。因此,本体变成了被动的参考,而不是主动的记忆,一致性在交互中逐渐瓦解。
本文探讨了一种不同的方法:本体记忆系统,一个专用的记忆层,使AI系统能够随时间保留、验证和重用结构化知识。
我们不是将Ontology视为静态工件或一次性上下文注入,而是将它们视为可以强化、检查冲突并在推理周期中重用的演化记忆对象。
结果不仅是更好的答案,而且是行为更像可靠知识工作者而非随机文本生成器的AI系统。
设想下,你是一家大型医院的医疗编码员。你的工作是将医生的诊断——比如“患者因未控制的2型糖尿病出现高血糖”——翻译成精确的医疗代码,如E11.65。这些代码是ICD-10-CM的一部分,这是一个拥有超过70,000个诊断代码的庞大系统。一个数字就能完全改变含义,错误可能导致保险索赔被拒、收入损失或合规问题。
随着大模型的兴起,一个关键问题出现了:AI能否准确记忆和回忆这些专业代码? 这个被称为本体记忆的挑战,对价值4.5万亿美元的医疗保健行业具有重大影响。
本体是一种结构化的知识表示,它映射概念、关系和规则------就像按类型、颜色和品牌整理你的衣柜一样。在医学领域,像 ICD-10-CM 这样的本体不仅编码疾病,还编码严重程度、解剖位置和因果关系。
对于 AI 来说,记忆意味着:
这与缓存、将数据保存到磁盘或在数据库中查找信息不同。
问题是:AI 是否已经充分学习了这些代码,以至于无需外部帮助就能回忆起它们?
即使是经验丰富的编码员也不会记住全部 7 万个 ICD-10 编码。他们:
即使是专家,准确率也只有 80-95%,这凸显了为什么 AI 在处理罕见或细微的代码时会遇到很大的挑战
医院每天要处理数百份理赔单。每份理赔都需要多个准确编码——出错代价高昂。目前合格的编码员稀缺,错误可能导致理赔延迟或被拒。AI辅助编码(注意此处不是程序员的编程)有望提升速度和一致性:AI建议编码,人工审核,系统随时间不断改进。
不过只有在AI能可靠记忆编码时, 才能正常工作。否则,它会产生更多错误和额外工作量。
凡是存在大规模、结构化、高价值知识的地缝,本体记忆都至关重要:
当人工智能能够可靠地记住这类知识时,它是一个巨大的优势。当它做不到时,就是一种风险。
在常见代码上实现 90%以上的准确率 是具有变革性的;而40%的准确率则意味着根本没有什么作用。正是这一挑战促使我们构建了一个 本体记忆评估系统,用以严格测试AI的性能——我们接下来将对此进行探讨。
在构建任何AI编码助手之前,我们需要严谨的数据。具体来说,我们提出了三个研究问题:
RQ1:记忆准确性 - 当给定一个概念标签时,大语言模型(LLM)能多准确地回忆起确切的医疗编码?例如,如果我们给LLM输入"2型糖尿病伴高血糖",它能准确输出E11.65吗?我们通过以下指标来衡量:
完全匹配准确率:它是否完全正确?
编辑距离:需要多少次字符编辑来修正错误?(例如,E11.65 → E11.3 需要2次编辑)
Jecard相似度:字符/标记之间的重叠程度如何?(衡量部分正确性)
RQ2:流行度相关性 - AI在常见编码上的表现是否比罕见编码更好?这一点很重要,因为医院遇到常见病情的频率远高于罕见病情。如果AI只对常见编码有效,它可能仍然对80%的病例有价值,而人类编码员可以处理罕见的20%。我们衡量:
高流行度准确率:在前25%最常见编码上的表现
低流行度准确率:在后25%最罕见编码上的表现
准确率下降程度:高流行度与低流行度之间的差距
RQ3:预测不变性 - AI的输出是否一致且稳定?如果我们问同一个问题三次,是否会得到相同的答案?如果我们稍微调整问题的表述,答案会改变吗?这对生产系统很重要——用户期望确定性的行为。我们测试:
PI-1:重复完全相同的提示3次——答案相同的频率是多少?
PI-2:改变温度参数(随机性)——输出变化有多大?
PI-3:重新表述问题(不同措辞、不同语言)——答案是否保持不变?
这些问题让我们全面了解:不仅仅是"它是否有效?",而是"它在何时有效,效果如何,以及我们能否依赖它?"
第一步是获取真实的医疗数据,这需要反映现实世界医疗编码的复杂性。我们获取了:
ICD-10-CM 诊断编码(来自 CDC/CMS 官方来源的 51 个概念):
每个编码都包含:
数据摄取脚本(ingest_real_data.py)执行几个关键步骤:
步骤 1:流行度分桶 - 我们不能只是随机抽取概念进行测试。如果那样做,我们很可能会得到大部分常见编码(因为它们在数据中出现得更多)。我们需要【分层抽样】:在不同流行度级别上实现均衡的代表性。
我们使用对数分布将概念划分为 50 个流行度桶:
这确保了当我们为评估抽取 30 个概念时,我们从每个桶级别获得 1-2 个概念,代表了从极其常见到极其罕见状况的完整谱系。
步骤 2:图结构创建 - 每个概念在 Neo4j 中成为一个节点,具有以下属性:
(:Concept {
concept_id: "E11.65",
label: "Type 2 diabetes mellitus with hyperglycemia",
category: "Endocrine",
popularity_score: 850,
popularity_bucket: 43,
ontology: "ICD-10-CM"
})
概念链接到其本体:
(:Concept)-[:PART_OF]->(:Ontology {name: "ICD-10-CM", version: "2024"})
步骤 3:验证 - 摄取脚本验证:
运行 python scripts/ingest_real_data.py 后,我们在 Neo4j Aura 中拥有了 101 个真实的医疗概念,准备进行评估。
数据加载完成后,我们构建了评估流程(run_full_evaluation.py)
分层抽样:比如,当评估30个概念时,系统不会只是从数据库中选取前30个。相反,它会:
这确保了平衡的代表性。如果糖尿病代码都在高流行度组,而罕见遗传病都在低流行度组,我们的样本会同时包含两者。
LLM 查询生成:对于每个概念,我们生成一个精心设计的提示。以 ICD-10-CM 为例:
You are a medical coding expert. Your task is to provide the exact ICD-10-CM code
for the following diagnosis.Diagnosis: Type 2 diabetes mellitus with hyperglycemia
Respond with ONLY the ICD-10-CM code, nothing else. Format: X00.00
Your response:
为什么采用这种特定格式?
异步评估:系统使用 Python 的 asyncio 并发发送所有查询:
async def evaluate_all_concepts(self, concepts):
tasks = [self.evaluate_concept(c) for c in concepts]
results = await asyncio.gather(*tasks)
return results
响应解析:LLM 的响应并不总是干净的。以下是各种可能的例子:
E11.65The ICD-10-CM code is E11.65Probably E11.65 or E11.9E11-65(用了短横线而不是句点)响应解析器使用特定于本体的正则表达式模式:
[A-Z][0-9]{2}\.?[0-9A-Z]*(匹配 E11.65, I10, Z79.4)它从响应中提取第一个有效代码,并根据已知模式进行验证。
指标计算:对于每个概念,我们计算:
预测值 == 真实值 吗?布尔值:正确或不正确。这些指标提供了超越简单对/错的细微差别。一个始终接近正确答案(E11.3 而不是 E11.65)的 LLM,经过后处理后可能仍然有用,而一个产生随机代码(用 K56.9 表示糖尿病)的 LLM 则不然。
原始指标本身用处不大。报告生成器能将评估结果转化为人们真正能用上的洞见, 可以让大模型生成以下报告
Markdown 报告
JSON 导出
CSV 导出
PNG 图表
语义理解: GPT-5.2 没有出现类别错误。
截断错误: 仍然常见,但在减少
罕见代码: GPT-5.2 达到了 > 80 % 的准确率,突破了“罕见代码障碍”。
不变的挑战:尽管准确性大幅提升,流行度偏差依然顽固存在:
看似矛盾的现象: 罕见代码的准确性有所提高,但常见代码与罕见代码之间的性能差距反而扩大了。GPT-5.2 显示出最大的差距,其性能差异达到 47.6%。
这为何重要: 模型似乎是为了追求整体准确性而优化的,而非均衡的性能。即使基础模型很强,罕见代码仍需要针对性技术,如上采样或微调。
业务影响: AI 呈现出明显的两级分化模式:
常见代码: 约 81% 的准确率 - 经过验证即可使用
罕见代码: 约 33% 的准确率 - 需要专家人工监督
我们进行了全面的不变性测试,以衡量每个模型输出结果的一致性。这对于生产部署至关重要——如果AI对同一个问题给出不同的答案,那它就是不可靠的。
不变性公式:PI = 1 - (U - 1) / (M - 1),其中 U = 唯一响应数,M = 提示词数量
GPT-5.2 预测不变性
不变性得分 (PI):
Example variations tested:
"What is the ICD-10-CM code for Type 2 diabetes with hyperglycemia?"
"Provide the diagnosis code for Type 2 diabetes mellitus with hyperglycemia"
"Give me the identifier for Type 2 diabetes with hyperglycemia"
关键洞察:预测不变性是衡量记忆置信度的可靠指标。当模型对某个编码不确定时,它会在不同的提示词变体下产生不一致的响应。这意味着我们可以使用PI分数来在没有真实答案的情况下估计可靠性——这对于生产环境中的筛选很有用。
业务影响:生产系统需要遵循提示词工程的最佳实践。如果没有这些保障措施,AI可能会根据问题表述方式的不同,对同一个诊断给出不同的编码——这在临床环境中是完全不可接受的。
python scripts/ingest_real_data.py
当你运行 python scripts/run_full_evaluation.py ICD-10-CM --model gpt-5.2 --sample-size 50 时,系统首先会连接到 Neo4j Aura:
query = """
MATCH (c:Concept)-[:PART_OF]->(o:Ontology {name: $ontology})
RETURN c.concept_id AS concept_id,
c.label AS label,
c.popularity_bucket AS popularity_bucket,
c.popularity_score AS popularity_score
ORDER BY c.popularity_bucket DESC
"""
results = session.run(query, ontology="ICD-10-CM")
这段 Cypher 查询(Neo4j 的查询语言)会获取属于 ICD-10-CM 本体的所有概念,以及它们的流行度指标。结果是:一个包含 51 个概念的列表,每个概念都有 ID、标签和流行度数据。
抽样算法确保平衡代表性:
def stratified_sample(concepts, sample_size):
# Group by popularity bucket
buckets = {}
for concept in concepts:
bucket = concept['popularity_bucket']
if bucket not in buckets:
buckets[bucket] = []
buckets[bucket].append(concept)
Output:
samples_per_bucket = max(1, sample_size // len(buckets))sampled = []for bucket, concepts_in_bucket in buckets.items():n = min(samples_per_bucket, len(concepts_in_bucket))sampled.extend(random.sample(concepts_in_bucket, n))
while len(sampled) < sample_size:remaining = [c for c in concepts if c not in sampled]sampled.append(random.choice(remaining))return sampled[:sample_size]
这样可以确保每个流行度等级都有代表性,避免偏向常见或罕见的代码。
### 第三步:LLM查询(异步处理)
针对每个医学概念,我们生成一个提示词并发送给大语言模型:
```python
async def evaluate_concept(concept):
prompt = f"""You are a medical coding expert. Your task is to provide the exact ICD-10-CM code for the following diagnosis.Diagnosis: {concept['label']}
Respond with ONLY the ICD-10-CM code, nothing else. Format: X00.00
Your response:"""
# 发送给LLM(Ollama)
response = await llm_client.aquery(prompt)
# 解析响应
predicted_code = parser.extract_code(response)
# 计算指标
is_correct = (predicted_code == concept['concept_id'])
lev_distance = levenshtein_distance(concept['concept_id'], predicted_code)
jaccard_sim = jaccard_similarity(concept['concept_id'], predicted_code)
return {
'concept_id': concept['concept_id'],
'label': concept['label'],
'predicted': predicted_code,
'is_correct': is_correct,
'levenshtein': lev_distance,
'jaccard': jaccard_sim,
'popularity_bucket': concept['popularity_bucket']
}
通过使用 async/await,我们可以同时运行所有10个(或30个、50个)评估任务。Python的事件循环能高效地管理这些I/O密集型的大语言模型请求。
在所有概念评估完成后,我们对各项指标进行汇总:
def calculate_summary_metrics(results):
total = len(results)
correct = sum(1 for r in results if r['is_correct'])
accuracy = correct / total
avg_levenshtein = sum(r['levenshtein'] for r in results) / total
avg_jaccard = sum(r['jaccard'] for r in results) / total
# 流行度分析
high_pop = [r for r in results if r['popularity_bucket'] >= 38]
low_pop = [r for r in results if r['popularity_bucket'] <= 13]
high_pop_acc = sum(1 for r in high_pop if r['is_correct']) / len(high_pop)
low_pop_acc = sum(1 for r in low_pop if r['is_correct']) / len(low_pop) if low_pop else 0
degradation = high_pop_acc - low_pop_acc
return {
'accuracy': accuracy,
'avg_levenshtein': avg_levenshtein,
'avg_jaccard': avg_jaccard,
'high_pop_accuracy': high_pop_acc,
'low_pop_accuracy': low_pop_acc,
'degradation': degradation
}
这样我们就得到了用于执行摘要的核心数据。
我们使用 Matplotlib 和 Seaborn 来创建图表:
这样就生成了一个专业质量的图表,展示了流行度与准确性之间的相关性。
最后,我们把所有内容整理成一份 Markdown 报告。
报告会保存为 report_ICD-10-CM_[timestamp].md,放在 data/results/ 目录下。
我们最初想解决一个看似简单的问题:AI能否足够好地记住医学编码,从而辅助人类编码员?但答案正如AI研究中常见的那样——是微妙的。
AI能够部分记忆:它能做到70%完全正确,还有更多是“差不多对”(子类型错,但大类对)。它展示了对医学本体的语义理解能力,尽管缺乏完美的记忆。
流行度偏差真实存在且影响显著:AI擅长处理常见编码,但在罕见编码上表现不佳。这不是一个程序错误,而是神经网络从数据中学习方式的根本局限。你无法记住你几乎没见过的东西。
生产部署是可行的,但需要精心设计:作为一种验证工具或常见病例的助手,AI可以带来巨大的商业价值。但完全自动化还为时过早,且充满危险。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-12-27
从智能体中抽取“业务知识图谱”:将其在大量对话中识别出的实体、关系与规则,反向沉淀为企业的结构化知识资产
2025-12-24
零噪声知识图谱提取革命:构建自适应本体驱动GraphRAG系统
2025-12-24
如何将任何文本语料库转化为知识图谱
2025-12-23
补充聊一下AI驱动的知识图谱生成器
2025-12-23
GraphRAG WorkBench:Microsoft GraphRAG 生成的交互式 3D 可视化知识图谱
2025-12-23
什么是本体(Ontology)?
2025-12-15
知识图谱本体如何从关系数据库中自动构建?再回顾本体定义及构建路径
2025-12-12
关于动态本体的一些新思考及多模态知识图谱构建思路VisKnow
2025-10-30
2025-10-19
2025-12-01
2025-10-21
2025-10-13
2025-11-24
2025-11-13
2025-12-05
2025-11-14
2025-11-20