feat(qualite): retenter automatiquement les traductions livrees dans la mauvaise ecriture
Le defaut le plus sournois du pipeline etait silencieux : de l'arabe livre pour une cible persane (meme ecriture, mauvaise langue) passe inapercu et part chez le lecteur. Desormais chaque lot traduit est verifie par le detecteur d'ecritures, et chaque segment fautif est redemande une fois au moteur avec une consigne renforcee (nom de la langue + lettres specifiques, ex. persan پ چ ژ گ). La seconde tentative ne remplace la premiere que si elle passe le meme controle. - services/quality/script_detector.py : extraction d'un controle script_issue() reutilisable ; detect_arabic_variant signale des ormais un long texte en ecriture arabe sans aucune lettre specifique de la langue cible (arabe pur livre pour du persan/ourdou/pachto) - translators/segments.py : retry_wrong_script() + construction de la consigne renforcee, sans jamais faire echouer le travail - Word, Excel, PDF : branchement apres la memoire de traduction et les validations humaines ; le texte inchange (chiffres, noms propres) ne declenche jamais de retentative - 14 tests nouveaux (tests/test_translators/test_script_retry.py)
This commit is contained in:
@@ -526,6 +526,24 @@ class ExcelTranslator:
|
||||
)
|
||||
miss_pos += 1
|
||||
|
||||
# Wrong-script guard: re-ask once (with a reinforced instruction)
|
||||
# for translations delivered in the wrong alphabet — e.g. Arabic
|
||||
# delivered for a Persian target.
|
||||
from translators.segments import retry_wrong_script
|
||||
|
||||
def _retry_translate(retry_texts, hint):
|
||||
if self._provider is not None:
|
||||
return self._translate_with_provider(
|
||||
retry_texts, target_language, source_language, extra_prompt=hint
|
||||
)
|
||||
return self._translate_with_legacy(
|
||||
retry_texts, target_language, source_language
|
||||
)
|
||||
|
||||
translated, _script_fixed = retry_wrong_script(
|
||||
texts, translated, target_language, _retry_translate
|
||||
)
|
||||
|
||||
recorder = getattr(self, "_segment_recorder", None)
|
||||
if recorder is not None:
|
||||
recorder.record_pairs(zip(texts, translated))
|
||||
@@ -539,7 +557,8 @@ class ExcelTranslator:
|
||||
return dict(self._translation_stats)
|
||||
|
||||
def _translate_with_provider(
|
||||
self, texts: List[str], target_language: str, source_language: str
|
||||
self, texts: List[str], target_language: str, source_language: str,
|
||||
extra_prompt: Optional[str] = None,
|
||||
) -> List[str]:
|
||||
"""Translate using the TranslationProvider.translate_batch() interface."""
|
||||
from services.providers.base import TranslationProvider as NewTranslationProvider
|
||||
@@ -557,6 +576,10 @@ class ExcelTranslator:
|
||||
if is_new_style:
|
||||
from services.providers.schemas import TranslationRequest
|
||||
custom_prompt = getattr(self, "_custom_prompt", None)
|
||||
if extra_prompt:
|
||||
custom_prompt = (
|
||||
f"{custom_prompt}\n\n{extra_prompt}" if custom_prompt else extra_prompt
|
||||
)
|
||||
metadata = {"custom_prompt": custom_prompt} if custom_prompt else None
|
||||
|
||||
requests = [
|
||||
|
||||
Reference in New Issue
Block a user