Skip to content

Make community labeling size-aware - #3618

Open
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:investigate/3586-size-aware-community-labels
Open

hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:investigate/3586-size-aware-community-labels

Conversation

@hopstreax

Copy link
Copy Markdown
Contributor

Summary

Fixes #3586 by making community labeling more representative for large communities and safer for large labeling batches.

Changes

  • Replace the fixed 12-node community sample with size-aware sampling, scaling up to 32 representatives for large communities.

  • Improve representative selection using:

    • Community-internal degree
    • Global degree
    • Deterministic node ordering
    • Source-file diversity with backfill
  • Add token-aware batching while preserving batch_size as the maximum number of communities per LLM call.

  • Preserve explicit top_k overrides and backward compatibility.

  • Add regression tests covering adaptive sampling, representative diversity, backfill, and token-aware batching.

Validation

  • pytest tests/test_labeling.py tests/test_llm_backends.py tests/test_community_hub_labels.py -q

    • 160 passed
  • git diff --check

    • Clean

Closes #3586

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 3 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Reworks community-label sampling to be size-aware: when top_k is None (now the default), _community_label_lines picks each community's representative count via _adaptive_sample_size (12–32 by membership), ranks members by god-node status, internal degree, global degree, then id, and applies a per-source-file diversity cap with a backfill pass so single-file communities still fill their quota; passing an explicit top_k keeps the old fixed-cap behaviour. Replaces the fixed count-based batching with _pack_label_batches, which greedily packs communities into batches bounded by both batch_size and an _LABEL_MAX_PROMPT_TOKENS (8000) budget estimated via _estimate_text_tokens, keeping largest-first order and emitting an oversized community as its own single-item batch rather than dropping it. Hoists the naming prompt into the shared _LABEL_PROMPT_PREAMBLE constant used by both the batch call and the token estimate.

Worth a look

  • label_communities default top_k changed from fixed cap to adaptive samplinggraphify/llm.py:3551 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • label_communities top_k default changed from int to None alters public behaviorgraphify/llm.py:3551 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • New parameter inserted before existing positional argumentgraphify/llm.py:3658 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 933 functions depend on the 281 functions this change touches.

Health — this change adds coupling hotspots:

  • new: deduplicate_entities() — 77 callers, 24 callees
  • new: build_merge() — 76 callers, 14 callees
  • new: extract_files_direct() — 17 callers, 20 callees
  • new: build() — 52 callers, 6 callees
  • new: _call_claude_cli() — 33 callers, 9 callees
  • new: extract_corpus_parallel() — 26 callers, 11 callees
  • new: dispatch_command() — 2 callers, 125 callees
  • new: _extract_with_adaptive_retry() — 22 callers, 10 callees
  • …and 16 more — each is listed as a finding

Verification — 933 functions in the blast radius were not formally verified this run (proofs are advisory here).

Health delta baseline: last indexed commit 26b02b5 (diverged from this PR's base — delta is approximate).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 598 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

41 of 286 test file(s) selected (14%) via static blast radius.

  • tests/test_backend_env_isolation.py — impact
  • tests/test_backend_extras.py — impact
  • tests/test_build.py — impact
  • tests/test_build_merge_dedup_scope.py — impact
  • tests/test_build_merge_hyperedges_and_prune.py — impact
  • tests/test_build_merge_shrink_guard.py — impact
  • tests/test_carried_hyperedge_remap.py — impact
  • tests/test_charmap_encoding.py — impact
  • tests/test_chunking.py — impact
  • tests/test_claude_cli_backend.py — impact
  • tests/test_corrupt_graph_json.py — impact
  • tests/test_cross_extension_reexport_self_cycle.py — impact
  • tests/test_dedup.py — impact
  • tests/test_dedup_remaps_hyperedges.py — impact
  • tests/test_dedup_survivor_richness.py — impact
  • tests/test_evidence_binding.py — impact
  • tests/test_file_slice.py — impact
  • tests/test_global_graph.py — impact
  • tests/test_go_qualified_resolution.py — impact
  • tests/test_hyperedge_member_shapes.py — impact
  • tests/test_image_vision.py — impact
  • tests/test_injection_sentinel_coverage.py — impact
  • tests/test_issue_3472_source_file_collision.py — impact
  • tests/test_label_retry.py — impact
  • tests/test_labeling.py — impact, changed-test
  • tests/test_llm_backends.py — impact
  • tests/test_llm_parser.py — impact
  • tests/test_llm_parser_reasoning.py — impact
  • tests/test_no_dedup_flag.py — impact
  • tests/test_non_string_node_ids.py — impact
  • tests/test_ollama.py — impact
  • tests/test_ollama_retry_cap.py — impact
  • tests/test_oversized_document_slicing.py — impact
  • tests/test_partial_cache.py — impact
  • tests/test_pdf_slicing.py — impact
  • tests/test_pdf_token_estimate.py — impact
  • tests/test_provider_registry.py — impact
  • tests/test_prs.py — impact
  • tests/test_prune_sweeps_orphans.py — impact
  • tests/test_semantic_fragment_sanitize.py — impact
  • tests/test_unverified_semantic_shrink.py — impact

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Formal verification

Could not verify: Could not verify \_community\_label\_lines.

The verifier did not have enough to check \_community\_label\_lines, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: no capturable inputs from the test suite; property tier: not verifiable: all 200 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly TypeError — names the real obstacle, not a sampling gap)

Could not verify: Could not verify generate\_community\_labels.

The verifier did not have enough to check generate\_community\_labels, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: no capturable inputs from the test suite; property tier: non-vacuity: domain too small (only 1 distinct inputs exercised, need 3) — 'no divergence' would be near-vacuous

Could not verify: Could not verify \_label\_batch\_with\_retry.

The verifier did not have enough to check \_label\_batch\_with\_retry, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: no capturable inputs from the test suite; property tier: not verifiable: all 9 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly TypeError — names the real obstacle, not a sampling gap)

Could not verify: Could not verify label\_communities.

The verifier did not have enough to check label\_communities, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: no capturable inputs from the test suite; property tier: not verifiable: all 49 sampled inputs raised on both versions — the function never executed, so 'no divergence' would be vacuous (mostly TypeError — names the real obstacle, not a sampling gap)

· 1 grounded finding(s) anchored inline below; 23 more finding(s) on lines outside this diff (see the check run).

Comment thread graphify/llm.py
return batches


def label_communities(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regressionlabel_communities()

22 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

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.

_LABEL_TOP_K = 12 is fixed regardless of community size — large communities get inaccurate/misleading labels

1 participant