universal_translator / translation_service.py
joelazo
Fixed runtime issues.
b77492f
"""
Translation Service Module
Contains the core translation logic separated from the UI.
"""
from typing import Tuple, Optional
from huggingface_hub import InferenceClient
from langdetect import detect, LangDetectException
from config import (
ModelConfig,
LanguageConfig,
PromptConfig,
ErrorMessages,
get_language_name
)
class LanguageDetector:
"""Handles language detection for input text."""
@staticmethod
def detect_language(text: str) -> Tuple[str, str]:
"""
Detect the language of the input text.
Args:
text: Input text to detect language
Returns:
Tuple of (language_code, language_name)
"""
try:
lang_code = detect(text)
lang_name = get_language_name(lang_code)
return lang_code, lang_name
except LangDetectException:
return "unknown", ErrorMessages.LANGUAGE_DETECTION_FAILED
class TranslationEngine:
"""Handles translation using the Apertus model."""
def __init__(self, model_name: Optional[str] = None):
"""
Initialize the translation engine.
Args:
model_name: Optional model name override
"""
self.model_name = model_name or ModelConfig.MODEL_NAME
self.client = InferenceClient(model=self.model_name)
self.language_detector = LanguageDetector()
def translate(
self,
text: str,
target_language: str,
max_tokens: int = None,
temperature: float = None
) -> Tuple[str, str, str]:
"""
Translate text to target language.
Args:
text: Text to translate
target_language: Target language name (e.g., 'Spanish', 'French')
max_tokens: Maximum tokens for response (defaults to config value)
temperature: Model temperature (defaults to config value)
Returns:
Tuple of (translated_text, source_lang_code, source_lang_name)
"""
if not text.strip():
return "", "unknown", ErrorMessages.LANGUAGE_DETECTION_FAILED
# Use defaults from config if not provided
max_tokens = max_tokens or ModelConfig.DEFAULT_MAX_TOKENS
temperature = temperature or ModelConfig.DEFAULT_TEMPERATURE
# Detect source language
source_lang_code, source_lang_name = self.language_detector.detect_language(text)
# Create translation prompt
system_prompt = PromptConfig.SYSTEM_PROMPT_TEMPLATE.format(
target_language=target_language
)
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": text}
]
try:
# Call the translation model with streaming enabled for faster response
response = self.client.chat_completion(
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
stream=True # Enable streaming for reduced latency
)
# Collect streamed response
translated_text = ""
for chunk in response:
# Safely access content attribute (not all chunks have content)
delta_content = getattr(chunk.choices[0].delta, 'content', None)
if delta_content:
translated_text += delta_content
translated_text = translated_text.strip()
return translated_text, source_lang_code, source_lang_name
except Exception as e:
error_message = ErrorMessages.TRANSLATION_ERROR.format(error=str(e))
return error_message, source_lang_code, source_lang_name
class TranslationService:
"""
High-level translation service that orchestrates translation and voice processing.
"""
def __init__(self, model_name: Optional[str] = None):
"""
Initialize the translation service.
Args:
model_name: Optional model name override
"""
self.engine = TranslationEngine(model_name)
def translate_text(
self,
text: str,
target_language: str,
max_tokens: Optional[int] = None,
temperature: Optional[float] = None
) -> Tuple[str, str]:
"""
Translate text and return formatted results.
Args:
text: Text to translate
target_language: Target language name
max_tokens: Maximum tokens for response
temperature: Model temperature
Returns:
Tuple of (translated_text, detected_language_info)
"""
if not text.strip():
return "", ErrorMessages.NO_INPUT
translated_text, source_code, source_name = self.engine.translate(
text, target_language, max_tokens, temperature
)
# Format detected language info
detected_info = f"Detected: {source_name} ({source_code})"
return translated_text, detected_info
def detect_language_only(self, text: str) -> str:
"""
Detect language without translating.
Args:
text: Text to detect language
Returns:
Formatted language detection string
"""
if not text.strip():
return ErrorMessages.NO_INPUT
source_code, source_name = self.engine.language_detector.detect_language(text)
return f"Detected: {source_name} ({source_code})"