143 lines
6.3 KiB
HTML
143 lines
6.3 KiB
HTML
<!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 d’utilisation 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 d’abord 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>
|