Improve AI text generation parsing for multiple variations

Refactor `parseGeneratedText` to handle various AI response formats and improve variant extraction logic.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/sEXz3DF
This commit is contained in:
michaelschal committed 2025-10-04 12:53:54 +00:00
1 parent a45b0989f8
commit d57bc0fb81
2 files changed
+99 -51

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

+99 -51
View File
@@ -96,64 +96,112 @@ VERSION 3 - ÉMOTIONNELLE:
} }
private parseGeneratedText(content: string): GeneratedText[] { private parseGeneratedText(content: string): GeneratedText[] {
// Normaliser les retours à la ligne
const normalizedContent = content.replace(/\r\n/g, '\n').trim();
console.log('🔍 Parsing AI response (length:', normalizedContent.length, ')');
// Stratégie 1: Détection des headers VERSION avec parsing intelligent
const variants = this.tryMultipleParsingStrategies(normalizedContent);
if (variants.length > 0) {
console.log('✅ Parsed successfully:', variants.length, 'variants');
return variants;
}
// Fallback: retourner le texte complet
console.log('⚠️ Parsing failed, using fallback');
return [{
variant: "Généré par IA",
text: normalizedContent,
characterCount: normalizedContent.length
}];
}
private tryMultipleParsingStrategies(content: string): GeneratedText[] {
// Stratégie 1: Split par headers de VERSION (le plus flexible)
const strategy1 = this.parseByVersionHeaders(content);
if (strategy1.length >= 3) return strategy1;
// Stratégie 2: Regex avec markdown **VERSION N:**
const strategy2 = this.parseWithMarkdownHeaders(content);
if (strategy2.length >= 3) return strategy2;
// Stratégie 3: Regex simple sans markdown
const strategy3 = this.parseWithSimpleHeaders(content);
if (strategy3.length >= 3) return strategy3;
// Retourner le meilleur résultat obtenu
return strategy1.length > 0 ? strategy1 : (strategy2.length > 0 ? strategy2 : strategy3);
}
private parseByVersionHeaders(content: string): GeneratedText[] {
const variants: GeneratedText[] = []; const variants: GeneratedText[] = [];
// Normaliser les retours à la ligne (CRLF -> LF) // Chercher tous les patterns VERSION N (très flexible)
const normalizedContent = content.replace(/\r\n/g, '\n'); const versionPattern = /(?:\*{2})?VERSION\s+(\d+)\s*[-–—]\s*([A-ZÀÂÄÉÈÊËÏÎÔÙÛÜ]+)(?:\*{2})?:?/gi;
const matches = Array.from(content.matchAll(versionPattern));
console.log('🔍 AI Response to parse (first 800 chars):\n', normalizedContent.substring(0, 800)); if (matches.length < 3) return variants;
console.log('🔍 AI Response length:', normalizedContent.length);
// Regex ultra-flexibles acceptant: // Extraire le texte entre chaque header
// - markdown (** optionnel) for (let i = 0; i < matches.length; i++) {
// - tirets variés (-, –, —) const match = matches[i];
// - espaces variables const versionNum = match[1];
// - deux-points optionnel const style = match[2];
// - séparateurs (---, ***, etc.) const startPos = match.index! + match[0].length;
const version1Match = normalizedContent.match(/\*{0,2}\s*VERSION\s+1\s*[-–—]\s*DYNAMIQUE\s*\*{0,2}:?\s*[\r\n]+([\s\S]*?)(?=\s*[-*]{3,}\s*[\r\n]+|\*{0,2}\s*VERSION\s+2|$)/i); const endPos = i < matches.length - 1 ? matches[i + 1].index! : content.length;
const version2Match = normalizedContent.match(/\*{0,2}\s*VERSION\s+2\s*[-–—]\s*INFORMATIVE?\s*\*{0,2}:?\s*[\r\n]+([\s\S]*?)(?=\s*[-*]{3,}\s*[\r\n]+|\*{0,2}\s*VERSION\s+3|$)/i);
const version3Match = normalizedContent.match(/\*{0,2}\s*VERSION\s+3\s*[-–—]\s*[ÉE]MOTIONNELLE?\s*\*{0,2}:?\s*[\r\n]+([\s\S]*?)$/i); let text = content.substring(startPos, endPos).trim();
// Nettoyer le texte (enlever les séparateurs, notes entre parenthèses au début, etc.)
text = text.replace(/^[-*]{3,}\s*/gm, ''); // Enlever les séparateurs
text = text.replace(/^\([^)]+\)\s*/gm, ''); // Enlever les notes entre parenthèses
text = text.trim();
if (text.length > 0) {
variants.push({
variant: `Version ${versionNum} - ${this.capitalizeFirst(style.toLowerCase())}`,
text,
characterCount: text.length
});
}
}
console.log('🔍 Matches found:', { v1: !!version1Match, v2: !!version2Match, v3: !!version3Match });
if (version1Match) {
const text = version1Match[1].trim();
variants.push({
variant: "Version 1 - Dynamique",
text,
characterCount: text.length
});
}
if (version2Match) {
const text = version2Match[1].trim();
variants.push({
variant: "Version 2 - Informative",
text,
characterCount: text.length
});
}
if (version3Match) {
const text = version3Match[1].trim();
variants.push({
variant: "Version 3 - Émotionnelle",
text,
characterCount: text.length
});
}
// Fallback if parsing fails
if (variants.length === 0) {
variants.push({
variant: "Généré par IA",
text: content.trim(),
characterCount: content.trim().length
});
}
return variants; return variants;
} }
private parseWithMarkdownHeaders(content: string): GeneratedText[] {
const variants: GeneratedText[] = [];
const v1 = content.match(/\*{2}VERSION\s+1\s*[-–—]\s*DYNAMIQUE:?\*{2}\s*\n([\s\S]*?)(?=\*{2}VERSION\s+2|$)/i);
const v2 = content.match(/\*{2}VERSION\s+2\s*[-–—]\s*INFORMATIVE?:?\*{2}\s*\n([\s\S]*?)(?=\*{2}VERSION\s+3|$)/i);
const v3 = content.match(/\*{2}VERSION\s+3\s*[-–—]\s*[ÉE]MOTIONNELLE?:?\*{2}\s*\n([\s\S]*?)$/i);
if (v1) variants.push({ variant: "Version 1 - Dynamique", text: v1[1].trim(), characterCount: v1[1].trim().length });
if (v2) variants.push({ variant: "Version 2 - Informative", text: v2[1].trim(), characterCount: v2[1].trim().length });
if (v3) variants.push({ variant: "Version 3 - Émotionnelle", text: v3[1].trim(), characterCount: v3[1].trim().length });
return variants;
}
private parseWithSimpleHeaders(content: string): GeneratedText[] {
const variants: GeneratedText[] = [];
const v1 = content.match(/VERSION\s+1\s*[-–—]\s*DYNAMIQUE:?\s*\n([\s\S]*?)(?=VERSION\s+2|$)/i);
const v2 = content.match(/VERSION\s+2\s*[-–—]\s*INFORMATIVE?:?\s*\n([\s\S]*?)(?=VERSION\s+3|$)/i);
const v3 = content.match(/VERSION\s+3\s*[-–—]\s*[ÉE]MOTIONNELLE?:?\s*\n([\s\S]*?)$/i);
if (v1) variants.push({ variant: "Version 1 - Dynamique", text: v1[1].trim(), characterCount: v1[1].trim().length });
if (v2) variants.push({ variant: "Version 2 - Informative", text: v2[1].trim(), characterCount: v2[1].trim().length });
if (v3) variants.push({ variant: "Version 3 - Émotionnelle", text: v3[1].trim(), characterCount: v3[1].trim().length });
return variants;
}
private capitalizeFirst(text: string): string {
return text.charAt(0).toUpperCase() + text.slice(1).toLowerCase();
}
} }
export const openRouterService = new OpenRouterService(); export const openRouterService = new OpenRouterService();