mirror of
https://github.com/semantica-agi/semantica.git
synced 2026-08-29 04:26:20 +00:00
- Robust ID extraction in CentralityCalculator, CommunityDetector, and ConnectivityAnalyzer - Support for direct Entity objects and dictionaries as node identifiers - Improved Entity hashability in utils/types.py - Added integration test to verify fix and prevent regression
166 lines
6.9 KiB
Python
166 lines
6.9 KiB
Python
import unittest
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
|
|
from semantica.semantic_extract import (
|
|
NERExtractor,
|
|
NamedEntityRecognizer,
|
|
RelationExtractor,
|
|
TripletExtractor,
|
|
Entity,
|
|
Relation
|
|
)
|
|
from semantica.semantic_extract.methods import get_entity_method, get_relation_method
|
|
|
|
pytestmark = pytest.mark.integration
|
|
|
|
class TestNotebooksVerification(unittest.TestCase):
|
|
"""
|
|
Test suite to verify the code snippets from the notebooks:
|
|
- 05_Entity_Extraction.ipynb
|
|
- 06_Relation_Extraction.ipynb
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.ner_extractor = NERExtractor()
|
|
self.relation_extractor = RelationExtractor()
|
|
|
|
def test_05_entity_extraction_notebook_flow(self):
|
|
"""Verify the flow demonstrated in 05_Entity_Extraction.ipynb"""
|
|
print("\nTesting 05_Entity_Extraction.ipynb flow...")
|
|
|
|
# --- Step 1: Basic Entity Extraction ---
|
|
text = """
|
|
Apple Inc. is a technology company founded by Steve Jobs, Steve Wozniak, and Ronald Wayne
|
|
in Cupertino, California on April 1, 1976. The company's current CEO is Tim Cook, who took
|
|
over from Steve Jobs in August 2011. Apple is headquartered at One Apple Park Way in Cupertino.
|
|
"""
|
|
|
|
entities = self.ner_extractor.extract(text)
|
|
self.assertIsInstance(entities, list)
|
|
if len(entities) > 0:
|
|
first_entity = entities[0]
|
|
# Notebook handles dict or object, let's verify what we get
|
|
is_dict = isinstance(first_entity, dict)
|
|
is_object = hasattr(first_entity, 'text')
|
|
self.assertTrue(is_dict or is_object, "Entity must be dict or object")
|
|
|
|
if is_object:
|
|
print(f"NERExtractor returned objects: {first_entity.text} ({first_entity.label})")
|
|
else:
|
|
print(f"NERExtractor returned dicts: {first_entity.get('text')} ({first_entity.get('label')})")
|
|
|
|
# --- Step 3: Different Extraction Methods ---
|
|
methods_to_try = ["pattern", "regex"] # Skipping 'ml' as it might require spaCy which might be missing/mocked
|
|
|
|
sample_text = "Apple Inc. was founded by Steve Jobs in Cupertino, California in 1976."
|
|
|
|
for method_name in methods_to_try:
|
|
try:
|
|
method = get_entity_method(method_name)
|
|
method_entities = method(sample_text)
|
|
self.assertIsInstance(method_entities, list)
|
|
print(f"Method '{method_name}' returned {len(method_entities)} entities")
|
|
except Exception as e:
|
|
print(f"Method '{method_name}' failed as expected/unexpected: {e}")
|
|
|
|
# --- Step 4: Advanced Entity Recognition ---
|
|
# Note: We use patterns/regex here to avoid spaCy dependency issues in CI/Test env
|
|
# but the notebook uses 'spacy'. We'll adapt for robustness.
|
|
ner = NamedEntityRecognizer(
|
|
methods=["pattern", "regex"],
|
|
confidence_threshold=0.5,
|
|
merge_overlapping=True,
|
|
include_standard_types=True
|
|
)
|
|
|
|
texts = [
|
|
"Tim Cook is the CEO of Apple Inc., based in Cupertino.",
|
|
"Microsoft Corporation, founded by Bill Gates, is headquartered in Redmond, Washington."
|
|
]
|
|
|
|
for text in texts:
|
|
entities = ner.extract_entities(text)
|
|
self.assertIsInstance(entities, list)
|
|
|
|
def test_06_relation_extraction_notebook_flow(self):
|
|
"""Verify the flow demonstrated in 06_Relation_Extraction.ipynb"""
|
|
print("\nTesting 06_Relation_Extraction.ipynb flow...")
|
|
|
|
# --- Step 1: Basic Relation Extraction ---
|
|
text = """
|
|
Apple Inc. was founded by Steve Jobs, Steve Wozniak, and Ronald Wayne in 1976.
|
|
The company is headquartered in Cupertino, California. Tim Cook is the current CEO
|
|
of Apple Inc. and took over from Steve Jobs in August 2011.
|
|
"""
|
|
|
|
# First extract entities
|
|
entities = self.ner_extractor.extract(text)
|
|
|
|
# Then extract relationships
|
|
# Note: RelationExtractor might default to 'dependency' which needs spaCy.
|
|
# We should check if it falls back or if we need to specify a method.
|
|
# The notebook calls `relation_extractor.extract(text, entities)` directly.
|
|
|
|
relationships = self.relation_extractor.extract(text, entities)
|
|
self.assertIsInstance(relationships, list)
|
|
|
|
if len(relationships) > 0:
|
|
first_rel = relationships[0]
|
|
is_dict = isinstance(first_rel, dict)
|
|
is_object = hasattr(first_rel, 'subject')
|
|
self.assertTrue(is_dict or is_object, "Relation must be dict or object")
|
|
|
|
if is_object:
|
|
print(f"RelationExtractor returned objects: {first_rel.subject} --[{first_rel.predicate}]--> {first_rel.object}")
|
|
else:
|
|
print(f"RelationExtractor returned dicts: {first_rel.get('subject')} --[{first_rel.get('predicate')}]--> {first_rel.get('object')}")
|
|
|
|
# --- Step 2: Different Extraction Methods ---
|
|
methods_to_try = ["pattern", "cooccurrence"] # Skipping 'dependency' to be safe
|
|
|
|
sample_text = "Apple Inc. was founded by Steve Jobs in Cupertino, California."
|
|
sample_entities = self.ner_extractor.extract(sample_text)
|
|
|
|
for method_name in methods_to_try:
|
|
try:
|
|
method = get_relation_method(method_name)
|
|
# Some methods might need specific args, but notebook shows standard call signature
|
|
if method_name == "cooccurrence":
|
|
# cooccurrence might return empty if window is small or entities far apart
|
|
# but interface should hold
|
|
rels = method(sample_text, sample_entities)
|
|
else:
|
|
rels = method(sample_text, sample_entities)
|
|
|
|
self.assertIsInstance(rels, list)
|
|
print(f"Method '{method_name}' returned {len(rels)} relations")
|
|
except Exception as e:
|
|
print(f"Method '{method_name}' failed: {e}")
|
|
|
|
# --- Step 3: Advanced Relation Extraction ---
|
|
advanced_extractor = RelationExtractor(
|
|
relation_types=["founded_by", "located_in", "works_for"],
|
|
confidence_threshold=0.1, # Low threshold to ensure we catch something
|
|
bidirectional=False,
|
|
max_distance=50
|
|
)
|
|
|
|
texts = [
|
|
"Microsoft was founded by Bill Gates and Paul Allen in Albuquerque, New Mexico.",
|
|
"Satya Nadella works for Microsoft as the CEO."
|
|
]
|
|
|
|
for text in texts:
|
|
ents = self.ner_extractor.extract(text)
|
|
rels = advanced_extractor.extract(text, ents)
|
|
self.assertIsInstance(rels, list)
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|