diff --git a/roadmap.md b/roadmap.md index c76437a..b5fa243 100644 --- a/roadmap.md +++ b/roadmap.md @@ -227,7 +227,18 @@ **Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos** y **Landing Pages de Cursos (Marketing) automatizadas**. +## Fase 20: IA Generativa Avanzada (En Diseño) 🧠 +- [ ] **Generación de Juegos de Memoria Conceptuales**: Creación automática de parejas (concepto/definición) a partir de transcripciones. +- [ ] **Simulaciones de Rol y Diálogos Ramificados**: Motor de escenarios interactivos con respuestas dinámicas de la IA. +- [ ] **Auto-Hotspots Pedagógicos**: Identificación automática de puntos de interés en imágenes con descripciones técnicas. +- [ ] **Diagramas de Mermaid Dinámicos**: Visualización automática de procesos y mapas mentales a partir del contenido de la lección. +- [ ] **Laboratorios de Código con Hints de IA**: Generación de desafíos de programación con pistas contextuales basadas en errores. + +--- + +**Estado Actual**: La plataforma cuenta con un motor de IA avanzado, gestión multi-tenant completa, tutoría inteligente con memoria histórica, una **interfaz 100% responsiva**, flujos de autenticación diferenciados, **sistema de foros de discusión funcional**, **gestión de anuncios segmentados**, **monetización integrada con Mercado Pago**, **Inscripción Masiva de Usuarios**, **Exportación Avanzada de Calificaciones**, **Librerías de Contenido reutilizables**, **Sistema de Rúbricas Avanzado**, **Secuencias de Aprendizaje**, **Gestión de Equipos Docentes**, **Vista Previa de Cursos**, **Dashboard de Progreso Estudiantil**, **Sistema de Marcadores**, **Biblioteca Global de Activos**, **Interoperabilidad LTI 1.3**, **Analíticas Predictivas**, **Integración de Jitsi**, **Portafolios con Perfiles Públicos** y **Landing Pages de Cursos (Marketing) automatizadas**. + **Próximas Prioridades**: -1. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1. -2. **Integraciones Empresariales**: Conectividad con HRIS y ERPs externos. -3. **IA Generativa Avanzada**: Generación automática de contenido interactivo adicional. +1. **Conceptual Memory Match (IA)**: Implementar el primer generador de actividades interactivas. +2. **Accesibilidad Universal**: Auditoría y ajustes de contraste para cumplimiento WCAG 2.1. +3. **Integraciones Empresariales**: Conectividad con HRIS y ERPs externos. diff --git a/services/cms-service/src/handlers.rs b/services/cms-service/src/handlers.rs index f4480b8..90dbf18 100644 --- a/services/cms-service/src/handlers.rs +++ b/services/cms-service/src/handlers.rs @@ -1204,7 +1204,15 @@ pub async fn generate_quiz( ) }; - let mut system_prompt = "You are an expert English Teacher. Generate 3 questions based on the lesson content to test the student's understanding of English grammar, vocabulary, or comprehension. Instructions can be in Spanish or English. Return ONLY a JSON object with a field 'blocks' which is an array of content blocks. Each block in the array must follow this exact structure: { \"id\": \"string-uuid\", \"type\": \"quiz\", \"title\": \"Quiz: Concept Check\", \"quiz_data\": { \"questions\": [ { \"id\": \"q-string\", \"type\": \"multiple-choice\", \"question\": \"String\", \"options\": [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\"], \"correct\": [0], \"explanation\": \"Explain why the answer is correct.\" } ] } }. Important: 'correct' MUST be an array of integers.".to_string(); + let mut system_prompt = if let Some(qtype) = &quiz_req.quiz_type { + if qtype == "memory-match" { + "You are an expert English Teacher. Generate a Memory Match game (Memory match concepts) based on the lesson content. Extract 6 important concepts or vocabulary terms and their corresponding definitions or translations. Return ONLY a JSON object with a field 'blocks' which is an array. The array must contain ONE block with this structure: { \"id\": \"string-uuid\", \"type\": \"memory-match\", \"title\": \"Memory Match: Concept Review\", \"pairs\": [ { \"id\": \"1\", \"left\": \"Concept 1\", \"right\": \"Definition/Match 1\" }, { \"id\": \"2\", \"left\": \"Concept 2\", \"right\": \"Definition/Match 2\" } ] }. Provide 6 pairs in total.".to_string() + } else { + "You are an expert English Teacher. Generate 3 questions based on the lesson content to test the student's understanding of English grammar, vocabulary, or comprehension. Instructions can be in Spanish or English. Return ONLY a JSON object with a field 'blocks' which is an array of content blocks. Each block in the array must follow this exact structure: { \"id\": \"string-uuid\", \"type\": \"quiz\", \"title\": \"Quiz: Concept Check\", \"quiz_data\": { \"questions\": [ { \"id\": \"q-string\", \"type\": \"multiple-choice\", \"question\": \"String\", \"options\": [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\"], \"correct\": [0], \"explanation\": \"Explain why the answer is correct.\" } ] } }. Important: 'correct' MUST be an array of integers.".to_string() + } + } else { + "You are an expert English Teacher. Generate 3 questions based on the lesson content to test the student's understanding of English grammar, vocabulary, or comprehension. Instructions can be in Spanish or English. Return ONLY a JSON object with a field 'blocks' which is an array of content blocks. Each block in the array must follow this exact structure: { \"id\": \"string-uuid\", \"type\": \"quiz\", \"title\": \"Quiz: Concept Check\", \"quiz_data\": { \"questions\": [ { \"id\": \"q-string\", \"type\": \"multiple-choice\", \"question\": \"String\", \"options\": [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\"], \"correct\": [0], \"explanation\": \"Explain why the answer is correct.\" } ] } }. Important: 'correct' MUST be an array of integers.".to_string() + }; if let Some(ctx) = &quiz_req.context { if !ctx.is_empty() { @@ -1213,7 +1221,7 @@ pub async fn generate_quiz( } if let Some(qtype) = &quiz_req.quiz_type { - if !qtype.is_empty() { + if !qtype.is_empty() && qtype != "memory-match" { system_prompt.push_str(&format!(" Question Type to use: {}. If the type is 'multiple-choice', follow the structure above. If it's something else, adapt the block 'type' (e.g., 'true-false') accordingly, but keep it within the 'blocks' array.", qtype)); } } diff --git a/web/studio/src/app/courses/[id]/lessons/[lessonId]/page.tsx b/web/studio/src/app/courses/[id]/lessons/[lessonId]/page.tsx index 8ad82d5..0c5b917 100644 --- a/web/studio/src/app/courses/[id]/lessons/[lessonId]/page.tsx +++ b/web/studio/src/app/courses/[id]/lessons/[lessonId]/page.tsx @@ -21,8 +21,7 @@ import { Brain, Library, BookMarked, - ArrowLeft, - ImageIcon + ArrowLeft } from 'lucide-react'; import DescriptionBlock from "@/components/blocks/DescriptionBlock"; import MediaBlock from "@/components/blocks/MediaBlock"; @@ -80,42 +79,10 @@ export default function LessonEditor({ params }: { params: { id: string; lessonI const [isAIQuizModalOpen, setIsAIQuizModalOpen] = useState(false); const [aiQuizContext, setAiQuizContext] = useState(""); const [aiQuizType, setAiQuizType] = useState("multiple-choice"); - const [aiImagePrompt, setAiImagePrompt] = useState(""); - const [isGeneratingImage, setIsGeneratingImage] = useState(false); const [editValue, setEditValue] = useState(""); - // Polling for AI status - useEffect(() => { - let interval: NodeJS.Timeout; - - if (lesson && ( - lesson.video_generation_status === 'queued' || - lesson.video_generation_status === 'processing' - )) { - interval = setInterval(async () => { - try { - const updated = await cmsApi.getLesson(params.lessonId); - setLesson(updated); - - // If it finished, update local states - if (updated.transcription_status === 'completed') { - if (updated.transcription) { - // Automatically update summary if available? No, wait for manual trigger or auto-trigger? - // For now just update lesson - } - } - } catch (err) { - console.error("Polling failed", err); - } - }, 3000); - } - - return () => { - if (interval) clearInterval(interval); - }; - }, [lesson, lesson?.transcription_status, params.lessonId]); useEffect(() => { @@ -369,31 +336,6 @@ export default function LessonEditor({ params }: { params: { id: string; lessonI } }; - const handleGenerateImage = async () => { - if (!lesson) return; - setIsGeneratingImage(true); - try { - // Option 2: Use lesson content (blocks) as script if no prompt - const scriptFromBlocks = blocks - .map(b => b.content || b.description || b.title || "") - .filter(txt => txt.trim().length > 0) - .join(". "); - - // Option 3: Prioritize manual prompt, then script - const finalPrompt = aiImagePrompt.trim() || scriptFromBlocks; - - const updated = await cmsApi.generateImage(lesson.id, { - prompt: finalPrompt - }); - setLesson(updated); - setAiImagePrompt(""); - alert("Generación de imagen iniciada con el prompt/guion detectado."); - } catch (err: any) { - alert(err.message || "Failed to initiate image generation."); - } finally { - setIsGeneratingImage(false); - } - }; if (loading) return