mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
Merge pull request #539 from Hawksight-AI/conflicts
fix(conflicts): consolidate duplicate detect_conflicts into single di…
This commit is contained in:
@@ -57,6 +57,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Fix: `ConflictDetector.detect_conflicts()` raises `AttributeError` when called with `method=` or `property_name=` kwargs** (issue #533, PR conflicts, by @KaifAhmad1):
|
||||
- `detect_conflicts` was defined twice in `conflict_detector.py`; Python silently overwrote the first (dispatcher) definition with the second (comprehensive), which accepted no `method` or `property_name` parameters — causing `AttributeError` or `TypeError` for any caller using those kwargs.
|
||||
- Removed the first (dead) definition and merged its dispatcher logic into the surviving method. New signature: `detect_conflicts(entities, method="all", property_name=None, entity_type=None, **kwargs)`.
|
||||
- Supported `method` values: `"all"` (default, comprehensive), `"value"`, `"property"`, `"type"`, `"relationship"`, `"temporal"`, `"logical"`, `"entity"`. Unknown values raise `ValueError`.
|
||||
- Fixed `method="relationship"` silently defaulting `relationships` to the entities list, which caused entity dicts to be iterated as relationship dicts producing silent wrong results (`None_None_None` keys). Now defaults to `[]` with dict normalization.
|
||||
- Removed unreachable dead code (`for field_name in fields_to_check` loop after `try/except raise`) in `detect_entity_conflicts`.
|
||||
|
||||
- **Fix: `semantica[all]` installation fails on Windows due to `faiss-gpu` dependency** (issue #532, PR #utlis, by @KaifAhmad1):
|
||||
- `[all]` bundled the `[gpu]` extra (`faiss-gpu>=1.7.0`, `cupy>=10.0.0`), which has no Windows builds, causing `pip install "semantica[all]"` to fail with `No matching distribution found for faiss-gpu>=1.7.0`.
|
||||
- Removed `gpu` from both `[all]` lines in `pyproject.toml` — `[all]` now installs only cross-platform dependencies. Users on Linux who need GPU acceleration can install `semantica[gpu]` explicitly.
|
||||
|
||||
@@ -133,48 +133,6 @@ class ConflictDetector:
|
||||
|
||||
self.detected_conflicts: Dict[str, Conflict] = {}
|
||||
|
||||
def detect_conflicts(
|
||||
self,
|
||||
entities: Union[List[Dict[str, Any]], Dict[str, Any]],
|
||||
method: str = "entity",
|
||||
property_name: Optional[str] = None,
|
||||
entity_type: Optional[str] = None,
|
||||
**kwargs,
|
||||
) -> List[Conflict]:
|
||||
"""
|
||||
Detect conflicts using the specified method (convenience method).
|
||||
|
||||
Args:
|
||||
entities: Entities to check (List of dicts or a KG dict)
|
||||
method: Detection method ("entity", "value", "type", "relationship", "temporal", "logical")
|
||||
property_name: Property name for "value" method
|
||||
entity_type: Optional entity type filter
|
||||
**kwargs: Additional arguments
|
||||
|
||||
Returns:
|
||||
List of detected conflicts
|
||||
"""
|
||||
# If passed a KG dict, extract entities
|
||||
if isinstance(entities, dict) and "entities" in entities:
|
||||
entities = entities["entities"]
|
||||
|
||||
if method == "value":
|
||||
if not property_name:
|
||||
raise ValueError("property_name is required for value conflict detection")
|
||||
return self.detect_value_conflicts(entities, property_name, entity_type)
|
||||
elif method == "type":
|
||||
return self.detect_type_conflicts(entities)
|
||||
elif method == "relationship":
|
||||
relationships = kwargs.get("relationships", [])
|
||||
return self.detect_relationship_conflicts(relationships)
|
||||
elif method == "temporal":
|
||||
return self.detect_temporal_conflicts(entities)
|
||||
elif method == "logical":
|
||||
return self.detect_logical_conflicts(entities)
|
||||
else:
|
||||
# Default to entity-wide detection
|
||||
return self.detect_entity_conflicts(entities, entity_type)
|
||||
|
||||
def detect_value_conflicts(
|
||||
self,
|
||||
entities: Union[List[Dict[str, Any]], Dict[str, Any]],
|
||||
@@ -596,11 +554,6 @@ class ConflictDetector:
|
||||
tracking_id, status="failed", message=str(e)
|
||||
)
|
||||
raise
|
||||
for field_name in fields_to_check:
|
||||
conflicts = self.detect_value_conflicts(entities, field_name, entity_type)
|
||||
all_conflicts.extend(conflicts)
|
||||
|
||||
return all_conflicts
|
||||
|
||||
def _calculate_conflict_confidence(
|
||||
self, values: List[Any], sources: List[Dict[str, Any]]
|
||||
@@ -1252,20 +1205,25 @@ class ConflictDetector:
|
||||
def detect_conflicts(
|
||||
self,
|
||||
entities: Union[List[Dict[str, Any]], Dict[str, Any]],
|
||||
method: str = "all",
|
||||
property_name: Optional[str] = None,
|
||||
entity_type: Optional[str] = None,
|
||||
**kwargs,
|
||||
) -> List[Conflict]:
|
||||
"""
|
||||
Detect all conflicts for entities (general method).
|
||||
|
||||
This method detects all types of conflicts: value, type, relationship,
|
||||
temporal, and logical conflicts.
|
||||
Detect conflicts using the specified method.
|
||||
|
||||
Args:
|
||||
entities: List of entity dictionaries or Graph dictionary (containing "entities" key)
|
||||
entities: List of entity dictionaries or Graph dictionary
|
||||
method: Detection method — "all" (default), "value", "property", "type",
|
||||
"relationship", "temporal", "logical", or "entity"
|
||||
property_name: Property name required for ``method="value"`` and ``method="property"``
|
||||
entity_type: Optional entity type filter
|
||||
**kwargs: Extra arguments forwarded to the underlying method
|
||||
(e.g. ``relationships=`` for ``method="relationship"``)
|
||||
|
||||
Returns:
|
||||
List of all detected conflicts
|
||||
List of detected conflicts
|
||||
"""
|
||||
# Handle graph dictionary input
|
||||
if isinstance(entities, dict):
|
||||
@@ -1275,6 +1233,31 @@ class ConflictDetector:
|
||||
# If it's a single entity dict, wrap in list
|
||||
entities = [entities]
|
||||
|
||||
# Dispatch to a specific sub-method when one is requested
|
||||
if method == "value":
|
||||
if not property_name:
|
||||
raise ValueError("property_name is required for method='value'")
|
||||
return self.detect_value_conflicts(entities, property_name, entity_type)
|
||||
elif method == "property":
|
||||
if not property_name:
|
||||
raise ValueError("property_name is required for method='property'")
|
||||
return self.detect_property_conflicts(entities, property_name)
|
||||
elif method == "type":
|
||||
return self.detect_type_conflicts(entities)
|
||||
elif method == "relationship":
|
||||
relationships = kwargs.get("relationships", [])
|
||||
if isinstance(relationships, dict):
|
||||
relationships = relationships.get("relationships", [relationships])
|
||||
return self.detect_relationship_conflicts(relationships)
|
||||
elif method == "temporal":
|
||||
return self.detect_temporal_conflicts(entities)
|
||||
elif method == "logical":
|
||||
return self.detect_logical_conflicts(entities)
|
||||
elif method == "entity":
|
||||
return self.detect_entity_conflicts(entities, entity_type)
|
||||
elif method != "all":
|
||||
raise ValueError(f"Unknown conflict detection method: {method!r}")
|
||||
|
||||
tracking_id = self.progress_tracker.start_tracking(
|
||||
file=None,
|
||||
module="conflicts",
|
||||
|
||||
Reference in New Issue
Block a user