Coverage for src/qdrant_loader_mcp_server/search/enhanced/kg/models.py: 95%
73 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-08 06:06 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-08 06:06 +0000
1from __future__ import annotations
3import uuid
4from dataclasses import dataclass, field
5from enum import Enum
6from typing import Any
9class NodeType(Enum):
10 DOCUMENT = "document"
11 SECTION = "section"
12 ENTITY = "entity"
13 TOPIC = "topic"
14 CONCEPT = "concept"
17class RelationshipType(Enum):
18 CONTAINS = "contains"
19 PART_OF = "part_of"
20 SIBLING = "sibling"
21 MENTIONS = "mentions"
22 DISCUSSES = "discusses"
23 RELATES_TO = "relates_to"
24 SIMILAR_TO = "similar_to"
25 REFERENCES = "references"
26 CITES = "cites"
27 BUILDS_ON = "builds_on"
28 CONTRADICTS = "contradicts"
29 CO_OCCURS = "co_occurs"
30 CATEGORIZED_AS = "categorized_as"
33@dataclass
34class GraphNode:
35 node_type: NodeType
36 title: str
37 id: str | None = None
38 content: str | None = None
39 metadata: dict[str, Any] = field(default_factory=dict)
41 centrality_score: float = 0.0
42 authority_score: float = 0.0
43 hub_score: float = 0.0
45 entities: list[str] = field(default_factory=list)
46 topics: list[str] = field(default_factory=list)
47 concepts: list[str] = field(default_factory=list)
48 keywords: list[str] = field(default_factory=list)
50 def __post_init__(self):
51 if self.id is None or self.id == "":
52 # Deterministic UUIDv5 id derived from stable inputs (node_type + title)
53 # Fixed namespace ensures stable generation across runs/processes
54 node_namespace = uuid.UUID("8f5b3e78-9b8c-4f07-b54e-27f7ac1d5a11")
55 name = f"{self.node_type.value}::{self.title}"
56 deterministic_uuid = uuid.uuid5(node_namespace, name)
57 self.id = f"{self.node_type.value}_{deterministic_uuid}"
60@dataclass
61class GraphEdge:
62 source_id: str
63 target_id: str
64 relationship_type: RelationshipType
65 weight: float = 1.0
66 metadata: dict[str, Any] = field(default_factory=dict)
67 evidence: list[str] = field(default_factory=list)
68 confidence: float = 1.0
70 def __post_init__(self):
71 self.weight = max(0.0, min(1.0, self.weight))
72 self.confidence = max(0.0, min(1.0, self.confidence))
75class TraversalStrategy(Enum):
76 BREADTH_FIRST = "breadth_first"
77 DEPTH_FIRST = "depth_first"
78 WEIGHTED = "weighted"
79 CENTRALITY = "centrality"
80 SEMANTIC = "semantic"
81 HIERARCHICAL = "hierarchical"
84@dataclass
85class TraversalResult:
86 path: list[str]
87 nodes: list[GraphNode]
88 edges: list[GraphEdge]
89 total_weight: float
90 semantic_score: float
91 hop_count: int
92 reasoning_path: list[str]