Encontrar datos personales antes de enviarlos
Un dato personal es cualquier dato sobre una persona viva que permita identificarla. Un nombre, un correo y un teléfono lo son.
Una aplicación que envía mensajes a un modelo puede enviarlos sin querer. No puedes proteger lo que no encuentras, así que buscar va primero. Aquí escribes un buscador y ves hasta dónde llega.
Al final de esta lección
Nota
Puedo encontrar datos personales en un mensaje con reglas y decir qué se les escapa.
Palabras clave
| Palabra | Qué significa | Ejemplo |
|---|---|---|
| Dato personal | un dato que apunta a una persona viva | |
| Regla | una prueba que un texto supera o no | tiene una arroba |
| Forma | cómo se escribe un tipo de valor | 600000001 |
| Falsa alarma | un texto que la regla marca y no es personal | |
| Omisión | un dato personal que las reglas no marcaron |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Las reglas encuentran datos con forma
Algunos datos personales se escriben siempre igual. Un correo tiene una arroba y un punto. Un móvil español tiene 9 dígitos y empieza por 6 o por 7.
Una regla prueba una forma. Un buscador parte un mensaje en palabras y prueba cada palabra con cada regla. Lo que halla sale en el orden de las palabras del mensaje, no en el orden de las reglas.
Ejemplo resuelto: cuatro reglas
| Tipo | Regla | Ejemplo inventado |
|---|---|---|
| correo | Una arroba y un punto después | [email protected] |
| telefono | 9 dígitos, el primero 6 o 7 | 600000001 |
| dni | Ocho dígitos y una letra mayúscula | 00000000U |
| tarjeta | 16 dígitos | 4000000000000002 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Las reglas fallan y dan falsas alarmas
Una regla solo conoce formas. Un nombre no tiene forma, así que ninguna regla lo halla. Un teléfono escrito con espacios se parte en tres palabras y ninguna encaja.
Una falsa alarma es el fallo contrario. Un número de pedido de 16 dígitos tiene la forma de una tarjeta, y la regla lo marca. Los dos fallos son normales. Cuéntalos para saber cuánto fiarte de las reglas.
Ejemplo resuelto: una omisión y una falsa alarma
| Parte del mensaje | Una persona dice | Las reglas dicen | Resultado |
|---|---|---|---|
| Bruno Muestra | Personal | No encuentran nada | Omisión |
| 600 000 002 | Personal | No encuentran nada | Omisión |
| 4000000000000002 (un número de pedido) | No personal | Tarjeta | Falsa alarma |
| [email protected] | Personal | Correo | Acierto |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que un buscador que no imprime nada demuestra que el mensaje está limpio. No es así. Solo significa que ninguna regla encajó. Un nombre o una dirección escrita con palabras no tiene forma. Di «no se halló ninguna forma conocida» y nunca «no hay datos personales».
Escribe el ayudante del modelo, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// Los tokens de una respuesta, o null si no trae ninguno.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el ayudante del modelo, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"estado \" + res.status);' ' const d = await res.json();' ' return { text: d.choices[0].message.content, inTokens: count(d, \"prompt_tokens\"), outTokens: count(d, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Muestra grabada: ningún modelo respondió (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el buscador, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const messages = [' ' \"Escribe a [email protected] sobre el reembolso.\",' ' \"Llámame al 600000001 después de las cinco.\",' ' \"Mi teléfono es 600 000 002, llama cuando quieras.\",' ' \"El DNI 00000000U viene en el formulario.\",' ' \"El pedido 4000000000000002 se envió a Bruno Muestra.\",' '];' 'const marked = [[\"[email protected]\"], [\"600000001\"], [\"600 000 002\"], [\"00000000U\"], [\"Bruno Muestra\"]];' > finder.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el buscador, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function clean(word) {' ' let w = word;' ' while (w.length > 0 && \".,;:?()\".includes(w[w.length - 1])) w = w.slice(0, -1);' ' return w;' '}' 'function digits(w, n) {' ' return w.length === n && w.split(\"\").every(function (c) { return c >= \"0\" && c <= \"9\"; });' '}' >> finder.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el buscador, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function kindOf(w) {' ' const at = w.indexOf(\"@\");' ' if (at > 0 && w.indexOf(\".\", at) > at + 1) return \"correo\";' ' if (digits(w, 9) && (w[0] === \"6\" || w[0] === \"7\")) return \"telefono\";' ' if (w.length === 9 && digits(w.slice(0, 8), 8) && /[A-Z]/.test(w[8])) return \"dni\";' ' if (digits(w, 16)) return \"tarjeta\";' ' return \"\";' '}' >> finder.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el buscador, parte 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function find(text) {' ' const out = [];' ' text.split(\" \").forEach(function (word) {' ' const w = clean(word);' ' if (kindOf(w).length > 0) out.push({ kind: kindOf(w), value: w });' ' });' ' return out;' '}' >> finder.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el buscador, parte 5
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' messages.forEach(function (text, i) {' ' const values = find(text).map(function (f) { return f.value; });' ' const missed = marked[i].filter(function (v) { return values.indexOf(v) < 0; });' ' const extra = values.filter(function (v) { return marked[i].indexOf(v) < 0; });' ' console.log((i + 1) + \" encontrado \" + JSON.stringify(find(text)) + \" omitido \" + JSON.stringify(missed) + \" falsa alarma \" + JSON.stringify(extra));' ' });' ' const q = \"En una frase corta, ¿por qué una regla no puede encontrar un nombre?\";' ' const sample = \"Un nombre no tiene una forma fija, así que una regla no tiene nada que comparar.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 60);' ' console.log(\"el modelo dijo: \" + reply.text);' '}' 'main();' >> finder.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta el buscador
docker exec -w /home/node/project agent node finder.jsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lo que imprime el Run
| Línea | Qué muestra |
|---|---|
| 1 encontrado correo ... omitido [] falsa alarma [] | Un acierto |
| 3 encontrado [] omitido ["600 000 002"] | Un número con espacios se escapa |
| 5 encontrado tarjeta ... omitido ["Bruno Muestra"] | Un nombre se escapa |
| 5 ... falsa alarma ["4000000000000002"] | Un número de pedido parece una tarjeta |
| el modelo dijo: ... | Una frase. Las palabras cambian en cada ejecución |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.