evolutia 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl

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.
evolutia/__init__.py CHANGED
@@ -2,4 +2,4 @@ from .evolutia_engine import EvolutiaEngine
2
2
  from .variation_generator import VariationGenerator
3
3
  from .llm_providers import LLMProvider, get_provider
4
4
 
5
- __version__ = "0.1.0"
5
+ __version__ = "0.1.1"
@@ -51,12 +51,14 @@ class ConfigManager:
51
51
  if root_config.exists():
52
52
  self.config_path = root_config
53
53
  else:
54
- # Default interno: evolutia/config/config.yaml
55
- # self.base_path suele ser root
56
- # Si base_path es root, la config está en root/evolutia/config/config.yaml
57
- self.config_path = self.base_path / 'evolutia' / 'config' / 'config.yaml'
54
+ # Default interno: ubicado en el paquete instalado
55
+ # Obtenemos la ruta de este archivo (config_manager.py) -> parent (evolutia/) -> config -> config.yaml
56
+ self.config_path = Path(__file__).parent / 'config' / 'config.yaml'
58
57
 
59
- logger.info(f"Usando archivo de configuración: {self.config_path}")
58
+ if self.config_path.exists():
59
+ logger.info(f"Usando archivo de configuración: {self.config_path}")
60
+ else:
61
+ logger.info(f"Archivo de configuración no encontrado en {self.config_path}. Usando configuración por defecto.")
60
62
 
61
63
  def validate_config(self, config_data: Dict[str, Any]) -> bool:
62
64
  """Valida la configuración contra el esquema JSON."""
@@ -187,6 +189,10 @@ class ConfigManager:
187
189
 
188
190
  logger.info(f"Configuración actualizada en {self.config_path}")
189
191
 
192
+ def update_config_from_structure(self):
193
+ """Alias para update_config, usado por compatibilidad."""
194
+ return self.update_config()
195
+
190
196
  def main():
191
197
  import argparse
192
198
  parser = argparse.ArgumentParser(description='Gestor de configuración automática de Evolutia')
evolutia/llm_providers.py CHANGED
@@ -13,6 +13,8 @@ class LLMProvider(ABC):
13
13
 
14
14
  def __init__(self, model_name: Optional[str] = None):
15
15
  self.model_name = model_name
16
+ self.client = None
17
+ self.genai = None # For Gemini
16
18
  self.api_key = self._get_api_key()
17
19
  if self.api_key:
18
20
  self._setup_client()
@@ -58,7 +58,201 @@ class VariationGenerator:
58
58
  return None
59
59
 
60
60
  return self._provider_instance
61
-
61
+
62
+ def _create_prompt(self, exercise: Dict, analysis: Dict) -> str:
63
+ """Crea el prompt para generar una variación."""
64
+
65
+ content = exercise.get('content', '')
66
+ complexity = analysis.get('total_complexity', 0)
67
+ concepts = ", ".join(analysis.get('concepts', []))
68
+
69
+ prompt = f"""Actúa como un profesor experto de física y matemáticas universitarias.
70
+ Tu tarea es crear una VARIACIÓN de un ejercicio existente.
71
+
72
+ EJERCICIO ORIGINAL:
73
+ {content}
74
+
75
+ ANÁLISIS DE COMPLEJIDAD ORIGINAL:
76
+ - Complejidad: {complexity:.2f}
77
+ - Conceptos: {concepts}
78
+
79
+ OBJETIVO:
80
+ Generar una nueva versión del ejercicio que sea MÁS COMPLEJA y DESAFIANTE, pero evaluando los mismos principios fundamentales.
81
+
82
+ ESTRATEGIAS PARA AUMENTAR COMPLEJIDAD:
83
+ 1. Cambia las variables numéricas por parámetros simbólicos (a, b, R, etc.)
84
+ 2. Introduce sistemas de coordenadas diferentes (cilíndricas/esféricas) si aplica
85
+ 3. Combina múltiples conceptos en un solo problema
86
+ 4. Agrega una restricción o condición de borde adicional
87
+ 5. Pide una generalización del resultado
88
+
89
+ REGLAS DE FORMATO:
90
+ 1. Usa Markdown estándar
91
+ 2. Usa LaTeX para matemáticas (bloques :::math o $$...$$)
92
+ 3. La salida debe contener DOS PARTES separadas por "SOLUCIÓN REQUERIDA:"
93
+ - Parte 1: El enunciado del nuevo ejercicio (encabezado con "EJERCICIO VARIADO:")
94
+ - Parte 2: La solución paso a paso
95
+
96
+ Genera solo el contenido solicitado."""
97
+ return prompt
98
+
99
+ def _create_quiz_prompt(self, context_info: Dict) -> str:
100
+ """Crea prompt para ejercicios de selección única."""
101
+ content = context_info.get('content', '')
102
+
103
+ prompt = f"""Actúa como un profesor experto. Genera una pregunta de examen de tipo SELECCIÓN ÚNICA (Quiz) basada en el siguiente material:
104
+
105
+ MATERIAL BASE:
106
+ {content}
107
+
108
+ REQUISITOS:
109
+ 1. La pregunta debe ser conceptual y desafiante.
110
+ 2. Genera 4 opciones (A, B, C, D).
111
+ 3. Solo una opción debe ser correcta, las otras deben ser distractores plausibles.
112
+ 4. Devuelve la respuesta EXCLUSIVAMENTE en formato JSON válido:
113
+ {{
114
+ "question": "Enunciado de la pregunta en Markdown...",
115
+ "options": {{
116
+ "A": "Texto opción A",
117
+ "B": "Texto opción B",
118
+ "C": "Texto opción C",
119
+ "D": "Texto opción D"
120
+ }},
121
+ "correct_option": "A",
122
+ "explanation": "Explicación detallada de por qué es la correcta..."
123
+ }}
124
+ """
125
+ return prompt
126
+
127
+ def generate_variation(self, exercise: Dict, analysis: Dict, exercise_type: str = "development") -> Optional[Dict]:
128
+ """
129
+ Genera una variación de un ejercicio existente.
130
+ """
131
+ # 1. Crear prompt según tipo
132
+ if exercise_type == 'multiple_choice':
133
+ context_info = {
134
+ 'content': f"Ejercicio Original:\n{exercise.get('content')}"
135
+ }
136
+ prompt = self._create_quiz_prompt(context_info)
137
+ else:
138
+ prompt = self._create_prompt(exercise, analysis)
139
+
140
+ # 2. Get Provider
141
+ provider = self._get_provider()
142
+ if not provider: return None
143
+
144
+ # 3. Generar
145
+ content = provider.generate_content(prompt, system_prompt="Eres un experto en diseño de exámenes de ingeniería.")
146
+
147
+ if not content:
148
+ return None
149
+
150
+ # 4. Parsear respuesta
151
+ variation_content = ""
152
+ variation_solution = ""
153
+
154
+ if exercise_type == 'multiple_choice':
155
+ data = extract_and_parse_json(content)
156
+ if data and 'question' in data:
157
+ variation_content = f"{data['question']}\n\n"
158
+ for opt, text in data.get('options', {}).items():
159
+ variation_content += f"- **{opt})** {text}\n"
160
+ variation_solution = f"**Respuesta Correcta: {data.get('correct_option', '?')}**\n\n{data.get('explanation', '')}"
161
+ else:
162
+ variation_content = content
163
+ variation_solution = "Error parseando JSON de quiz."
164
+ else:
165
+ # Parseo texto plano
166
+ parts = content.split("SOLUCIÓN REQUERIDA:")
167
+ if len(parts) == 2:
168
+ variation_content = parts[0].replace("EJERCICIO VARIADO:", "").strip()
169
+ variation_solution = parts[1].strip()
170
+ else:
171
+ variation_content = content
172
+ variation_solution = ""
173
+
174
+ return {
175
+ 'variation_content': variation_content,
176
+ 'variation_solution': variation_solution,
177
+ 'original_frontmatter': exercise.get('frontmatter', {}),
178
+ 'original_label': exercise.get('label'),
179
+ 'type': exercise_type
180
+ }
181
+
182
+ def _create_new_exercise_prompt(self, topic: str, tags: list, context: Dict, difficulty: str) -> str:
183
+ """Crea prompt para ejercicio nuevo desde cero."""
184
+ tags_str = ", ".join(tags)
185
+
186
+ prompt = f"""Diseña un NUEVO ejercicio de examen universitario para:
187
+ Asignatura/Tema: {topic}
188
+ Conceptos Clave (Tags): {tags_str}
189
+ Nivel de Dificultad: {difficulty.upper()} (donde ALTA implica demostraciones o conexiones no triviales).
190
+
191
+ INSTRUCCIONES:
192
+ 1. Crea un problema original que evalúe comprensión profunda.
193
+ 2. No copies ejercicios de libros de texto.
194
+ 3. Formato de salida:
195
+ EJERCICIO NUEVO:
196
+ [Enunciado en Markdown con LaTeX]
197
+
198
+ SOLUCIÓN REQUERIDA:
199
+ [Solución paso a paso]
200
+ """
201
+ return prompt
202
+
203
+ def generate_new_exercise_from_topic(self, topic: str, tags: list = None, difficulty: str = "alta", exercise_type: str = "development") -> Optional[Dict]:
204
+ """
205
+ Genera un ejercicio nuevo desde cero.
206
+ """
207
+ tags = tags or []
208
+ context = {} # Base implementations doesn't use context
209
+
210
+ # 1. Crear prompt
211
+ if exercise_type == 'multiple_choice':
212
+ context_info = {
213
+ 'content': f"Tema: {topic}\nTags: {', '.join(tags)}\nDificultad: {difficulty}"
214
+ }
215
+ prompt = self._create_quiz_prompt(context_info)
216
+ else:
217
+ prompt = self._create_new_exercise_prompt(topic, tags, context, difficulty)
218
+
219
+ # 2. Get Provider
220
+ provider = self._get_provider()
221
+ if not provider: return None
222
+
223
+ # 3. Generar
224
+ content = provider.generate_content(prompt)
225
+ if not content: return None
226
+
227
+ # 4. Parsear
228
+ # Reutilizamos lógica simple de parseo
229
+ if exercise_type == 'multiple_choice':
230
+ data = extract_and_parse_json(content)
231
+ if data and 'question' in data:
232
+ var_content = f"{data['question']}\n\n"
233
+ # ... (simplificado, igual que arriba)
234
+ for k, v in data.get('options',{}).items():
235
+ var_content += f"- **{k})** {v}\n"
236
+ var_sol = f"R: {data.get('correct_option')}. {data.get('explanation')}"
237
+ else:
238
+ var_content = content
239
+ var_sol = ""
240
+ else:
241
+ parts = content.split("SOLUCIÓN REQUERIDA:")
242
+ if len(parts) == 2:
243
+ var_content = parts[0].replace("EJERCICIO NUEVO:", "").strip()
244
+ var_sol = parts[1].strip()
245
+ else:
246
+ var_content = content
247
+ var_sol = ""
248
+
249
+ return {
250
+ 'variation_content': var_content,
251
+ 'variation_solution': var_sol,
252
+ 'original_frontmatter': {'topic': topic, 'tags': tags},
253
+ 'type': exercise_type
254
+ }
255
+
62
256
  def generate_variation_with_solution(self, exercise: Dict, analysis: Dict) -> Optional[Dict]:
