This commit is contained in:
2025-11-11 16:58:03 +01:00
parent f23f4b71d8
commit 324751eb5d
14 changed files with 1108 additions and 18 deletions

View File

@@ -160,6 +160,147 @@ class OllamaClient:
'duration': time.time() - start_time
}
def translate_title(self, title, target_language='English'):
"""
Translate article title to target language
Args:
title: Original title (typically German)
target_language: Target language (default: 'English')
Returns:
{
'success': bool, # Whether translation succeeded
'translated_title': str or None, # Translated title
'error': str or None, # Error message if failed
'duration': float # Time taken in seconds
}
"""
if not self.enabled:
return {
'success': False,
'translated_title': None,
'error': 'Ollama is not enabled',
'duration': 0
}
if not title or len(title.strip()) == 0:
return {
'success': False,
'translated_title': None,
'error': 'Title is empty',
'duration': 0
}
start_time = time.time()
try:
# Construct prompt
prompt = self._build_translation_prompt(title, target_language)
# Prepare request
url = f"{self.base_url}/api/generate"
headers = {'Content-Type': 'application/json'}
if self.api_key:
headers['Authorization'] = f'Bearer {self.api_key}'
payload = {
'model': self.model,
'prompt': prompt,
'stream': False,
'options': {
'temperature': 0.3, # Lower temperature for consistent translations
'num_predict': 100 # Limit response length for title-length outputs
}
}
# Make request
response = requests.post(
url,
json=payload,
headers=headers,
timeout=self.timeout
)
response.raise_for_status()
# Parse response
result = response.json()
translated_title = result.get('response', '').strip()
if not translated_title:
return {
'success': False,
'translated_title': None,
'error': 'Ollama returned empty translation',
'duration': time.time() - start_time
}
# Clean the translation output
translated_title = self._clean_translation(translated_title)
return {
'success': True,
'translated_title': translated_title,
'error': None,
'duration': time.time() - start_time
}
except requests.exceptions.Timeout:
return {
'success': False,
'translated_title': None,
'error': f'Request timed out after {self.timeout} seconds',
'duration': time.time() - start_time
}
except requests.exceptions.ConnectionError:
return {
'success': False,
'translated_title': None,
'error': f'Cannot connect to Ollama server at {self.base_url}',
'duration': time.time() - start_time
}
except requests.exceptions.HTTPError as e:
return {
'success': False,
'translated_title': None,
'error': f'HTTP error: {e.response.status_code} - {e.response.text[:100]}',
'duration': time.time() - start_time
}
except Exception as e:
return {
'success': False,
'translated_title': None,
'error': f'Unexpected error: {str(e)}',
'duration': time.time() - start_time
}
def _build_translation_prompt(self, title, target_language):
"""Build prompt for title translation"""
prompt = f"""Translate the following German news headline to {target_language}. Provide only the translation without any explanations, quotes, or additional text.
German headline:
{title}
{target_language} translation:"""
return prompt
def _clean_translation(self, translation):
"""Clean translation output by removing quotes and extra text"""
# Extract first line only
translation = translation.split('\n')[0]
# Remove surrounding quotes (single and double)
translation = translation.strip()
if (translation.startswith('"') and translation.endswith('"')) or \
(translation.startswith("'") and translation.endswith("'")):
translation = translation[1:-1]
# Trim whitespace again after quote removal
translation = translation.strip()
return translation
def _build_summarization_prompt(self, content, max_words):
"""Build prompt for article summarization"""
# Truncate content if too long (keep first 5000 words)