Repository navigation
Conversation
- 新增版本化 prompt profile 加载器(结构 fail-closed 校验),10 个 generate method 全部支持 config 级模板覆盖 - pms_policy.v2 内置 profile:迁移 PMS 侧 v2 出题策略模板为正本 - 输出门注册表(pms_project_anchor)与 LLM 并发封顶成为 GenerateService 一等参数 - 复位历史上随 checkout 重建丢失的三个补丁:空响应重试、空抽取 prefill、logprob 调用关思考(env 开关语义不变) - 台账见 docs/PMS_PATCHES.md
- 事件抽取:SAG extract_document v3.1 提示词改编 + 严格响应合同 + 数字接地校验(MIT 归因) - 星型编码进图:事件=EVENT 节点+成员边(边属性含角色),merge/SEP 血缘复用官方 LightRAG - build_kg kg_method 分发:event_entity 与 light_rag 并存,默认行为逐字节不变 - event_join 分区器:共享实体 join + 同锚硬约束,产出官方 Community,metadata 带 event_ids - <support> 审计链:生成端引用分区节点集合校验,失败剥离保留题面;pms_policy.v3 profile - 台账 docs/PMS_PATCHES.md InternScience#7;fork 测试基线与上游一致(23F/6P,零回归) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- event_contract 抽为纯 stdlib 模块(rft 契约测试可按路径加载) - builder 补回 json 导入;EVENT 节点/成员边/参与者实体确定性 SEP 合并,不再触发 LightRAG LLM 摘要(摘要器曾把 event id 扩写成伪业务事实污染出题上下文) - EventJoinPartitioner 继承 BasePartitioner(community2batch);models lazy export 补齐 - v3 profile support 大括号转义(str.format KeyError);分区服务移除 metadata 依赖 (support 校验以持久化分区节点集合为准,JSONL 往返一致) - 真实 10 记录端到端 smoke 全通:7 分区→7 题全锚点合规、cited 全部通过分区校验 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
引入版本化事件抽取profile,将实体类型、prompt、锚点和数字接地策略从PMS专用代码解耦。event_join基于显式锚点属性隔离,生成prompt隐藏内部事件ID并把support引用映射回canonical节点。\n\n新增多项目SDK与不可变tag发布文档,修正安装包资源声明和过时的partition integration测试;保留LightRAG+ECE默认路径及PMS事件ID兼容。完成真实非PMS抽取、分区和问答生成smoke,默认生成结果未泄漏内部事件ID。\n\nCo-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
新增可配置 Ray LLM actor 并发并保持默认串行兼容。 为缺失 logger 上下文的 Ray 调用提供标准 logger fallback;加入并发与日志回归测试,更新版本及发行说明。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ChenZiHong-Gavin
left a comment
There was a problem hiding this comment.
Thanks for the detailed PR. The opt-in mechanisms here (versioned prompt profiles with fail-closed structural validation, output-gate registry, per-loop LLM concurrency cap, the env-gated LLM client fixes) are genuinely useful, and the default LightRAG + ECE path is indeed untouched. The partitioner test fixes (async → sync) are also correct; those tests are broken on main today.
That said, I don't think this can merge as-is:
- Three functional bugs (inline, two of them reproduced locally): path-based event profiles fail on second load; edge citations in
<support>are always stripped; the extraction prefill uses tuple format against a JSON parser. - Fork identity leaks into upstream:
setup.pyURL/author, version 1.1.0, fork README section, fork release docs. - PMS domain policy ships in the core package:
pms_policy.v2/v3prompts,pms_project_anchorgate,pms_event.v1as the implicit default. - CI is red: Pylint exits 28 (line length, too-many-branches/statements, unused imports, duplicate
validate_supportimport ingenerate_service.py, andarguments-differon all 10build_promptoverrides after the static → instance change).
Suggested split, smallest first:
- PR A: partitioner test fixes only.
- PR B: prompt-profile mechanism + gate registry +
llm_concurrency+ the four env-gated LLM client patches, with nopms_*assets. - PR C:
event_entitybuilder +event_joinpartitioner + profile loader, shipping onlygeneric_event.v1as an example, with the three bugs fixed. - PMS profiles and fork release docs stay in the fork.
| if self.kg_method == "event_entity": | ||
| from graphgen.templates.event_profile_loader import load_event_profile | ||
|
|
||
| self.event_profile = load_event_profile(self.event_profile).profile_id |
There was a problem hiding this comment.
Bug (verified): this keeps only profile_id after loading, and build_event_entity_kg then calls load_event_profile(profile_id) again, which only looks in the packaged event_profiles/ directory. Any profile passed as a filesystem path (the flow docs/MULTI_PROJECT_SDK.md tells new projects to use) fails on the second load.
Repro: copy generic_event.v1 to a temp dir as myproj.v1, set event_profile: /tmp/.../profile.json → event_profile_not_found:myproj.v1.
Suggest passing the loaded EventExtractionProfile object down instead of the id.
| display_target = display_by_id.get(str(target), target) | ||
| edges.append((display_source, display_target, data)) | ||
| if str(source) in display_by_id: | ||
| support_aliases[f"{display_source} - {display_target}"] = f"{source} - {target}" |
There was a problem hiding this comment.
Bug (verified): edge citations are resolved to "{source} - {target}", but validate_support (L103) only checks against the node-name set, so every edge citation is stripped. Also the alias separator here is a single -, while MultiHopGenerator.build_prompt renders edges with --, so the alias never matches what the model actually sees.
Tested: node citation passes; T - A and T -- A both come back None.
Either add edges to the validation set (and use one separator everywhere), or document that support.cited is node-only.
| # that seeds the opening of the expected output; non-empty responses | ||
| # are never retried or modified. | ||
| if not response.strip() and os.environ.get("GRAPHGEN_EMPTY_EXTRACTION_PREFILL", "0") == "1": | ||
| prefill = '("entity"<|>' |
There was a problem hiding this comment.
Bug: ("entity"<|> is the LightRAG tuple-format opener from kg_extraction.py. This extractor parses the response with json.loads a few lines below, so a response that starts with this prefill can never parse. The retry will always fail. This patch belongs in the LightRAGKGBuilder extraction path, not here.
| return await self._merge_event_node(entity_name, node_list, kg_instance) | ||
| # 星型事件参与者是图投影,不需要再次 LLM 摘要;只做确定性去重合并, | ||
| # 避免 LightRAG summarizer 把跨事件上下文扩写成伪业务事实。 | ||
| return await self._merge_entity_node(entity_name, node_list, kg_instance) |
There was a problem hiding this comment.
docs/PMS_PATCHES.md #7 says entity descriptions and normal edges "continue to reuse the official merge", but this routes all entity nodes through the custom SEP-dedup merge and never calls the LightRAG summarizer. Code and docs disagree; please align one of them.
| event_ids = { | ||
| str(dp["src_id"]) | ||
| for dp in edge_list | ||
| if dp.get("event_member") and dp.get("src_id") |
There was a problem hiding this comment.
merge_edges depends on event_member, but extract() never sets it. The flag is injected afterwards by build_event_kg.py (L47). Anyone using the builder directly gets the wrong branch. Set it in extract() where the edge is created.
|
|
||
| from graphgen.templates.event_profile_loader import load_event_profile | ||
|
|
||
| _pms_profile = load_event_profile("pms_event.v1") |
There was a problem hiding this comment.
This runs file I/O at import time for every import graphgen.templates, and the exported EVENT_ENTITY_EXTRACTION_PROMPT is not used by the builder itself. It is a compatibility shim for fork consumers; it should not be in upstream.
| import zipfile | ||
|
|
||
| output = tmp_path / "dist" | ||
| subprocess.run(["uv", "build", str(REPO), "--out-dir", str(output)], check=True, capture_output=True, text=True) |
There was a problem hiding this comment.
This shells out to uv build and builds the whole package inside a unit test. It requires uv on PATH and is slow. This belongs in a packaging CI job, not in pytest.
| name="graphg", | ||
| version=get_version(), | ||
| url="https://github.com/open-sciencelab/GraphGen", | ||
| url="https://github.com/Leon-Algo/GraphGen", |
There was a problem hiding this comment.
Package URL / author / version (_version.py → 1.1.0) are fork release metadata and must not be changed in an upstream PR. Same for the "Maintained fork" README section, docs/RELEASING.md and the two RELEASE_NOTES files.
| - `get_current_logger` falls back to the standard `GraphGen` logger only when the ContextVar is absent. This does not catch or replace LLM/model errors and does not fabricate generation output. | ||
| - Covered by `tests/unit_tests/utils/test_init_llm_actor_concurrency.py` and `tests/unit_tests/utils/test_log.py`. | ||
|
|
||
| ## #9 Ray LLM actor concurrency and logger context fallback (1.1.0) |
There was a problem hiding this comment.
Section #9 is duplicated (L97 and L103).
| from collections import defaultdict | ||
| from typing import Any | ||
|
|
||
| PMS_ENTITY_TYPES: list[dict] = [ |
There was a problem hiding this comment.
PMS-specific defaults are hard-coded into the core package: PMS_ENTITY_TYPES, PROJECT_ID_RE, and load_event_profile(None) falling back to pms_event.v1. For upstream, there should be no default profile; a missing profile should be an error. The pms_* prompt/gate/profile assets should stay in the fork.
内置 pms_event.v1 提示词要求锚点必须原样取自片段,并加入防照抄回归测试;与生成策略 v2_2 的加固一致。版本号升至 1.1.1。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Code reviewFound 1 issue:
BuildKGService passes only profile_id; the loader switches to packaged lookup for ID-only references; the documented external-path contract. Generated with Claude Code |
Code reviewFound 1 issue:
Merge payload construction · Documented membership-edge role |
修复文件型事件 profile 传递、双向 support 边引用、无锚事件分区、JSON prefill 和逐请求限流;保留事件成员标记与角色属性。升级 graphg 到 1.1.2,补充回归测试和发行记录。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
登记最终候选提交、wheel/sdist 哈希及 Python 3.12 安装证据。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
记录 fork tag、PMSAgent pin、锁文件同步与兼容测试最终结果。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Validation
Notes
kg_method: event_entityandpartition.method: event_join.🤖 Generated with Claude Code