Amélioration majeure du système de traduction Confluent
- Prompt système strict avec Chain-of-Thought obligatoire
- Retrait des racines en dur du prompt (context skimming pur)
- Amélioration logique fallback (activation si <50% couverture)
- Ajout lexique : loup, frère, manger + fichier famille
- Debug endpoint /api/debug/prompt pour inspection
- Documentation complète système racines françaises
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
894645e640
commit
bbd8d5f9c9
@ -336,8 +336,16 @@ function analyzeContext(text, lexique, options = {}) {
|
||||
expansionLevel
|
||||
);
|
||||
|
||||
// 5. Fallback si aucune entrée trouvée
|
||||
const useFallback = expandedEntries.length === 0;
|
||||
// 5. Fallback si trop de mots manquants (>50% de mots non trouvés)
|
||||
const wordsFoundCount = searchResult.wordsFound.length;
|
||||
const wordsNotFoundCount = searchResult.wordsNotFound.length;
|
||||
const totalWords = wordsFoundCount + wordsNotFoundCount;
|
||||
const coveragePercent = totalWords > 0 ? (wordsFoundCount / totalWords) * 100 : 0;
|
||||
|
||||
// Activer fallback si :
|
||||
// - Aucune entrée trouvée OU
|
||||
// - Couverture < 50% (majorité de mots manquants)
|
||||
const useFallback = expandedEntries.length === 0 || coveragePercent < 50;
|
||||
const rootsFallback = useFallback ? extractRoots(lexique) : [];
|
||||
|
||||
// 6. Calculer tokens économisés (estimation)
|
||||
|
||||
@ -1,11 +1,26 @@
|
||||
Tu es un traducteur spécialisé en Ancien Confluent, langue de la Civilisation de la Confluence.
|
||||
Tu es un traducteur expert en Ancien Confluent, langue construite de la Civilisation de la Confluence.
|
||||
|
||||
# RÈGLES STRICTES
|
||||
# MÉTHODOLOGIE OBLIGATOIRE : CHAIN-OF-THOUGHT
|
||||
|
||||
1. Tu DOIS traduire du français vers l'Ancien Confluent UNIQUEMENT
|
||||
2. Utilise UNIQUEMENT les racines du lexique fourni
|
||||
3. Respecte STRICTEMENT la syntaxe et les liaisons sacrées
|
||||
4. Fournis la traduction suivie d'une décomposition explicative
|
||||
Tu DOIS suivre cette structure de réponse en 3 étapes :
|
||||
|
||||
1. **ANALYSE** : Identifier les défis de traduction et les limitations du système
|
||||
2. **STRATÉGIE** : Proposer une approche de traduction valide
|
||||
3. **TRADUCTION** : Produire la traduction finale avec décomposition
|
||||
|
||||
# RÈGLES ABSOLUES - INTERDICTIONS
|
||||
|
||||
❌ **INTERDIT** d'inventer des racines qui ne sont pas dans le lexique fourni
|
||||
❌ **INTERDIT** d'inventer des conjugateurs (seulement : u, at, aan, ait, amat, en, il, eol, eon, eom, ok, es, ul, uv)
|
||||
❌ **INTERDIT** d'utiliser les liaisons sacrées (i, ie, ii, iu, u, ui, a, aa, ae, ao, o, oa, e, ei, ea, eo) comme pronoms relatifs
|
||||
❌ **INTERDIT** de créer des structures syntaxiques non documentées
|
||||
|
||||
# RÈGLES ABSOLUES - OBLIGATIONS
|
||||
|
||||
✅ **OBLIGATOIRE** : Utiliser UNIQUEMENT les racines du lexique fourni (vocabulaire contextuel + racines disponibles)
|
||||
✅ **OBLIGATOIRE** : Respecter l'ordre SOV (Sujet - Objet - Verbe)
|
||||
✅ **OBLIGATOIRE** : Si un mot n'existe pas, composer à partir des racines ou reformuler
|
||||
✅ **OBLIGATOIRE** : Indiquer dans l'ANALYSE si tu reformules la phrase
|
||||
|
||||
# PHONOLOGIE
|
||||
|
||||
@ -31,53 +46,66 @@ Autres:
|
||||
- zo/zom/zob/zoe = négation
|
||||
- ka = question (fin)
|
||||
|
||||
# LIAISONS SACRÉES (16)
|
||||
# LIAISONS SACRÉES (16) - COMPOSITION UNIQUEMENT
|
||||
|
||||
Fusionnent deux racines. Exemples:
|
||||
- i (agent actif): sili + aska → sil-i-aska
|
||||
- u (appartenance): naki + ura → nak-u-ura
|
||||
- a (ensemble): ura + kota → ur-aa-kota
|
||||
- o (obstacle): aki + zana → ak-oa-zana
|
||||
- e (source): vuku + ura → vuk-u-ura
|
||||
⚠️ Les liaisons sacrées servent à COMPOSER deux racines, PAS à faire des propositions relatives.
|
||||
|
||||
# VERBES
|
||||
Structure : racine1 (forme liée) + liaison + racine2
|
||||
|
||||
Structure: racine + conjugateur
|
||||
Liaisons disponibles :
|
||||
- **i** (agent actif) : celui qui fait/porte → sili + aska = sil-i-aska (porteur du regard libre)
|
||||
- **ie** (agent récepteur) : celui qui reçoit
|
||||
- **ii** (agent essentiel) : celui qui EST (essence)
|
||||
- **iu** (agent potentiel) : celui qui devient
|
||||
- **u** (appartenance) : de, appartenant à → naki + ura = nak-u-ura (enfant de l'eau)
|
||||
- **ui** (but/service) : pour, destiné à
|
||||
- **a** (avec) : ensemble → ora + umi = or-a-umi (aurore avec esprit)
|
||||
- **aa** (fusion) : mêlé, confluent → ura + kota = ur-aa-kota (eau mêlée à l'union)
|
||||
- **ae** (égal) : équivalent
|
||||
- **ao** (domine) : supérieur → aki + zana = ak-oa-zana (faucon vainqueur)
|
||||
- **o** (tension) : face à, contre
|
||||
- **oa** (résolution) : surmonté
|
||||
- **e** (source) : origine, cause
|
||||
- **ei** (centre) : présent, actuel
|
||||
- **ea** (direction) : futur, but
|
||||
- **eo** (totalité) : universel
|
||||
|
||||
Temps:
|
||||
- u = présent
|
||||
- at = passé vécu
|
||||
- en = futur
|
||||
❌ **"i" n'est PAS le pronom relatif "qui"** - c'est une liaison de composition !
|
||||
|
||||
Modes:
|
||||
- ok = impératif
|
||||
- es = souhait
|
||||
- ul = capacité
|
||||
# VERBES ET CONJUGAISONS
|
||||
|
||||
# RACINES PRINCIPALES
|
||||
Structure STRICTE : **VERBE + CONJUGATEUR**
|
||||
|
||||
## Sacrées (V initial)
|
||||
aska (libre), aita (ancêtre), asa (sacré), avi/aru (oiseau/grue), aki (faucon), ura (eau), umi (esprit), iko (un), ita (être), ena (origine), eka (tout), oki (épreuve), ora (aurore), onu (son), anu (âme), eku (étoile), osi (mort), ava (aile)
|
||||
Les verbes sont des racines de 5 lettres (CVCVC) qui finissent par une consonne.
|
||||
|
||||
## Éléments
|
||||
zeru (ciel), toka (terre), suki (feu), vena (air), kari (pierre), nura (rivière), tasa (montagne), viku (forêt), luna (lune), sora (soleil)
|
||||
## Conjugateurs EXHAUSTIFS (tous ceux qui existent)
|
||||
|
||||
## Corps
|
||||
sili (regard), kanu (main), voki (voix), tiku (oreille), muka (visage), kori (cœur), sanu (corps), peki (pied), keko (écho)
|
||||
### Temps
|
||||
- **u** = présent neutre
|
||||
- **at** = passé vécu (dans ma vie)
|
||||
- **aan** = passé regretté ("oups")
|
||||
- **ait** = passé ancestral (nos ancêtres)
|
||||
- **amat** = passé mythique (cérémoniel, temps des Premiers)
|
||||
- **en** = futur
|
||||
|
||||
## Actions principales
|
||||
mira (voir), teki (aller), kita (donner), pasa (prendre), neka (faire), vosa (dire), seka (savoir), moki (apprendre), kisu (transmettre), zaki (garder), taka (porter), zana (chasser)
|
||||
### Aspects
|
||||
- **il** = accompli (terminé)
|
||||
- **eol** = habituel (régulièrement)
|
||||
- **eon** = cyclique (saisons)
|
||||
- **eom** = éternel (immuable)
|
||||
|
||||
## Êtres
|
||||
naki (enfant), tori (personne), vaku (ami), zoka (ennemi), mitu (famille), kasi (chef), kota (union), tibu (tribu)
|
||||
### Modes
|
||||
- **ok** = impératif (ordre)
|
||||
- **es** = souhait (désir)
|
||||
- **ul** = capacité (pouvoir)
|
||||
|
||||
## Concepts
|
||||
veri (vrai), tosa (bon), mako (grand), pisu (petit), novu (nouveau), paki (paix), vali (valeur), voli (vouloir), varu (guerre), mori (mémoire)
|
||||
### Évidentiel
|
||||
- **uv** = c'est écrit (source textuelle)
|
||||
|
||||
## Lieux
|
||||
vuku (profond/gouffre), riku (cercle), vela (veille), savu (serment), talu (hall), kova (fresque), loku (lieu)
|
||||
❌ **Ces conjugateurs sont EXHAUSTIFS** - il n'existe AUCUN autre conjugateur.
|
||||
❌ **INTERDIT** de créer "-en" comme négation (c'est le FUTUR !)
|
||||
|
||||
# CASTES ET LIEUX VALIDÉS
|
||||
# CASTES ET LIEUX VALIDÉS (noms propres)
|
||||
|
||||
Castes:
|
||||
- Nakukeko (Enfants des Échos): nak-u-keko
|
||||
@ -98,34 +126,123 @@ Lieux:
|
||||
Peuple:
|
||||
- Siliaska (Porteurs du regard libre): sil-i-aska
|
||||
|
||||
# FORMAT DE RÉPONSE
|
||||
# LIMITATIONS SYNTAXIQUES DU SYSTÈME
|
||||
|
||||
⚠️ L'Ancien Confluent ne possède PAS ces structures (elles n'existent pas) :
|
||||
|
||||
❌ **Propositions relatives** ("qui", "que", "dont") → Utiliser juxtaposition ou composition
|
||||
❌ **Subordination** ("parce que", "afin de", "bien que") → Utiliser connecteurs simples (se, lo)
|
||||
❌ **Participes présents** ("en mangeant", "étant") → Reformuler avec verbes
|
||||
|
||||
## Stratégies de contournement OBLIGATOIRES
|
||||
|
||||
### Pour les propositions relatives :
|
||||
|
||||
**Français :** "Le loup qui chasse"
|
||||
**❌ FAUX :** na zoka i zanak (i n'est pas "qui")
|
||||
**✅ CORRECT :** Utiliser une composition ou juxtaposer :
|
||||
- Option 1 (composition) : zok-i-zana (loup-chasseur, concept figé)
|
||||
- Option 2 (juxtaposition) : "va zoka zanaku" (le loup chasse) - phrase séparée
|
||||
|
||||
**Français :** "C'est le collier du loup qui a mangé mon frère"
|
||||
**✅ STRATÉGIE :** Séparer en 2 phrases :
|
||||
1. "C'est le collier du loup" → Tisikopuu na zoka
|
||||
2. "Le loup a mangé mon frère" → Va zoka vo vaku pasak at
|
||||
|
||||
### Pour les mots manquants :
|
||||
|
||||
Si un mot n'existe pas dans le lexique :
|
||||
1. **Composer** à partir de racines existantes (ex: grand-eau pour océan)
|
||||
2. **Approximer** avec un mot proche (ex: "prendre" pour "manger")
|
||||
3. **Indiquer dans l'ANALYSE** que tu fais une approximation
|
||||
|
||||
# FORMAT DE RÉPONSE OBLIGATOIRE
|
||||
|
||||
Tu DOIS suivre cette structure exacte :
|
||||
|
||||
```
|
||||
ANALYSE:
|
||||
[Identifier les défis : propositions relatives, mots manquants, structures complexes]
|
||||
|
||||
STRATÉGIE:
|
||||
[Expliquer comment tu vas contourner les limitations]
|
||||
|
||||
Ancien Confluent:
|
||||
[traduction]
|
||||
[traduction finale]
|
||||
|
||||
Décomposition:
|
||||
[composition avec liaisons si applicable]
|
||||
[explication mot à mot avec particules et conjugaisons]
|
||||
```
|
||||
|
||||
# EXEMPLES
|
||||
# EXEMPLES AVEC CHAIN-OF-THOUGHT
|
||||
|
||||
## Exemple 1 : Phrase simple
|
||||
|
||||
**Français:** L'enfant voit l'eau.
|
||||
|
||||
ANALYSE:
|
||||
- Phrase simple SOV
|
||||
- Tous les mots existent (naki, ura, mirak)
|
||||
- Pas de limitation syntaxique
|
||||
|
||||
STRATÉGIE:
|
||||
- Traduction directe avec ordre SOV
|
||||
|
||||
Français: L'enfant voit l'eau.
|
||||
Ancien Confluent:
|
||||
va naki vo ura miraku
|
||||
va naki vo ura mirak u
|
||||
|
||||
Décomposition:
|
||||
va naki = SUJET enfant
|
||||
vo ura = OBJET eau
|
||||
miraku = voir (présent -u)
|
||||
mirak u = voir + présent
|
||||
|
||||
---
|
||||
|
||||
Français: Les Passes-bien portent les biens.
|
||||
## Exemple 2 : Avec proposition relative
|
||||
|
||||
**Français:** Le faucon qui chasse voit l'eau.
|
||||
|
||||
ANALYSE:
|
||||
- Proposition relative "qui chasse" → NON SUPPORTÉ
|
||||
- Verbes : mirak (voir), zanak (chasser) existent
|
||||
- Besoin de reformuler
|
||||
|
||||
STRATÉGIE:
|
||||
- Option 1 : Composition "ak-oa-zana" (faucon-chasseur) déjà validée
|
||||
- Option 2 : Deux phrases séparées
|
||||
- Je choisis Option 1 (plus concis)
|
||||
|
||||
Ancien Confluent:
|
||||
va Takitosa su vo tosa su takanu
|
||||
va Akoazana vo ura mirak u
|
||||
|
||||
Décomposition:
|
||||
va Takitosa su = SUJET Passes-bien PLURIEL
|
||||
vo tosa su = OBJET bien PLURIEL
|
||||
takanu = porter (présent -u)
|
||||
va Akoazana = SUJET Faucon-Chasseur (composition ak-oa-zana)
|
||||
vo ura = OBJET eau
|
||||
mirak u = voir + présent
|
||||
|
||||
IMPORTANT: Ne fournis QUE la traduction et la décomposition. Pas de commentaire additionnel.
|
||||
Note: "qui chasse" intégré dans la composition nominale Akoazana
|
||||
|
||||
---
|
||||
|
||||
## Exemple 3 : Mot manquant
|
||||
|
||||
**Français:** L'enfant mange la pierre.
|
||||
|
||||
ANALYSE:
|
||||
- "manger" n'existe pas dans le lexique
|
||||
- Verbes disponibles : pasak (prendre), nekan (faire)
|
||||
- Approximation nécessaire
|
||||
|
||||
STRATÉGIE:
|
||||
- Utiliser "pasak" (prendre) comme approximation de "manger"
|
||||
- Indiquer l'approximation
|
||||
|
||||
Ancien Confluent:
|
||||
va naki vo kari pasak u
|
||||
|
||||
Décomposition:
|
||||
va naki = SUJET enfant
|
||||
vo kari = OBJET pierre
|
||||
pasak u = prendre + présent (approximation de "manger")
|
||||
|
||||
Note: "manger" traduit par "prendre" (verbe le plus proche disponible)
|
||||
|
||||
@ -128,6 +128,57 @@ ${summary}
|
||||
`;
|
||||
}
|
||||
|
||||
// Debug endpoint: Generate prompt without calling LLM
|
||||
app.post('/api/debug/prompt', (req, res) => {
|
||||
const { text, target = 'ancien', useLexique = true } = req.body;
|
||||
|
||||
if (!text) {
|
||||
return res.status(400).json({ error: 'Missing parameter: text' });
|
||||
}
|
||||
|
||||
const variant = target === 'proto' ? 'proto' : 'ancien';
|
||||
|
||||
try {
|
||||
let systemPrompt;
|
||||
let contextMetadata = null;
|
||||
|
||||
// MÊME CODE QUE /translate
|
||||
if (useLexique) {
|
||||
const contextResult = analyzeContext(text, lexiques[variant]);
|
||||
systemPrompt = buildContextualPrompt(contextResult, variant);
|
||||
|
||||
const promptStats = getPromptStats(systemPrompt, contextResult);
|
||||
contextMetadata = {
|
||||
wordsFound: contextResult.metadata.wordsFound,
|
||||
wordsNotFound: contextResult.metadata.wordsNotFound,
|
||||
entriesUsed: contextResult.metadata.entriesUsed,
|
||||
totalLexiqueSize: contextResult.metadata.totalLexiqueSize,
|
||||
tokensFullLexique: promptStats.fullLexiqueTokens,
|
||||
tokensUsed: promptStats.promptTokens,
|
||||
tokensSaved: promptStats.tokensSaved,
|
||||
savingsPercent: promptStats.savingsPercent,
|
||||
useFallback: contextResult.useFallback,
|
||||
expansionLevel: contextResult.metadata.expansionLevel
|
||||
};
|
||||
} else {
|
||||
systemPrompt = getBasePrompt(variant);
|
||||
}
|
||||
|
||||
res.json({
|
||||
prompt: systemPrompt,
|
||||
metadata: contextMetadata,
|
||||
stats: {
|
||||
promptLength: systemPrompt.length,
|
||||
promptLines: systemPrompt.split('\n').length
|
||||
}
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Prompt generation error:', error);
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
// Translation endpoint (NOUVEAU SYSTÈME CONTEXTUEL)
|
||||
app.post('/translate', async (req, res) => {
|
||||
const { text, target, provider, model, useLexique = true } = req.body;
|
||||
@ -217,8 +268,10 @@ app.post('/translate', async (req, res) => {
|
||||
// Layer 2: Contexte (COT hors LLM)
|
||||
layer2: contextMetadata,
|
||||
|
||||
// Layer 3: Explications LLM
|
||||
// Layer 3: Explications LLM (avec COT)
|
||||
layer3: {
|
||||
analyse: parsed.analyse,
|
||||
strategie: parsed.strategie,
|
||||
decomposition: parsed.decomposition,
|
||||
notes: parsed.notes,
|
||||
wordsCreated: parsed.wordsCreated || []
|
||||
@ -237,13 +290,15 @@ app.post('/translate', async (req, res) => {
|
||||
});
|
||||
|
||||
/**
|
||||
* Parse la réponse du LLM pour extraire les différentes sections
|
||||
* Parse la réponse du LLM pour extraire les différentes sections (avec COT)
|
||||
* @param {string} response - Réponse brute du LLM
|
||||
* @returns {Object} - Sections parsées
|
||||
*/
|
||||
function parseTranslationResponse(response) {
|
||||
const lines = response.split('\n');
|
||||
|
||||
let analyse = '';
|
||||
let strategie = '';
|
||||
let translation = '';
|
||||
let decomposition = '';
|
||||
let notes = '';
|
||||
@ -252,7 +307,15 @@ function parseTranslationResponse(response) {
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
|
||||
// Détecter les sections
|
||||
// Détecter les sections (nouveau format COT)
|
||||
if (trimmed.match(/^ANALYSE:/i)) {
|
||||
currentSection = 'analyse';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.match(/^STRAT[ÉE]GIE:/i)) {
|
||||
currentSection = 'strategie';
|
||||
continue;
|
||||
}
|
||||
if (trimmed.match(/^(Ancien )?Confluent:/i)) {
|
||||
currentSection = 'translation';
|
||||
continue;
|
||||
@ -267,19 +330,25 @@ function parseTranslationResponse(response) {
|
||||
}
|
||||
|
||||
// Ajouter le contenu à la section appropriée
|
||||
if (currentSection === 'translation' && trimmed && !trimmed.match(/^---/)) {
|
||||
if (currentSection === 'analyse' && trimmed && !trimmed.match(/^---/)) {
|
||||
analyse += line + '\n';
|
||||
} else if (currentSection === 'strategie' && trimmed && !trimmed.match(/^---/)) {
|
||||
strategie += line + '\n';
|
||||
} else if (currentSection === 'translation' && trimmed && !trimmed.match(/^---/)) {
|
||||
translation += line + '\n';
|
||||
} else if (currentSection === 'decomposition' && trimmed) {
|
||||
decomposition += line + '\n';
|
||||
} else if (currentSection === 'notes' && trimmed) {
|
||||
notes += line + '\n';
|
||||
} else if (!currentSection && trimmed && !trimmed.match(/^---/)) {
|
||||
} else if (!currentSection && trimmed && !trimmed.match(/^---/) && !trimmed.match(/^\*\*/)) {
|
||||
// Si pas de section détectée, c'est probablement la traduction
|
||||
translation += line + '\n';
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
analyse: analyse.trim(),
|
||||
strategie: strategie.trim(),
|
||||
translation: translation.trim() || response.trim(),
|
||||
decomposition: decomposition.trim(),
|
||||
notes: notes.trim()
|
||||
|
||||
@ -493,6 +493,32 @@
|
||||
"note": "Chasser dans l'eau"
|
||||
}
|
||||
]
|
||||
},
|
||||
"manger": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "mukis",
|
||||
"type": "verbe",
|
||||
"racine": "muki",
|
||||
"forme_liee": "muk",
|
||||
"structure": "CVCVC",
|
||||
"domaine": "action",
|
||||
"note": "Consommer de la nourriture"
|
||||
}
|
||||
]
|
||||
},
|
||||
"dévorer": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "mukiuzana",
|
||||
"type": "composition",
|
||||
"composition": "muk-i-zana",
|
||||
"sens_litteral": "Manger avec chasse",
|
||||
"racines": ["muki", "zana"],
|
||||
"domaine": "action",
|
||||
"note": "Manger violemment, comme un prédateur"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,6 +167,29 @@
|
||||
"note": "Créature jamais observée"
|
||||
}
|
||||
]
|
||||
},
|
||||
"loup": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "loku",
|
||||
"type": "racine",
|
||||
"forme_liee": "lok",
|
||||
"domaine": "animal",
|
||||
"note": "Prédateur sauvage"
|
||||
}
|
||||
]
|
||||
},
|
||||
"meute": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "lokusu",
|
||||
"type": "composition",
|
||||
"composition": "loku + su",
|
||||
"sens_litteral": "Loups (pluriel)",
|
||||
"racines": ["loku"],
|
||||
"domaine": "animal"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
ancien-confluent/lexique/21-famille.json
Normal file
76
ancien-confluent/lexique/21-famille.json
Normal file
@ -0,0 +1,76 @@
|
||||
{
|
||||
"_comment": "Relations familiales",
|
||||
"_mots_a_gerer": [],
|
||||
"dictionnaire": {
|
||||
"frère": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "vaki",
|
||||
"type": "racine",
|
||||
"forme_liee": "vak",
|
||||
"domaine": "famille",
|
||||
"note": "Frère de sang"
|
||||
}
|
||||
],
|
||||
"synonymes_fr": ["frères"]
|
||||
},
|
||||
"sœur": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "seki",
|
||||
"type": "racine",
|
||||
"forme_liee": "sek",
|
||||
"domaine": "famille",
|
||||
"note": "Sœur de sang"
|
||||
}
|
||||
],
|
||||
"synonymes_fr": ["sœurs"]
|
||||
},
|
||||
"mère": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "matu",
|
||||
"type": "racine",
|
||||
"forme_liee": "mat",
|
||||
"domaine": "famille",
|
||||
"note": "Mère biologique"
|
||||
}
|
||||
]
|
||||
},
|
||||
"père": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "patu",
|
||||
"type": "racine",
|
||||
"forme_liee": "pat",
|
||||
"domaine": "famille",
|
||||
"note": "Père biologique"
|
||||
}
|
||||
]
|
||||
},
|
||||
"famille": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "mitu",
|
||||
"type": "racine",
|
||||
"forme_liee": "mit",
|
||||
"domaine": "famille",
|
||||
"note": "Unité familiale"
|
||||
}
|
||||
]
|
||||
},
|
||||
"frères et sœurs": {
|
||||
"traductions": [
|
||||
{
|
||||
"confluent": "vakisu",
|
||||
"type": "composition",
|
||||
"composition": "vaki + su",
|
||||
"sens_litteral": "Frères (pluriel inclusif)",
|
||||
"racines": ["vaki"],
|
||||
"domaine": "famille"
|
||||
}
|
||||
],
|
||||
"synonymes_fr": ["fratrie"]
|
||||
}
|
||||
}
|
||||
}
|
||||
391
docs/TRAVAIL_RACINES_FRANCAISES.md
Normal file
391
docs/TRAVAIL_RACINES_FRANCAISES.md
Normal file
@ -0,0 +1,391 @@
|
||||
# Travail : Système de Racines Françaises
|
||||
|
||||
## Objectif
|
||||
|
||||
Améliorer le matching des mots français conjugués/accordés en utilisant un système de **racines françaises** au lieu de se fier uniquement à la lemmatisation automatique.
|
||||
|
||||
## Problème actuel
|
||||
|
||||
- "manger" trouve "mukis" ✅
|
||||
- "mangé" ne trouve RIEN ❌
|
||||
- "vu" ne trouve pas "voir" ❌
|
||||
- "pris" ne trouve pas "prendre" ❌
|
||||
|
||||
Le lemmatizer actuel est trop basique et rate beaucoup de formes conjuguées.
|
||||
|
||||
## Solution : Double approche
|
||||
|
||||
### 1. Système de racines automatique (pour verbes réguliers)
|
||||
|
||||
**Principe** : Extraire les 4 premières lettres d'un mot comme "racine"
|
||||
|
||||
**Exemples qui marchent** :
|
||||
- "manger", "mangé", "mange", "mangeait" → racine **"mang"** → trouve "mukis" ✅
|
||||
- "donner", "donné", "donne", "donnait" → racine **"donn"** → trouve "kitan" ✅
|
||||
- "aller", "allé", "allait" → racine **"alle"** → trouve "tekis" ✅
|
||||
|
||||
**Code à ajouter** :
|
||||
```javascript
|
||||
/**
|
||||
* Extrait la racine française d'un mot (4 premières lettres)
|
||||
* Minimum 4 lettres pour éviter les faux positifs
|
||||
* @param {string} word - Mot français
|
||||
* @returns {string|null} - Racine ou null si mot trop court
|
||||
*/
|
||||
function extractFrenchRoot(word) {
|
||||
if (word.length < 4) return null;
|
||||
return word.slice(0, 4).toLowerCase();
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Exceptions manuelles (verbes irréguliers + racines courtes)
|
||||
|
||||
**Principe** : Ajouter toutes les formes conjuguées dans le champ `synonymes_fr` du lexique
|
||||
|
||||
**Exemples qui NE marchent PAS avec racines automatiques** :
|
||||
|
||||
#### Racines trop courtes
|
||||
- **"voir"** → racine "voir" (4 lettres OK) MAIS "vu", "vus" → racine "vu" (2 lettres ❌)
|
||||
- **"être"** → racine impossible (formes trop différentes)
|
||||
- **"avoir"** → racine impossible (formes trop différentes)
|
||||
|
||||
#### Verbes irréguliers
|
||||
- **"prendre"** → racine "pren" mais "pris", "prit" ont racine "pris" ❌
|
||||
- **"faire"** → racine "fair" mais "fait", "faite" ont racine "fait" ❌
|
||||
|
||||
**Solution** : Ajouter manuellement dans `synonymes_fr`
|
||||
|
||||
---
|
||||
|
||||
## TRAVAIL 1 : Modification du code (contextAnalyzer.js)
|
||||
|
||||
**Fichier** : `ConfluentTranslator/contextAnalyzer.js`
|
||||
|
||||
### Modifications à faire :
|
||||
|
||||
#### A. Ajouter la fonction extractFrenchRoot()
|
||||
|
||||
```javascript
|
||||
/**
|
||||
* Extrait la racine française d'un mot (4 premières lettres minimum)
|
||||
* Pour matcher des conjugaisons : manger/mangé/mange → "mang"
|
||||
* @param {string} word - Mot français (déjà en lowercase)
|
||||
* @returns {string|null} - Racine de 4 lettres ou null si trop court
|
||||
*/
|
||||
function extractFrenchRoot(word) {
|
||||
if (word.length < 4) return null;
|
||||
return word.slice(0, 4);
|
||||
}
|
||||
```
|
||||
|
||||
#### B. Modifier searchWord() pour utiliser les racines
|
||||
|
||||
**Emplacement** : ligne ~124
|
||||
|
||||
**Ajouter après la ligne 126** :
|
||||
```javascript
|
||||
const results = [];
|
||||
const lemmas = simpleLemmatize(word);
|
||||
const root = extractFrenchRoot(word); // NOUVEAU
|
||||
```
|
||||
|
||||
**Ajouter après la ligne 146 (après matching sur synonymes lemmatisés)** :
|
||||
```javascript
|
||||
// NOUVEAU: Correspondance sur racine française (4 lettres)
|
||||
else if (root && key.toLowerCase().startsWith(root)) {
|
||||
score = 0.75;
|
||||
}
|
||||
// NOUVEAU: Correspondance sur racine dans synonymes
|
||||
else if (root && entry.synonymes_fr?.some(syn => syn.toLowerCase().startsWith(root))) {
|
||||
score = 0.70;
|
||||
}
|
||||
```
|
||||
|
||||
**Code final de searchWord()** :
|
||||
```javascript
|
||||
function searchWord(word, dictionnaire) {
|
||||
const results = [];
|
||||
const lemmas = simpleLemmatize(word);
|
||||
const root = extractFrenchRoot(word); // NOUVEAU
|
||||
|
||||
for (const [key, entry] of Object.entries(dictionnaire)) {
|
||||
let score = 0;
|
||||
|
||||
// Correspondance exacte sur le mot français
|
||||
if (key === word || entry.mot_francais?.toLowerCase() === word) {
|
||||
score = 1.0;
|
||||
}
|
||||
// Correspondance sur formes lemmatisées
|
||||
else if (lemmas.some(lemma => key === lemma || entry.mot_francais?.toLowerCase() === lemma)) {
|
||||
score = 0.95;
|
||||
}
|
||||
// Correspondance sur synonymes
|
||||
else if (entry.synonymes_fr?.some(syn => syn.toLowerCase() === word)) {
|
||||
score = 0.9;
|
||||
}
|
||||
// Correspondance sur synonymes lemmatisés
|
||||
else if (entry.synonymes_fr?.some(syn => lemmas.includes(syn.toLowerCase()))) {
|
||||
score = 0.85;
|
||||
}
|
||||
// NOUVEAU: Correspondance sur racine française (4 lettres)
|
||||
else if (root && key.toLowerCase().startsWith(root)) {
|
||||
score = 0.75;
|
||||
}
|
||||
// NOUVEAU: Correspondance sur racine dans synonymes
|
||||
else if (root && entry.synonymes_fr?.some(syn => syn.toLowerCase().startsWith(root))) {
|
||||
score = 0.70;
|
||||
}
|
||||
|
||||
if (score > 0) {
|
||||
results.push({
|
||||
mot_francais: entry.mot_francais || key,
|
||||
traductions: entry.traductions || [],
|
||||
score,
|
||||
source: entry.source_files || []
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
```
|
||||
|
||||
#### C. Exporter la nouvelle fonction
|
||||
|
||||
**Emplacement** : ligne ~387 (module.exports)
|
||||
|
||||
```javascript
|
||||
module.exports = {
|
||||
tokenizeFrench,
|
||||
calculateMaxEntries,
|
||||
simpleLemmatize,
|
||||
extractFrenchRoot, // NOUVEAU
|
||||
searchWord,
|
||||
findRelevantEntries,
|
||||
expandContext,
|
||||
extractRoots,
|
||||
analyzeContext
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TRAVAIL 2 : Compléter les exceptions dans le lexique
|
||||
|
||||
**Objectif** : Ajouter manuellement les formes conjuguées des verbes irréguliers dans `synonymes_fr`
|
||||
|
||||
### Fichiers à modifier :
|
||||
|
||||
`ancien-confluent/lexique/06-actions.json`
|
||||
|
||||
### Verbes à compléter (par priorité)
|
||||
|
||||
#### Priorité 1 : Verbes très courants
|
||||
|
||||
**1. voir** (déjà présent)
|
||||
```json
|
||||
"voir": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["observer", "regarder", "voit", "vois", "vu", "vus", "vue", "vues", "voyait", "voyais", "voyant", "verra", "verras", "verront"]
|
||||
}
|
||||
```
|
||||
|
||||
**2. prendre**
|
||||
```json
|
||||
"prendre": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["pris", "prit", "prise", "prises", "prend", "prends", "prenait", "prenais", "prenant", "prendra", "prendras", "prendront"]
|
||||
}
|
||||
```
|
||||
|
||||
**3. faire**
|
||||
```json
|
||||
"faire": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["créer", "fait", "faits", "faite", "faites", "fais", "faisait", "faisais", "faisant", "fera", "feras", "feront"]
|
||||
}
|
||||
```
|
||||
|
||||
**4. manger** (nouveau verbe, déjà ajouté)
|
||||
```json
|
||||
"manger": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["mange", "manges", "mangé", "mangée", "mangés", "mangées", "mangeait", "mangeais", "mangeant", "mangera", "mangeras", "mangeront"]
|
||||
}
|
||||
```
|
||||
|
||||
**5. aller**
|
||||
```json
|
||||
"aller": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["va", "vas", "vais", "allé", "allée", "allés", "allées", "allait", "allais", "allant", "ira", "iras", "iront"]
|
||||
}
|
||||
```
|
||||
|
||||
**6. donner**
|
||||
```json
|
||||
"donner": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["donne", "donnes", "donné", "donnée", "donnés", "données", "donnait", "donnais", "donnant", "donnera", "donneras", "donneront"]
|
||||
}
|
||||
```
|
||||
|
||||
**7. dire**
|
||||
```json
|
||||
"dire": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["parler", "dit", "dits", "dite", "dites", "dis", "disait", "disais", "disant", "dira", "diras", "diront"]
|
||||
}
|
||||
```
|
||||
|
||||
#### Priorité 2 : Verbes auxiliaires (très irréguliers)
|
||||
|
||||
**8. être**
|
||||
```json
|
||||
"être": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["est", "es", "suis", "sont", "été", "était", "étais", "étant", "sera", "seras", "seront", "fut", "fus"]
|
||||
}
|
||||
```
|
||||
|
||||
**9. avoir**
|
||||
```json
|
||||
"avoir": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["a", "as", "ai", "ont", "eu", "eue", "eus", "eues", "avait", "avais", "ayant", "aura", "auras", "auront"]
|
||||
}
|
||||
```
|
||||
|
||||
#### Priorité 3 : Autres verbes courants
|
||||
|
||||
**10. savoir**
|
||||
```json
|
||||
"savoir": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["connaître", "sait", "sais", "su", "sue", "sus", "sues", "savait", "savais", "sachant", "saura", "sauras", "sauront"]
|
||||
}
|
||||
```
|
||||
|
||||
**11. chasser**
|
||||
```json
|
||||
"chasser": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["traquer", "chasse", "chasses", "chassé", "chassée", "chassés", "chassées", "chassait", "chassais", "chassant", "chassera", "chasseras", "chasseront"]
|
||||
}
|
||||
```
|
||||
|
||||
**12. transmettre**
|
||||
```json
|
||||
"transmettre": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["enseigner", "transmet", "transmets", "transmis", "transmise", "transmises", "transmettait", "transmettais", "transmettant", "transmettra", "transmettras", "transmettront"]
|
||||
}
|
||||
```
|
||||
|
||||
**13. garder**
|
||||
```json
|
||||
"garder": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["protéger", "garde", "gardes", "gardé", "gardée", "gardés", "gardées", "gardait", "gardais", "gardant", "gardera", "garderas", "garderont"]
|
||||
}
|
||||
```
|
||||
|
||||
**14. porter**
|
||||
```json
|
||||
"porter": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["transporter", "porte", "portes", "porté", "portée", "portés", "portées", "portait", "portais", "portant", "portera", "porteras", "porteront"]
|
||||
}
|
||||
```
|
||||
|
||||
**15. apprendre**
|
||||
```json
|
||||
"apprendre": {
|
||||
"traductions": [...],
|
||||
"synonymes_fr": ["apprend", "apprends", "appris", "apprise", "apprises", "apprenait", "apprenais", "apprenant", "apprendra", "apprendras", "apprendront"]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tests à faire après modifications
|
||||
|
||||
### Test 1 : Vérifier les racines automatiques
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/debug/prompt \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "Il mangeait le pain", "target": "ancien"}' | grep -A 5 "wordsFound"
|
||||
```
|
||||
|
||||
**Résultat attendu** : "mangeait" → trouve "mukis" via racine "mang"
|
||||
|
||||
### Test 2 : Vérifier les exceptions manuelles
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:3000/api/debug/prompt \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "Il a vu et pris", "target": "ancien"}' | grep -A 10 "wordsFound"
|
||||
```
|
||||
|
||||
**Résultat attendu** :
|
||||
- "vu" → trouve "mirak" via synonymes_fr
|
||||
- "pris" → trouve "pasak" via synonymes_fr
|
||||
|
||||
### Test 3 : Phrase complète
|
||||
|
||||
```bash
|
||||
# Même test que le problématique
|
||||
curl -X POST http://localhost:3000/api/debug/prompt \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"text": "C est le collier du loup qui a mange mon frere", "target": "ancien"}' | python -c "import sys, json; data=json.load(sys.stdin); print('Found:', [w['input'] for w in data['metadata']['wordsFound']])"
|
||||
```
|
||||
|
||||
**Résultat attendu** : ["collier", "loup", "mange", "frere"] tous trouvés
|
||||
|
||||
---
|
||||
|
||||
## Estimation de travail
|
||||
|
||||
- **Code (contextAnalyzer.js)** : ~30 lignes, 15 minutes
|
||||
- **Lexique (06-actions.json)** : 15 verbes × ~12 formes = ~180 formes à ajouter, 45-60 minutes
|
||||
|
||||
**Total** : ~1h15 de travail
|
||||
|
||||
---
|
||||
|
||||
## Notes importantes
|
||||
|
||||
1. **Lowercase** : Tout est déjà en lowercase dans tokenizeFrench(), pas besoin de le refaire
|
||||
2. **Normalisation des accents** : Déjà fait (mangé → mange dans la tokenization)
|
||||
3. **Ordre de priorité matching** :
|
||||
- 1.0 = Exacte
|
||||
- 0.95 = Lemma
|
||||
- 0.9 = Synonyme exact
|
||||
- 0.85 = Synonyme lemmatisé
|
||||
- **0.75 = Racine sur clé** (NOUVEAU)
|
||||
- **0.70 = Racine sur synonyme** (NOUVEAU)
|
||||
4. **Longueur minimum racine** : 4 lettres pour éviter faux positifs ("il", "du", "un", etc.)
|
||||
|
||||
---
|
||||
|
||||
## Commandes pour lancer un agent
|
||||
|
||||
Si tu veux déléguer le travail lexique à un agent :
|
||||
|
||||
```
|
||||
Lance un agent general-purpose avec cette tâche :
|
||||
|
||||
Complète le fichier ancien-confluent/lexique/06-actions.json en ajoutant les formes conjuguées dans synonymes_fr pour tous les verbes selon le document docs/TRAVAIL_RACINES_FRANCAISES.md section "TRAVAIL 2".
|
||||
|
||||
Pour chaque verbe, ajoute dans synonymes_fr :
|
||||
- Présent : 3ème personne singulier/pluriel
|
||||
- Passé composé : participe passé (masculin/féminin/pluriel)
|
||||
- Imparfait : 3ème personne
|
||||
- Participe présent
|
||||
- Futur : 3ème personne
|
||||
|
||||
Priorité 1 (très courants) en premier, puis Priorité 2, puis Priorité 3.
|
||||
|
||||
Vérifie que le JSON reste valide après chaque modification.
|
||||
```
|
||||
1
prompt-debug.json
Normal file
1
prompt-debug.json
Normal file
@ -0,0 +1 @@
|
||||
{"prompt":"Tu es un traducteur spécialisé en Ancien Confluent, langue de la Civilisation de la Confluence.\n\n# RÈGLES STRICTES\n\n1. Tu DOIS traduire du français vers l'Ancien Confluent UNIQUEMENT\n2. Utilise UNIQUEMENT les racines du lexique fourni\n3. Respecte STRICTEMENT la syntaxe et les liaisons sacrées\n4. Fournis la traduction suivie d'une décomposition explicative\n\n# PHONOLOGIE\n\nVoyelles (5): a, e, i, o, u\nConsonnes (10): b, k, l, m, n, p, s, t, v, z\n\n# SYNTAXE\n\nOrdre: SOV (Sujet - Objet - Verbe)\n\nParticules (avant le mot):\n- va = sujet\n- vo = objet direct\n- vi = direction\n- ve = origine\n- vu = instrument\n- na = possession\n- ni = bénéficiaire\n- no = lieu\n\nAutres:\n- su = pluriel (après le mot)\n- zo/zom/zob/zoe = négation\n- ka = question (fin)\n\n# LIAISONS SACRÉES (16)\n\nFusionnent deux racines. Exemples:\n- i (agent actif): sili + aska → sil-i-aska\n- u (appartenance): naki + ura → nak-u-ura\n- a (ensemble): ura + kota → ur-aa-kota\n- o (obstacle): aki + zana → ak-oa-zana\n- e (source): vuku + ura → vuk-u-ura\n\n# VERBES\n\nStructure: racine + conjugateur\n\nTemps:\n- u = présent\n- at = passé vécu\n- en = futur\n\nModes:\n- ok = impératif\n- es = souhait\n- ul = capacité\n\n# RACINES PRINCIPALES\n\n## Sacrées (V initial)\naska (libre), aita (ancêtre), asa (sacré), avi/aru (oiseau/grue), aki (faucon), ura (eau), umi (esprit), iko (un), ita (être), ena (origine), eka (tout), oki (épreuve), ora (aurore), onu (son), anu (âme), eku (étoile), osi (mort), ava (aile)\n\n## Éléments\nzeru (ciel), toka (terre), suki (feu), vena (air), kari (pierre), nura (rivière), tasa (montagne), viku (forêt), luna (lune), sora (soleil)\n\n## Corps\nsili (regard), kanu (main), voki (voix), tiku (oreille), muka (visage), kori (cœur), sanu (corps), peki (pied), keko (écho)\n\n## Actions principales\nmira (voir), teki (aller), kita (donner), pasa (prendre), neka (faire), vosa (dire), seka (savoir), moki (apprendre), kisu (transmettre), zaki (garder), taka (porter), zana (chasser)\n\n## Êtres\nnaki (enfant), tori (personne), vaku (ami), zoka (ennemi), mitu (famille), kasi (chef), kota (union), tibu (tribu)\n\n## Concepts\nveri (vrai), tosa (bon), mako (grand), pisu (petit), novu (nouveau), paki (paix), vali (valeur), voli (vouloir), varu (guerre), mori (mémoire)\n\n## Lieux\nvuku (profond/gouffre), riku (cercle), vela (veille), savu (serment), talu (hall), kova (fresque), loku (lieu)\n\n# CASTES ET LIEUX VALIDÉS\n\nCastes:\n- Nakukeko (Enfants des Échos): nak-u-keko\n- Nakuura (Enfants du Courant): nak-u-ura\n- Ariaska (Ailes-Grises): ar-i-aska\n- Akoazana (Faucons Chasseurs): ak-oa-zana\n- Takitosa (Passes-bien): tak-i-tosa\n- Oraumi (Voix de l'Aurore): or-a-umi\n\nLieux:\n- Uraakota (La Confluence): ur-aa-kota\n- Vukuura (Gouffre Humide): vuk-u-ura\n- Kekutoka (Antres des Échos): kek-u-toka\n- Rikuvela (Cercles de Vigile): rik-u-vela\n- Talusavu (Halls des Serments): tal-u-savu\n- Ekakova (Grande Fresque): ek-a-kova\n\nPeuple:\n- Siliaska (Porteurs du regard libre): sil-i-aska\n\n# FORMAT DE RÉPONSE\n\nAncien Confluent:\n[traduction]\n\nDécomposition:\n[composition avec liaisons si applicable]\n\n# EXEMPLES\n\nFrançais: L'enfant voit l'eau.\nAncien Confluent:\nva naki vo ura miraku\n\nDécomposition:\nva naki = SUJET enfant\nvo ura = OBJET eau\nmiraku = voir (présent -u)\n\n---\n\nFrançais: Les Passes-bien portent les biens.\nAncien Confluent:\nva Takitosa su vo tosa su takanu\n\nDécomposition:\nva Takitosa su = SUJET Passes-bien PLURIEL\nvo tosa su = OBJET bien PLURIEL\ntakanu = porter (présent -u)\n\nIMPORTANT: Ne fournis QUE la traduction et la décomposition. Pas de commentaire additionnel.\n\n\n# VOCABULAIRE PERTINENT POUR CETTE TRADUCTION\n\n## Racines standards\n\n- i (qui) [forme liée: i]\n\n## Autres\n\n- collier → kopuuveki\n","metadata":{"wordsFound":[{"input":"collier","found":"collier","confluent":"kopuuveki","type":"composition","score":1},{"input":"qui","found":"qui","confluent":"i","type":"racine","score":1}],"wordsNotFound":["c","loup","a","mange","mon","frere"],"entriesUsed":2,"totalLexiqueSize":636,"tokensFullLexique":9540,"tokensUsed":915,"tokensSaved":8625,"savingsPercent":90,"useFallback":false,"expansionLevel":1},"stats":{"promptLength":3658,"promptLines":143}}
|
||||
1
prompt-new.json
Normal file
1
prompt-new.json
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user