Spaces:
Runtime error
Runtime error
import asyncio | |
import logging | |
from app.services.base import load_spacy_model | |
from app.core.config import APP_NAME, SPACY_MODEL_ID | |
from app.core.exceptions import ServiceError, ModelNotDownloadedError | |
logger = logging.getLogger(f"{APP_NAME}.services.voice_detection") | |
class VoiceDetector: | |
def __init__(self): | |
self._nlp = None | |
def _get_nlp(self): | |
if self._nlp is None: | |
self._nlp = load_spacy_model(SPACY_MODEL_ID) | |
return self._nlp | |
async def classify(self, text: str) -> dict: | |
try: | |
text = text.strip() | |
if not text: | |
raise ServiceError(status_code=400, detail="Input text is empty for voice detection.") | |
nlp = self._get_nlp() | |
doc = await asyncio.to_thread(nlp, text) | |
passive_sentences = 0 | |
total_sentences = 0 | |
for sent in doc.sents: | |
total_sentences += 1 | |
is_passive_sentence = False | |
for token in sent: | |
if token.dep_ == "nsubjpass" and token.head.pos_ == "VERB": | |
is_passive_sentence = True | |
break | |
if is_passive_sentence: | |
passive_sentences += 1 | |
if total_sentences == 0: | |
return {"voice": "unknown", "passive_ratio": 0.0} | |
ratio = passive_sentences / total_sentences | |
voice_type = "Passive" if ratio > 0.1 else "Active" | |
return { | |
"voice": voice_type, | |
"passive_ratio": round(ratio, 3), | |
"passive_sentences_count": passive_sentences, | |
"total_sentences_count": total_sentences | |
} | |
except Exception as e: | |
logger.error(f"Voice detection error for text: '{text[:50]}...': {e}", exc_info=True) | |
raise ServiceError(status_code=500, detail="An internal error occurred during voice detection.") from e | |