Skip to content

fix(knowledge-graph): KG Build 管线七项级联缺陷端到端修复 — 从根因到下游全链路优化 - #523

Merged
ThreeFish-AI merged 3 commits into
feature/1.x.xfrom
ThreeFish-AI/optimize-kg-build-pipeline
May 12, 2026
Merged

fix(knowledge-graph): KG Build 管线七项级联缺陷端到端修复 — 从根因到下游全链路优化#523
ThreeFish-AI merged 3 commits into
feature/1.x.xfrom
ThreeFish-AI/optimize-kg-build-pipeline

Conversation

@ThreeFish-AI

Copy link
Copy Markdown
Owner

背景

  • 本次变更要解决的问题:KG Build 一次完整构建日志暴露 ~740 条事务级联崩溃 + 全部下游阶段跳过——20 chunks 耗时 18 分钟,317 实体仅同步 22 个、444 关系同步 0 条,PageRank/Community/Summary 三阶段全部因 empty_graph 跳过。
  • 关联上下文/Issue/文档docs/issue.md ISSUE-081(详细 RCA 与同类问题影响)。

核心变更

按依赖顺序的 10 项正交修复(7 项主修复 + 3 项二轮 review 补齐):

  • Issue 0(根因) sync_entity_from_knowledge 幂等 SELECT 移除 entity_type 列条件,与 UNIQUE 约束 uq_kg_entity_corpus_name(corpus_id, canonical_name) 对齐;命中已有记录时按 type_precedence 更新 entity_type,消除 `UniqueViolationError` "第一块多米诺骨牌"。
  • Issue 1(防御层) batch_sync_from_graph_build 每条 entity/relation 操作包裹在 async with db.begin_nested() 中(SAVEPOINT),单条失败仅回滚该 savepoint(Kleppmann DDIA §7.3)。
  • Issue 2(容错) _execute_buildsyncing/pagerank/communities/summaries 四阶段开始前各加 session 健康检查(in_transaction → rollback);graph_algorithms.pycompute_pagerank / compute_communities 入口同步做防御。
  • Issue 3(LLM 退避) 抽出 _compute_retry_backoff() 统一函数,检测 524/timeout 采用递增退避(30s/60s/90s + jitter),普通错误指数退避;KG_LLM_TIMEOUT_SECONDS 默认 300 → 110(低于 Cloudflare 120s Proxy Read Timeout)。
  • Issue 4(实体质量) 新增 _GENERIC_ENTITY_STOPWORDS frozenset + is_noise_entity() — 过滤泛化术语、URL、日期、文件名、源码引用、过短/过长实体;RegexEntityExtractor 复用同一函数;LLM prompt 显式约束避免噪声。
  • Issue 5(可见性) chunk_processing 起止日志升至 INFO(含 chunk_index/total_chunks/elapsed_ms/mode);小批次(≤50 chunks)进度上报间隔 5s→2s;emit_phase 输出 prev_phase_elapsed_ms 便于排查阶段瓶颈。
  • Issue 6(降级) CommunitySummarizercommunity_entities 为空但实体表非空时,调用 _load_all_entities() 加载 Top-200 实体作为单一全局社区生成 level=0 摘要,确保 GraphRAG Global Search 仍有召回基线。

风险与回滚

  • 主要风险
    1. SELECT/INSERT 列对齐改动 sync_entity_from_knowledge 的语义——已有记录若 entity_type 不同会按 precedence 升级;不会下降。
    2. KG_LLM_TIMEOUT_SECONDS 默认值从 300 降至 110——极端复杂 chunk 可能触发更频繁的 fallback,但断路器 + co-occurrence fallback 保证图谱非空。
    3. SAVEPOINT 引入额外 round-trip——对 100 实体级 batch 影响可忽略;保守起见仍保留原 try/except 兜底。
  • 回滚方式git revert 393a90cc fbb947db 即可;无 DB schema 变更,无数据迁移。

验证证据

  • 单元测试:knowledge 单元测试 669 通过(1 个 test_extraction_llm_plan 失败为 pre-existing 与本次改动无关);新增 SAVEPOINT mock 支持。
  • 集成测试:暂无(本次为修复型变更,验证通过单测 + 端到端日志比对完成)。
  • E2E/Workflow:建议合入后对同一 20-chunks 语料触发完整 KG Build,验证六阶段全部执行 + sync_result 实体/关系计数对齐 + build_duration_ms 显著降低。
  • 覆盖率/关键截图:N/A(本次修改集中于异常处理与可观测性,新增分支覆盖由 SAVEPOINT + fallback 路径单测覆盖)。

影响范围

  • 前端:无。
  • 后端apps/negentropy/src/negentropy/knowledge/graph/ 下 5 个核心源文件(community_summarizer / entity_service / extractors / graph_algorithms / service / strategy)+ 测试支持。
  • GitHub Actions / 文档docs/issue.md 新增 ISSUE-081 详细 RCA 条目。

