FEMentor 用 14 篇面经生成知识图谱时,得到 266 个去重知识点,但大量节点彼此孤立。图谱看起来很丰富,实际却难以用于检索和浏览。

问题主要来自三处:

  1. 初始骨架只有十个技术分类,缺少行为面、项目、安全、网络等常见主题;
  2. 每篇面经独立调用 LLM 标注,同一概念会产生不同措辞;
  3. Prompt 没有词表约束,新增标签的边界过于宽松。

第一版:手工维护同义词

最直接的方法是增加一百多条 SYNONYMS 映射。但它很快遇到语义边界问题:“双 Token”与“JWT”有关,却不是同一个概念;把它们直接合并会丢掉层级信息。

这套方案最终被删除,归一化只处理格式差异,例如空格、连字符和大小写;语义关系交给骨架层级与数据共现处理。

第二版:让骨架生成全部节点

骨架扩展到 16 个一级分类、215 个以上预定义知识点后,部署环境一度只显示 33 个顶层节点。初始修复遍历所有 children,主动创建全部节点。

节点数量恢复了,却出现新的问题:大量从未在 14 篇面经中出现的概念也进入图谱。结构完整了,数据真实性却下降了。

第三版:数据决定节点,骨架提供结构

最终实现改为数据驱动:

  • 只有真实面经标签才创建知识节点;
  • 骨架负责提供 parent、children 和 related 关系;
  • 子节点存在而父分类缺失时,补充父节点;
  • 每个节点记录 both、cooccurrence 或 skeleton 来源。

归一化同时采用“精确词表匹配 + 最长优先的子串匹配”,避免 CSS 之类短词过早吞掉更具体的概念。

对 14 篇面经重新清洗后,去重知识点从 266 降到 197,骨架覆盖率约从 30% 提升到 65%。在后续数据驱动构图中形成 208 个节点,其中 157 个同时具有骨架定义和真实数据来源,51 个来自纯共现数据。

部署问题也是模型的一部分

这次排查还暴露了多项工程问题:骨架文件被 .gitignore 意外排除、线上入口没有触发构图、Fastify 与原生 HTTP 两套路由返回不同结果、线上数据库变量仍指向本地地址。

这些问题提醒我:图谱算法正确,不代表线上图谱正确。数据文件是否进入制品、启动入口是否执行构建、接口是否走到预期实现,都是知识结构的一部分。

最终留下的原则很简单:骨架负责约束,真实数据负责存在性,来源字段负责解释。只有三者同时成立,图谱才不是一张预先画好的分类图。