Skip to content

feat(knowledge-graph): 引入实体抽取密度上限与类型纠偏防御层 - #535

Merged
ThreeFish-AI merged 2 commits into
feature/1.x.xfrom
ThreeFish-AI/kg-llm-extraction-tune
May 13, 2026
Merged

feat(knowledge-graph): 引入实体抽取密度上限与类型纠偏防御层#535
ThreeFish-AI merged 2 commits into
feature/1.x.xfrom
ThreeFish-AI/kg-llm-extraction-tune

Conversation

@ThreeFish-AI

Copy link
Copy Markdown
Owner

背景

  • 本次变更要解决的问题:构建 Harness Engineering 语料图谱时暴露两类 LLM 抽取质量缺陷——chunk 6(1137 字符)产出 16 实体 / 15 关系(过度抽取,密度约 71 字符/实体),且 `Claude`(AI 产品)被分类为 `person`。这些假阳实体会污染下游 entity_resolver → community_summarizer → context_builder 整条链路,且现有噪声过滤与置信度阈值无法解决类型层的错误。
  • 关联上下文/Issue/文档:延续 feat(knowledge-graph): 新增 Model Settings 面板,支持按语料库配置 LLM / Embedding 模型 #532(按语料库配置 LLM/Embedding 模型)后续质量调优。设计参考 Martinez-Rodriguez 等(Semantic Web J., 2018)的 Schema-Guided Extraction 范式,以及 Neo4j LLM-Graph-Builder 的 schema-first 默认设计。

核心变更

  • Prompt 工程:实体抽取 Prompt 增加密度引导(每 200 字符约 1 个核心实体)、AI 产品/机构 vs 真人名的分类引导与正反例、Chain-of-Thought 推理步骤;关系抽取 Prompt 增加 `⌈|E|×1.2⌉` 上限避免组合配对爆炸。
  • 后置校验防御层(新增 `extraction_validator.py`):white-list 覆盖 LLM 错判(`Claude/person → product`)、AI 产品 regex 兜底未列型号变体(`Claude 3.7 Sonnet` 等)、按 `max(3, chunk_len // 200)` 的密度截断(按 confidence 降序保留)。被纠偏的实体在 metadata 标记 `type_override_source` 与 `original_type` 以支持审计回滚。
  • 数据 SSOT(新增 `known_entities.yml`):维护 AI 产品 / 机构白名单(Claude / GPT-4 / Anthropic / OpenAI 等),代码不再硬编码;后续仅需追加 YAML 条目。
  • 可观测性:`KgBuildMetrics` 扩展 `over_extraction_chunks` / `type_override_count` / `entity_density_p95` 三个观测字段;service 层每 chunk 抽取后聚合,触发密度截断或类型改判时 WARN 日志。
  • 接口契约:`LLMEntityExtractor.extract` / `CompositeEntityExtractor.extract` 增加 keyword-only `stats_out: ChunkExtractionStats | None` 参数,向后兼容,仅 service 调用方主动传入。

风险与回滚

  • 主要风险:① 白名单不全导致漏判(缓解:保留 `original_type` metadata,可审计后补录);② 密度上限对术语极密集 chunk 误伤(缓解:`max(3, …)` 下界 + 命中时 WARN,可按 corpus 调整 `DENSITY_CHARS_PER_ENTITY`);③ Prompt 增量约 30 行 → token 成本上升 < 5%。
  • 回滚方式:单 commit `8b0cbddb` 完整覆盖六个文件,`git revert` 即可恢复;改动均为新 build 增量生效,不影响历史构建产物。

验证证据

  • 单元测试:新增 21 项单测覆盖白名单加载、类型重判(含 chunk 6 复现 `16 → 5`)、密度截断、边界与 `_parse_entity_response` 端到端集成。`uv run pytest tests/unit_tests/knowledge/test_extraction_validator.py` 全绿。
  • 集成测试:`uv run pytest tests/unit_tests/knowledge/` 全量 784 通过 / 0 回归(唯一失败 `test_extraction_llm_plan.py` 经 `git stash` 验证为 pre-existing,与本 PR 无关)。
  • E2E/Workflow:待此 PR 合入后在 Harness Engineering corpus 上重新构建,对照 `over_extraction_chunks` / `type_override_count` / `entity_density_p95` 字段验证效果。
  • 覆盖率:`extraction_validator.py` 单测覆盖率 97%。