63
257
  """
64
258
  Genera una variación con su solución.
@@ -69,23 +263,19 @@ class VariationGenerator:
69
263
  if not variation:
70
264
  return None
71
265
 
266
+ # Si ya tiene solución (porque el prompt único la pidió), retornarla
267
+ if variation.get('variation_solution'):
268
+ return variation
269
+
72
270
  provider = self._get_provider()
73
271
  if not provider: return None
74
272
 
75
- # Luego generar la solución
76
- solution_prompt = f"""Eres un experto en métodos matemáticos para física e ingeniería. Resuelve el siguiente ejercicio paso a paso, mostrando todos los cálculos y procedimientos.
77
-
273
+ # Si no, generar la solución por separado (fallback legacy)
274
+ solution_prompt = f"""Eres un experto en métodos matemáticos. Resuelve el siguiente ejercicio paso a paso:
275
+
78
276
  EJERCICIO:
79
277
  {variation['variation_content']}
80
278
 
81
- INSTRUCCIONES:
82
- 1. Resuelve el ejercicio de forma completa y detallada
83
- 2. Muestra todos los pasos intermedios
84
- 3. Usa notación matemática LaTeX correcta
85
- 4. Explica el razonamiento cuando sea necesario
86
- 5. Usa bloques :::{{math}} para ecuaciones display y $...$ para inline
87
- 6. Escribe en español
88
-
89
279
  GENERA LA SOLUCIÓN COMPLETA:"""
90
280
 
91
281
  solution_content = provider.generate_content(solution_prompt)
