"""
NLP Processor Service - Extracts location entities from text using spaCy.
"""
import spacy
from typing import List, Optional
from ..utils.logger import setup_logger
logger = setup_logger(__name__)
# Lazy loading of spaCy models
_nlp_en: Optional[spacy.Language] = None
_nlp_tr: Optional[spacy.Language] = None
def _load_nlp_model(lang: str) -> Optional[spacy.Language]:
"""
Lazy loads spaCy models. Returns None if model is not installed.
"""
global _nlp_en, _nlp_tr
try:
if lang == "tr":
if _nlp_tr is None:
try:
_nlp_tr = spacy.load("tr_core_news_sm")
except OSError:
logger.warning("Turkish spaCy model (tr_core_news_sm) not found. Install with: python -m spacy download tr_core_news_sm")
return None
return _nlp_tr
else:
if _nlp_en is None:
try:
_nlp_en = spacy.load("en_core_web_sm")
except OSError:
logger.warning("English spaCy model (en_core_web_sm) not found. Install with: python -m spacy download en_core_web_sm")
return None
return _nlp_en
except Exception as e:
logger.error(f"Error loading spaCy model for {lang}: {e}")
return None
def extract_locations(text: str, lang: str = "en") -> List[str]:
"""
Extracts location entities (cities, countries, regions) from text.
Args:
text: The text to analyze
lang: Language code ("en" or "tr")
Returns:
List of location names found in the text
"""
if not text or not text.strip():
return []
nlp = _load_nlp_model(lang)
if nlp is None:
logger.warning(f"spaCy model not available for {lang}, returning empty list")
return []
try:
doc = nlp(text)
places = []
for ent in doc.ents:
# GPE = Geopolitical Entity (countries, cities, states)
# LOC = Location (mountains, bodies of water, etc.)
if ent.label_ in ("GPE", "LOC"):
places.append(ent.text)
# Remove duplicates while preserving order
seen = set()
unique_places = []
for place in places:
if place not in seen:
seen.add(place)
unique_places.append(place)
return unique_places
except Exception as e:
logger.error(f"Error extracting locations: {e}")
return []