Tutorial: LLM de tercero afinado con LoRA (crédito SGCD)
✅ Estable — El reproductor es REAL: el pipeline DVC afina LittleLamb 0.3B con LoRA en GPU y mide la evidencia. El arco entero —rojo (V1 base) → ámbar (V2 LoRA) → aprobado— está publicado en el repositorio y sus cuatro etiquetas las vigila el nightly. Las cifras de precisión que se citan (AUC) son observaciones del build dorado, no números derivados en la doc: el curso no los reclama como veredicto (línea futura), igual que en los Niveles 2 y 4.
Este tutorial recorre el sistema pilot-banco-atlantico-credito-llm: un LLM que evalúa la solvencia de solicitudes de crédito al consumo. Es el reproductor del repositorio de demostración público vldemo-santander-credit, y su historia es la del modelo de tercero como riesgo gobernado:
- El motor de puntuación es LittleLamb 0.3B (Multiverse Computing, Apache-2.0), comprimido desde Qwen3-0.6B con la tecnología CompactifAI. El banco no lo entrena: lo integra como GPAI de tercero — es el integrador del EU AI Act (Art. 25), con las obligaciones de exactitud, robustez y seguridad del Art. 15.
- Los datos son el SGCD (Stressed German Credit Dataset, Santander AI Lab, CC-BY-4.0,
SGCD-v0.1): 1.000 solicitudes reales derivadas del Statlog German Credit, con perturbaciones documentadas («shocks») en dos ejes ortogonales. - El banco operador es ficticio — «Banco Demo Atlántico SA», con un LEI inventado. Solo el dataset (Santander AI Lab) y el modelo (Multiverse Computing) son fuentes públicas reales; el resto es una plantilla de gobernanza de demostración, no un sistema de puntuación real.
Es un sistema de alto riesgo: puntuación crediticia automatizada (EU AI Act Anexo III §5(b)) operada por una entidad financiera → activo TIC sujeto a DORA (Reg. UE 2022/2554). La fuente de verdad de este tutorial es el guion steps/ del repositorio: los comandos, los mensajes de commit, los diffs y el color de cada barrera no están escritos a mano — cada bloque los lee del guion publicado. Si un paso no existiera, el build fallaría; lo que lees es exactamente lo que el repositorio hace.
Lo que aprenderás:
- Cómo se gobierna un LLM de tercero (GPAI, Art. 25) sin reentrenarlo: el fine-tuning LoRA es un cambio de parámetro versionado en git y, por tanto, un tratamiento de riesgo (ISO 23894 §6.5) atribuible y reproducible.
- Por qué la V1 base sale ROJA (precisión casi aleatoria) y el LoRA la lleva a un ÁMBAR honesto (la precisión pasa el umbral, pero la robustez sobre los inputs contradictorios queda inconclusa por muestra pequeña) — sin fabricar un verde.
- Cómo los cuatro riesgos por shock del SGCD (F1 ausencia · F2 ambigüedad · F4 contradicción + un eje cosmético ortogonal) se declaran antes del modelo, cada uno con una cobertura gateada que atestigua que la clase está representada en la cohorte de medición.
- Cómo la conformidad se gatea por entitlement (las normas de pago exigen una licencia firmada) y cómo la aprobación acepta conscientemente el residual ámbar, con el motivo del auditor en acta.
- El contraste con el Nivel 4 · Crédito al consumo: allí el modelo es una regresión logística entrenada en el propio pipeline; aquí es un LLM de tercero y el tratamiento es un fine-tuning, no un reentrenamiento desde cero.
Los tres papeles del ciclo aparecen desde el primer hito: Nerea (producto · declara identidad, encuadre y riesgos), Marta (desarrollo · trae datos, mide, trata y firma desde la CLI) y Diego (calidad · acepta el residual y aprueba). Las etiquetas de rol de cada bloque de abajo salen del who del guion.
El arco, hito a hito
Sección titulada «El arco, hito a hito»Arrancar el repo y declarar la identidad y el encuadre §5(b) + DORA
Sección titulada «»El repositorio arranca como un proyecto uv + DVC (sin SCM todavía), con el README del reproductor. Después, la PO declara quién es el sistema y qué rol regulatorio ocupa el banco: froga.yaml crece por commits del manifiesto — identidad (v0), y luego el encuadre con los estándares aplicables y la clasificación §5(b) + DORA declarada por un humano.
15
git init -q -b maingit config user.email marta@demo.seigarrena.devgit config user.name "Marta Demo"uv init --bare --name vldemo-santander-credit --python 3.12patch: pyproject-index.patchuv add "dvc>=3" pyyaml froga "venturalitica==0.6.11" transformers torch peft accelerate pyarrow pandas scikit-learnpatch: gitignore.patchpatch: gitattributes.patchpatch: readme.patchuv syncuv run dvc init --no-scm -quv run dvc config core.analytics falsefroga pubkey --out .froga/PUBKEY.txtgit add -Agit commit -m "init: repo, proyecto uv (deps reales) y README del reproductor"
En el diff del encuadre se ve lo esencial: context.applicable_standards enumera prEN 18228, ISO 23894, EU AI Act y DORA; la entidad DORA (ficticia) queda declarada; y classification.tier: high se justifica en palabras — «evaluación de solvencia §5(b)» + «riesgo TIC de la entidad financiera (DORA Art. 6)». El motor no infiere el nivel: una persona lo declara y lo asume.
Traer los datos del SGCD y declarar el programa de riesgos (antes del modelo)
Sección titulada «»Antes de que exista modelo, se traen los datos reales y se fija el programa de riesgos con sus barreras numéricas. Es RDD puro: primero se declara contra qué se va a medir; el modelo viene después.
Cada solicitud del SGCD viene en doble vista: una json_view estructurada (el registro tal como consta) y una text_view en lenguaje natural. El LLM puntúa sobre la text_view — y ahí es donde los shocks del dataset importan, porque el modelo solo ve el texto:
{ "id": "SGCD-0000", "label": 0, "metadata": { "shock_semantic": "F0", "shock_cosmetic": false }, "value": { "json_view": { "duration": 9, "credit_amount": 1366, "age": 22, "personal_status_sex": "A92", "...": "..." }, "text_view": "Checking account status: < 0 DM. Credit duration: 9 months. ... Personal status: female : divorced/separated/married. ... Age: 22 years old. ... Foreign worker: yes." }}El paso de rasgos (featurize.py) carga el SGCD, deriva sex de personal_status_sex y produce los parquet de entrenamiento y evaluación. Todavía sin modelo ni dvc.yaml: solo el primer eslabón del pipeline.
Y ahora el corazón de este hito: la PO declara el programa de riesgos completo (risk.risks[]) con sus barreras numéricas, antes de tener un solo número medido. El diff de este commit es el programa entero:
Los cuatro riesgos por shock son los protagonistas. El SGCD documenta que sus inputs vienen degradados en dos ejes ortogonales, y el manifiesto identifica un riesgo hermano por cada clase — cada uno con una medida de cobertura (shock-coverage-*) que atestigua, con una barrera bloqueante > 0,99, que esa clase de shock está representada en la cohorte de medición (ISO 23894 §6.4.2):
| Clase de shock | Riesgo | Qué le pasa a la text_view | Medida (barrera > 0,99) |
|---|---|---|---|
| F1 · ausencia (12,8 %) | risk.data-quality-shock-f1-missingness | un campo desaparece del texto; el modelo decide como si no existiera | shock-coverage-f1 |
| F2 · ambigüedad (11,5 %) | risk.data-quality-shock-f2-ambiguity | un valor preciso se vuelve una redacción vaga | shock-coverage-f2 |
| F4 · contradicción (6,0 %) | risk.data-quality-shock-f4-contradiction | el texto afirma un valor válido distinto del estructurado — nada «parece» roto | shock-coverage-f4 |
| Cosmético (13,5 %, ortogonal) | risk.data-quality-shock-f3-cosmetic | ruido de formato: orden de campos, delimitadores, cifras vagas («unos 13 meses») | shock-coverage-cosmetic |
El eje semántico (F1/F2/F4) y el cosmético son independientes y co-ocurren: un registro puede llevar ambos. El manifiesto declara además el riesgo de precisión (que la V1 base incumplirá, y que el LoRA tratará), el de robustez sobre F4 (la peor condición, analizada con IC bootstrap) y los de equidad (paridad por sexo), abstención (el LLM nunca abstiene) y supervisión humana (Art. 14).
Medir la V1 base: la barrera de precisión sale en rojo
Sección titulada «»Marta compila primero el plan de evaluación OSCAL desde froga.yaml —el contrato de la barrera: qué controles se miden y con qué umbral—. froga compile no necesita modelo: compila el OSCAL desde la declaración.
froga compilegit add -Agit commit -m "compile: assessment plan OSCAL (contrato del gate, antes del modelo)"
Ahora añade el modelo base V1 —LittleLamb 0.3B sin fine-tuning (mitigate: false en params.yaml)— y corre la evidencia. froga run reproduce el pipeline, mide los controles y aplica la barrera:
patch: params.patchpatch: dvc-model.patchpatch: train-llm.patchpatch: infer.patchpatch: evaluate.patchpatch: characterize.patchpatch: compliance-eval.patchfroga runpuede fallargit add -Agit commit -m "modelo: LittleLamb base V1 (train/infer/evaluate + dvc.yaml) — run: V1 evidencia base (gate RED esperado; seed=42)"
El resultado es ROJO. LittleLamb 0.3B es un modelo comprimido de propósito general, sin ajuste al dominio crediticio: sobre la text_view produce puntuaciones casi aleatorias —en el build dorado, un AUC limpio observado del orden de 0,42–0,54— por debajo del mínimo de precisión que exige una decisión de crédito automatizada (Art. 15, barrera > 0,65). froga run sale con código ≠ 0 —de ahí el aviso «puede fallar»— pero el paquete queda firmado y anclado: un ROJO también es evidencia, registrada honestamente. El chip «reproducir» clona la etiqueta santander-v1.0.0-llm-base y reproduce este mismo color.
Tratar con LoRA y re-medir: ámbar honesto, infrapotenciado
Sección titulada «»El tratamiento no reentrena el modelo desde cero ni edita el umbral: activa el fine-tuning LoRA sobre las solicitudes etiquetadas del banco. En el repositorio ese cambio es un único booleano en params.yaml —el diff es el tratamiento— y, con el LoRA activo, el mismo paso re-mide: trata y re-mide en un solo paso.
git checkout -b tratamiento/afina-lorapatch: params-mitigate.patchfroga runpuede fallargit add -Agit commit -m "treatment: afina el modelo LittleLamb con LoRA sobre las solicitudes etiquetadas del SGCD — ISO 23894 §6.5 (tratamiento: REDUCE → re-medición)"
Cambiar mitigate a true es el tratamiento ISO 23894 §6.5: un cambio de parámetro versionado en git —con autoría, fecha y mensaje— que el motor atribuye a la reducción del riesgo de precisión. Es el §6.5 del bucle de tratamiento, proyectable a la norma que proceda.
El resultado es ÁMBAR honesto. El fine-tuning eleva el AUC limpio observado a ≈ 0,71 (build dorado) → pasa la barrera de precisión. Pero la robustez sobre los inputs contradictorios (F4, la peor condición) queda inconclusa: la caída de AUC bajo F4 es pequeña, pero la muestra es diminuta (n = 60) y el IC bootstrap es ancho → cruza el umbral. El motor marca el control inconcluso y el veredicto es ÁMBAR, no un verde fabricado.
Gobernanza: conformidad gateada, aprobación consciente y re-emisión
Sección titulada «»Con la V2 tratada, Marta emite la conformidad por norma + el reconstruct del ciclo, firmados. Aquí aparece el entitlement: froga conformance proyecta el mismo paquete sobre cada estándar aplicable, pero las normas de pago exigen una licencia firmada.
patch: entitlement.patchfroga conformance --standard eu/pren-18228@2026 --outpuede fallarfroga conformance --standard iso/23894@2023 --outpuede fallarfroga conformance --standard eu/ai-act@2024 --outpuede fallarfroga conformance --standard eu/dora@2022 --outpuede fallarfroga reconstruct --outpuede fallargit add -Agit commit -m ".froga: conformance + reconstruct firmados"
El fichero .froga/entitlement.json es un DSSE firmado (predicado in-toto entitlement/v1) que declara qué estándares puede emitir el sistema. Su carga útil, para este sistema, habilita dos normas de pago:
{ "predicateType": "https://venturalitica.ai/entitlement/v1", "predicate": { "systemId": "pilot-banco-atlantico-credito-llm", "org": "demo", "entitledStandards": ["eu/pren-18228@2026", "eu/dora@2022"], "issuedAt": "2026-07-14T00:00:00Z", "expiresAt": "2099-01-01T00:00:00Z", "...": "..." }}El motor separa las normas en dos tiers: ISO 23894 es gratis (nunca exige entitlement — es la barrera base del open-core, la misma frontera que enseña el Quickstart); prEN 18228 y DORA son de pago y aquí las habilita este entitlement firmado. Una norma de pago sin entitlement válido saldría Unlicensed; una norma sin catálogo proyectable —como el propio EU AI Act, la regulación raíz, que no está en el registro de normas— no produce veredicto («sin catálogo»). Por eso cada froga conformance del paso lleva allowFailure: la norma no habilitada sale Unlicensed y la no registrada no emite veredicto, sin abortar el paso. En este expediente se emiten ISO 23894, prEN 18228 y DORA; la proyección de EU AI Act no produce veredicto.
Marta solicita la aprobación (un acto de ciclo de vida; el acto firmado .froga/acts/NNNN-request.json lo emite froga):
solicitud de aprobación del plan de tratamiento (el acto lo commitea froga request)Y ahora la pieza de gobernanza: Diego, calidad, aprueba — pero el residual es ÁMBAR, así que no es un visto bueno automático. Es una aceptación consciente, y el portal exige el motivo del auditor en acta:
Motivo: «Aceptación consciente del residual ámbar: el control bloqueante de precisión (risk.credit-accuracy) certifica en VERDE tras el tratamiento LoRA (V2, AUC limpio ≈ 0.71 por encima del umbral > 0.65), pero la caída de robustez sobre F4 (risk.robustness-shock, n=60) queda INCONCLUSA por IC bootstrap ancho y el residual global agregado excede el apetito MEDIUM; se aprueba con el gap documentado y revisión semestral (P6M). Remedio real: ampliar la cohorte F4 para dar potencia estadística a la medición de robustez (Art.15, línea futura).»
La aprobación es un acto git-nativo y firmado: un acto DSSE .froga/acts/NNNN-approve.json —firmado ECDSA-P256 y verificado contra la clave de Diego declarada en signers:— que registra la identidad del aprobador y viaja con la historia. El commit que lo añade es texto plano, sin firma GPG (no esperes la insignia «Verified» al pincharlo en GitHub), pero el acto sí va criptográficamente firmado; y junto a él van firmadas —ECDSA-P256 + DSSE— la evidencia (bundle.json.sig, reconstruct.json.sig) y las conformidades. El motivo —la caída de robustez sobre F4 (n = 60) inconclusa por IC ancho, el residual agregado por encima del apetito y la revisión semestral (P6M)— queda registrado en el acta del portal: la aprobación desde la interfaz exige ese textarea; la CLI, que no admite --reason, lo omite con aviso. El acto firmado dice quién aprobó por su firma, como acto atribuible en git; el acta guarda por qué; la firma prueba que el acto y el paquete están intactos.
Con la aprobación real en la historia git, Marta re-emite la conformidad: froga conformance deriva el ciclo de la historia y ahora ve la aprobación. La cláusula de revisión de gestión de riesgo (prEN 18228 cl. 11, satisfecha por la evidencia de aprobación) pasa de Gap a Cubierta al leer el acto de aprobación .froga/acts/NNNN-approve.json. La de residual global (cl. 10) ya salía Cubierta desde la primera emisión: el residual agregado (ALTO) queda dentro del criterio declarado (overall_residual_criterion: HIGH). Lo que excede es el apetito (MEDIO) — y esa señal es justo la que obligó a la aceptación consciente con el motivo del auditor en acta: el expediente no maquilla el residual, lo gobierna. El agregado se re-firma.
froga conformance --standard eu/pren-18228@2026 --outpuede fallarfroga conformance --standard iso/23894@2023 --outpuede fallarfroga conformance --standard eu/ai-act@2024 --outpuede fallarfroga conformance --standard eu/dora@2022 --outpuede fallarfroga reconstruct --outpuede fallargit add -Agit commit -m ".froga: re-emisión de conformance + reconstruct tras aprobar (cl.11 = Approved)"
Lo que este tutorial demuestra
Sección titulada «Lo que este tutorial demuestra»- Un LLM de tercero (LittleLamb 0.3B, GPAI, Art. 25) gobernado como sistema de alto riesgo §5(b) + DORA, sin reentrenarlo: el banco es el integrador.
- El fine-tuning LoRA como tratamiento (ISO 23894 §6.5): un cambio de parámetro versionado en git —el diff es la evidencia—, no un reentrenamiento opaco.
- Un arco honesto en los dos extremos: la V1 base es ROJA (precisión casi aleatoria, real), la V2 LoRA es ÁMBAR (precisión apta, robustez sobre F4 inconclusa por n = 60) — sin verdes fabricados.
- Cuatro riesgos por shock (F1/F2/F4 semánticos + eje cosmético ortogonal) declarados antes del modelo, cada uno con cobertura gateada que atestigua su representación en la cohorte.
- Conformidad gateada por entitlement: ISO 23894 gratis; prEN 18228 y DORA de pago, habilitadas por una licencia DSSE firmada; una norma sin licencia (
Unlicensed) o sin catálogo proyectable (EU AI Act) falla sin abortar (allowFailure). - Aceptación consciente del residual ámbar (dentro del criterio declarado, por encima del apetito) con el motivo del auditor en acta (aprobación como acto firmado git-nativo
.froga/acts/NNNN-approve.json, evidencia firmada) + re-emisión que pasa cl. 11 a Cubierta.