Next Best Action

  • 合入后:触发一次同语料完整 KG Build 验证端到端通顺度;观察 prev_phase_elapsed_ms 找出真正瓶颈阶段。
  • 后续优化:考虑让 export_graph_to_networkx 优先从 AGE 图读取(当前只读一等公民表,Issue 7 — 长期方案)。
  • 可观测性增强:在 Grafana 看板增加 chunks_fallback / circuit_breaker_opened 指标曲线。

🤖 Generated with Claude Code

修复 KG Build 日志中暴露的 ~740 条事务级联崩溃 + 全部下游阶段跳过问题。
日志现象:20 chunks 耗时 18 分钟,317 实体仅同步 22 个、444 关系同步 0 条,
PageRank/Community/Summary 三阶段全部因 empty_graph 跳过。

七项正交修复(按依赖顺序):

Issue 0(根因):sync_entity_from_knowledge 的幂等 SELECT 移除 entity_type 列
条件,与 UNIQUE 约束 uq_kg_entity_corpus_name(corpus_id, canonical_name) 对齐;
命中已有记录时按 type_precedence 更新 entity_type,消除 UniqueViolationError
"第一块多米诺骨牌"。

Issue 1(防御层):batch_sync_from_graph_build 中每条 entity/relation 操作
包裹在 async with db.begin_nested() 中(SAVEPOINT),单条失败仅回滚该
savepoint,杜绝整批级联崩溃(Kleppmann DDIA §7.3)。

Issue 2(容错):_execute_build 在 PageRank/Community/Summary 三阶段开始前
各加 session 健康检查(in_transaction → rollback),防御前序阶段失败
污染 session 状态。

Issue 3(LLM 退避):抽出 _compute_retry_backoff() 统一函数,检测 524/
timeout 采用递增退避(30s/60s/90s + jitter),普通错误指数退避。
KG_LLM_TIMEOUT_SECONDS 默认 300→110(低于 Cloudflare 120s Proxy Read
Timeout),让应用层先于代理斩断连接。

Issue 4(实体质量):新增 _GENERIC_ENTITY_STOPWORDS frozenset +
is_noise_entity() — 过滤泛化术语(CSS/HTML/JSON/agent/spec/UI/...)、
URL、日期字符串、文件名、源码引用、过短/过长实体。RegexEntityExtractor
复用同一函数;LLM prompt 显式约束避免提取噪声。

Issue 5(可见性):chunk_processing 起止日志升至 INFO,含 chunk_index/
total_chunks/elapsed_ms/mode(5 种路径区分);小批次(≤50 chunks)
进度上报间隔 5s→2s。

Issue 6(降级):CommunitySummarizer 当 community_entities 为空但实体表
非空时,调用 _load_all_entities() 加载 Top-200 实体作为单一全局社区
生成 level=0 摘要,确保 GraphRAG Global Search 仍有召回基线。

测试:669 个 knowledge 单元测试通过(test_extraction_llm_plan 1 个失败为
pre-existing 与本次改动无关);新增 SAVEPOINT mock 支持(conftest +
test_graph_entity_service)。

详细 RCA 记录于 docs/issue.md ISSUE-081。

🤖 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>
二轮 review Plan 实施完整度后发现的三处遗漏,本次一并补齐:

缺口 A(Issue 2 补漏):service.py syncing 阶段(emit_phase 调用前)缺少
session 健康检查,可能在 resolving 异常时让 shared_session.begin() 重抛
"Can't operate on closed transaction"。补加 `if shared_session.in_transaction():
await rollback()` 与下游三个阶段保持一致。

缺口 B(Issue 2 补漏):graph_algorithms.py 的 compute_pagerank 和
compute_communities 入口未做防御性 session 检查。Plan 原文明确要求
"在 export_graph_to_networkx 调用前添加 session 状态检查"——对外部调用方
(非 service.py 主链路)同样有保护作用。

缺口 C(Issue 5 补漏):emit_phase 未输出前一阶段 elapsed_ms。补加
phase_timing 闭包字典记录 prev_name / prev_started_at,在 graph_phase_started
日志中追加 prev_phase + prev_phase_elapsed_ms 字段,便于排查各阶段
性能瓶颈(如 extracting 80s vs syncing 0.5s)。

测试:knowledge 单元测试 669 通过(同 pre-existing 1 个 test_extraction_llm_plan
失败与本次改动无关)。

🤖 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>
- extractors: 新增 JS/TS 框架白名单短路放行 _FILE_NAME_PATTERN
  避免 Node.js / Vue.js / Three.js / Next.js / Express.js 等
  高价值产品实体被误判为文件名过滤
- strategy: 移除宽泛 try/except Exception: pass,将 is_noise_entity
  import 上提到模块顶部,恢复异常反馈信号
- graph_algorithms: compute_pagerank / compute_communities 改用
  try/except PendingRollbackError 仅在事务 invalid 时回滚,
  避免对调用方健康事务产生破坏性副作用

🤖 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 949d77e into feature/1.x.x May 12, 2026
7 checks passed
@ThreeFish-AI
ThreeFish-AI deleted the ThreeFish-AI/optimize-kg-build-pipeline branch May 12, 2026 01:55
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