Harden spaCy NER fallback in semantic extract

This commit is contained in:
KaifAhmad1
2026-03-23 23:12:48 +05:30
parent bc55dcc57a
commit 62b03d4fa5
4 changed files with 29 additions and 0 deletions
+5
View File
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
- **spaCy Runtime Fallback for NER Benchmarks**:
- Hardened `NERExtractor` spaCy initialization so installed-but-broken spaCy environments no longer crash during extractor construction.
- Updated ML entity extraction fallback behavior to catch runtime spaCy initialization failures, not just missing-model errors.
- Added regression coverage for the "spaCy present but unusable at runtime" initialization path.
### Added
- **Configurable LLM Retry Logic**:
- Exposed `max_retries` parameter in `NERExtractor`, `RelationExtractor`, `TripletExtractor` and low-level extraction methods (`extract_entities_llm`, `extract_relations_llm`, `extract_triplets_llm`).
+10
View File
@@ -683,6 +683,16 @@ def extract_entities_ml(
"spaCy model not available, falling back to pattern extraction"
)
return extract_entities_pattern(text, **kwargs)
except Exception as exc:
logger.warning(
f"spaCy model failed to initialize ({exc}), falling back to pattern extraction"
)
return extract_entities_pattern(text, **kwargs)
except Exception as exc:
logger.warning(
f"spaCy model {model} failed to initialize ({exc}), falling back to pattern extraction"
)
return extract_entities_pattern(text, **kwargs)
doc = nlp(text)
entities = []
@@ -154,6 +154,10 @@ class NERExtractor:
self.logger.warning(
f"spaCy model {self.model_name} not found. ML method will fallback."
)
except Exception as exc:
self.logger.warning(
f"spaCy model {self.model_name} failed to initialize ({exc}). ML method will fallback."
)
def extract(self, text: Union[str, List[Dict[str, Any]], List[str]], pipeline_id: Optional[str] = None, **kwargs) -> Union[List[Entity], List[List[Entity]]]:
"""
+10
View File
@@ -101,6 +101,16 @@ class TestNERConfigurations(unittest.TestCase):
self.assertEqual(entities[0].metadata["extraction_method"], "ml")
self.assertEqual(entities[0].metadata["model"], "en_core_web_trf")
@patch('semantica.semantic_extract.ner_extractor.spacy')
def test_ner_ml_init_falls_back_when_spacy_runtime_is_broken(self, mock_spacy):
"""Test NER init does not crash when spaCy is installed but unusable at runtime."""
mock_spacy.load.side_effect = RuntimeError("ConfigSchemaNlp is not fully defined")
with patch('semantica.semantic_extract.ner_extractor.SPACY_AVAILABLE', True):
extractor = NERExtractor(method="ml", model="en_core_web_sm")
self.assertIsNone(extractor.nlp)
def test_ner_regex_config(self):
"""Test NER with Regex configuration"""
print("\nTesting NER with Regex configuration...")