mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
- Reduced code examples in all guide pages (getting-started, quickstart, concepts, modules, examples, use-cases, learning-more) - Added comprehensive cookbook links with descriptions (topics, difficulty, time, use cases) - Improved structure and organization across all guide pages - Updated use-cases.md to only include use cases with corresponding cookbooks - Removed 'Last Updated: 2024' from all documentation files - Enhanced navigation with better 'Next Steps' sections
775 lines
22 KiB
Markdown
775 lines
22 KiB
Markdown
# Deduplication
|
||
|
||
> **Advanced entity deduplication and resolution system for maintaining a clean, single-source-of-truth Knowledge Graph.**
|
||
|
||
---
|
||
|
||
## 🎯 Overview
|
||
|
||
<div class="grid cards" markdown>
|
||
|
||
- :material-content-duplicate:{ .lg .middle } **Duplicate Detection**
|
||
|
||
---
|
||
|
||
Identify duplicates using multi-factor similarity metrics
|
||
|
||
- :material-set-merge:{ .lg .middle } **Entity Merging**
|
||
|
||
---
|
||
|
||
Merge entities with configurable strategies (Keep First, Most Complete, etc.)
|
||
|
||
- :material-group:{ .lg .middle } **Clustering**
|
||
|
||
---
|
||
|
||
Cluster similar entities for efficient batch processing
|
||
|
||
- :material-calculator:{ .lg .middle } **Similarity Metrics**
|
||
|
||
---
|
||
|
||
Levenshtein, Jaro-Winkler, Cosine, and Jaccard similarity support
|
||
|
||
- :material-history:{ .lg .middle } **Provenance**
|
||
|
||
---
|
||
|
||
Preserve data lineage and history during merges
|
||
|
||
- :material-scale:{ .lg .middle } **Scalable**
|
||
|
||
---
|
||
|
||
Batch processing and blocking for large datasets
|
||
|
||
</div>
|
||
|
||
!!! tip "When to Use"
|
||
- **Data Ingestion**: Clean incoming data before adding to the graph
|
||
- **Graph Maintenance**: Periodically clean up existing knowledge graphs
|
||
- **Entity Resolution**: Resolve entities from different sources (e.g., "Apple" vs "Apple Inc.")
|
||
|
||
---
|
||
|
||
## ⚙️ Algorithms Used
|
||
|
||
### Similarity Calculation
|
||
|
||
The deduplication system uses multiple similarity metrics:
|
||
|
||
- **Levenshtein Distance**: Edit distance for string difference
|
||
- **Jaro-Winkler**: String similarity with prefix weighting (Default for strings, optimized for entity names)
|
||
- **Cosine Similarity**: Vector similarity for embeddings
|
||
- **Jaccard Similarity**: Set overlap for properties/relationships
|
||
- **Property Matching**: Handles disjoint properties with neutral scoring (`` `0.5` ``) to prevent false negatives
|
||
- **Multi-factor Aggregation**: Weighted sum of multiple metrics
|
||
|
||
### Default Configuration
|
||
|
||
The deduplication module uses the following default weights to prioritize name matching while considering other factors:
|
||
|
||
- **String Similarity**: `` `0.6` `` (Primary factor, using Jaro-Winkler)
|
||
- **Property Similarity**: `` `0.2` `` (Handles missing values neutrally)
|
||
- **Relationship Similarity**: `` `0.2` ``
|
||
- **Embedding Similarity**: `` `0.0` `` (Optional, enabled if embeddings are present)
|
||
|
||
### Duplicate Detection
|
||
|
||
The system uses efficient detection algorithms:
|
||
|
||
- **Pairwise Comparison**: `` `O(n²)` `` comparison (for small sets)
|
||
- **Blocking/Indexing**: Reduce search space for large sets
|
||
- **Union-Find**: Disjoint set data structure for grouping duplicates
|
||
- **Confidence Scoring**: `` `0.0 - 1.0` `` probability score for duplicates
|
||
|
||
### Clustering
|
||
|
||
The module provides clustering algorithms for grouping similar entities:
|
||
- **Hierarchical Clustering**: Agglomerative bottom-up clustering
|
||
- **Connected Components**: Graph-based cluster detection
|
||
- **Cluster Quality**: Cohesion and separation metrics
|
||
|
||
### Entity Merging
|
||
- **Strategy Pattern**: Pluggable merge logic
|
||
- **Property Union**: Combining unique properties
|
||
- **Relationship Merging**: Re-linking relationships to the merged entity
|
||
|
||
---
|
||
|
||
## Main Classes
|
||
|
||
### DuplicateDetector
|
||
|
||
Identifies potential duplicates in a dataset using similarity metrics and confidence scoring.
|
||
|
||
**Initialization:**
|
||
|
||
```python
|
||
DuplicateDetector(
|
||
similarity_threshold: float = 0.7,
|
||
confidence_threshold: float = 0.6,
|
||
use_clustering: bool = True,
|
||
config: Optional[Dict[str, Any]] = None,
|
||
**kwargs
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `detect_duplicates(entities, threshold=None, **options)` | Find duplicate pairs | `List[DuplicateCandidate]` |
|
||
| `detect_duplicate_groups(entities, threshold=None, **options)` | Find clusters of duplicates | `List[DuplicateGroup]` |
|
||
| `incremental_detect(new_entities, existing_entities, threshold=None, **options)` | Detect duplicates between new and existing entities | `List[DuplicateCandidate]` |
|
||
| `detect_relationship_duplicates(relationships, **options)` | Detect duplicate relationships | `List[Tuple[Dict, Dict]]` |
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication import DuplicateDetector
|
||
|
||
detector = DuplicateDetector(similarity_threshold=0.85, confidence_threshold=0.7)
|
||
candidates = detector.detect_duplicates(entities)
|
||
groups = detector.detect_duplicate_groups(entities)
|
||
|
||
for candidate in candidates:
|
||
print(f"Duplicate: {candidate.entity1['name']} <-> {candidate.entity2['name']}")
|
||
print(f" Similarity: {candidate.similarity_score:.2f}, Confidence: {candidate.confidence:.2f}")
|
||
```
|
||
|
||
### EntityMerger
|
||
|
||
Merges duplicate entities into a single canonical entity using configurable strategies.
|
||
|
||
**Initialization:**
|
||
|
||
```python
|
||
EntityMerger(
|
||
preserve_provenance: bool = True,
|
||
config: Optional[Dict[str, Any]] = None,
|
||
**kwargs
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `merge_duplicates(entities, strategy=None, **options)` | Execute merge on duplicate entities | `List[MergeOperation]` |
|
||
| `merge_entity_group(entities, strategy=None, **options)` | Merge a specific group of entities | `MergeOperation` |
|
||
| `incremental_merge(new_entities, existing_entities, **options)` | Incrementally merge new entities with existing ones | `List[MergeOperation]` |
|
||
| `get_merge_history()` | Get merge operation history | `List[MergeOperation]` |
|
||
| `validate_merge_quality(merge_operation)` | Validate quality of a merge operation | `Dict[str, Any]` |
|
||
|
||
**Strategies:**
|
||
- `"keep_first"`: Keep the first entity encountered
|
||
- `"keep_last"`: Keep the last entity encountered
|
||
- `"keep_most_complete"`: Keep entity with most properties/relationships
|
||
- `"keep_highest_confidence"`: Keep entity with highest confidence score
|
||
- `"merge_all"`: Create new entity combining all info
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication import EntityMerger
|
||
|
||
merger = EntityMerger(preserve_provenance=True)
|
||
|
||
# Merge with specific strategy
|
||
operations = merger.merge_duplicates(
|
||
entities,
|
||
strategy="keep_most_complete"
|
||
)
|
||
|
||
# Get merge history
|
||
history = merger.get_merge_history()
|
||
```
|
||
|
||
### SimilarityCalculator
|
||
|
||
Calculates multi-factor similarity between entities using string, property, relationship, and embedding similarity.
|
||
|
||
**Initialization:**
|
||
|
||
```python
|
||
SimilarityCalculator(
|
||
embedding_weight: float = 0.4,
|
||
string_weight: float = 0.3,
|
||
property_weight: float = 0.2,
|
||
relationship_weight: float = 0.1,
|
||
similarity_threshold: float = 0.7,
|
||
config: Optional[Dict[str, Any]] = None,
|
||
**kwargs
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `calculate_similarity(entity1, entity2, **options)` | Calculate overall similarity | `SimilarityResult` |
|
||
| `calculate_string_similarity(str1, str2, method="levenshtein")` | Calculate string similarity | `float` |
|
||
| `calculate_property_similarity(entity1, entity2)` | Calculate property similarity | `float` |
|
||
| `calculate_relationship_similarity(entity1, entity2)` | Calculate relationship similarity | `float` |
|
||
| `calculate_embedding_similarity(embedding1, embedding2)` | Calculate embedding similarity | `float` |
|
||
| `batch_calculate_similarity(entities, threshold=None)` | Calculate similarity for all pairs | `List[Tuple[Dict, Dict, float]]` |
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication import SimilarityCalculator
|
||
|
||
calculator = SimilarityCalculator(
|
||
string_weight=0.4,
|
||
property_weight=0.3,
|
||
embedding_weight=0.3
|
||
)
|
||
|
||
result = calculator.calculate_similarity(entity1, entity2)
|
||
print(f"Similarity: {result.score:.2f}")
|
||
print(f"Components: {result.components}")
|
||
```
|
||
|
||
### ClusterBuilder
|
||
|
||
Builds clusters of similar entities for efficient batch deduplication.
|
||
|
||
**Initialization:**
|
||
|
||
```python
|
||
ClusterBuilder(
|
||
similarity_threshold: float = 0.7,
|
||
min_cluster_size: int = 2,
|
||
max_cluster_size: int = 100,
|
||
use_hierarchical: bool = False,
|
||
config: Optional[Dict[str, Any]] = None,
|
||
**kwargs
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `build_clusters(entities, **options)` | Build clusters of similar entities | `ClusterResult` |
|
||
| `update_clusters(existing_clusters, new_entities, **options)` | Incrementally update clusters with new entities | `ClusterResult` |
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication import ClusterBuilder
|
||
|
||
builder = ClusterBuilder(
|
||
similarity_threshold=0.8,
|
||
min_cluster_size=2,
|
||
max_cluster_size=50
|
||
)
|
||
|
||
result = builder.build_clusters(entities)
|
||
print(f"Found {len(result.clusters)} clusters")
|
||
print(f"Unclustered: {len(result.unclustered)} entities")
|
||
print(f"Quality metrics: {result.quality_metrics}")
|
||
```
|
||
|
||
### MergeStrategyManager
|
||
|
||
Manages merge strategies and property-specific merge rules with conflict resolution.
|
||
|
||
**Initialization:**
|
||
|
||
```python
|
||
MergeStrategyManager(
|
||
default_strategy: str = "keep_most_complete",
|
||
config: Optional[Dict[str, Any]] = None,
|
||
**kwargs
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `merge_entities(entities, strategy=None, **options)` | Merge entities using specified strategy | `MergeResult` |
|
||
| `add_property_rule(property_name, strategy, conflict_resolution=None, priority=0)` | Add property-specific merge rule | `None` |
|
||
| `validate_merge(merge_result)` | Validate merge result quality | `Dict[str, Any]` |
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication import MergeStrategyManager, MergeStrategy
|
||
|
||
manager = MergeStrategyManager(default_strategy="keep_most_complete")
|
||
manager.add_property_rule("name", MergeStrategy.KEEP_FIRST)
|
||
manager.add_property_rule("description", MergeStrategy.MERGE_ALL)
|
||
|
||
result = manager.merge_entities(entities)
|
||
print(f"Merged entity: {result.merged_entity}")
|
||
print(f"Conflicts: {len(result.conflicts)}")
|
||
```
|
||
|
||
### MethodRegistry
|
||
|
||
Registry for custom deduplication methods, enabling extensibility.
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `register(task, name, method_func)` | Register a custom deduplication method | `None` |
|
||
| `get(task, name)` | Get method by task and name | `Optional[Callable]` |
|
||
| `list_all(task=None)` | List all registered methods | `Dict[str, List[str]]` |
|
||
| `unregister(task, name)` | Unregister a method | `None` |
|
||
| `clear(task=None)` | Clear all registered methods | `None` |
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication.registry import method_registry
|
||
|
||
# Register custom similarity method
|
||
def custom_similarity(entity1, entity2, **kwargs):
|
||
# Custom logic
|
||
return SimilarityResult(score=0.85, method="custom")
|
||
|
||
method_registry.register("similarity", "custom_method", custom_similarity)
|
||
|
||
# Use custom method
|
||
method = method_registry.get("similarity", "custom_method")
|
||
result = method(entity1, entity2)
|
||
```
|
||
|
||
### DeduplicationConfig
|
||
|
||
Configuration manager for deduplication operations, supporting environment variables, config files, and programmatic configuration.
|
||
|
||
**Initialization:**
|
||
|
||
```python
|
||
DeduplicationConfig(config_file: Optional[str] = None)
|
||
```
|
||
|
||
**Methods:**
|
||
|
||
| Method | Description | Returns |
|
||
|--------|-------------|---------|
|
||
| `set(key, value)` | Set configuration value programmatically | `None` |
|
||
| `get(key, default=None)` | Get configuration value | `Any` |
|
||
| `set_method_config(method, **config)` | Set method-specific configuration | `None` |
|
||
| `get_method_config(method)` | Get method-specific configuration | `Dict` |
|
||
| `get_all()` | Get all configuration | `Dict[str, Any]` |
|
||
|
||
**Example:**
|
||
|
||
```python
|
||
from semantica.deduplication.config import dedup_config
|
||
|
||
# Get configuration
|
||
threshold = dedup_config.get("similarity_threshold", default=0.7)
|
||
|
||
# Set configuration
|
||
dedup_config.set("similarity_threshold", 0.8)
|
||
|
||
# Method-specific configuration
|
||
dedup_config.set_method_config("levenshtein", case_sensitive=False)
|
||
levenshtein_config = dedup_config.get_method_config("levenshtein")
|
||
```
|
||
|
||
---
|
||
|
||
## Data Classes
|
||
|
||
### DuplicateCandidate
|
||
|
||
Represents a duplicate candidate pair with confidence scores.
|
||
|
||
**Fields:**
|
||
- `entity1`: First entity dictionary
|
||
- `entity2`: Second entity dictionary
|
||
- `similarity_score`: Similarity score (0.0 to 1.0)
|
||
- `confidence`: Confidence score (0.0 to 1.0)
|
||
- `reasons`: List of reasons why they're considered duplicates
|
||
- `metadata`: Additional metadata dictionary
|
||
|
||
### DuplicateGroup
|
||
|
||
Represents a group of duplicate entities.
|
||
|
||
**Fields:**
|
||
- `entities`: List of duplicate entity dictionaries
|
||
- `similarity_scores`: Dict mapping entity pairs to similarity scores
|
||
- `representative`: Representative entity (most complete)
|
||
- `confidence`: Group confidence score (0.0 to 1.0)
|
||
- `metadata`: Additional group metadata
|
||
|
||
### MergeOperation
|
||
|
||
Represents an entity merge operation.
|
||
|
||
**Fields:**
|
||
- `source_entities`: List of original entities that were merged
|
||
- `merged_entity`: Resulting merged entity dictionary
|
||
- `merge_result`: Detailed merge result with conflicts
|
||
- `timestamp`: Optional timestamp of merge operation
|
||
- `metadata`: Additional operation metadata
|
||
|
||
### SimilarityResult
|
||
|
||
Represents a similarity calculation result.
|
||
|
||
**Fields:**
|
||
- `score`: Overall similarity score (0.0 to 1.0)
|
||
- `method`: Calculation method used
|
||
- `components`: Dict of individual component scores
|
||
- `metadata`: Additional metadata dictionary
|
||
|
||
### Cluster
|
||
|
||
Represents an entity cluster.
|
||
|
||
**Fields:**
|
||
- `cluster_id`: Unique cluster identifier
|
||
- `entities`: List of entities in the cluster
|
||
- `centroid`: Optional representative entity (centroid)
|
||
- `quality_score`: Cluster quality score (0.0 to 1.0)
|
||
- `metadata`: Additional cluster metadata
|
||
|
||
### ClusterResult
|
||
|
||
Represents the result of cluster building.
|
||
|
||
**Fields:**
|
||
- `clusters`: List of Cluster objects
|
||
- `unclustered`: List of entities not in any cluster
|
||
- `quality_metrics`: Cluster quality metrics dictionary
|
||
- `metadata`: Additional result metadata
|
||
|
||
### MergeResult
|
||
|
||
Represents the result of a merge operation.
|
||
|
||
**Fields:**
|
||
- `merged_entity`: Resulting merged entity dictionary
|
||
- `merged_entities`: List of original entities that were merged
|
||
- `conflicts`: List of unresolved conflicts
|
||
- `metadata`: Additional merge metadata
|
||
|
||
### PropertyMergeRule
|
||
|
||
Represents a rule for merging specific properties.
|
||
|
||
**Fields:**
|
||
- `property_name`: Property name
|
||
- `strategy`: Merge strategy to use
|
||
- `conflict_resolution`: Optional custom conflict resolution function
|
||
- `priority`: Rule priority (higher priority rules take precedence)
|
||
|
||
### MergeStrategy
|
||
|
||
Enumeration of available merge strategies.
|
||
|
||
**Values:**
|
||
- `KEEP_FIRST`: Keep the first entity encountered
|
||
- `KEEP_LAST`: Keep the last entity encountered
|
||
- `KEEP_MOST_COMPLETE`: Keep entity with most properties/relationships
|
||
- `KEEP_HIGHEST_CONFIDENCE`: Keep entity with highest confidence score
|
||
- `MERGE_ALL`: Create new entity combining all info
|
||
- `CUSTOM`: Use custom merge logic
|
||
|
||
---
|
||
|
||
## Convenience Functions
|
||
|
||
### detect_duplicates
|
||
|
||
Convenience function for duplicate detection with multiple methods.
|
||
|
||
```python
|
||
from semantica.deduplication.methods import detect_duplicates
|
||
|
||
# Pairwise detection
|
||
candidates = detect_duplicates(
|
||
entities,
|
||
method="pairwise",
|
||
similarity_threshold=0.8,
|
||
confidence_threshold=0.7
|
||
)
|
||
|
||
# Group detection
|
||
groups = detect_duplicates(
|
||
entities,
|
||
method="group",
|
||
similarity_threshold=0.8
|
||
)
|
||
|
||
# Incremental detection
|
||
new_candidates = detect_duplicates(
|
||
new_entities,
|
||
method="incremental",
|
||
existing_entities=existing_entities,
|
||
similarity_threshold=0.8
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
- `"pairwise"`: O(n²) comparison of all entity pairs
|
||
- `"batch"`: Efficient batch similarity calculation
|
||
- `"incremental"`: O(n×m) comparison for new vs existing entities
|
||
- `"group"`: Union-find algorithm for duplicate group formation
|
||
|
||
### merge_entities
|
||
|
||
Convenience function for entity merging with multiple strategies.
|
||
|
||
```python
|
||
from semantica.deduplication.methods import merge_entities
|
||
|
||
operations = merge_entities(
|
||
duplicate_entities,
|
||
method="keep_most_complete",
|
||
preserve_provenance=True
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
- `"keep_first"`: Preserve first entity, merge others
|
||
- `"keep_last"`: Preserve last entity, merge others
|
||
- `"keep_most_complete"`: Preserve entity with most properties/relationships
|
||
- `"keep_highest_confidence"`: Preserve entity with highest confidence
|
||
- `"merge_all"`: Combine all properties and relationships
|
||
|
||
### calculate_similarity
|
||
|
||
Convenience function for similarity calculation with multiple methods.
|
||
|
||
```python
|
||
from semantica.deduplication.methods import calculate_similarity
|
||
|
||
# Different similarity methods
|
||
exact_result = calculate_similarity(entity1, entity2, method="exact")
|
||
lev_result = calculate_similarity(entity1, entity2, method="levenshtein")
|
||
jaro_result = calculate_similarity(entity1, entity2, method="jaro_winkler")
|
||
multi_result = calculate_similarity(entity1, entity2, method="multi_factor")
|
||
```
|
||
|
||
**Methods:**
|
||
- `"exact"`: Exact string matching
|
||
- `"levenshtein"`: Levenshtein distance-based similarity
|
||
- `"jaro_winkler"`: Jaro-Winkler similarity with prefix bonus
|
||
- `"cosine"`: Cosine similarity for embeddings
|
||
- `"property"`: Property value comparison
|
||
- `"relationship"`: Jaccard similarity of relationships
|
||
- `"embedding"`: Cosine similarity of vector embeddings
|
||
- `"multi_factor"`: Weighted aggregation of all components
|
||
|
||
### build_clusters
|
||
|
||
Convenience function for cluster building with multiple methods.
|
||
|
||
```python
|
||
from semantica.deduplication.methods import build_clusters
|
||
|
||
# Graph-based clustering
|
||
result = build_clusters(
|
||
entities,
|
||
method="graph_based",
|
||
similarity_threshold=0.8
|
||
)
|
||
|
||
# Hierarchical clustering
|
||
result = build_clusters(
|
||
entities,
|
||
method="hierarchical",
|
||
similarity_threshold=0.8
|
||
)
|
||
```
|
||
|
||
**Methods:**
|
||
- `"graph_based"`: Union-find algorithm for connected components
|
||
- `"hierarchical"`: Agglomerative clustering for large datasets
|
||
|
||
### get_deduplication_method
|
||
|
||
Get deduplication method by task and name.
|
||
|
||
```python
|
||
from semantica.deduplication.methods import get_deduplication_method
|
||
|
||
method = get_deduplication_method("similarity", "levenshtein")
|
||
if method:
|
||
result = method(entity1, entity2)
|
||
```
|
||
|
||
### list_available_methods
|
||
|
||
List all available deduplication methods.
|
||
|
||
```python
|
||
from semantica.deduplication.methods import list_available_methods
|
||
|
||
# List all methods
|
||
all_methods = list_available_methods()
|
||
|
||
# List methods for specific task
|
||
similarity_methods = list_available_methods("similarity")
|
||
```
|
||
|
||
---
|
||
|
||
## Configuration
|
||
|
||
The deduplication module supports multiple configuration sources: environment variables, config files (YAML, JSON, TOML), and programmatic configuration.
|
||
|
||
### Environment Variables
|
||
|
||
```bash
|
||
export DEDUP_SIMILARITY_THRESHOLD=0.8
|
||
export DEDUP_CONFIDENCE_THRESHOLD=0.7
|
||
export DEDUP_USE_CLUSTERING=true
|
||
export DEDUP_PRESERVE_PROVENANCE=true
|
||
export DEDUP_DEFAULT_STRATEGY=keep_most_complete
|
||
export DEDUP_MIN_CLUSTER_SIZE=2
|
||
export DEDUP_MAX_CLUSTER_SIZE=100
|
||
```
|
||
|
||
### YAML Configuration
|
||
|
||
```yaml
|
||
deduplication:
|
||
similarity_threshold: 0.8
|
||
confidence_threshold: 0.7
|
||
use_clustering: true
|
||
preserve_provenance: true
|
||
default_strategy: keep_most_complete
|
||
min_cluster_size: 2
|
||
max_cluster_size: 100
|
||
|
||
deduplication_methods:
|
||
levenshtein:
|
||
case_sensitive: false
|
||
multi_factor:
|
||
string_weight: 0.4
|
||
property_weight: 0.3
|
||
embedding_weight: 0.3
|
||
```
|
||
|
||
### Programmatic Configuration
|
||
|
||
```python
|
||
from semantica.deduplication.config import dedup_config
|
||
|
||
# Set configuration values
|
||
dedup_config.set("similarity_threshold", 0.8)
|
||
dedup_config.set("confidence_threshold", 0.7)
|
||
|
||
# Get configuration values
|
||
threshold = dedup_config.get("similarity_threshold", default=0.7)
|
||
|
||
# Method-specific configuration
|
||
dedup_config.set_method_config("levenshtein", case_sensitive=False)
|
||
levenshtein_config = dedup_config.get_method_config("levenshtein")
|
||
|
||
# Load from config file
|
||
from semantica.deduplication.config import DeduplicationConfig
|
||
config = DeduplicationConfig(config_file="config.yaml")
|
||
```
|
||
|
||
### Configuration File Support
|
||
|
||
The `DeduplicationConfig` class supports loading configuration from:
|
||
- **YAML files** (`.yaml`, `.yml`)
|
||
- **JSON files** (`.json`)
|
||
- **TOML files** (`.toml`)
|
||
|
||
Configuration is loaded in the following priority order:
|
||
1. Programmatic configuration (via `set()`)
|
||
2. Environment variables
|
||
3. Config file values
|
||
4. Default values
|
||
|
||
---
|
||
|
||
## Integration Examples
|
||
|
||
### Ingestion Pipeline
|
||
|
||
```python
|
||
from semantica.core import Semantica
|
||
from semantica.ingest import FileIngestor
|
||
from semantica.parse import DocumentParser
|
||
from semantica.semantic_extract import NERExtractor
|
||
from semantica.deduplication import DuplicateDetector, EntityMerger, MergeStrategy
|
||
|
||
# 1. Build knowledge base using individual modules
|
||
ingestor = FileIngestor()
|
||
parser = DocumentParser()
|
||
ner = NERExtractor()
|
||
|
||
all_entities = []
|
||
for file_path in files:
|
||
doc = ingestor.ingest_file(file_path)
|
||
parsed = parser.parse_document(file_path)
|
||
text = parsed.get("full_text", "")
|
||
entities = ner.extract_entities(text)
|
||
all_entities.extend(entities)
|
||
|
||
raw_entities = all_entities
|
||
|
||
# 2. Deduplicate
|
||
detector = DuplicateDetector(similarity_threshold=0.85)
|
||
duplicate_groups = detector.detect_duplicate_groups(raw_entities)
|
||
|
||
merger = EntityMerger(preserve_provenance=True)
|
||
merge_operations = merger.merge_duplicates(
|
||
raw_entities,
|
||
strategy=MergeStrategy.MERGE_ALL
|
||
)
|
||
|
||
# Extract merged entities
|
||
merged_entities = [op.merged_entity for op in merge_operations]
|
||
```
|
||
|
||
---
|
||
|
||
## Best Practices
|
||
|
||
1. **Block First**: For >1000 entities, enable blocking to avoid O(n²) performance.
|
||
2. **Tune Thresholds**: Start with 0.85 and adjust based on false positive/negative rates.
|
||
3. **Preserve Provenance**: Keep `preserve_provenance=True` to track where merged data came from.
|
||
4. **Normalize**: Run `normalize` module before deduplication for best results.
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
**Issue**: Merging "Apple" and "Apple Pie" (False Positive).
|
||
**Solution**: Increase threshold or use Jaro-Winkler which penalizes prefix mismatches.
|
||
|
||
```python
|
||
detector = DuplicateDetector(
|
||
similarity_method="jaro_winkler",
|
||
similarity_threshold=0.9
|
||
)
|
||
```
|
||
|
||
**Issue**: Slow performance on large datasets.
|
||
**Solution**: Use `ClusterBuilder` with blocking.
|
||
|
||
---
|
||
|
||
## See Also
|
||
|
||
- [Conflicts Module](conflicts.md) - Handling conflicting values during merge
|
||
- [Normalize Module](normalize.md) - Pre-processing for better matching
|
||
- [Knowledge Graph Module](kg.md) - Target for deduplicated data
|
||
|
||
## Cookbook
|
||
|
||
Interactive tutorials to learn deduplication:
|
||
|
||
- **[Deduplication](https://github.com/Hawksight-AI/semantica/blob/main/cookbook/introduction/18_Deduplication.ipynb)**: Advanced deduplication techniques for entity resolution
|
||
- **Topics**: Entity deduplication, fuzzy matching, similarity thresholds, merge strategies
|
||
- **Difficulty**: Intermediate
|
||
- **Use Cases**: Entity resolution, data cleaning, multi-source integration
|