@@ -0,0 +1,221 @@
1
+ Metadata-Version: 2.4
2
+ Name: evolutia
3
+ Version: 0.1.1
4
+ Summary: Sistema automatizado para generar preguntas de examen desafiantes basadas en materiales didácticos existentes
5
+ Home-page: https://github.com/glacy/evolutIA
6
+ Author: Gerardo Lacy-Mora
7
+ Author-email: gerardolacymora@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: Apache Software License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: PyYAML
15
+ Requires-Dist: requests
16
+ Requires-Dist: python-dotenv
17
+ Requires-Dist: openai
18
+ Requires-Dist: anthropic
19
+ Requires-Dist: google-generativeai
20
+ Requires-Dist: tqdm
21
+ Dynamic: author
22
+ Dynamic: author-email
23
+ Dynamic: classifier
24
+ Dynamic: description
25
+ Dynamic: description-content-type
26
+ Dynamic: home-page
27
+ Dynamic: license-file
28
+ Dynamic: requires-dist
29
+ Dynamic: requires-python
30
+ Dynamic: summary
31
+
32
+ # EvolutIA: Generador de preguntas de examen
33
+
34
+ Sistema automatizado para generar preguntas de examen desafiantes basadas en materiales didácticos existentes (lecturas, prácticas, tareas). El sistema aumenta la complejidad matemática de los ejercicios mientras mantiene el formato y estructura familiar.
35
+
36
+ ## Características Principales
37
+
38
+ - **Multi-Modo**:
39
+ - **Variación**: Incrementa la complejidad de ejercicios existentes.
40
+ - **Creación**: Genera ejercicios nuevos desde cero basados en temas y tags.
41
+ - **RAG (Retrieval-Augmented Generation)**: Usa tus propios apuntes y ejercicios previos como contexto para generar contenido más alineado al curso.
42
+ - **Multi-Proveedor**: Soporte nativo para OpenAI (GPT-4), Anthropic (Claude 3), Google (Gemini 1.5) y Modelos Locales (via Ollama/LM Studio).
43
+ - **Análisis de Complejidad**: Valida automáticamente que las nuevas preguntas sean matemáticamente más exigentes.
44
+ - **Formato MyST**: Salida compatible con Curvenote y Jupyter Book.
45
+
46
+ ---
47
+
48
+ ## Instalación
49
+
50
+ ### Requisitos Previos
51
+ - Python 3.8 o superior
52
+ - API Key de tu proveedor preferido (OpenAI, Anthropic, Google) o un servidor local (Ollama).
53
+
54
+ ### Opción 1: Instalación desde PyPI (Recomendada)
55
+ Para uso general, instala directamente el paquete:
56
+
57
+ ```bash
58
+ # Crear entorno virtual (Recomendado)
59
+ python -m venv venv
60
+ source venv/bin/activate # Windows: venv\Scripts\activate
61
+
62
+ # Instalar
63
+ pip install evolutia
64
+ ```
65
+
66
+ ### Opción 2: Instalación desde Fuente (Desarrollo)
67
+ Si deseas modificar el código o contribuir:
68
+
69
+ ```bash
70
+ git clone https://github.com/glacy/evolutIA.git
71
+ cd evolutia
72
+ pip install -e .
73
+ ```
74
+
75
+ ### Configuración Inicial
76
+ Crea un archivo `.env` en la raíz de tu proyecto con tus credenciales:
77
+
78
+ ```bash
79
+ OPENAI_API_KEY=sk-...
80
+ ANTHROPIC_API_KEY=sk-ant-...
81
+ GOOGLE_API_KEY=...
82
+ ```
83
+
84
+ ---
85
+
86
+ ## Guía de Uso Rápido
87
+
88
+ El comando principal es `evolutia`. Aquí tienes los casos de uso más comunes:
89
+
90
+ ### 1. Generar Variaciones (Modo Clásico)
91
+ Toma ejercicios existentes de un tema y crea versiones más complejas.
92
+
93
+ ```bash
94
+ # Generar 3 variaciones del tema 'analisis_vectorial'
95
+ evolutia --tema analisis_vectorial --num_ejercicios 3 --output examenes/parcial1
96
+ ```
97
+
98
+ O variar ejercicios específicos por su etiqueta (Label):
99
+ ```bash
100
+ evolutia --tema analisis_vectorial --label ex1-s1 ex2-s1 --output examenes/recuperacion
101
+ ```
102
+
103
+ ### 2. Crear Nuevos Ejercicios (Modo Creación)
104
+ Genera ejercicios desde cero sin necesitar un "ejercicio semilla".
105
+
106
+ ```bash
107
+ # Crear 3 ejercicios nuevos sobre 'numeros_complejos'
108
+ evolutia --mode creation --tema numeros_complejos --num_ejercicios 3 --output examenes/quiz1
109
+ ```
110
+
111
+ ### 3. Usar RAG (Contexto del Curso)
112
+ Enriquece la generación indexando tus lecturas y prácticas.
113
+
114
+ ```bash
115
+ # La primera vez, usa --reindex para leer tus materiales
116
+ evolutia --tema matrices --num_ejercicios 3 --use_rag --reindex --output examenes/final
117
+
118
+ # Consultas posteriores (usa el índice ya creado)
119
+ evolutia --tema matrices --num_ejercicios 3 --use_rag --output examenes/final
120
+ ```
121
+
122
+ ### 4. Consultar tu Base de Conocimiento
123
+ Pregúntale al sistema qué sabe sobre un concepto (útil para verificar RAG):
124
+ ```bash
125
+ evolutia --query "Teorema de Stokes"
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Configuración Avanzada
131
+
132
+ EvolutIA es altamente configurable a través del archivo `evolutia_config.yaml` o argumentos CLI.
133
+
134
+ ### Archivo de Configuración
135
+ Puedes colocar un `evolutia_config.yaml` en la raíz de tu carpeta de curso. Si no existe, puedes generarlo o ver el estado actual con:
136
+
137
+ ```bash
138
+ # Analiza tu estructura de carpetas y genera/actualiza la config
139
+ evolutia --analyze
140
+ # O explícitamente usando el script auxiliar
141
+ python evolutia/config_manager.py
142
+ ```
143
+
144
+ ### Argumentos CLI Disponibles
145
+
146
+ | Argumento | Descripción | Default |
147
+ |-----------|-------------|---------|
148
+ | `--tema` | Identificador del tema (carpeta) | **Requerido** |
149
+ | `--output` | Carpeta de salida | **Requerido** |
150
+ | `--num_ejercicios` | Cantidad a generar | 1 |
151
+ | `--complejidad` | Nivel objetivo (`media`, `alta`, `muy_alta`) | `alta` |
152
+ | `--api` | Proveedor (`openai`, `anthropic`, `gemini`, `local`) | `openai` |
153
+ | `--type` | Tipo de pregunta (`problem`, `multiple_choice`) | `problem` |
154
+ | `--no_generar_soluciones` | Omite la creación de archivos de solución | False |
155
+
156
+ ### Uso con Modelos Locales (Offline)
157
+ Para usar modelos como Llama 3 o Mistral sin costo de API:
158
+
159
+ 1. Ejecuta tu servidor (ej. `ollama serve`).
160
+ 2. Configura `evolutia_config.yaml` (opcional, si usas defaults de Ollama no es necesario):
161
+ ```yaml
162
+ local:
163
+ base_url: "http://localhost:11434/v1"
164
+ model: "llama3"
165
+ ```
166
+ 3. Ejecuta con el flag local:
167
+ ```bash
168
+ evolutia --tema basicos --api local --output prueba_local
169
+ ```
170
+
171
+ ---
172
+
173
+ ## Gestión de Materiales (Cómo "ve" los ejercicios EvolutIA)
174
+
175
+ Para que el sistema encuentre tus ejercicios y lecturas, utiliza una estrategia de descubrimiento basada en carpetas y metadatos.
176
+
177
+ 1. **Escaneo de Carpetas**: Busca archivos `.md` dentro de la carpeta del tema (ej: `./analisis_vectorial/`).
178
+ 2. **Tags y Metadatos**: Para archivos fuera de esa carpeta (ej. en `tareas/`), el sistema lee el *frontmatter* YAML. Incluye el tag del tema para hacerlo visible:
179
+
180
+ ```yaml
181
+ ---
182
+ title: Tarea 1
183
+ tags:
184
+ - analisis_vectorial # <--- Este tag permite que evolutia encuentre el archivo
185
+ - stokes
186
+ ---
187
+ ```
188
+
189
+ ### Trazabilidad
190
+ Los ejercicios generados heredan los tags de sus "padres". El archivo final del examen (`examenX.md`) resume todos los temas cubiertos.
191
+
192
+ ---
193
+
194
+ ## Estructura del Proyecto
195
+
196
+ Se recomienda la siguiente estructura para tus cursos:
197
+
198
+ ```
199
+ MiCurso/
200
+ ├── evolutia_config.yaml # Configuración específica del curso
201
+ ├── analisis_vectorial/ # Materiales del tema 1
202
+ │ ├── lectura.md
203
+ │ └── practica.md
204
+ ├── matrices/ # Materiales del tema 2
205
+ ├── examenes/ # Salida generada por EvolutIA
206
+ └── .env # API Keys (no subir a git)
207
+ ```
208
+
209
+ > **Nota para usuarios antiguos**: Anteriormente se recomendaba usar Git Submodules. Ese método ha sido archivado. Si lo necesitas, consulta [docs/legacy/GUIDE_SUBMODULES.md](docs/legacy/GUIDE_SUBMODULES.md).
210
+
211
+ ## Contribuciones y Desarrollo
212
+
213
+ El código fuente está organizado modularmente en `evolutia/`:
214
+ - `evolutia_engine.py`: Orquestador principal.
215
+ - `variation_generator.py`: Lógica de prompts y llamadas a LLMs.
216
+ - `rag/`: Subsistema de indexación y recuperación.
217
+
218
+ Para reportar bugs o mejoras, por favor visita el repositorio en GitHub.
219
+
220
+ ## Licencia
221
+ Apache 2.0
@@ -1,13 +1,13 @@
1
- evolutia_cli.py,sha256=z5QEpPGQGN8BCwtOn6HGl8ZcQ86_HGw84ZNvesNsRdI,7357
2
- evolutia/__init__.py,sha256=iYpwX9uyvy1h1kblwQtfSmR5m7y_K0jhZ-Anh5Milxc,172
1
+ evolutia_cli.py,sha256=suMvTD2v7075-pQmyji2jCTOHuxZWENJM8Se0ynIl-k,7784
2
+ evolutia/__init__.py,sha256=BydLq-f4ekW6SKFPKFA-W5QJLizRbNhqscAiLQGgeVI,172
3
3
  evolutia/complexity_validator.py,sha256=7LL7X9mfEb6S8o_Nj3U7gBpKRBUd49IKIvMGk0e6G6M,7258
4
- evolutia/config_manager.py,sha256=242KgmRSNG1U-WaPcmw9JdSECw1GG2eMESjKX7K49QU,8179
4
+ evolutia/config_manager.py,sha256=gmaRb1tKD7G5OW61rO01cYu3O6o8ATS7JMxrRy0hoVI,8492
5
5
  evolutia/evolutia_engine.py,sha256=ZJOox50c7PiBuiqDnwx49P0vN0_Gu5_l0SG0K9UPVSQ,11969
6
6
  evolutia/exam_generator.py,sha256=bLMbSg4LV9boMjv3KUiOR4K2Auw90mOk60gjTY8Tymk,13670
7
7
  evolutia/exercise_analyzer.py,sha256=4g7LJv4oY0BagSZCm_iqodpKjoVcGCJn90y2Nz2f6ro,8784
8
- evolutia/llm_providers.py,sha256=JtzKasxjAO4QeQgdA-yEX-SH-hqsUp73bK0EfSwHQhM,7724
8
+ evolutia/llm_providers.py,sha256=9sKu3x9ffZhomTR72R3rGBQUVUvO3U3un2VqxkLRBYk,7790
9
9
  evolutia/material_extractor.py,sha256=d2wnApRfWdc-1f5tibX5tmNr0yPBmNDN3aO9TsYQjj4,9732
10
- evolutia/variation_generator.py,sha256=w50WSffMvbz3A_nCiJ1uQ-FkLH_I-3M7hwuXpEEm2a4,3296
10
+ evolutia/variation_generator.py,sha256=F6dQUwsljtAT5hO_1NyQA_uQ8YBr9Gep5tU3Ypcbc3M,10807
11
11
  evolutia/rag/__init__.py,sha256=c4tpP4b-C6BruvO1G865ta-RvZewqECy94QDN2fFRJA,112
12
12
  evolutia/rag/consistency_validator.py,sha256=jsPPCIjiMQ8oCkffvww142kGWfBUl70Bq4YiTwe8eqk,8337
13
13
  evolutia/rag/context_enricher.py,sha256=WnOVLOWByiX9_XZayaVsExbzldIWzl9AGwf5rAuSv4c,11723
@@ -19,9 +19,9 @@ evolutia/utils/__init__.py,sha256=rD3hl92fM5L3_7QCRrCjyR91bx_bOsw0baVQrCjy6vg,56
19
19
  evolutia/utils/json_parser.py,sha256=jZModUbVhR4MvzbD7qZOCtUricx9j_Tomc_M-zfuGIM,2872
20
20
  evolutia/utils/markdown_parser.py,sha256=7m1oqfe4eSkX1yi_VteEM2Q784UczOZ6YNngf8UWedc,4872
21
21
  evolutia/utils/math_extractor.py,sha256=pBscN0aDk9CFV-vKbk43e-lHI_vo2RyhxLMmwx3dgEQ,4832
22
- evolutia-0.1.0.dist-info/licenses/LICENSE,sha256=UdFWht_yODCzH9WTU6_GxLba0ascss31jBUjwvsDnU8,11559
23
- evolutia-0.1.0.dist-info/METADATA,sha256=GHh3YwnMMWkTyG8E6aOmZU18cE5UUzWhxugBgmECTcs,26960
24
- evolutia-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
25
- evolutia-0.1.0.dist-info/entry_points.txt,sha256=BMYhya9XcbrfsjGfp4lMVQF0TK3Bd_Kj6mZtFhVJ7zo,47
26
- evolutia-0.1.0.dist-info/top_level.txt,sha256=GrIvEW8qAI8CIW5XTPnCqC7o06qJIL8p9CGwVhCEC4s,22
27
- evolutia-0.1.0.dist-info/RECORD,,
22
+ evolutia-0.1.1.dist-info/licenses/LICENSE,sha256=jyOI5zt59oNBGE33KX2L1py7ZwWKqVFNcgEePR6o6YA,11564
23
+ evolutia-0.1.1.dist-info/METADATA,sha256=bvapXA__5RRN2-OVqIkmX5iuI1PlrtPq1dK-UM-B0R8,7412
24
+ evolutia-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ evolutia-0.1.1.dist-info/entry_points.txt,sha256=BMYhya9XcbrfsjGfp4lMVQF0TK3Bd_Kj6mZtFhVJ7zo,47
26
+ evolutia-0.1.1.dist-info/top_level.txt,sha256=GrIvEW8qAI8CIW5XTPnCqC7o06qJIL8p9CGwVhCEC4s,22
27
+ evolutia-0.1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.10.2)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright 2024-2025 glacy (glacy@tec.ac.cr)
189
+ Copyright 2026 glacy (gerardolacymora@gmail.com)
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
evolutia_cli.py CHANGED
@@ -7,6 +7,10 @@ import argparse
7
7
  import logging
8
8
  import sys
9
9
  from pathlib import Path
10
+ from dotenv import load_dotenv
11
+
12
+ # Cargar variables de entorno desde el directorio actual (donde el usuario ejecuta el comando)
13
+ load_dotenv()
10
14
 
11
15
  # Add current directory to path so we can import 'evolutia' package if running locally without install
12
16
  sys.path.insert(0, str(Path(__file__).parent))
@@ -56,9 +60,15 @@ Ejemplos:
56
60
  parser.add_argument('--list', action='store_true', help='Listar ejercicios')
57
61
  parser.add_argument('--query', type=str, help='Consulta RAG')
58
62
  parser.add_argument('--workers', type=int, default=5, help='Número de hilos para generación paralela')
63
+ parser.add_argument('--analyze', action='store_true', help='Analizar estructura y generar config.yaml')
59
64
 
60
65
  args = parser.parse_args()
61
66
 
67
+ if args.analyze:
68
+ print("Analizando estructura del proyecto...")
69
+ ConfigManager(str(Path.cwd())).update_config_from_structure()
70
+ return 0
71
+
62
72
  # Validaciones básicas de argumentos
63
73
  if not args.reindex and not args.list and not args.query:
64
74
  if not args.tema and not args.label:
@@ -1,723 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: evolutia
3
- Version: 0.1.0
4
- Summary: Sistema automatizado para generar preguntas de examen desafiantes basadas en materiales didácticos existentes
5
- Home-page: https://github.com/glacy/evolutIA
6
- Author: Gerardo Lacy-Mora
7
- Author-email: glacycr@gmail.com
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: Apache Software License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: PyYAML
15
- Requires-Dist: requests
16
- Requires-Dist: python-dotenv
17
- Requires-Dist: openai
18
- Requires-Dist: anthropic
19
- Requires-Dist: google-generativeai
20
- Requires-Dist: tqdm
21
- Dynamic: author
22
- Dynamic: author-email
23
- Dynamic: classifier
24
- Dynamic: description
25
- Dynamic: description-content-type
26
- Dynamic: home-page
27
- Dynamic: license-file
28
- Dynamic: requires-dist
29
- Dynamic: requires-python
30
- Dynamic: summary
31
-
32
- # EvolutIA: Generador de preguntas de examen
33
-
34
- Sistema automatizado para generar preguntas de examen desafiantes basadas en materiales didácticos existentes (lecturas, prácticas, tareas). El sistema aumenta la complejidad matemática de los ejercicios mientras mantiene el formato y estructura familiar.
35
-
36
-
37
- ## Características
38
-
39
- - **Extracción automática**: Lee y procesa materiales didácticos en formato Markdown/MyST
40
- - **Análisis de complejidad**: Identifica tipo, pasos, variables y conceptos de cada ejercicio
41
- - **Generación inteligente**: Usa IA (OpenAI GPT-4 o Claude) para crear variaciones más complejas
42
- - **Validación automática**: Verifica que las variaciones sean más desafiantes que los originales
43
- - **Formato consistente**: Genera archivos en formato MyST/Markdown compatible con Curvenote
44
- - **Multi-proveedor**: Soporte para OpenAI (GPT-4), Anthropic (Claude 3) y Google (Gemini 1.5).
45
- - **RAG (Retrieval-Augmented Generation)**: Utiliza apuntes de clase y ejercicios existentes para dar contexto.
46
- - **Modo Creación**: Genera ejercicios nuevos desde cero basados en temas y tags del curso.
47
- - **Generación Paralela**: Utiliza concurrencia para acelerar drásticamente la generación de múltiples ejercicios.
48
- - **Parseo Robusto**: Sistema avanzado para manejar y limpiar JSON con alta densidad de LaTeX.
49
-
50
- ```mermaid
51
- flowchart LR
52
- A[📚 Materiales Didácticos<br>Lecturas, Tareas, Prácticas] --> B(🔍 Extracción y Análisis<br>Identifica ejercicios y conceptos)
53
- B --> C{⚙️ Motor de Generación}
54
- subgraph C [ ]
55
- direction LR
56
- D[Modo Variación<br>Incrementa complejidad]
57
- E[Modo Creación<br>Nuevos ejercicios desde cero]
58
- end
59
- C --> F(🧠 Inteligencia Artificial<br>LLM + RAG opcional)
60
- F --> G(✅ Validación<br>Verifica aumento de dificultad)
61
- G --> H[📝 Generación de Archivos<br>Examen y Soluciones en MyST/Markdown]
62
- H --> I(🎯 Evaluación Coherente y Desafiante)
63
- I --> J(🚀 Generación Paralela<br>Concurrencia para acelerar)
64
- ```
65
-
66
- ## Requisitos
67
-
68
- - Python 3.8 o superior
69
- - API key de OpenAI o Anthropic (Claude)
70
- - Opcional: Servidor LLM local (Ollama, LM Studio) para generación offline
71
-
72
- ### Instalación
73
-
74
- 1. Clona el repositorio:
75
- ```bash
76
- git clone https://github.com/glacy/evolutIA.git
77
- cd evolutia
78
- ```
79
-
80
- 2. Crea y activa un entorno virtual:
81
- ```bash
82
- python -m venv venv
83
- source venv/bin/activate # En Windows: venv\Scripts\activate
84
- ```
85
-
86
- 3. Instala el paquete en modo editable (esto instalará también las dependencias):
87
- ```bash
88
- pip install -e .
89
- ```
90
-
91
- 4. Configura las variables de entorno:
92
- ```bash
93
- cp .env.example .env
94
- # Edita .env con tus API keys
95
- ```
96
- Y edita `.env` con tus claves reales:
97
- ```
98
- OPENAI_API_KEY=sk-tu-api-key-aqui
99
- ANTHROPIC_API_KEY=sk-ant-tu-api-key-aqui
100
- GOOGLE_API_KEY=tu-api-key-aqui
101
- ```
102
-
103
- **Obtener API keys**:
104
- - OpenAI: https://platform.openai.com/api-keys
105
- - Anthropic: https://console.anthropic.com/
106
- - Google: https://console.cloud.google.com/ai/generative-ai/credentials
107
-
108
- ## Uso
109
-
110
- ### Uso básico
111
-
112
- ```bash
113
- python evolutia.py \
114
- --tema analisis_vectorial \
115
- --num_ejercicios 4 \
116
- --output examenes/examen3
117
- ```
118
-
119
- ### Variación de ejercicios específicos
120
-
121
- ```bash
122
- python evolutia.py \
123
- --tema analisis_vectorial \
124
- --label ex1-s1 ex2-s1 \
125
- --output variacion_especifica
126
- ```
127
-
128
- ### Listar ejercicios disponibles
129
-
130
- ```bash
131
- python evolutia.py --tema analisis_vectorial --list
132
- ```
133
-
134
- Si no se indica un tema, el sistema buscará en todos los archivos disponibles.
135
-
136
- ### Opciones disponibles
137
-
138
- - `--tema`: Tema del examen (requerido)
139
- - Ejemplos: `analisis_vectorial`, `matrices`, `edps`, `espacios_vectoriales`, `numeros_complejos`
140
-
141
- - `--num_ejercicios`: Número de ejercicios a generar (default: 1)
142
-
143
- - `--output`: Directorio de salida (requerido)
144
- - Se creará automáticamente si no existe
145
-
146
- - `--complejidad`: Nivel de complejidad objetivo
147
- - Opciones: `media`, `alta` (default), `muy_alta`
148
-
149
- - `--api`: Proveedor de API de IA
150
- - Opciones: `openai` (default), `anthropic`, `local`, `gemini`
151
-
152
- - `--label`: ID(s) específico(s) del ejercicio a variar (ej: `ex1-s1` o múltiples: `ex1-s1 ex2-s1`).
153
- - Si se usa, ignora `--num_ejercicios` y genera variaciones **solo** para los ejercicios indicados.
154
-
155
- - `--config`: Ruta a un archivo de configuración externo (ej: `./mi_curso_config.yaml`). (default: busca `evolutia_config.yaml` en la raíz, o usa el interno).
156
-
157
- - `--base_path`: Ruta base del proyecto (default: directorio actual)
158
-
159
- - `--examen_num`: Número del examen (se infiere del nombre del directorio si no se especifica)
160
-
161
- - `--no_generar_soluciones`: NO genera las soluciones (por defecto siempre se generan)
162
-
163
- - `--subject`: Asignatura del examen (default: "IF3602 - II semestre 2025")
164
-
165
- - `--keywords`: Palabras clave para el examen (múltiples valores)
166
-
167
- - `--use_rag`: Usa RAG para enriquecer generación con contexto del curso (requiere indexación inicial)
168
-
169
- - `--reindex`: Fuerza re-indexación de materiales (solo con `--use_rag`)
170
-
171
- - `--list`: Lista todos los ejercicios encontrados en los temas seleccionados y muestra sus etiquetas, archivo origen y preview.
172
-
173
- - `--query`: Realiza una búsqueda semántica en la base de datos RAG y muestra los fragmentos de texto más relevantes encontrados. Útil para verificar qué "sabe" el sistema sobre un tema.
174
-
175
- - `--workers`: Número de hilos simultáneos para la generación paralela (default: 5). Útil para ajustar el rendimiento o evitar límites de rate.
176
-
177
- ### Ejemplos
178
-
179
- **Generar examen de análisis vectorial con 4 ejercicios:**
180
- ```bash
181
- python evolutia.py \
182
- --tema analisis_vectorial \
183
- --num_ejercicios 4 \
184
- --output examenes/examen3
185
- ```
186
-
187
- **Generar examen usando Claude (las soluciones se generan automáticamente):**
188
- ```bash
189
- python evolutia.py \
190
- --tema matrices \
191
- --num_ejercicios 3 \
192
- --api anthropic \
193
- --output examenes/examen4
194
- ```
195
-
196
- ### Uso Básico
197
-
198
- Una vez instalado, puedes usar el comando `evolutia` (o ejecutar el wrapper `python evolutia_cli.py`):
199
-
200
- 1. **Analizar el repositorio y entender la estructura:**
201
- ```bash
202
- evolutia --analyze
203
- ```
204
- *(Esto generará `config.yaml` si no existe)*
205
-
206
- 2. **Generar examen con variaciones de ejercicios existentes:**
207
- ```bash
208
- evolutia --exam-number 1 --num-ejercicios 3 --tema "Derivadas" --complejidad "media"
209
- ```
210
- **Generar examen SIN soluciones:**
211
- ```bash
212
- python evolutia.py \
213
- --tema matrices \
214
- --num_ejercicios 3 \
215
- --no_generar_soluciones \
216
- --output examenes/examen5
217
- ```
218
-
219
- **Generar examen con complejidad muy alta:**
220
- ```bash
221
- python evolutia.py \
222
- --tema edps \
223
- --num_ejercicios 5 \
224
- --complejidad muy_alta \
225
- --output examenes/examen5
226
- ```
227
-
228
- **Generar examen usando RAG (recomendado para mejor calidad):**
229
- ```bash
230
- python evolutia.py \
231
- --tema analisis_vectorial \
232
- --num_ejercicios 4 \
233
- --use_rag \
234
- --output examenes/examen3
235
- ```
236
-
237
- ### Herramienta de Consulta RAG
238
- Puedes "preguntarle" al sistema qué información tiene sobre un concepto específico sin generar nada:
239
-
240
- ```bash
241
- python evolutia.py --query "Teorema de Stokes"
242
- ```
243
-
244
- Esto mostrará una lista de ejercicios y lecturas relevantes con su puntuación de similitud.
245
-
246
- ### Modo Creación (Nuevo)
247
- Genera ejercicios totalmente nuevos desde cero, basándose en un tema y tags opcionales, en lugar de variar ejercicios existentes.
248
-
249
- **Generar 3 ejercicios nuevos de variable compleja:**
250
- ```bash
251
- python evolutia.py \
252
- --mode creation \
253
- --tema numeros_complejos \
254
- --num_ejercicios 3 \
255
- --output examenes/parcial1
256
- ```
257
-
258
- **Generar con tags específicos y usar Gemini:**
259
- ```bash
260
- python evolutia.py \
261
- --mode creation \
262
- --tema analisis_vectorial \
263
- --tags stokes divergencia \
264
- --api gemini \
265
- --output examenes/quiz3
266
- ```
267
-
268
- ### Tipos de Ejercicio
269
- Ahora puedes elegir entre ejercicios de desarrollo (default) o selección única (quiz).
270
-
271
- **Generar pregunta de Selección Única (Conceptual):**
272
- ```bash
273
- python evolutia.py \
274
- --mode creation \
275
- --tema matrices \
276
- --type multiple_choice \
277
- --api anthropic \
278
- --output examenes/quiz_rapido
279
- ```
280
-
281
- ## Uso de LLM local (offline)
282
-
283
- EvolutIA soporta la generación de exámenes usando modelos locales como Llama 3, Mistral, o Qwen, ejecutándose en tu propia máquina a través de herramientas como [Ollama](https://ollama.com/) o [LM Studio](https://lmstudio.ai/).
284
-
285
- **Requisitos:**
286
- 1. Tener corriendo un servidor local compatible con OpenAI API.
287
- - **Ollama**: Ejecuta `ollama serve` (por defecto en puerto 11434).
288
- - **LM Studio**: Inicia el servidor local desde la interfaz.
289
-
290
- 2. **Ejemplo de ejecución:**
291
- ```bash
292
- python evolutia.py \
293
- --tema matrices \
294
- --num_ejercicios 3 \
295
- --api local \
296
- --output examenes/examen_local
297
- ```
298
-
299
- 3. **Configuración avanzada (opcional):**
300
- Si tu servidor no usa el puerto por defecto o quieres cambiar el modelo, edita `evolutia/config/config.yaml`:
301
- ```yaml
302
- local:
303
- base_url: "http://localhost:11434/v1" # URL de tu servidor
304
- model: "llama3" # Modelo a utilizar
305
- api_key: "not-needed"
306
- ```
307
-
308
- ## Sistema RAG (Retrieval-Augmented Generation)
309
-
310
- El sistema incluye un módulo RAG opcional que mejora significativamente la calidad de las variaciones generadas.
311
-
312
- ### ¿Qué es RAG?
313
-
314
- RAG (Retrieval-Augmented Generation) es un sistema que:
315
- - **Indexa** todos tus materiales didácticos (ejercicios, soluciones y **lecturas/teoría**)
316
- - **Busca** ejercicios similares y conceptos teóricos relevantes cuando generas variaciones
317
- - **Enriquece** los prompts con información del curso para generar variaciones más coherentes
318
- - **Valida** consistencia comparando con ejercicios y teoría reales del curso
319
-
320
- ### Ventajas de usar RAG
321
-
322
- 1. **Mejor contexto**: Las variaciones son más coherentes con el estilo y nivel del curso
323
- 2. **Consistencia**: Los ejercicios generados se alinean mejor con materiales existentes
324
- 3. **Relevancia**: Selección inteligente de ejercicios base por similitud semántica
325
- 4. **Validación mejorada**: Compara con ejercicios reales del curso
326
-
327
- ### Cómo usar RAG
328
-
329
- **Primera vez (indexación inicial):**
330
- ```bash
331
- python evolutia.py \
332
- --tema analisis_vectorial \
333
- --num_ejercicios 4 \
334
- --use_rag \
335
- --reindex \
336
- --output examenes/examen3
337
- ```
338
-
339
- La primera vez con `--use_rag` indexará automáticamente todos los materiales. Esto puede tardar unos minutos.
340
-
341
- **Uso posterior:**
342
- ```bash
343
- python evolutia.py \
344
- --tema analisis_vectorial \
345
- --num_ejercicios 4 \
346
- --use_rag \
347
- --output examenes/examen4
348
- ```
349
-
350
- El índice se reutiliza automáticamente. Solo usa `--reindex` si cambias materiales y quieres actualizar el índice.
351
-
352
- ### Configuración de RAG
353
-
354
- Edita `config/config.yaml` para personalizar RAG:
355
- ```yaml
356
- rag:
357
- vector_store:
358
- # Base de datos vectorial persistente
359
- persist_directory: "./storage/vector_store"
360
- collection_name: "mi_curso_coleccion"
361
- embeddings:
362
- provider: openai
363
- model: text-embedding-3-small
364
- retrieval:
365
- top_k: 5
366
- similarity_threshold: 0.7
367
- ```
368
-
369
- **Opciones de embeddings:**
370
- - `openai`: Más rápido y preciso, pero tiene costo (~$0.02 por 1M tokens)
371
- - `sentence-transformers`: Gratis y local, pero más lento
372
-
373
- ### Costos de RAG
374
-
375
- - **Indexación inicial**: ~$1-5 dependiendo del volumen de materiales
376
- - **Búsquedas**: Mínimas, solo cuando generas variaciones
377
- - **Alternativa gratuita**: Usa `sentence-transformers` en lugar de OpenAI
378
-
379
- ### Cuándo usar RAG
380
-
381
- **Usa RAG si:**
382
- - Tienes muchos materiales (50+ ejercicios)
383
- - Quieres máxima consistencia con el curso
384
- - Tienes presupuesto para embeddings de OpenAI
385
-
386
- **No uses RAG si:**
387
- - Tienes pocos materiales (<20 ejercicios)
388
- - Prefieres simplicidad y rapidez
389
- - El costo es una preocupación
390
-
391
- ## Gestión de metadatos y descubrimiento
392
-
393
- ### Organización y visibilidad de ejercicios
394
-
395
- Para que `evolutia` encuentre ejercicios ubicados en carpetas generales como `examenes/` o `tareas/` cuando filtras por un tema (ej: `--tema analisis_vectorial`), es fundamental que los archivos fuente incluyan los metadatos correctos.
396
-
397
- El sistema utiliza la siguiente lógica de "descubrimiento":
398
-
399
- 1. **Escaneo directo**: Todos los archivos dentro de la carpeta del tema (ej: `analisis_vectorial/`) son incluidos automáticamente.
400
- 2. **Escaneo de exámenes y tareas**: Para archivos fuera de la carpeta del tema, el sistema revisa el *frontmatter* y los incluye **SOLO SI** encuentra coincidencias con el tema en:
401
- - **`tags`**: (Recomendado) Incluye el código del tema (ej: `analisis_vectorial`) en la lista.
402
- - **`subject`**: El nombre de la asignatura o tema.
403
- - **`keywords`**: Palabras clave relacionadas.
404
-
405
- **Ejemplo de Frontmatter para que un examen sea "visible":**
406
- ```yaml
407
- ---
408
- title: Examen Parcial 1
409
- tags:
410
- - analisis_vectorial # <--- CRÍTICO: Permite que el extractor lo encuentre
411
- - stokes
412
- subject: Cálculo Superior
413
- ---
414
- ```
415
-
416
- > **Nota**: Si usas `--label` para seleccionar un ejercicio específico, el filtro de tema se ignora y el sistema buscará el ID en todos los archivos disponibles.
417
-
418
- ### Propagación de tags (trazabilidad)
419
-
420
- `EvolutIA` asegura que los metadatos de los ejercicios originales se conserven en las variaciones generadas. Esto es crucial para mantener un registro de qué conceptos se están evaluando.
421
-
422
- **¿Cómo funciona?**
423
- 1. **Lectura**: El sistema lee los tags del archivo fuente (`.md`) donde reside el ejercicio original.
424
- 2. **Transferencia**: Al generar la variación, estos tags se copian al nuevo archivo generado.
425
- 3. **Agregación**: El archivo final del examen (`examenX.md`) recopila automáticamente los tags de *todos* los ejercicios incluidos, generando un resumen temático del examen.
426
-
427
- #### Ejemplo práctico
428
-
429
- **1. Archivo fuente (ej: `matrices/semana11_practica.md`)**
430
- Este archivo contiene los ejercicios originales ("semilla") y define el contexto temático:
431
-
432
- ```yaml
433
- ---
434
- title: Ejercicios Semana 11
435
- tags:
436
- - autovalores # Concepto clave
437
- - diagonalizacion # Concepto clave
438
- - procedimental # Tipo de competencia
439
- - intermedio # Nivel de dificultad
440
- subject: Matrices y Algebra Lineal
441
- ---
442
- ```
443
-
444
- **2. Archivo generado (ej: `examenes/examen1/ex1_e1.md`)**
445
- La variación generada hereda estos metadatos y agrega los suyos propios:
446
-
447
- ```yaml
448
- ---
449
- generator: evolutia
450
- source: ai_variation
451
- tags: [autovalores, diagonalizacion, procedimental, intermedio] # <--- Tags heredados
452
- original_subject: Matrices y Algebra Lineal
453
- complexity: media
454
- mode: variation # <--- Nuevo: Modo de generación
455
- target_difficulty: alta # <--- Nuevo: Dificultad objetivo
456
- based_on: ex1-e1 # <--- Nuevo: ID del ejercicio semilla
457
- rag_references: # <--- Nuevo: Contexto usado (con --use_rag)
458
- - ex5-e2
459
- - semana3_lectura.md
460
- ---
461
- ```
462
-
463
-
464
- ## Estructura de archivos generados
465
-
466
- El script genera la siguiente estructura:
467
-
468
- ```
469
- examenes/examen3/
470
- ├── examen3.md # Archivo principal del examen
471
- ├── ex1_e3.md # Ejercicio 1
472
- ├── ex2_e3.md # Ejercicio 2
473
- ├── ex3_e3.md # Ejercicio 3
474
- ├── ex4_e3.md # Ejercicio 4
475
- ├── solucion_ex1_e3.md # Solución ejercicio 1
476
- ├── solucion_ex2_e3.md # Solución ejercicio 2
477
- ├── solucion_ex3_e3.md # Solución ejercicio 3
478
- └── solucion_ex4_e3.md # Solución ejercicio 4
479
- ```
480
-
481
- ## ¿Cómo funciona?
482
-
483
- 1. **Extracción**: El sistema busca y lee materiales didácticos del tema especificado
484
- - Busca en directorios del tema (ej: `analisis_vectorial/`)
485
- - Lee archivos de prácticas (`*practica*.md`)
486
- - Lee archivos de tareas (`tareas/tarea*/tarea*.md`)
487
-
488
- 2. **Análisis**: Analiza cada ejercicio encontrado
489
- - Identifica tipo (demostración, cálculo, aplicación)
490
- - Cuenta pasos en soluciones
491
- - Extrae variables y conceptos matemáticos
492
- - Calcula complejidad matemática
493
-
494
- 3. **Generación**: Crea variaciones más complejas usando IA
495
- - Aumenta número de variables
496
- - Combina múltiples conceptos
497
- - Agrega pasos intermedios
498
- - Modifica sistemas de coordenadas
499
-
500
- 4. **Validación**: Verifica que las variaciones sean más complejas
501
- - Compara complejidad total
502
- - Verifica aumento en pasos, variables, conceptos
503
- - Valida operaciones matemáticas
504
-
505
- 5. **Generación de archivos**: Crea archivos en formato MyST/Markdown
506
- - Frontmatter YAML apropiado
507
- - Estructura de ejercicios con labels
508
- - Bloques de solución
509
-
510
- ## Configuración
511
-
512
- Puedes personalizar el comportamiento editando `config/config.yaml`:
513
-
514
- - **APIs**: Configurar modelos y parámetros
515
- - **Rutas**: Especificar directorios de materiales (dentro de `materials_directories`)
516
- - **Complejidad**: Ajustar umbrales de validación
517
- - **Exámenes**: Configurar valores por defecto y **keywords** por tema
518
- - **RAG**: Definir persistencia (local vs nube) y nombres de colección
519
-
520
- ### Cambiar Proveedor por Defecto
521
- Puedes definir qué IA usar si no se especifica el argumento `--api`:
522
-
523
- ```yaml
524
- api:
525
- default_provider: gemini # openai, anthropic, gemini, local
526
- gemini:
527
- model: gemini-1.5-pro # Cambiar modelo específico
528
- ```
529
-
530
- ### Nota Importante sobre Configuración
531
- Para evitar errores de validación, asegúrate de que tu `evolutia_config.yaml` incluya la sección `api`. El sistema usa esto para determinar los modelos por defecto.
532
-
533
- ### Configuración Avanzada / Multi-Curso
534
-
535
- Para usar `evolutia` en múltiples cursos o sin modificar el código fuente:
536
-
537
- 1. **Archivo de Configuración Externo**: Crea un archivo `evolutia_config.yaml` en la raíz de tu proyecto (junto a la carpeta `evolutia/`). El sistema lo detectará automáticamente.
538
- 2. **Argumento CLI**: Usa `--config ruta/a/mi_config.yaml` para especificar un archivo arbitrario.
539
-
540
- **Ejemplo de estructura recomendada para un nuevo curso:**
541
- ```
542
- NuevoCurso/
543
- ├── evolutia/ # Carpeta copiada o submódulo git
544
- ├── evolutia_config.yaml # Configuración específica de este curso
545
- └── temas/ # Carpetas de contenido
546
- ```
547
-
548
- > **IMPORTANTE**: No edites `evolutia/config/config.yaml` para datos de un curso específico. Ese archivo es una plantilla del motor. Crea un `evolutia_config.yaml` en la raíz de tu proyecto para tus ajustes personales.
549
-
550
- > **Guía Detallada**: Para instrucciones paso a paso sobre cómo usar Git Submodules, consulta [GUIDE_SUBMODULES.md](GUIDE_SUBMODULES.md).
551
-
552
- ## Estrategias de aumento de complejidad
553
-
554
- El sistema aplica las siguientes estrategias para aumentar la complejidad:
555
-
556
- 1. **Más variables independientes**: Introduce parámetros adicionales
557
- 2. **Combinación de conceptos**: Integra múltiples teoremas en un ejercicio
558
- 3. **Pasos intermedios**: Agrega cálculos adicionales
559
- 4. **Casos límite**: Introduce condiciones especiales
560
- 5. **Sistemas de coordenadas**: Cambia de cartesianas a cilíndricas/esféricas
561
- 6. **Dimensiones adicionales**: Aumenta la dimensionalidad del problema
562
-
563
- ## Solución de Problemas
564
-
565
- ### Error: "No se encontraron materiales"
566
- - Verifica que el tema especificado existe como directorio
567
- - Asegúrate de que hay archivos `.md` con ejercicios en ese directorio
568
- - Usa `--base_path` para especificar la ruta correcta
569
-
570
- ### Error: "API key no configurada"
571
- - Verifica que el archivo `.env` existe y contiene la API key
572
- - Asegúrate de que el archivo está en el directorio `evolutia/`
573
- - Revisa que la variable se llama correctamente (`OPENAI_API_KEY` o `ANTHROPIC_API_KEY`)
574
-
575
- ### Error: "No se generaron variaciones válidas"
576
- - Intenta aumentar el número de ejercicios candidatos
577
- - Verifica que los ejercicios originales tienen suficiente complejidad
578
- - Considera usar `--complejidad media` para requisitos menos estrictos
579
-
580
- ### Variaciones no son suficientemente complejas
581
- - Ajusta los umbrales en `config/config.yaml`
582
- - Usa `--complejidad muy_alta`
583
- - Revisa los prompts en `variation_generator.py` y ajústalos según necesites
584
- - Considera usar `--use_rag` para mejor contexto
585
-
586
- ### Error: "RAG no disponible"
587
- - Instala dependencias: `pip install chromadb sentence-transformers`
588
- - Verifica que `OPENAI_API_KEY` está configurada si usas embeddings de OpenAI
589
- - Si prefieres embeddings locales, cambia `provider: sentence-transformers` en `config.yaml`
590
-
591
- ## Limitaciones
592
-
593
- - Requiere conexión a internet para usar APIs de IA
594
- - Los costos de API dependen del número de ejercicios generados
595
- - La calidad depende de la calidad de los materiales originales
596
- - Las variaciones requieren revisión manual antes de usar
597
-
598
- ## Mejores prácticas
599
-
600
- 1. **Revisar siempre**: Las variaciones generadas deben revisarse manualmente
601
- 2. **Ajustar según necesidad**: Modifica los ejercicios generados según tu criterio
602
- 3. **Probar primero**: Genera un examen de prueba antes de usar en evaluación real
603
- 4. **Mantener materiales actualizados**: Asegúrate de que los materiales fuente están completos
604
- 5. **Documentar cambios**: Si modificas ejercicios, documenta los cambios realizados
605
-
606
- ## Configuración automática
607
-
608
- El proyecto incluye una herramienta para sincronizar automáticamente el archivo de configuración con la estructura de carpetas y los metadatos de los archivos de lectura.
609
-
610
- ### config_manager.py
611
-
612
- Este script escanea el directorio del proyecto para:
613
- 1. Identificar carpetas de temas existentes.
614
- 2. Leer los archivos de lectura (`semana*_lectura.md`) y extraer las palabras clave (`keywords`) del frontmatter.
615
- 3. Actualizar el archivo de configuración activo (`evolutia_config.yaml` o interno).
616
-
617
- **Uso:**
618
-
619
- ```bash
620
- # Uso básico (detecta configuración automáticamente)
621
- python evolutia/config_manager.py
622
-
623
- # Uso con archivo específico
624
- python evolutia/config_manager.py --config ./evolutia_config.yaml
625
- ```
626
-
627
- Ejecuta este script cada vez que agregues nuevos temas o modifiques las palabras clave en los materiales de lectura.
628
-
629
- ### Validación de Configuración (Schema)
630
-
631
- Evolutia incluye un sistema de validación estricta para el archivo de configuración (`evolutia_config.yaml`).
632
-
633
- - **JSON Schema**: La estructura válida se define en `evolutia/schemas/config.schema.json`.
634
- - **Validación Automática**: Cada vez que ejecutas `evolutia.py` o `config_manager.py`, el sistema verifica que tu archivo de configuración cumpla con el esquema.
635
- - **Errores Claros**: Si tu configuración tiene errores (campos faltantes, tipos incorrectos), el sistema detendrá la ejecución y te indicará exactamente dónde está el problema.
636
-
637
- Esto facilita la adopción de la herramienta por nuevos usuarios, reduciendo errores de configuración inicial.
638
-
639
- ## Estructura del repositorio (Contexto)
640
-
641
- El generador está diseñado para funcionar dentro de la estructura estándar del curso. A continuación se muestra el esquema de directorios esperado:
642
-
643
- ```
644
- .
645
- ├── tema1/ # Carpeta del primer tema (ej: analisis_vectorial)
646
- ├── tema2/ # Carpeta del segundo tema
647
- ├── ... # Otros temas
648
- ├── tareas/ # Tareas evaluadas (fuente de ejercicios)
649
- ├── proyecto/ # Enunciados de proyectos
650
- ├── examenes/ # Directorio de salida para exámenes generados
651
- ├── evolutia/ # Este sistema de generación
652
- ├── myst.yml # Configuración del sitio Curvenote
653
- └── programa-curso.md # Información general del curso
654
- ```
655
-
656
- ### Estructura interna de cada tema
657
-
658
- Cada carpeta de tema (ej: `tema1/`) debe seguir una estructura similar para que el extractor encuentre los materiales:
659
-
660
- ```
661
- tema1/
662
- ├── semana1_lectura.md # Material teoría (puede contener ejemplos)
663
- ├── semana1_practica.md # Ejercicios de práctica
664
- ├── semana2_lectura.md
665
- ├── semana2_practica.md
666
- └── otros_archivos.md # Otros materiales complementarios
667
- ```
668
-
669
- ## Estructura del código (generador)
670
-
671
- ```
672
- evolutia/
673
- ├── evolutia.py # Script principal (CLI Wrapper)
674
- ├── evolutia_engine.py # Motor central de orquestación
675
- ├── config_manager.py # Gestor de configuración automática
676
- ├── material_extractor.py # Extracción de materiales
677
- ├── exercise_analyzer.py # Análisis de complejidad
678
- ├── variation_generator.py # Generación de variaciones
679
- ├── llm_providers.py # Proveedores de LLM (OpenAI, Anthropic, Gemini, Local)
680
- ├── complexity_validator.py # Validación de complejidad
681
- ├── exam_generator.py # Generación de archivos
682
- ├── rag/ # Sistema RAG (opcional)
683
- │ ├── rag_indexer.py # Indexación de materiales
684
- │ ├── rag_retriever.py # Búsqueda semántica
685
- │ ├── context_enricher.py # Enriquecimiento de contexto
686
- │ ├── enhanced_variation_generator.py # Generador con RAG
687
- │ ├── consistency_validator.py # Validación de consistencia
688
- │ └── rag_manager.py # Gestor principal
689
- ├── storage/
690
- │ └── vector_store/ # Base de datos vectorial (RAG)
691
- ├── config/
692
- │ └── config.yaml # Configuración
693
- ├── templates/
694
- │ ├── exam_template.md # Plantilla de examen
695
- │ └── exercise_template.md # Plantilla de ejercicio
696
- ├── utils/
697
- │ ├── markdown_parser.py # Parser de Markdown
698
- │ ├── math_extractor.py # Extracción de matemáticas
699
- │ └── json_parser.py # Parser robusto de JSON (LaTeX friendly)
700
- ├── requirements.txt # Dependencias
701
- └── README.md # Esta documentación
702
- ```
703
-
704
- ## Contribuciones
705
-
706
- Para mejorar el sistema:
707
-
708
- 1. Ajusta los prompts en `variation_generator.py` para mejor generación
709
- 2. Agrega nuevos patrones de conceptos en `exercise_analyzer.py`
710
- 3. Mejora las métricas de complejidad en `complexity_validator.py`
711
- 4. Personaliza las plantillas en `templates/`
712
-
713
- ## Licencia
714
-
715
- Este proyecto está bajo la Licencia Apache 2.0. Consulta el archivo [LICENSE](LICENSE) para más detalles.
716
-
717
- ## Reconocimientos
718
-
719
- Este proyecto fue desarrollado utilizando asistencia de Inteligencia Artificial:
720
-
721
- - **Cursor**: Entorno de desarrollo asistido por IA.
722
- - **Antigravity** (Google DeepMind): Agente de codificación y planificación avanzado.
723
-