Skip to content

cluster-only on a merge-graphs output remaps against per-source community ids, so saved LLM labels are mostly lost on every rebuild #3858

Description

@Davy45270

Summary

When cluster-only re-clusters, it maps the new communities onto the previous ones
(remap_communities_to_previous, #822/#1027) using the community attribute of the nodes in
the input graph.json (cli.py, previous_node_community = {n["id"]: n["community"] ...}).

In a multi-source pipeline, that input is the fresh output of merge-graphs, which carries
each source's own community ids (overlapping 0..N per source before 0.9.50, offset per
input since 0.9.50, original kept in local_community). It does not carry the previous
merged clustering, which is what .graphify_labels.json / .graphify_labels.json.sig
were written against. The remap therefore aligns new communities to the wrong groups, the
per-cid signature check fails for most communities, and they are renamed by their hub.

Version

Measured on 0.9.46; code path unchanged in 0.9.69 (label-reuse branch identical by diff,
previous_node_community still read from the input file).

Evidence

Pipeline: per-source graphify update → graphify merge-graphs a.json b.json ... --out merged/graphify-out/graph.json → cd merged && graphify cluster-only . (labels file kept).
~15 000 nodes, ~1 700 communities, 5 sources.

Rebuild after a small commit (a few nodes changed) Communities renamed by hub
As above, 0.9.46 1 130 / 1 709
Same, but the previous merged graph.json is saved before merge-graphs and its community value is copied back onto each node (by node id) before cluster-only — 0.9.69, first build after the upgrade 128 / 1 660

The saved merged graph.json from the day before had 660 distinct community values
after merge-graphs (per-source ids) vs 1 709 in the previous merged clustering.

Offline simulation on the same graph (0.9.69 offsets, no workaround): if one early source
gains a single community, all later offsets shift and only 285 / 1 702 labels survive.

Workaround (10 lines)

cp merged/graphify-out/graph.json merged/graphify-out/graph.previous.json
graphify merge-graphs ... --out merged/graphify-out/graph.json
python3 - <<'PY'
import json
prev = {n["id"]: n["community"] for n in json.load(open("merged/graphify-out/graph.previous.json"))["nodes"]
        if n.get("community") is not None}
g = json.load(open("merged/graphify-out/graph.json"))
for n in g["nodes"]:
    if n["id"] in prev: n["community"] = prev[n["id"]]
    else: n.pop("community", None)
json.dump(g, open("merged/graphify-out/graph.json", "w"))
PY
(cd merged && graphify cluster-only .)

Related

#3014 (merge-graphs namespacing — this is the downstream effect on label reuse), #2452 (seed
cluster() with a previous partition), #2298 (exact-membership signature), #3334.

Suggested fix

Either merge-graphs could accept --previous <merged graph.json> and emit the previous merged
community (keeping per-source ids only in local_community), or cluster-only could prefer
graphify-out/graph.json already on disk (the previous run's output) over the input's
community attribute when a labels sidecar exists.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions