2026-03-18 15:09:51 +01:00

143 lines
6.3 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Business-QA Anonymisation et recontextualisation</title>
<style>
:root { --bg: #1a1a2e; --card: #16213e; --accent: #0f3460; --text: #e8e8e8; --muted: #a0a0a0; }
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; background: var(--bg); color: var(--text); margin: 0; padding: 1rem; line-height: 1.5; }
h1 { font-size: 1.25rem; margin: 0 0 1rem; }
section { background: var(--card); border: 1px solid var(--accent); border-radius: 8px; padding: 1rem; margin-bottom: 1rem; }
section h2 { font-size: 1rem; margin: 0 0 0.5rem; color: var(--muted); }
textarea { width: 100%; min-height: 100px; font-family: monospace; font-size: 12px; background: #0d0d1a; color: var(--text); border: 1px solid var(--accent); border-radius: 4px; padding: 8px; resize: vertical; }
button { background: var(--accent); color: var(--text); border: none; padding: 8px 14px; border-radius: 4px; cursor: pointer; font-size: 14px; }
button:hover { filter: brightness(1.1); }
pre { margin: 0; white-space: pre-wrap; word-break: break-all; font-size: 12px; }
.error { color: #e06060; }
.success { color: #60e080; }
.grid { display: grid; gap: 1rem; }
@media (min-width: 800px) { .grid { grid-template-columns: 1fr 1fr; } }
</style>
</head>
<body>
<h1>Business-QA Anonymisation et recontextualisation</h1>
<p>Exemple dutilisation du module : anonymiser un payload dossier notaire, puis recontextualiser une réponse IA.</p>
<section>
<h2>1. Payload (question + folder_context)</h2>
<textarea id="payload" placeholder='{"question": "Quelles pièces pour M. Dupont ?", "folder_context": {"members": [{"firstName": "Jean", "lastName": "Dupont", "email": "jean@example.com"}]}}'>{"question": "Quelles pièces pour M. Dupont ?", "folder_context": {"members": [{"firstName": "Jean", "lastName": "Dupont", "email": "jean@example.com"}], "type": "vente"}}</textarea>
<p><button type="button" id="btnAnonymize">Anonymiser</button></p>
<p id="anonStatus" class="muted"></p>
</section>
<div class="grid">
<section>
<h2>2. Payload anonymisé</h2>
<pre id="anonPayload"></pre>
</section>
<section>
<h2>3. Mapping (placeholder → valeur)</h2>
<pre id="mapping"></pre>
</section>
</div>
<section>
<h2>4. Réponse IA (avec placeholders) à recontextualiser</h2>
<textarea id="responseToRestore" placeholder='{"answer": "Pour PII_0 PII_1, prévoir les pièces suivantes…", "nextActionsTable": "", "membersInfoSheet": "", "synthesisRecommendation": ""}'>{"answer": "Pour PII_0 PII_1, prévoir les pièces d'identité et justificatif de domicile.", "nextActionsTable": "- Contacter PII_0 PII_1", "membersInfoSheet": "Membre : PII_0 PII_1 (PII_2)", "synthesisRecommendation": "Dossier standard pour PII_0 PII_1."}</textarea>
<p><button type="button" id="btnRecontext">Recontextualiser la réponse</button></p>
<p id="recontextStatus" class="muted"></p>
</section>
<section>
<h2>5. Réponse recontextualisée</h2>
<pre id="recontextResult"></pre>
</section>
<script>
const base = window.location.pathname.replace(/\/example\/?.*$/, "");
const api = (path) => base + path;
document.getElementById("btnAnonymize").addEventListener("click", async () => {
const payloadEl = document.getElementById("payload");
const statusEl = document.getElementById("anonStatus");
const anonPayloadEl = document.getElementById("anonPayload");
const mappingEl = document.getElementById("mapping");
let payload;
try {
payload = JSON.parse(payloadEl.value);
} catch (e) {
statusEl.textContent = "JSON invalide.";
statusEl.className = "error";
return;
}
statusEl.textContent = "Envoi…";
statusEl.className = "";
try {
const res = await fetch(api("/anonymize"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ payload }),
});
const data = await res.json();
if (!res.ok) {
statusEl.textContent = data.message || "Erreur " + res.status;
statusEl.className = "error";
return;
}
anonPayloadEl.textContent = JSON.stringify(data.anonymizedPayload, null, 2);
mappingEl.textContent = JSON.stringify(data.mapping, null, 2);
window._lastMapping = data.mapping;
statusEl.textContent = "Anonymisation OK.";
statusEl.className = "success";
} catch (e) {
statusEl.textContent = "Erreur réseau : " + e.message;
statusEl.className = "error";
}
});
document.getElementById("btnRecontext").addEventListener("click", async () => {
const mapping = window._lastMapping;
const responseEl = document.getElementById("responseToRestore");
const statusEl = document.getElementById("recontextStatus");
const resultEl = document.getElementById("recontextResult");
if (!mapping || !mapping.length) {
statusEl.textContent = "Anonymisez dabord un payload pour obtenir le mapping.";
statusEl.className = "error";
return;
}
let response;
try {
response = JSON.parse(responseEl.value);
} catch (e) {
statusEl.textContent = "JSON réponse invalide.";
statusEl.className = "error";
return;
}
statusEl.textContent = "Envoi…";
statusEl.className = "";
try {
const res = await fetch(api("/recontextualize"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ mapping, response }),
});
const data = await res.json();
if (!res.ok) {
statusEl.textContent = data.message || "Erreur " + res.status;
statusEl.className = "error";
return;
}
resultEl.textContent = JSON.stringify(data.response, null, 2);
statusEl.textContent = "Recontextualisation OK.";
statusEl.className = "success";
} catch (e) {
statusEl.textContent = "Erreur réseau : " + e.message;
statusEl.className = "error";
}
});
</script>
</body>
</html>