影响范围

  • 前端:无。
  • 后端:`apps/negentropy/src/negentropy/knowledge/graph/` 下 extractors / metrics / service 三处改动 + validator / known_entities 两处新增。仅作用于 LLM 抽取路径,fallback(regex / cooccurrence)路径不受影响。
  • GitHub Actions / 文档:无配置变更;ruff lint / format pre-commit hook 全过。

Next Best Action

  • 合入后在 Harness Engineering corpus 触发一次重新构建,抽样 5-10 个 `product` 类型节点人工核验命名合理性;若出现新误判 case,仅需追加 `known_entities.yml` 即可,无需改代码。
  • 后续可在 `extraction_schema.py` 注册 `HARNESS_ENGINEERING_SCHEMA` 作为独立 PR,把领域感知 schema 与本次的通用纠偏分层解耦。

针对 Harness Engineering 语料构建中暴露的两类缺陷:单 chunk 实体过度抽取(如
1137 字符产出 16 实体)与类型误分类(Claude 被标为 person),按"宁缺毋滥"
原则补强 LLM 抽取链路:

- 实体 Prompt 增加密度引导(每 200 字符约 1 个核心实体)、AI 产品/机构 vs
  真人名的分类引导、Chain-of-Thought 推理步骤;关系 Prompt 增加 ⌈|E|×1.2⌉
  上限避免组合爆炸。
- 新增 extraction_validator 后置校验模块:known_entities 白名单覆盖 LLM 错判,
  AI 产品 regex 兜底未列型号变体,按 confidence 降序的密度截断(cap = max(3,
  chunk_len // 200)),全部信号回写到 ChunkExtractionStats。
- 新增 known_entities.yml 维护 AI 产品/机构白名单(Claude / GPT-4 / Anthropic
  等),作为 SSOT 避免代码硬编码。
- 解析层接入 validator:被纠偏的实体在 metadata 标记 type_override_source 与
  original_type,支持审计回滚。
- KgBuildMetrics 扩展 over_extraction_chunks / type_override_count /
  entity_density_p95 三个观测字段;service 层在每 chunk 抽取后聚合并按需 WARN。
- 配套 21 项单测覆盖白名单加载、类型重判、密度截断、边界与端到端集成。

参考:Martinez-Rodriguez 等 (Semantic Web J., 2018) 的 Schema-Guided Extraction
范式,以及 Neo4j LLM-Graph-Builder 的 schema-first 设计。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
依据代码审查意见落实两处修复:

1. `AI_PRODUCT_PATTERN` 尾部分组 `(?:[- ]?[\w.]+)*` 过于宽松,会把
   `Claude Shannon` / `Claude Monet` / `Gemini Cricket` 等真人复合名
   整体吞掉并误改为 product。现要求触发词后至少跟随一个“型号样式”
   后缀(数字开头或 opus/sonnet/haiku/pro/ultra/mini/turbo 等已知规格
   关键字),裸名继续由 known_entities 白名单覆盖。

2. `_parse_entity_response` 在 `entity_density_truncated` 日志中
   `cap=len(results) + dropped - dropped` 是恒等式,简化为
   `cap=len(results)`,避免读者怀疑特殊意图。

同步更新单元测试:删除“裸名命中正则”的过时断言,新增对真人复合名
(`Claude Shannon` 等)的负向断言以防回归。21 个用例全部通过。

🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist)
Co-Authored-By: Aurelius Huang<threefish.ai@gmail.com>
@ThreeFish-AI
ThreeFish-AI merged commit f636b4a into feature/1.x.x May 13, 2026
3 checks passed
@ThreeFish-AI
ThreeFish-AI deleted the ThreeFish-AI/kg-llm-extraction-tune branch May 13, 2026 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant