From 34f30bfe2b3f25b58cd4d006665bc15054e421f1 Mon Sep 17 00:00:00 2001 From: Sergio Date: Sat, 12 Sep 2026 02:29:03 +0000 Subject: [PATCH] =?UTF-8?q?ia-modelo-embeddings:=20el=20guardi=C3=A1n=20pr?= =?UTF-8?q?obado=20EN=20EL=20HUB=20antes=20de=20gastar=20un=20turno=20de?= =?UTF-8?q?=20build=20=E2=80=94=20tres=20fallos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El guardián nuevo (tokeniza español + el espacio distingue) se corrió a mano contra el modelo antes de esperar el lock, y estaba mal de tres formas distintas: 1. **`cos` es una función interna de awk**, así que `cos[2]` muere con un `syntax error` que no menciona el nombre. Se llama `cs`. 2. el `sed` que partía por corchete de apertura **se comía el último vector** (salían 2 de 3, y el `test -ge 3` lo habría cazado, pero fallando por el motivo equivocado). Ahora `grep -o` por el corchete completo. 3. y los backslashes iban DOBLES: en un literal TOML de comilla triple no se escapan, así que la shell recibía `\\n` y `tr` se ponía a borrar las letras «n». Y una cuarta, de mi propio comentario: al explicar el punto 3 escribí la comilla triple **dentro** de la cadena que empieza con comilla triple. Cerró el literal y el TOML dejó de parsear, con el error apuntando a la línea del comentario. Queda avisado ahí mismo. Verificado en el hub: guardián 2 → 11 y 14 tokens distintos, 0 comunes; guardián 3 → gato~perro=0,8436 contra gato~cortafuegos=0,6292. Los dos PASAN con el modelo bueno. --- recipes/ia-modelo-embeddings.toml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/recipes/ia-modelo-embeddings.toml b/recipes/ia-modelo-embeddings.toml index ef0ce177..89891acc 100644 --- a/recipes/ia-modelo-embeddings.toml +++ b/recipes/ia-modelo-embeddings.toml @@ -79,7 +79,7 @@ test "$n" -gt 500000000 || { echo "!! el GGUF pesa $n bytes: está truncado" >&2 # aparece semanas después como «la búsqueda devuelve siempre lo mismo». Dos frases SIN palabras en # común tienen que dar conjuntos de tokens distintos; si todo cae en el mismo id de desconocido, se # parecen demasiado y esto falla. -tok() { llama-tokenize --model "$M" --prompt "$1" 2>/dev/null | sed 's/ *\\([0-9]*\\) ->.*/\\1/' | sort -u; } +tok() { llama-tokenize --model "$M" --prompt "$1" 2>/dev/null | sed 's/ *\([0-9]*\) ->.*/\1/' | sort -u; } tok "el cortafuegos bloquea la salida de una aplicación" > /tmp/t1 tok "un minino atigrado dormía sobre las tejas del tejado" > /tmp/t2 c1=$(wc -l < /tmp/t1); c2=$(wc -l < /tmp/t2); comunes=$(comm -12 /tmp/t1 /tmp/t2 | wc -l) @@ -112,13 +112,21 @@ curl -s --unix-socket "$S" -H 'Content-Type: application/json' \ -d '{"input":["gato","perro","cortafuegos"]}' http://localhost/v1/embeddings > /tmp/emb.json kill $SRV 2>/dev/null # Los tres vectores, uno por línea, y el coseno en awk: el lab no trae python y para esto alcanza. -tr -d ' \\n' < /tmp/emb.json | sed 's/.*"data"://' | tr '[' '\\n' | sed -n 's/^\\([-0-9.,e]*\\)\\].*/\\1/p' > /tmp/vs +# ⚠ OJO CON LOS BACKSLASHES: esto es un literal TOML de comilla triple, así que NO se escapan — lo +# que se escribe es lo que ve la shell. Un backslash DOBLE manda dos caracteres, y entonces `tr` se +# pone a borrar las letras «n». (Y ojo también con teclear una comilla triple en un comentario de +# acá: cierra la cadena y el TOML deja de parsear. Pasó, y el error señala a la línea del comentario.) +# ⚠ Las dos cosas de abajo se probaron EN EL HUB antes de gastar un turno de build, y las dos +# estaban mal en el primer intento: un `sed` por corchete de apertura se comía el último vector +# (salían 2 de 3), y el arreglo no puede llamarse `cos` — **`cos` es una función interna de awk** y +# el script muere con un `syntax error` que no menciona el nombre. +tr -d ' \n' < /tmp/emb.json | grep -o '\[[-0-9.,e]*\]' | tr -d '[]' > /tmp/vs test "$(wc -l < /tmp/vs)" -ge 3 || { echo "!! no salieron tres vectores" >&2; head -c 300 /tmp/emb.json >&2; exit 1; } -awk -F, 'NR<=3{n=0;s=0;for(i=1;i<=NF;i++){v[NR,i]=$i;s+=$i*$i;n++};len[NR]=sqrt(s);cols=n} +awk -F, 'NR<=3{s=0;for(i=1;i<=NF;i++){v[NR,i]=$i;s+=$i*$i};len[NR]=sqrt(s);cols=NF} END{ - for(p=2;p<=3;p++){d=0;for(i=1;i<=cols;i++)d+=v[1,i]*v[p,i];cos[p]=d/(len[1]*len[p])} - printf "guardián: gato~perro=%.4f gato~cortafuegos=%.4f\\n", cos[2], cos[3] - if (cos[2] <= cos[3] + 0.02) { + for(p=2;p<=3;p++){d=0;for(i=1;i<=cols;i++)d+=v[1,i]*v[p,i];cs[p]=d/(len[1]*len[p])} + printf "guardián: gato~perro=%.4f gato~cortafuegos=%.4f\n", cs[2], cs[3] + if (cs[2] <= cs[3] + 0.02) { print "!! el espacio no distingue: un gato se parece a un cortafuegos tanto como a un perro" > "/dev/stderr" exit 1 }