evolutia 0.1.0__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.
@@ -0,0 +1,144 @@
1
+ """
2
+ Utilidades para extraer y analizar expresiones matemáticas de archivos Markdown.
3
+ """
4
+ import re
5
+ from typing import List, Dict, Set
6
+
7
+ # Patrones comunes para variables
8
+ # Variables latinas: \vec{A}, A, \mathbf{B}, etc.
9
+ LATIN_PATTERN = re.compile(r'\\vec\{([A-Za-z])\}|\\mathbf\{([A-Za-z])\}|\\hat\{([A-Za-z])\}|([A-Za-z])(?![a-z])')
10
+
11
+ # Letras griegas: \alpha, \beta, \theta, etc.
12
+ GREEK_PATTERN = re.compile(r'\\(alpha|beta|gamma|delta|epsilon|theta|phi|rho|omega|sigma|lambda|mu|nu|pi|tau)')
13
+
14
+
15
+ def extract_math_expressions(content: str) -> List[str]:
16
+ r"""
17
+ Extrae todas las expresiones matemáticas del contenido.
18
+
19
+ Busca expresiones en formato LaTeX:
20
+ - Inline: $...$ o \(...\)
21
+ - Display: $$...$$ o \[...\]
22
+ - Math blocks: :::{math} ... :::
23
+
24
+ Args:
25
+ content: Contenido Markdown
26
+
27
+ Returns:
28
+ Lista de expresiones matemáticas encontradas
29
+ """
30
+ expressions = []
31
+
32
+ # 1. Bloques math de MyST: :::{math} ... :::
33
+ # Se procesan primero y se eliminan del contenido para evitar duplicados si contienen $ o $$
34
+ math_block_pattern = r':::\{math\}\s*(.*?)\s*:::'
35
+ for match in re.finditer(math_block_pattern, content, re.DOTALL):
36
+ expr = match.group(1).strip()
37
+ if expr:
38
+ expressions.append(expr)
39
+ content = re.sub(math_block_pattern, '', content, flags=re.DOTALL)
40
+
41
+ # 2. Expresiones display: $$...$$ o \[...\]
42
+ display_pattern = r'\$\$([^$]+)\$\$|\\\[([^\]]+)\\\]'
43
+ for match in re.finditer(display_pattern, content, re.DOTALL):
44
+ expr = match.group(1) or match.group(2)
45
+ if expr:
46
+ expressions.append(expr.strip())
47
+ content = re.sub(display_pattern, '', content, flags=re.DOTALL)
48
+
49
+ # 3. Expresiones inline: $...$ o \(...\)
50
+ inline_pattern = r'\$([^$]+)\$|\\\(([^\)]+)\\\)'
51
+ for match in re.finditer(inline_pattern, content):
52
+ expr = match.group(1) or match.group(2)
53
+ if expr:
54
+ expressions.append(expr.strip())
55
+
56
+ return expressions
57
+
58
+
59
+ def extract_variables(math_expressions: List[str]) -> Set[str]:
60
+ """
61
+ Extrae variables de expresiones matemáticas.
62
+
63
+ Identifica letras griegas, variables latinas, y símbolos comunes.
64
+
65
+ Args:
66
+ math_expressions: Lista de expresiones matemáticas
67
+
68
+ Returns:
69
+ Conjunto de variables identificadas
70
+ """
71
+ variables = set()
72
+
73
+ for expr in math_expressions:
74
+ # Buscar variables latinas
75
+ for match in LATIN_PATTERN.finditer(expr):
76
+ var = match.group(1) or match.group(2) or match.group(3) or match.group(4)
77
+ if var and var.isalpha():
78
+ variables.add(var)
79
+
80
+ # Buscar letras griegas
81
+ for match in GREEK_PATTERN.finditer(expr):
82
+ variables.add(match.group(1))
83
+
84
+ return variables
85
+
86
+
87
+ def count_math_operations(expression: str) -> Dict[str, int]:
88
+ """
89
+ Cuenta operaciones matemáticas en una expresión.
90
+
91
+ Args:
92
+ expression: Expresión matemática
93
+
94
+ Returns:
95
+ Diccionario con conteo de operaciones
96
+ """
97
+ operations = {
98
+ 'integrals': len(re.findall(r'\\int|\\oint', expression)),
99
+ 'derivatives': len(re.findall(r'\\partial|\\nabla|\\frac\{d', expression)),
100
+ 'sums': len(re.findall(r'\\sum|\\prod', expression)),
101
+ 'vectors': len(re.findall(r'\\vec|\\mathbf', expression)),
102
+ 'matrices': len(re.findall(r'\\begin\{matrix\}|\\begin\{pmatrix\}|\\begin\{bmatrix\}', expression)),
103
+ 'functions': len(re.findall(r'\\sin|\\cos|\\tan|\\exp|\\log|\\ln', expression)),
104
+ }
105
+ return operations
106
+
107
+
108
+ def estimate_complexity(expressions: List[str]) -> float:
109
+ """
110
+ Estima la complejidad matemática de un conjunto de expresiones.
111
+
112
+ Args:
113
+ expressions: Lista de expresiones matemáticas
114
+
115
+ Returns:
116
+ Puntuación de complejidad (mayor = más complejo)
117
+ """
118
+ if not expressions:
119
+ return 0.0
120
+
121
+ total_complexity = 0.0
122
+
123
+ for expr in expressions:
124
+ # Longitud de la expresión
125
+ total_complexity += len(expr) * 0.01
126
+
127
+ # Operaciones complejas
128
+ ops = count_math_operations(expr)
129
+ total_complexity += ops['integrals'] * 2.0
130
+ total_complexity += ops['derivatives'] * 1.5
131
+ total_complexity += ops['sums'] * 1.5
132
+ total_complexity += ops['vectors'] * 1.0
133
+ total_complexity += ops['matrices'] * 2.5
134
+ total_complexity += ops['functions'] * 0.5
135
+
136
+ # Número de variables
137
+ vars_count = len(extract_variables([expr]))
138
+ total_complexity += vars_count * 0.3
139
+
140
+ # Bloques align (ecuaciones múltiples)
141
+ if '\\begin{align' in expr or '\\begin{aligned' in expr:
142
+ total_complexity += 2.0
143
+
144
+ return total_complexity
@@ -0,0 +1,97 @@
1
+ """
2
+ Generador de variaciones de ejercicios con mayor complejidad.
3
+ Utiliza APIs de IA para generar variaciones inteligentes.
4
+ """
5
+ import os
6
+ import logging
7
+ from typing import Dict, Optional
8
+ from dotenv import load_dotenv
9
+ from pathlib import Path
10
+
11
+ # Imports for new Provider system
12
+ from .llm_providers import get_provider
13
+ from .utils.json_parser import extract_and_parse_json
14
+
15
+ # Cargar variables de entorno explícitamente desde el directorio del script
16
+ env_path = Path(__file__).parent / '.env'
17
+ load_dotenv(dotenv_path=env_path)
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+
23
+ class VariationGenerator:
24
+ """Genera variaciones de ejercicios con mayor complejidad."""
25
+
26
+ def __init__(self, api_provider: str = "openai"):
27
+ """
28
+ Inicializa el generador.
29
+
30
+ Args:
31
+ api_provider: Proveedor de API ('openai', 'anthropic', 'gemini' o 'local')
32
+ """
33
+ self.api_provider = api_provider
34
+ self.base_url = None # For local overrides
35
+ self.local_model = None # For local overrides
36
+ self.model_name = None # For overrides
37
+
38
+ self._provider_instance = None
39
+
40
+ def _get_provider(self):
41
+ """Lazy loader para el proveedor, permitiendo configuración tardía de props."""
42
+ if self._provider_instance:
43
+ return self._provider_instance
44
+
45
+ kwargs = {}
46
+ if self.model_name:
47
+ kwargs['model_name'] = self.model_name
48
+ elif self.local_model and self.api_provider == 'local':
49
+ kwargs['model_name'] = self.local_model
50
+
51
+ if self.base_url and self.api_provider == 'local':
52
+ kwargs['base_url'] = self.base_url
53
+
54
+ try:
55
+ self._provider_instance = get_provider(self.api_provider, **kwargs)
56
+ except ValueError as e:
57
+ logger.error(f"Error inicializando proveedor: {e}")
58
+ return None
59
+
60
+ return self._provider_instance
61
+
62
+ def generate_variation_with_solution(self, exercise: Dict, analysis: Dict) -> Optional[Dict]:
63
+ """
64
+ Genera una variación con su solución.
65
+ """
66
+ # Primero generar el ejercicio
67
+ variation = self.generate_variation(exercise, analysis)
68
+
69
+ if not variation:
70
+ return None
71
+
72
+ provider = self._get_provider()
73
+ if not provider: return None
74
+
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
+
78
+ EJERCICIO:
79
+ {variation['variation_content']}
80
+
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
+ GENERA LA SOLUCIÓN COMPLETA:"""
90
+
91
+ solution_content = provider.generate_content(solution_prompt)
92
+
93
+ if solution_content:
94
+ variation['variation_solution'] = solution_content
95
+
96
+ return variation
97
+