Qwen3-1.7B Spanish-reasoning LoRA
Also published for transformers/peft: axiom-of-choice/qwen3-1.7b-es-reasoning-peft -- same adapter weights, verified against this one (phase-2 parity numbers on the linked repo's card). Use
this repo with
mlx-lm; use the linked one for
transformers,
vLLM, or anything else.
A LoRA adapter that makes
Qwen/Qwen3-1.7B
produce its chain-of-thought
in Spanish. It does that perfectly, and it costs
5.7 points of math accuracy. Both facts are measured on the full
held-out eval split below. Read the trade-off before using this.
Published at scale 6.0, not the 8.0 it was trained at.
Lowering the scale at inference is worth
+5.3 accuracy points
with zero language loss, and no retraining matched it. Details in
Why the scale is lowered. If you re-create this
adapter from the training config, set
scale to 6.0 yourself.
What it does, and what it costs
All 283 rows of the held-out Spanish GSM8K split. Identical sampling
throughout: temp 0.0 (greedy), max_tokens 2048,
repetition_penalty 1.1, batch 16, no
\boxed{} hint for either model.
| accuracy | reasoned only | Spanish | English traces | truncated |
|---|
| base model | 79.9% | 87.6% | 0.0040 | 250/251 | 11.3% |
| this adapter | 74.2% | 84.2% | 1.0000 | 0/247 | 12.7% |
The language result is the entire point and it is unambiguous. Qwen3-1.7B already
does math; what it would not do is reason in Spanish — it code-switches to
English inside <think> regardless of instruction (documented R1-lineage
"language mixing", confirmed unfixable by prompting during this project). Given a
Spanish question and a Spanish system prompt, langdetect classified
250 of the base model's 251 reasoning traces as
English. This adapter: 0, with minimum Spanish confidence
1.0000 across all 247. Unanimous in both
directions, not an average hiding variance.
The cost is equally real. Use this only if Spanish-language reasoning is worth
more to you than 5.7 points of accuracy. If you want correct answers
in Spanish but do not need the reasoning trace to be Spanish, the base model is
strictly better.
Statistical honesty: paired McNemar exact test on the 54 rows
where the two disagree gives p = 0.0402
(35 base-only wins vs 19). The gap is
real, not sampling noise. (An earlier version of this card reported n=100 numbers
where it was not separable; more data made it significant, not less.)
Why the scale is lowered
scale multiplies the low-rank update directly in mlx-lm, so lowering it
interpolates continuously between the base model and the fine-tune using the
same weights — a one-line config change, no retraining. Measured across the
full split:
| scale | accuracy | reasoned only | Spanish | English traces | truncated |
|---|
| 8.0 (as trained) | 68.9% | 79.3% | 1.0000 | 0/241 | 14.8% |
| 6.0 (published) | 74.2% | 84.2% | 1.0000 | 0 | 12.7% |
| 4.0 | 76.3% | 82.0% | 0.9234 | 20/261 | 7.4% |
At the trained scale the adapter scores 68.9%; at
6.0 it scores 74.2%, an improvement of
5.3 points (paired p = 0.0534) with Spanish
still at 1.0000. The math ability was never destroyed by
training — it was being applied too strongly. Four separate retraining attempts
(higher rank, prompt masking, earlier checkpoints, lower LR) failed to find what
this one config value did.
"Then why not train at 6.0?"
Because it would land back where it started. scale sits inside the forward
pass (y + scale * (x @ A) @ B), so it is not a knob the optimizer is blind to —
gradients w.r.t. B are scaled by it, and training at a lower scale just grows
B to compensate. Confirmed by re-evaluating these same weights with the LoRA
layers rebuilt at each scale:
| scale | validation loss |
|---|
| 4.0 | 0.7460 |
| 6.0 (published) | 0.6914 |
| 8.0 (trained) | 0.6735 ← minimum |
| 10.0 | 0.6842 |
Validation loss is minimized exactly at the trained scale. So
scale 6.0 is not a better fit to the training data — it is a
deliberate under-fit that happens to score better on GSM8K. The objective
("reproduce the teacher's Spanish traces") and the metric ("get the arithmetic
right") are correlated but not identical, and any run minimizing that loss walks
straight back to 8.0-equivalent.
A sibling run demonstrated the same thing from the other direction: rank 32 at
scale 2.0, a 4× smaller scale, re-converged to the same accuracy and the same
validation loss.
The takeaway, if you are doing this on your own adapter: when a metric and a loss
disagree, an inference-time interpolation can exploit the gap and a retrain
cannot. Beating it requires changing the objective, not the hyperparameters.
scale 4.0 is a real option, with a real catch
scale 4.0 has the highest raw accuracy of the three (76.3% vs
74.2%) and the lowest truncation rate. But that advantage comes
from abandoning Spanish on hard problems, not from better reasoning:
- 20 of its 261 traces revert to English, and
15 of those 20 are correct — it inherits base-model
performance on exactly the rows it gives up on.
- On the 220 rows where both configs reasoned in Spanish,
scale 6.0 wins: 87.3% vs
84.1%.
So scale 4.0 is not the better Spanish reasoner; it is a partial fall-back to
the base model. Its language failure is also all-or-nothing rather than gradual:
every one of those 20 traces scores exactly 0.0 Spanish and reads
as fluent English from the first token ("Okay, let's see..."). Checked for partial
code-switching by scoring each trace in 400-character chunks — zero passing
traces at either scale contain an English passage, so the per-trace figure is not
hiding anything.
Pick scale 4.0 if you want maximum accuracy and can tolerate ~7% of answers
reasoning in English. Pick the published 6.0 if "reasons in
Spanish" needs to be a guarantee.
For completeness, against the base model: scale 4.0 is the only configuration
statistically indistinguishable from it (p = 0.2529), while the
published scale trails at p = 0.0402 and the trained scale at
p = 0.0002.
Where the remaining points go
Same prompt, same 283 items, both models, so regressions are
attributable per row rather than inferred from aggregate rates:
- 24 rows hit the token ceiling without closing
</think> under the adapter but not under the base model. Each is an automatic
miss.
- On the 227 rows both models completed, the base model wins
207 to 198 — so
9 rows are lost
to reasoning quality, independent of truncation.
- On those rows the adapter generates fewer tokens
(696 vs 873 mean). Not
verbosity; it is shorter and wronger, and separately loops on a different subset.
Usage
Requires
MLX on Apple silicon. Note that
adapter_path takes a
local directory, not a repo id —
mlx-lm does not
resolve adapters from the Hub, so download it first:
1pip install mlx-lm
2hf download axiom-of-choice/qwen3-1.7b-es-reasoning-lora --local-dir ./es-reasoning-lora
1from mlx_lm import load, generate
2
3model, tokenizer = load("Qwen/Qwen3-1.7B", adapter_path="./es-reasoning-lora")
4
5messages = [
6 {"role": "system", "content": "Eres un asistente experto que resuelve "
7 "problemas pensando y explicando completamente en espanol."},
8 {"role": "user", "content": "Si un tren viaja 60 km en 45 minutos, "
9 "cuanto viaja en 2 horas?"},
10]
11prompt = tokenizer.apply_chat_template(
12 messages, tokenize=False, add_generation_prompt=True, enable_thinking=True,
13)
14print(generate(model, tokenizer, prompt, max_tokens=2048))
Three things are not optional:
enable_thinking=True. Without it the chat template never opens a
<think> block, and the adapter's whole contribution lives inside that block.
- The system prompt above, verbatim. It is the one every training example used.
- The shipped
adapter_config.json. It carries scale: 6.0,
which is the measured configuration. Raising it to the trained
8.0 costs 5.3 accuracy points.
Recommended sampling: temp 0.0 and repetition_penalty 1.1. The penalty is not
cosmetic — at 1.0, truncation roughly doubles (17% → 35% measured on an earlier
checkpoint) and accuracy falls with it, because greedy decoding cannot escape a
repetition loop once it enters one. Going above 1.1 gained nothing.
Prompt sensitivity (measured at n=100, unlike everything above)
The training data prefixes 29% of its questions with "Devuelve tu respuesta final dentro de \boxed{}.". Adding that to the eval prompt moves the two models in
opposite directions:
| prompt | base model | adapter (trained scale) |
|---|
| plain question | 76.0% | 71.0% |
with the \boxed{} hint | 84.0% | 65.0% |
It gains the base model 8 points and
costs the adapter 6. Two consequences
worth stating plainly:
- Matching the training prompt makes the adapter worse, which rules out a
train/eval prompt mismatch as the cause of the accuracy gap.
- There is no single well-defined "gap". It is
5 points on the plain prompt and
19 with the hint. All headline
figures on this card use the plain prompt for both models, which is the
controlled comparison.
Training
| |
|---|
| Base model | Qwen/Qwen3-1.7B |
| Dataset | axiom-of-choice/bespoke-stratos-es, 8786 train / 976 valid |
| Method | LoRA, rank 8, dropout 0.0, 16 layers |
| Trained scale | 8.0 (published at 6.0, see above) |
| Trainable params | 4.98M (0.245% of the base model) |
| Optimizer | adamw, lr 5e-06 → 5e-07 cosine, warmup 100, weight decay 0.01 |
| Batch / seq | 4 × 2048 tokens, gradient checkpointing on |
| Stopped at | iter 707, val loss 0.7102 (2.2 h on an M-series Mac mini, 32 GB) |
| Prompt masking | yes (loss on the assistant turn only) |
Trained with a custom trainer, not mlx_lm.lora directly, for two load-bearing
reasons:
mlx_lm.lora has no gradient clipping and no NaN guard. Four runs died with
Train loss nan, one as early as iter 10 at lr 4.5e-07. The gradient norm
explodes on specific batches (measured going 4.2 → 1.8e8 → NaN while the loss
stayed finite), which no loss-based check can catch. The fix is
clip_grad_norm plus a skip guard — clipping alone is insufficient because
MLX's clip_grad_norm propagates NaN to every gradient in the tree.
16 batches were skipped this way; without the guard any one of them
would have ended training.
- Best-checkpoint tracking and early stopping, so the published weights are the
best validation loss rather than whatever the last iteration happened to be.
Weight displacement grows monotonically
lora_b initializes to exactly zero, so its Frobenius norm is how far the adapter
moved from the base model:
| iter | displacement |
|---|
| 100 | 0.600 |
| 200 | 0.854 |
| 300 | 0.977 |
| 400 | 1.055 |
| 500 | 1.111 |
| 600 | 1.149 |
| 700 | 1.178 |
It never plateaus, and it front-loads: 51% of the final
displacement is reached by iter 100, the first saved checkpoint. The
Spanish behaviour saturates early while math accuracy keeps falling — a sibling
run trained 300 iterations longer scored worse on the answers it reasoned through
(78.7% vs
83.1%, n=100).
Caveat on reading that table: a norm is a scalar and discards direction. Measured
properly, cos(ΔW_250, ΔW_1000) = 0.852 — the update keeps rotating after its
norm settles, so "most of the change happens early" is only about half true (53%
of the actual movement by iter 250, not the 75% the norms suggest).
What was tried to close the gap, and failed
Every row is a measured eval, not a guess. Recorded because a refuted hypothesis
is a result. These used n=100, so read them as directional:
| Attempt | Result |
|---|
| Lower the scale at inference | The only thing that worked: +5.3 points. |
Raise max_tokens to 4096 | Worse, 2× slower. A higher ceiling gives looping rows more rope. |
repetition_penalty 1.15 | No gain over 1.1. |
| Earlier checkpoint (iter 250) | Worse: 62.0% vs 71.0%. Less training does not help. |
| Match the training prompt | Worse for the adapter, better for the base model. |
| Bad dataset answers | Refuted: 94.9% of the dataset's answers verified correct against the source. |
| Prompt masking | +1 point, i.e. nothing measurable. |
| LoRA rank 8 → 32 | 68.0% vs 71.0%; reasoned-accuracy 76.4% vs 76.3%. 4× capacity, identical math. Also halved the weight displacement, which did not help either. |
Rows referring to other checkpoints come from sibling runs of the same recipe,
evaluated identically — evidence that the trade-off is a property of the approach,
not of one unlucky run.
English replay was also tried — 15% English traces of the same problems,
the standard remedy for catastrophic forgetting, and the only attempt that
changed the training objective rather than how the Spanish data was fitted. At
n=283: 71.0% against this adapter's
74.2%, paired p = 0.2430, so no measurable
effect either way. Its one real consequence was worse termination
(47 truncated rows
vs 36); on the rows both configurations finished
they score the same. The reasoning quality replay was meant to protect was
already intact at this scale.
So there is no known configuration of this recipe that closes the gap. Five
interventions across five training runs all landed within a few points of each
other, which suggests the cost is structural for a rank-8 adapter on a 1.7B
model rather than a bug waiting to be found.
Reproducing the evaluation
The eval set is 283 problems from
openai/gsm8k's
test split
with
only the question translated to Spanish — the ground-truth answer comes
from GSM8K's own
#### N suffix, so no re-solving and no grading model is
involved. It is a different source and a different generation path from the
training data; nothing in it was ever trained on.
Scoring: the last \boxed{} value, falling back to the last number in the
response, compared as an integer. A response is counted truncated when it hits
the token ceiling without ever closing </think>, and those count as wrong,
not as excluded — a non-terminating answer is a failure for a user.
The Spanish figure is langdetect's Spanish probability on the <think> block
only (with a fixed seed), never on the final answer. Answers are largely digits
and would score as meaningless noise; the reasoning trace is where the claim
actually lives.
Limitations
- 5.7 points below the base model on GSM8K-es (paired
p = 0.0402). Stated again here because it is the single most
important fact about this adapter.
- Evaluated on 283 problems: a bootstrap 95% CI on any single accuracy here
is about ±5 points wide. Differences between configurations are reported with a
paired McNemar test instead, which is far more sensitive because every
configuration scored the same items. Do not compare the accuracies in these
tables by eye.
- n=100 results moved by up to 4 points when re-measured at n=283, and one
conclusion reversed (
scale 4.0 overtook the published scale on raw accuracy).
Sections explicitly labelled n=100 are directional only.
- Math word problems only. No measurement on the dataset's
competitive-programming portion, on general instruction-following, on English
ability, or on any safety-relevant behaviour.
- 12.7% of generations never emit
</think>. Training rows
were capped at 2048 rendered tokens, so the model was
never shown a long reasoning trace that terminates.
- The training data is AI-generated (DeepSeek V4 Flash) and ~3.7% of its answers
are wrong, inherited teacher error. See the dataset card.
- MLX adapter format. Usable outside MLX only after conversion.
Qwen3-1.7B LoRA de razonamiento en español
También publicado para transformers/peft: axiom-of-choice/qwen3-1.7b-es-reasoning-peft -- mismos pesos del adaptador, verificados contra este (números de paridad de fase 2 en la ficha del repo enlazado). Usa
este repo con
mlx-lm; usa el enlazado para
transformers,
vLLM, o cualquier otra cosa.
Un adaptador LoRA que hace que
Qwen/Qwen3-1.7B produzca su cadena de
razonamiento
en español. Lo consigue de forma perfecta, y cuesta
5.7 puntos de precisión matemática. Ambos hechos están medidos
sobre el split de evaluación completo. Lee el trade-off antes de usarlo.
Publicado con scale 6.0, no con el 8.0 con el
que se entrenó. Bajar la escala en inferencia vale
+5.3 puntos sin perder nada de español, y ningún
reentrenamiento igualó eso. Si recreas este adaptador desde la configuración de
entrenamiento, pon scale a 6.0 tú mismo.
Qué hace y qué cuesta
Las 283 filas del split de evaluación en español, fuera del entrenamiento.
Muestreo idéntico en todo: temp 0.0, max_tokens 2048, repetition_penalty 1.1, batch 16, sin pista de \boxed{}
para ninguno de los dos modelos.
| precisión | solo razonadas | español | trazas en inglés | truncado |
|---|
| modelo base | 79.9% | 87.6% | 0.0040 | 250/251 | 11.3% |
| este adaptador | 74.2% | 84.2% | 1.0000 | 0/247 | 12.7% |
El resultado de idioma es todo el objetivo y no admite matices. Qwen3-1.7B ya hace
matemáticas; lo que no hacía era razonar en español — cambia a inglés dentro de
<think> sin importar la instrucción (el "language mixing" documentado de la
familia R1, confirmado como no arreglable por prompting en este proyecto). Con una
pregunta en español y un system prompt en español, langdetect clasificó
250 de las 251 trazas del modelo base como inglés.
Este adaptador: 0, con una confianza mínima en español de
1.0000 en las 247. Unánime en ambas
direcciones, no es un promedio que esconda varianza.
El costo es igual de real. Úsalo solo si el razonamiento en español vale más
para ti que 5.7 puntos de precisión. Si quieres respuestas correctas
en español pero no necesitas que la traza de razonamiento sea española, el
modelo base es estrictamente mejor.
Honestidad estadística: el test emparejado de McNemar exacto sobre las
54 filas en las que ambos discrepan da p = 0.0402
(35 aciertos exclusivos del base contra
19). La brecha es real, no ruido de muestreo.
Por qué se baja la escala
En mlx-lm scale multiplica directamente la actualización de bajo rango, así que
bajarlo interpola de forma continua entre el modelo base y el fine-tune con los
mismos pesos: un cambio de una línea en la configuración, sin reentrenar. Medido
sobre el split completo:
| scale | precisión | solo razonadas | español | trazas en inglés | truncado |
|---|
| 8.0 (como se entrenó) | 68.9% | 79.3% | 1.0000 | 0/241 | 14.8% |
| 6.0 (publicado) | 74.2% | 84.2% | 1.0000 | 0 | 12.7% |
| 4.0 | 76.3% | 82.0% | 0.9234 | 20/261 | 7.4% |
Con la escala de entrenamiento el adaptador saca 68.9%; con
6.0 saca 74.2%, una mejora de
5.3 puntos (p emparejado = 0.0534) con el
español todavía en 1.0000. El entrenamiento nunca destruyó
la capacidad matemática: se estaba aplicando con demasiada fuerza. Cuatro
reentrenamientos distintos (más rank, enmascarado de prompt, checkpoints
tempranos, LR más bajo) no encontraron lo que encontró este único valor de
configuración.
"¿Y por qué no entrenar directamente con 6.0?"
Porque acabaría en el mismo sitio. scale está dentro del forward pass
(y + scale * (x @ A) @ B), así que no es un parámetro que el optimizador ignore:
los gradientes respecto a B van escalados por él, y entrenar con una escala más
baja simplemente hace crecer B para compensar. Confirmado re-evaluando estos
mismos pesos con las capas LoRA reconstruidas en cada escala:
| scale | val loss |
|---|
| 4.0 | 0.7460 |
| 6.0 (publicado) | 0.6914 |
| 8.0 (entrenado) | 0.6735 ← mínimo |
| 10.0 | 0.6842 |
La val loss se minimiza exactamente en la escala de entrenamiento. Así que
scale 6.0 no ajusta mejor los datos de entrenamiento: es un
sub-ajuste deliberado que casualmente puntúa mejor en GSM8K. El objetivo
("reproducir las trazas en español del teacher") y la métrica ("acertar la
aritmética") están correlacionados pero no son lo mismo, y cualquier corrida que
minimice esa loss vuelve derecha al equivalente de 8.0.
Una corrida hermana demostró lo mismo desde el otro lado: rank 32 con
scale 2.0, una escala 4× menor, volvió a converger a la misma precisión y la
misma val loss.
La conclusión general: cuando una métrica y una loss discrepan, una interpolación
en inferencia puede explotar ese hueco y un reentrenamiento no. Para superarlo hay
que cambiar el objetivo, no los hiperparámetros.
scale 4.0 es una opción real, con una pega real
scale 4.0 tiene la precisión bruta más alta de las tres
(76.3% contra 74.2%) y la menor tasa de
truncamiento. Pero esa ventaja viene de abandonar el español en los problemas
difíciles, no de razonar mejor:
- 20 de sus 261 trazas vuelven al inglés, y
15 de esas 20 son correctas — hereda el
rendimiento del modelo base exactamente en las filas en las que se rinde.
- En las 220 filas donde ambas configuraciones razonaron en
español,
scale 6.0 gana: 87.3% contra
84.1%.
Así que scale 4.0 no razona mejor en español; es una vuelta parcial al modelo
base. Su fallo de idioma además es de todo o nada, no gradual: cada una de esas
20 trazas puntúa exactamente 0.0 de español y se lee como inglés
fluido desde el primer token ("Okay, let's see..."). Comprobamos si había
code-switching parcial puntuando cada traza en trozos de 400 caracteres:
cero trazas aprobadas en cualquiera de las dos escalas contienen un pasaje en
inglés, así que la cifra por traza no esconde nada.
Elige scale 4.0 si quieres precisión máxima y toleras que ~7% de las respuestas
razonen en inglés. Elige el 6.0 publicado si "razona en español"
tiene que ser una garantía.
Para ser completos, frente al modelo base: scale 4.0 es la única configuración
estadísticamente indistinguible de él (p = 0.2529), mientras la
escala publicada queda por detrás con p = 0.0402 y la escala de
entrenamiento con p = 0.0002.
A dónde se van los puntos restantes
Mismo prompt, mismos 283 ítems, los dos modelos, así que las
regresiones se atribuyen fila por fila y no se infieren de tasas agregadas:
- 24 filas agotan el presupuesto de tokens sin cerrar
</think> con el adaptador pero no con el modelo base. Cada una es un fallo
automático.
- En las 227 filas que ambos completaron, el modelo base gana
207 a 198 — así que
9 filas se
pierden por calidad de razonamiento, independientemente del truncamiento.
- En esas filas el adaptador genera menos tokens
(696 contra 873 de
media). No es verborrea: es más corto y más equivocado, y aparte entra en bucle
en un subconjunto distinto.
Uso
Ver el ejemplo de código en la sección en inglés. Tres cosas no son opcionales:
enable_thinking=True en apply_chat_template (sin eso la plantilla nunca abre
el bloque <think>, que es donde vive toda la contribución del adaptador); el
system prompt exacto que usó cada ejemplo de entrenamiento; y el
adapter_config.json que se distribuye, que lleva scale: 6.0,
la configuración medida.
Eres un asistente experto que resuelve problemas pensando y explicando
completamente en espanol.
Muestreo recomendado: temp 0.0 y repetition_penalty 1.1. La penalización no es
cosmética — con 1.0 el truncamiento casi se duplica (17% → 35% medido en un
checkpoint anterior) y la precisión cae con él, porque el decodificado greedy no
puede salir de un bucle de repetición una vez que entra. Subir de 1.1 no aportó
nada.
Entrenamiento
Detalles completos en la tabla de la sección en inglés. Lo relevante: LoRA rank
8 sobre 16 capas
(4.98M parámetros entrenables,
0.245% del modelo), adamw con
lr 5e-06, detenido en la iteración 707 con val loss
0.7102, entrenado con scale 8.0 y publicado con
scale 6.0.
Entrenado con un trainer propio, no con mlx_lm.lora directamente, porque
mlx_lm.lora no tiene clipping de gradiente ni guarda contra NaN. Cuatro
corridas murieron con Train loss nan, una en la iteración 10 con lr 4.5e-07. La
causa: en batches concretos la norma del gradiente explota (medido: 4.2 → 1.8e8 →
NaN mientras la loss seguía siendo finita), algo que ninguna comprobación basada
en la loss puede detectar. El arreglo es clip_grad_norm más un guard de salto;
el clipping solo no basta porque el clip_grad_norm de MLX propaga el NaN a todos
los gradientes del árbol. 16 batches se saltaron así en esta corrida;
sin el guard, cualquiera de ellos habría matado el entrenamiento.
Limitaciones
- 5.7 puntos por debajo del modelo base en GSM8K-es (p emparejado
= 0.0402). Se repite aquí porque es el hecho más importante sobre
este adaptador.
- Evaluado en 283 problemas: un intervalo de confianza bootstrap al 95% sobre
cualquier precisión individual mide unos ±5 puntos. Las diferencias entre
configuraciones se reportan con un test emparejado de McNemar, mucho más
sensible porque todas las configuraciones evaluaron los mismos ítems. No
compares a ojo las precisiones de estas tablas.
- Los resultados con n=100 se movieron hasta 4 puntos al re-medirlos con
n=283, y una conclusión se invirtió (
scale 4.0 superó a la escala
publicada en precisión bruta). Las secciones etiquetadas como n=100 son solo
indicativas.
- Solo problemas matemáticos de enunciado. Sin medición sobre la parte de
programación competitiva del dataset, sobre seguimiento de instrucciones
general, sobre capacidad en inglés, ni sobre ningún comportamiento relevante
para seguridad.
- 12.7% de las generaciones nunca emiten
</think>. Las
filas de entrenamiento se cortaron en 2048 tokens
renderizados, así que el modelo nunca vio una traza de razonamiento larga que
termine.
- Los datos de entrenamiento son generados por IA (DeepSeek V4 Flash) y ~3.7% de
sus respuestas son incorrectas, error heredado del teacher. Ver la card del
dataset.
- Formato de adaptador MLX. Usable fuera de MLX solo tras conversión.