项目实训(十一)|中医智能诊疗系统 知识关联构建——基于大模型的 related 字段自动生成

1. 问题背景

知识库中的卡片目前是孤立的。用户查看“红枣”卡片时,并不知道它与“枸杞”、“四君子汤”有何关联。为了让知识卡片形成网络,我需要在每个实体卡片中增加 related 字段,自动推荐 3-5 个相关实体。

2. 方案设计

采用离线 LLM 生成的方式,因为在线实时生成会导致用户等待时间过长,且成本高。针对不同表设计不同的 prompt,利用表中已有的字段(如食材的“功效”、“应用”,方剂的“组成”、“主治”等)作为上下文,让大模型推理出相关实体。

关键设计点:

  • 限定实体类型为“食材、穴位、方剂、疾病、体质”五种,与前端分类 Tab 保持一致

  • 后处理过滤:排除自身、过滤非标准体质、限制穴位数量

  • 批次处理:避免一次性处理过多导致超时或内存溢出

3. 开发过程与迭代

3.1 食材表先行

我编写了第一个脚本 generate_food_related.py,核心逻辑是遍历食材表,为每个食材调用大模型生成 related。

prompt = f"""
你是一位中医食疗专家。请根据以下食材信息,推荐 3-5 个最相关的具体中医知识实体,必须严格从以下五种类型中选择:
1. 食材:具体的食材名称,如“山药”、“枸杞”。可以是相关食材、配伍食材或功能相似的食材。
2. 方剂:具体的方剂名称,如“四君子汤”、“六味地黄丸”。
3. 穴位:具体的穴位名称,优先推荐与该食材功效直接相关的特定穴位。
4. 疾病:具体的疾病名称,如“风寒感冒”、“脾胃虚弱”。
5. 体质:只能从九种标准体质中选择。
食材名称:{food.name}
功效:{food.efficacy or ''}
应用:{food.application or ''}
性味:{food.nature or ''}
请只输出 JSON 数组。
"""

第一次运行,我查看了几个食材的生成结果,发现了一个问题:几乎所有补气类食材都推荐了“足三里”作为穴位关联。

{
  "name": "足三里",
  "type": "穴位"
}

这个现象是合理的(足三里确实是健脾补气的常用穴位),但过于单一。我需要让模型推荐更多样化的穴位,比如补气类食材可推荐“气海”、“关元”,养血类食材可推荐“血海”、“三阴交”。

于是修改 prompt,增加穴位推荐的具体约束:

3. 穴位:具体的穴位名称。要求:
   - 优先推荐与该食材功效直接相关的特定穴位,避免泛用穴。
   - 例如:补气 → 气海、关元;养血 → 血海、三阴交;健脾 → 中脘、足三里(仅在确实相关时)

同时在后处理中限制每个食材最多只能有 2 个穴位,避免穴位占比过高。

3.2 方剂表拓展

食材表处理完成后,我复制脚本修改为方剂表。但遇到了新问题:生成的 related 中包含了方剂自身。

{
  "name": "四君子汤",
  "type": "方剂"
}

这显然不合理,一个方剂不应该推荐自己。我在后处理中增加了排除自身的逻辑:

if name == pres.name:
    continue  # 跳过自身

另一个问题是体质推荐出现了“气血不足”、“肝郁脾虚”等非标准体质名称。我的前端体质 Tab 只展示九种体质,这些非标准体质无法对应任何分类。

{
  "name": "气血不足",
  "type": "体质"
}

我在 prompt 中明确限定体质只能从九种标准体质中选择,并在后处理中增加校验:

ALLOWED_CONSTITUTIONS = {
    "平和体质", "气虚体质", "阳虚体质", "阴虚体质",
    "血瘀体质", "痰湿体质", "湿热体质", "气郁体质", "特禀体质"
}
if typ == "体质" and name not in ALLOWED_CONSTITUTIONS:
    continue
3.3 大模型额度问题

处理到一半时,大模型返回了额度不足的错误。当时使用的是 qwen-turbo,免费额度用完后无法继续。我切换到 qwen3-coder-flash,价格更低,而且效果足够。

3.4 批量处理与进度监控

数据量较大(食材 500+,方剂 600+),如果一次性处理完,中途出错就需要全部重来。我引入了批次处理逻辑,每批 50 条,每批提交一次数据库事务,并打印进度。

BATCH_SIZE = 50
for batch_idx in range(batch_count):
    start = batch_idx * BATCH_SIZE
    end = min(start + BATCH_SIZE, total)
    batch = prescriptions[start:end]
    for pres in batch:
        # 生成 related
        ...
    await db.commit()
    print(f"✅ 批次 {batch_idx + 1} 提交完成")

4. 最终效果

所有知识表(食材、方剂、疾病、穴位)均已填充 related 字段。卡片详情页底部展示相关知识,支持点击跳转查询。
![[Pasted image 20260619202258.png|470]]

Logo

脑启社区是一个专注类脑智能领域的开发者社区。欢迎加入社区,共建类脑智能生态。社区为开发者提供了丰富的开源类脑工具软件、类脑算法模型及数据集、类脑知识库、类脑技术培训课程以及类脑应用案例等资源。

更多推荐