Macros de carte floue et logique de support

Aura prend en charge le regroupement de plusieurs règles de prétraitement dans des fichiers « FUZZY_MAP_pre.py » pour les exécuter séquentiellement en tant que pipeline cohérent une fois qu’une « règle de démarrage » est déclenchée. Ce document décrit la philosophie de conception, la syntaxe et le flux d’exécution de cette fonctionnalité.

Principes de conception de base

  1. Zéro redondance : les règles à l’intérieur d’un groupe restent des tuples Python standard : ('replacement_text', r'regex_pattern', seuil, flags_and_options)

  2. Double utilisation : les règles individuelles au sein d’un groupe sont des règles autonomes entièrement fonctionnelles. Si le groupe n’est pas déclenché, ils sont évalués normalement dans la boucle parent.

  3. Marqueur de fin passif : La fin d’un groupe est définie par une entrée de règle passive qui ne correspond jamais seule. Il agit uniquement comme une limite pour l’analyseur.

  4. Repli hybride (Append-on-Non-Match) : lorsqu’un groupe est actif, chaque règle interne doit contribuer à la sortie. Si l’expression régulière d’une règle interne correspond au texte, la substitution normale a lieu. S’il ne correspond pas, son texte de remplacement est ajouté au texte actuel avec un espace.


Syntaxe et structure

Un groupe de macros est défini en encapsulant une série de règles standard entre une Règle de début et une Règle de fin dans FUZZY_MAP_pre.py.

1. La règle de départ

La règle de démarrage est une règle standard qui déclenche la macro lorsqu’elle correspond. Il inclut une clé ``group_start’` dans son dictionnaire d’options :

('replacement', r'start_pattern', 100, {'group_start': 'unique_group_name'})

2. Règles intérieures

Les règles internes sont des règles standard placées séquentiellement après la règle de départ. Ils ne nécessitent aucune métadonnée particulière :

('inner_replacement', r'inner_pattern', 100, {})

3. La règle de fin (marqueur passif)

La règle de fin a un remplacement « None », un modèle vide et une clé « group_end » dans son dictionnaire d’options :

(None, r'', 100, {'group_end': 'unique_group_name'})

Exemple concret

Voici un cas de test pratique défini dans un fichier FUZZY_MAP_pre.py :

FUZZY_MAP_pre = [
    # Start Rule: Triggers the group 'sandbox_test' when "start sandbox" matches
    ('Sandbox:', r'start\w* sandbox', 100, {'group_start': 'sandbox_test'}),
    
    # Inner Rule 1: Replaces "apfel" with "birne" if present
    ('birne', r'apfel', 100, {}),
    
    # Inner Rule 2: Replaces "banane" if present, otherwise appends "banane"
    ('banane', r'banane', 100, {}),
    
    # End Rule: Passive boundary marker
    (None, r'', 100, {'group_end': 'sandbox_test'}),
]

Scénarios de flux d’exécution :

  • Scénario A (Macro déclenchée) :

  • Entrée : "démarrer le bac à sable avec apfel"

  • Débit attendu :

  1. La règle de démarrage correspond à "start sandbox" et la remplace par "Sandbox:" -> texte actuel : "Sandbox: mit apfel".

  2. Le groupe ``sandbox_test’` est déclenché.

  3. Nous exécutons les règles internes de manière récursive sur "Sandbox: mit apfel" :

  • La règle interne 1 correspond à "apfel" et remplace par "birne" -> texte actuel : "Sandbox: mit birne".

  • La règle interne 2 ne correspond pas à "banane". Puisque le groupe est actif, il revient à ajouter "banane" -> Texte actuel : "Sandbox: mit birne banane".

  1. Le texte final "Sandbox: mit birne banane" est renvoyé et corrigé par LanguageTool.

  • Sortie : "Bac à sable : avec Birne Banane"

  • Scénario B (Macro non déclenchée - Double utilisation) :

  • Entrée : "un apfel et un kirsche"

  • Débit attendu :

  1. La règle de départ ne correspond pas. Le groupe ``sandbox_test’` reste inactif.

  2. La boucle passe à la règle suivante.

  3. Règle intérieure 1 : correspond à "apfel" et le remplace par "birne" -> Texte actuel : "ein birne und eine kirsche".

  4. Règle intérieure 2 : Ne correspond pas. Étant donné que le groupe n’a pas été déclenché, la règle se comporte comme une règle autonome normale et rien n’est ajouté.

  5. La règle de fin est ignorée.

  • Sortie : "un birne et un kirsche"


Détails techniques (sous le capot)

  • Récursion isolée : lorsqu’un groupe est déclenché, le moteur appelle de manière récursive process_text_in_background avec custom_rules=[inner_rule]. Cela permet à chaque règle interne de s’exécuter dans le cadre d’une passe de pipeline complète et synchrone.

  • Garanties de performance et de stabilité :

  • Sequence Bypass : les exécutions récursives internes contournent la file d’attente de séquence chunk_id pour éviter les blocages et les retards d’exécution.

  • Suppression des E/S et TTS : les exécutions récursives suppriment l’écriture de fichiers intermédiaire et les sorties vocales TTS, garantissant que seul le texte final stabilisé est écrit et prononcé.

  • Garantie de stabilité : les exécutions récursives s’interrompent strictement après une itération pour éviter des boucles de stabilité infinies lors des ajouts de repli.

  • Terminaison sécurisée : le contrôle de stabilité repose strictement sur le nombre maximal d’itérations (MAX_ITERATIONS_FOR_SAFETY) pour empêcher les boucles infinies, en contournant la limitation basée sur le temps qui pourrait interrompre prématurément les exécutions de macros légitimes et plus lentes. CODE_BLOCK_4