Merge multiple extraction results into one graph. directed=True produces a DiGraph that preserves edge direction (source→target). directed=False (default) produces an undirected Graph for backward compatibility. dedup=True (default) runs entity deduplication before building the graph.
(
extractions: list[dict],
*,
directed: bool = False,
dedup: bool = True,
dedup_llm_backend: str | None = None,
root: str | Path | None = None,
)
| 633 | |
| 634 | |
| 635 | def build( |
| 636 | extractions: list[dict], |
| 637 | *, |
| 638 | directed: bool = False, |
| 639 | dedup: bool = True, |
| 640 | dedup_llm_backend: str | None = None, |
| 641 | root: str | Path | None = None, |
| 642 | ) -> nx.Graph: |
| 643 | """Merge multiple extraction results into one graph. |
| 644 | |
| 645 | directed=True produces a DiGraph that preserves edge direction (source→target). |
| 646 | directed=False (default) produces an undirected Graph for backward compatibility. |
| 647 | dedup=True (default) runs entity deduplication before building the graph. |
| 648 | dedup_llm_backend: if set (e.g. "gemini", "claude", or "kimi"), uses LLM to resolve |
| 649 | ambiguous pairs in the 75–92 Jaro-Winkler score zone. |
| 650 | root: if given, absolute source_file paths are made relative to root (#932). |
| 651 | |
| 652 | Extractions are merged in order. For nodes with the same ID, the last |
| 653 | extraction's attributes win (NetworkX add_node overwrites). Pass AST |
| 654 | results before semantic results so semantic labels take precedence, or |
| 655 | reverse the order if you prefer AST source_location precision to win. |
| 656 | """ |
| 657 | from graphify.dedup import deduplicate_entities |
| 658 | combined: dict = {"nodes": [], "edges": [], "hyperedges": [], "input_tokens": 0, "output_tokens": 0} |
| 659 | for ext in extractions: |
| 660 | combined["nodes"].extend(ext.get("nodes", [])) |
| 661 | combined["edges"].extend(ext.get("edges", [])) |
| 662 | combined["hyperedges"].extend(ext.get("hyperedges", [])) |
| 663 | combined["input_tokens"] += ext.get("input_tokens", 0) |
| 664 | combined["output_tokens"] += ext.get("output_tokens", 0) |
| 665 | if dedup and combined["nodes"]: |
| 666 | combined["nodes"], combined["edges"] = deduplicate_entities( |
| 667 | combined["nodes"], combined["edges"], communities={}, |
| 668 | dedup_llm_backend=dedup_llm_backend, |
| 669 | ) |
| 670 | return build_from_json(combined, directed=directed, root=root) |
| 671 | |
| 672 | |
| 673 | def _norm_label(label: str | None) -> str: |