@zodic/shared 0.0.230 → 0.0.231
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/services/ConceptService.ts +40 -67
- package/package.json +1 -1
|
@@ -551,22 +551,11 @@ export class ConceptService {
|
|
|
551
551
|
structuredContentEN: StructuredConceptContent;
|
|
552
552
|
structuredContentPT: StructuredConceptContent;
|
|
553
553
|
} {
|
|
554
|
-
console.log(
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
let cleanedResponse = response
|
|
560
|
-
.replace(/[*#•]/g, '') // Remove bullet points, bold markers, headings
|
|
561
|
-
.replace(/---+/g, '') // Remove dividers (like "---")
|
|
562
|
-
.replace(/\n\s*\n/g, '\n\n') // Normalize multiple line breaks
|
|
563
|
-
.trim();
|
|
564
|
-
|
|
565
|
-
console.log(
|
|
566
|
-
'🔹 [CLEANED RESPONSE]:',
|
|
567
|
-
cleanedResponse.slice(0, 500) + '...'
|
|
568
|
-
);
|
|
569
|
-
|
|
554
|
+
console.log(`📌 [START] Parsing structured content for ${conceptSlug} from ChatGPT response.`);
|
|
555
|
+
|
|
556
|
+
// ✅ Step 1: Log the entire raw response before processing
|
|
557
|
+
console.log('🔹 [RAW RESPONSE]:', response);
|
|
558
|
+
|
|
570
559
|
// ✅ Step 2: Define Section Titles Per Concept
|
|
571
560
|
const conceptSections: Record<string, { en: string[]; pt: string[] }> = {
|
|
572
561
|
crown: {
|
|
@@ -666,83 +655,67 @@ export class ConceptService {
|
|
|
666
655
|
],
|
|
667
656
|
},
|
|
668
657
|
};
|
|
669
|
-
|
|
658
|
+
|
|
670
659
|
const sectionsEN = conceptSections[conceptSlug]?.en;
|
|
671
660
|
const sectionsPT = conceptSections[conceptSlug]?.pt;
|
|
672
|
-
|
|
661
|
+
|
|
673
662
|
if (!sectionsEN || !sectionsPT) {
|
|
674
663
|
throw new Error(`❌ Unknown concept: ${conceptSlug}`);
|
|
675
664
|
}
|
|
676
|
-
|
|
665
|
+
|
|
677
666
|
// ✅ Step 3: Extract English and Portuguese content separately
|
|
678
|
-
const enMatches =
|
|
679
|
-
const ptMatches =
|
|
680
|
-
|
|
667
|
+
const enMatches = response.match(/EN:\s*([\s\S]+?)\s*PT:/);
|
|
668
|
+
const ptMatches = response.match(/PT:\s*([\s\S]+)/);
|
|
669
|
+
|
|
681
670
|
if (!enMatches || !ptMatches) {
|
|
682
|
-
console.error(
|
|
683
|
-
'❌ [ERROR] Missing English or Portuguese content in response.'
|
|
684
|
-
);
|
|
671
|
+
console.error('❌ [ERROR] Missing English or Portuguese content in response.');
|
|
685
672
|
throw new Error('❌ Missing English or Portuguese content in response.');
|
|
686
673
|
}
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
console.log(
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
'
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
// ✅ Step 4: Extract structured sections
|
|
674
|
+
|
|
675
|
+
let enContent = enMatches[1].trim();
|
|
676
|
+
let ptContent = ptMatches[1].trim();
|
|
677
|
+
|
|
678
|
+
console.log('✅ [MATCH SUCCESS] Extracted English Content:', enContent.slice(0, 500) + '...');
|
|
679
|
+
console.log('✅ [MATCH SUCCESS] Extracted Portuguese Content:', ptContent.slice(0, 500) + '...');
|
|
680
|
+
|
|
681
|
+
// ✅ Step 4: Debug **why** PT content has "EN:"
|
|
682
|
+
if (ptContent.includes('EN:')) {
|
|
683
|
+
console.warn('⚠️ PT content contains "EN:". Check if parsing was incorrect.');
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// ✅ Step 5: Extract structured sections
|
|
701
687
|
function extractSections(text: string, sectionTitles: string[]) {
|
|
702
688
|
return sectionTitles.map((title) => {
|
|
703
689
|
console.log(`🔍 [PROCESSING] Extracting section: "${title}"`);
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
const regex = new RegExp(
|
|
707
|
-
`\\d+\\.\\s*${title}:\\s*([\\s\\S]+?)(?=\\n\\d+\\.\\s*[A-Z]|$)`
|
|
708
|
-
);
|
|
690
|
+
|
|
691
|
+
const regex = new RegExp(`\\d+\\.\\s*${title}:\\s*([\\s\\S]+?)(?=\\n\\d+\\.\\s*[A-Z]|$)`);
|
|
709
692
|
const match = text.match(regex);
|
|
710
|
-
|
|
693
|
+
|
|
711
694
|
if (!match) {
|
|
712
695
|
console.warn(`⚠️ [WARNING] Missing section: "${title}"`);
|
|
713
696
|
return { type: 'section', title, content: ['❌ Section Missing'] };
|
|
714
697
|
}
|
|
715
|
-
|
|
716
|
-
// ✅ Split content into paragraphs and clean them
|
|
698
|
+
|
|
717
699
|
const paragraphs = match[1]
|
|
718
700
|
.trim()
|
|
719
|
-
.split(/\n{2,}/)
|
|
701
|
+
.split(/\n{2,}/)
|
|
720
702
|
.map((p) => p.trim())
|
|
721
|
-
.filter((p) => p.length > 0);
|
|
722
|
-
|
|
703
|
+
.filter((p) => p.length > 0);
|
|
704
|
+
|
|
723
705
|
console.log(`✅ [EXTRACTED] "${title}" - Parsed Content:`, paragraphs);
|
|
724
|
-
|
|
706
|
+
|
|
725
707
|
return { type: 'section', title, content: paragraphs };
|
|
726
708
|
});
|
|
727
709
|
}
|
|
728
|
-
|
|
729
|
-
// ✅ Return parsed and cleaned structured content
|
|
710
|
+
|
|
730
711
|
const structuredContentEN = extractSections(enContent, sectionsEN);
|
|
731
712
|
const structuredContentPT = extractSections(ptContent, sectionsPT);
|
|
732
|
-
|
|
733
|
-
console.log(
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
);
|
|
737
|
-
|
|
738
|
-
'🎯 [FINAL RESULT] Parsed Portuguese Content:',
|
|
739
|
-
JSON.stringify(structuredContentPT, null, 2)
|
|
740
|
-
);
|
|
741
|
-
|
|
742
|
-
console.log(
|
|
743
|
-
'✅ [COMPLETE] Structured content parsing finished successfully.'
|
|
744
|
-
);
|
|
745
|
-
|
|
713
|
+
|
|
714
|
+
console.log('🎯 [FINAL RESULT] Parsed English Content:', JSON.stringify(structuredContentEN, null, 2));
|
|
715
|
+
console.log('🎯 [FINAL RESULT] Parsed Portuguese Content:', JSON.stringify(structuredContentPT, null, 2));
|
|
716
|
+
|
|
717
|
+
console.log('✅ [COMPLETE] Structured content parsing finished successfully.');
|
|
718
|
+
|
|
746
719
|
return {
|
|
747
720
|
structuredContentEN,
|
|
748
721
|
structuredContentPT,
|