Phase 6: train a second LoRA for real Penpot UI design capability #5
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,134 @@
|
|||||||
|
"""Re-escanea resultados YA MEDIDOS de la puerta 5 con la lista de comportamiento prohibido
|
||||||
|
CORREGIDA (post hallazgo 54: `board.flex.appendChild` no esta roto, se saco del veto), sin volver
|
||||||
|
a correr el modelo ni tocar Penpot. Los payloads de `code` ya quedaron guardados en los JSON de
|
||||||
|
resultados, asi que el veto se puede recalcular offline con `scan_forbidden` / `score_prompt` del
|
||||||
|
propio scripts/35_gate5_penpot_design.py (fuente de verdad unica, nunca se reimplementa la logica).
|
||||||
|
|
||||||
|
python3 scripts/36_gate5_rescan_veto.py
|
||||||
|
|
||||||
|
Escribe *-corrected.json junto a cada archivo de entrada. No modifica los originales.
|
||||||
|
"""
|
||||||
|
import importlib.util
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
GATE5_PATH = REPO_ROOT / "scripts" / "35_gate5_penpot_design.py"
|
||||||
|
|
||||||
|
FILES_HOLDOUT = [REPO_ROOT / "data" / "gate5_holdout_v2b-bf16-holdout.json"]
|
||||||
|
FILES_FULL = [
|
||||||
|
REPO_ROOT / "data" / "gate5_results_v2b-bf16-full.json",
|
||||||
|
REPO_ROOT / "data" / "gate5_results_v2b-bf16-generalization.json",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def load_gate5_module():
|
||||||
|
spec = importlib.util.spec_from_file_location("gate5_penpot_design", GATE5_PATH)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
def rescan_holdout(gate5, path):
|
||||||
|
data = json.loads(path.read_text(encoding="utf-8"))
|
||||||
|
patrones = {}
|
||||||
|
con_api_prohibida = 0
|
||||||
|
cambios = []
|
||||||
|
for r in data["resultados"]:
|
||||||
|
veto_hits = []
|
||||||
|
for code in r.get("code_payloads", []):
|
||||||
|
veto, _otros = gate5.scan_forbidden(code)
|
||||||
|
veto_hits.extend(veto)
|
||||||
|
antes = bool(r.get("veto_hits"))
|
||||||
|
r["veto_hits"] = veto_hits
|
||||||
|
despues = bool(veto_hits)
|
||||||
|
if antes != despues:
|
||||||
|
cambios.append({"id": r.get("id"), "antes_vetado": antes, "despues_vetado": despues})
|
||||||
|
if despues:
|
||||||
|
con_api_prohibida += 1
|
||||||
|
for hit in veto_hits:
|
||||||
|
patrones[hit["patron"]] = patrones.get(hit["patron"], 0) + 1
|
||||||
|
total = data["total"]
|
||||||
|
tasa = con_api_prohibida / total if total else 0.0
|
||||||
|
data["con_api_prohibida"] = con_api_prohibida
|
||||||
|
data["tasa"] = tasa
|
||||||
|
data["aprueba"] = tasa <= data["umbral"]
|
||||||
|
data["patrones"] = patrones
|
||||||
|
data["_rescan_veto_corregido"] = {
|
||||||
|
"motivo": "hallazgo 54: board.flex.appendChild no esta roto, se sacio del veto de comportamiento prohibido",
|
||||||
|
"cambios_por_prompt": cambios,
|
||||||
|
}
|
||||||
|
return data, cambios
|
||||||
|
|
||||||
|
|
||||||
|
def rescan_full(gate5, path):
|
||||||
|
data = json.loads(path.read_text(encoding="utf-8"))
|
||||||
|
cambios = []
|
||||||
|
scores_antes = []
|
||||||
|
scores_despues = []
|
||||||
|
for p in data["prompts"]:
|
||||||
|
score_antes = p["score"]
|
||||||
|
scores_antes.append(score_antes)
|
||||||
|
veto_hits = []
|
||||||
|
for entry in p.get("code_payloads", []):
|
||||||
|
code = entry["code"] if isinstance(entry, dict) else entry
|
||||||
|
veto, _otros = gate5.scan_forbidden(code)
|
||||||
|
veto_hits.extend(veto)
|
||||||
|
p["veto_hits"] = veto_hits
|
||||||
|
p["metricas_crudas"]["forbiddenBehavior"] = len(veto_hits)
|
||||||
|
raw = p["metricas_crudas"]
|
||||||
|
resultado = gate5.score_prompt(p["id"], raw)
|
||||||
|
p["score"] = resultado["score"]
|
||||||
|
p["pasadas"] = resultado["pasadas"]
|
||||||
|
p["aplicables"] = resultado["aplicables"]
|
||||||
|
p["veto_violado"] = resultado["veto_violado"]
|
||||||
|
p["metricas"] = resultado["metricas"]
|
||||||
|
scores_despues.append(resultado["score"])
|
||||||
|
if resultado["score"] != score_antes:
|
||||||
|
cambios.append({"id": p["id"], "score_antes": score_antes, "score_despues": resultado["score"]})
|
||||||
|
score_medio_antes = sum(scores_antes) / len(scores_antes) if scores_antes else 0.0
|
||||||
|
score_medio_despues = sum(scores_despues) / len(scores_despues) if scores_despues else 0.0
|
||||||
|
veto_limpio_despues = sum(1 for p in data["prompts"] if not p["veto_violado"])
|
||||||
|
prompts_60_despues = sum(1 for p in data["prompts"] if p["score"] >= 60)
|
||||||
|
data["_rescan_veto_corregido"] = {
|
||||||
|
"motivo": "hallazgo 54: board.flex.appendChild no esta roto, se sacio del veto de comportamiento prohibido",
|
||||||
|
"score_medio_antes": round(score_medio_antes, 2),
|
||||||
|
"score_medio_despues": round(score_medio_despues, 2),
|
||||||
|
"veto_limpio_despues": f"{veto_limpio_despues}/{len(data['prompts'])}",
|
||||||
|
"prompts_60_despues": f"{prompts_60_despues}/{len(data['prompts'])}",
|
||||||
|
"cambios_por_prompt": cambios,
|
||||||
|
}
|
||||||
|
return data, cambios
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
gate5 = load_gate5_module()
|
||||||
|
|
||||||
|
for path in FILES_HOLDOUT:
|
||||||
|
if not path.exists():
|
||||||
|
print(f"[SKIP] {path} no existe")
|
||||||
|
continue
|
||||||
|
data, cambios = rescan_holdout(gate5, path)
|
||||||
|
out = path.with_name(path.stem + "-corrected.json")
|
||||||
|
out.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||||
|
print(f"[HOLDOUT] {path.name}: con_api_prohibida={data['con_api_prohibida']} "
|
||||||
|
f"tasa={data['tasa']:.4f} aprueba={data['aprueba']} patrones={data['patrones']}")
|
||||||
|
print(f" cambios: {cambios}")
|
||||||
|
print(f" -> {out}")
|
||||||
|
|
||||||
|
for path in FILES_FULL:
|
||||||
|
if not path.exists():
|
||||||
|
print(f"[SKIP] {path} no existe")
|
||||||
|
continue
|
||||||
|
data, cambios = rescan_full(gate5, path)
|
||||||
|
out = path.with_name(path.stem + "-corrected.json")
|
||||||
|
out.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8")
|
||||||
|
info = data["_rescan_veto_corregido"]
|
||||||
|
print(f"[FULL] {path.name}: score_medio {info['score_medio_antes']} -> {info['score_medio_despues']} "
|
||||||
|
f"veto_limpio_despues={info['veto_limpio_despues']} prompts_60_despues={info['prompts_60_despues']}")
|
||||||
|
print(f" cambios: {cambios}")
|
||||||
|
print(f" -> {out}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user