Le message avec un numéro de téléphone
Garder les données personnelles hors des prompts, c’est ne montrer au modèle que ce dont il a besoin pour la tâche. Cela compte, car un prompt part vers un autre service et finit souvent dans un journal.
Un outil d’assistance envoie chaque message à un modèle pour rédiger une réponse. Le message contient un nom, une adresse et un numéro. La réponse n’en a besoin d’aucun. L’outil peut les remplacer par des repères, puis les remettre.
À la fin de cette leçon
Remarque
Je peux remplacer des données personnelles par des repères avant un appel au modèle et les remettre après.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Donnée personnelle | tout détail qui identifie une personne vivante | |
| Minimisation | n’envoyer que ce que la tâche demande | |
| Masquer | remplacer une valeur par un substitut | |
| Repère | une étiquette qui remplace une valeur retirée | [COURRIEL_1] |
| Correspondance | la table qui relie chaque repère à sa valeur |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
N’envoyez que ce que la tâche demande
Demandez d’abord si le modèle a besoin de la valeur. Répondre à une réclamation demande la réclamation, pas le numéro de téléphone. Retirez ce qui n’est pas nécessaire.
Si la réponse doit citer une personne, utilisez un repère. Le modèle écrit « Chère [NOM_1] » et votre propre code remet ensuite le vrai nom.
Exemple : avant et après
| Valeur | Envoyé au modèle | Gardé dans la correspondance |
|---|---|---|
| Camille | [NOM_1] | [NOM_1] est Camille |
| [email protected] | [COURRIEL_1] | [COURRIEL_1] est [email protected] |
| 0639980123 | [TEL_1] | [TEL_1] est 0639980123 |
| Camille, encore | [NOM_1] | La même valeur garde le même repère |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Le masquage a des limites
Une règle trouve les formes que vous avez écrites : un mot avec un arobase, une longue suite de chiffres, un nom d’une liste. Elle rate un nom de rue, un surnom ou un numéro écrit avec des espaces.
Le masquage réduit donc le risque sans le supprimer. Testez-le sur des exemples brouillons et gardez un contrôle qui cherche ce qui reste.
Écrire l’aide du modèle, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' 'async function demander(messages, echantillon, 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 || 200 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"statut \" + res.status);' ' return (await res.json()).choices[0].message.content;' > model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire l’aide du modèle, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' } catch (erreur) {' ' console.log(\"Échantillon enregistré : aucun modèle n’a répondu (\" + erreur.message + \").\");' ' const liste = [].concat(echantillon);' ' const tour = messages.filter(function (m) { return m.role === \"assistant\"; }).length;' ' return liste[Math.min(tour, liste.length - 1)];' ' }' '}' 'module.exports = { demander };' >> model.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de masquage, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { demander } = require(\"./model\");' '' 'const noms = [\"Camille\", \"Hugo\"];' 'const message = \"Bonjour, je suis Camille. Écrivez à [email protected] ou appelez 0639980123. Hugo m’a aidée hier.\";' 'function tousChiffres(texte) {' ' return texte.length >= 8 && texte.split(\"\").every(function (c) { return c >= \"0\" && c <= \"9\"; });' '}' > masquer.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de masquage, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function masquer(texte, noms) {' ' const table = {};' ' const vus = {};' ' const mots = texte.split(\" \");' ' for (let i = 0; i < mots.length; i++) {' ' let nu = mots[i];' ' while (nu.endsWith(\".\") || nu.endsWith(\",\")) nu = nu.slice(0, -1);' ' const fin = mots[i].slice(nu.length);' ' let genre = \"\";' ' if (nu.includes(\"@\")) genre = \"COURRIEL\";' ' if (tousChiffres(nu)) genre = \"TEL\";' ' if (noms.includes(nu)) genre = \"NOM\";' >> masquer.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de masquage, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' if (genre === \"\") continue;' ' if (vus[nu] === undefined) {' ' const n = Object.keys(table).filter(function (k) { return k.startsWith(\"[\" + genre); }).length + 1;' ' vus[nu] = \"[\" + genre + \"_\" + n + \"]\";' ' table[vus[nu]] = nu;' ' }' ' mots[i] = vus[nu] + fin;' ' }' ' return { texte: mots.join(\" \"), table: table };' '}' >> masquer.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de masquage, partie 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function restituer(texte, table) {' ' let sortie = texte;' ' for (const cle of Object.keys(table)) sortie = sortie.split(cle).join(table[cle]);' ' return sortie;' '}' 'async function main() {' ' const sur = masquer(message, noms);' ' console.log(\"Envoyé au modèle : \" + sur.texte);' ' console.log(\"Il reste un @ dedans : \" + sur.texte.includes(\"@\"));' ' const regle = \"Écris une réponse de deux phrases au client. Garde chaque repère entre crochets exactement comme il est écrit.\";' ' const messages = [{ role: \"system\", content: regle }, { role: \"user\", content: sur.texte }];' ' const echantillon = \"Chère [NOM_1], merci pour votre message. Nous écrirons à [COURRIEL_1] aujourd’hui.\";' >> masquer.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script de masquage, partie 5
docker exec -w /home/node/project agent sh -c "printf '%s\n' ' const reponse = await demander(messages, echantillon, 100);' ' console.log(\"Réponse avec repères : \" + reponse);' ' console.log(\"Remise au client : \" + restituer(reponse, sur.table));' ' console.log(\"Ligne de journal : \" + Object.keys(sur.table).length + \" éléments masqués, réponse de \" + reponse.length + \" caractères\");' '}' 'main();' >> masquer.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer le script de masquage
docker exec -w /home/node/project agent node masquer.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une sortie possible
| Ligne | Ce qu’elle montre |
|---|---|
| Envoyé au modèle | Le message avec [NOM_1], [COURRIEL_1], [TEL_1] et [NOM_2] à la place des valeurs |
| Il reste un @ dedans | false |
| Réponse avec repères | Deux phrases qui gardent les repères. Les mots changent à chaque exécution |
| Remise au client | La réponse avec les vraies valeurs remises |
| Ligne de journal | Des nombres et une longueur, sans texte personnel |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Ce qu’un journal peut contenir
Un journal est lu par plus de monde que l’application, et il dure plus longtemps. Journalisez ce qu’il faut pour trouver une panne : un identifiant de requête, un identifiant d’utilisateur, un nombre, une heure, une décision.
Ne journalisez pas le prompt ni la réponse en entier. Si vous devez en garder un pour déboguer, gardez la copie masquée, peu de temps, avec un accès contrôlé.
Une erreur fréquente
Attention
Beaucoup pensent qu’une fois le prompt masqué, les journaux sont sûrs. La réponse, les messages d’erreur et la requête d’origine peuvent encore contenir les vraies valeurs. Vérifiez chaque endroit où passe le texte : le prompt, la réponse, les journaux et tout cache.