Spaces:
Running
Running
more update to ux / ui
Browse files- index.html +26 -65
- wasm-demo.js +26 -8
- zama_logo.webp +0 -0
index.html
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
<head>
|
4 |
<meta charset="utf-8" />
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
6 |
-
<title>Private
|
7 |
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
8 |
|
9 |
<style>
|
@@ -56,9 +56,7 @@
|
|
56 |
margin-inline: auto;
|
57 |
}
|
58 |
.logo {
|
59 |
-
|
60 |
-
font-weight: 700;
|
61 |
-
letter-spacing: -0.02em;
|
62 |
}
|
63 |
.contact-btn {
|
64 |
border: 2px solid var(--black);
|
@@ -88,7 +86,7 @@
|
|
88 |
max-width: var(--container-max);
|
89 |
margin: calc(var(--spacing-unit) * 4) auto calc(var(--spacing-unit) * 10);
|
90 |
padding-inline: calc(var(--spacing-unit) * 4);
|
91 |
-
grid-template-columns: 1fr
|
92 |
}
|
93 |
.hero h1 {
|
94 |
font-size: clamp(3rem, 6vw, 4.5rem);
|
@@ -301,6 +299,19 @@
|
|
301 |
opacity: 0.8;
|
302 |
}
|
303 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
/* Responsive adjustments */
|
305 |
@media (max-width: 968px) {
|
306 |
.hero {
|
@@ -340,71 +351,22 @@
|
|
340 |
|
341 |
<!-- external scripts -->
|
342 |
<script type="module" src="https://belladoreai.github.io/llama3-tokenizer-js/bundle/llama3-tokenizer-with-baked-data.js"></script>
|
343 |
-
<script type="module">
|
344 |
-
import mermaid from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
|
345 |
-
mermaid.initialize({
|
346 |
-
startOnLoad: true,
|
347 |
-
theme: 'base',
|
348 |
-
themeVariables: {
|
349 |
-
primaryColor: '#ffd200',
|
350 |
-
primaryTextColor: '#000',
|
351 |
-
lineColor: '#000',
|
352 |
-
tertiaryColor: '#fff',
|
353 |
-
fontFamily: 'Telegraf',
|
354 |
-
fontSize: '1.4rem'
|
355 |
-
},
|
356 |
-
flowchart: {
|
357 |
-
nodeSpacing: 50,
|
358 |
-
rankSpacing: 50,
|
359 |
-
curve: 'basis',
|
360 |
-
fontSize: '1.4rem'
|
361 |
-
},
|
362 |
-
sequence: {
|
363 |
-
actorFontSize: '1.4rem',
|
364 |
-
noteFontSize: '1.4rem',
|
365 |
-
messageFontSize: '1.4rem'
|
366 |
-
}
|
367 |
-
});
|
368 |
-
</script>
|
369 |
</head>
|
370 |
<body>
|
371 |
<!-- Navbar -->
|
372 |
<nav class="navbar">
|
373 |
-
<
|
374 |
<a href="https://www.zama.ai/contact" class="contact-btn" target="_blank" rel="noopener noreferrer">Contact us</a>
|
375 |
</nav>
|
376 |
|
377 |
<!-- Hero -->
|
378 |
<header class="hero" role="banner">
|
379 |
<div class="hero-copy">
|
380 |
-
<h1>Private
|
381 |
<div class="explanation-text">
|
382 |
-
Private SynthID uses Google's SynthID technology to
|
383 |
</div>
|
384 |
</div>
|
385 |
-
|
386 |
-
<div class="hero-diagram">
|
387 |
-
<pre class="mermaid">
|
388 |
-
sequenceDiagram
|
389 |
-
participant Userπ§βπ»
|
390 |
-
participant Browserπ
|
391 |
-
participant RustServerπ¦
|
392 |
-
|
393 |
-
Userπ§βπ»->>Browserπ: 1οΈβ£ Generate keys
|
394 |
-
Browserπ->>Browserπ: TFHE keygen (WASM)
|
395 |
-
Browserπ->>RustServerπ¦: 2οΈβ£ /handshake (server_key_b64)
|
396 |
-
RustServerπ¦->>Browserπ: UID (uuid-v4)
|
397 |
-
|
398 |
-
Userπ§βπ»->>Browserπ: 3οΈβ£ Enter text
|
399 |
-
Browserπ->>Browserπ: Tokenise β HF tokenizer
|
400 |
-
Browserπ->>Browserπ: Encrypt tokens (WASM)
|
401 |
-
Browserπ->>RustServerπ¦: 4οΈβ£ /detect (uid, ciphertext_b64)
|
402 |
-
RustServerπ¦->>RustServerπ¦: FHE SynthID detect
|
403 |
-
RustServerπ¦->>Browserπ: Encrypted result_b64
|
404 |
-
Browserπ->>Browserπ: Decrypt result (WASM)
|
405 |
-
Browserπ-->>Userπ§βπ»: flag / score / g
|
406 |
-
</pre>
|
407 |
-
</div>
|
408 |
</header>
|
409 |
|
410 |
<!-- Wizard Steps -->
|
@@ -415,12 +377,12 @@ sequenceDiagram
|
|
415 |
<h2 id="step1">1. Keys</h2>
|
416 |
<div class="card-content">
|
417 |
<div class="controls" style="margin-top: 0;">
|
418 |
-
<p id="keygenStatus" class="status" aria-live="polite">
|
419 |
<span id="keygenSpin" class="loader" hidden aria-label="Generating keys"></span>
|
420 |
</div>
|
421 |
<div style="display:flex; gap:var(--spacing-unit); margin-top:auto">
|
422 |
-
<button id="btnKeygen" class="btn" aria-describedby="keygenStatus">π Generate keys</button>
|
423 |
-
<button id="btnLoadSaved" class="btn" aria-describedby="keygenStatus">ποΈ Load keys</button>
|
424 |
</div>
|
425 |
</div>
|
426 |
</section>
|
@@ -436,8 +398,7 @@ sequenceDiagram
|
|
436 |
<label for="tokenInput" class="visually-hidden">Text to encrypt</label>
|
437 |
<textarea id="tokenInput" rows="2" placeholder="Enter text to encrypt or use the example below" autocomplete="off"></textarea>
|
438 |
<div style="display: flex; gap: calc(var(--spacing-unit) * 1); margin-bottom: calc(var(--spacing-unit) * 2); flex-wrap: wrap; align-items: center;">
|
439 |
-
<button id="btnWatermarked" class="btn" style="min-width: auto; padding: calc(var(--spacing-unit) * 1) calc(var(--spacing-unit) * 1.5); font-size: 1rem;">β¨
|
440 |
-
<span style="font-size: 1rem; color: var(--black); opacity: 0.7;">β Try this to see watermark detection in action</span>
|
441 |
</div>
|
442 |
<div class="controls" style="margin-top: auto;">
|
443 |
<button id="btnEncrypt" class="btn" disabled>π‘οΈ Encrypt</button>
|
@@ -453,8 +414,8 @@ sequenceDiagram
|
|
453 |
<h2 id="step3">3. Send to server</h2>
|
454 |
<div class="card-content">
|
455 |
<div>
|
456 |
-
<p id="srvStatus" class="status" aria-live="polite">Waiting for encrypted data
|
457 |
-
<p id="srvComputing" class="status" aria-live="polite" hidden>Server computing
|
458 |
</div>
|
459 |
<div class="controls" style="margin-top: auto;">
|
460 |
<button id="btnSend" class="btn" disabled>π‘ Send</button>
|
@@ -474,7 +435,7 @@ sequenceDiagram
|
|
474 |
<button id="btnDecrypt" class="btn" disabled>π Decrypt</button>
|
475 |
</div>
|
476 |
<div class="disclaimer" style="margin-top: calc(var(--spacing-unit) * 3); font-size: 0.9rem; color: var(--black); opacity: 0.7; line-height: 1.5;">
|
477 |
-
<p><strong>Note about reliability:</strong>
|
478 |
</div>
|
479 |
</div>
|
480 |
</section>
|
|
|
3 |
<head>
|
4 |
<meta charset="utf-8" />
|
5 |
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
6 |
+
<title>Private AI Text Detector β Check if your encrypted text is AI-generated</title>
|
7 |
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
8 |
|
9 |
<style>
|
|
|
56 |
margin-inline: auto;
|
57 |
}
|
58 |
.logo {
|
59 |
+
height: 40px;
|
|
|
|
|
60 |
}
|
61 |
.contact-btn {
|
62 |
border: 2px solid var(--black);
|
|
|
86 |
max-width: var(--container-max);
|
87 |
margin: calc(var(--spacing-unit) * 4) auto calc(var(--spacing-unit) * 10);
|
88 |
padding-inline: calc(var(--spacing-unit) * 4);
|
89 |
+
grid-template-columns: 1fr;
|
90 |
}
|
91 |
.hero h1 {
|
92 |
font-size: clamp(3rem, 6vw, 4.5rem);
|
|
|
299 |
opacity: 0.8;
|
300 |
}
|
301 |
|
302 |
+
/* Result type styling */
|
303 |
+
.watermark-flag.inconclusive {
|
304 |
+
color: #f57c00;
|
305 |
+
}
|
306 |
+
|
307 |
+
.watermark-flag.watermarked {
|
308 |
+
color: #2e7d32;
|
309 |
+
}
|
310 |
+
|
311 |
+
.watermark-flag.ai-generated {
|
312 |
+
color: #1976d2;
|
313 |
+
}
|
314 |
+
|
315 |
/* Responsive adjustments */
|
316 |
@media (max-width: 968px) {
|
317 |
.hero {
|
|
|
351 |
|
352 |
<!-- external scripts -->
|
353 |
<script type="module" src="https://belladoreai.github.io/llama3-tokenizer-js/bundle/llama3-tokenizer-with-baked-data.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
354 |
</head>
|
355 |
<body>
|
356 |
<!-- Navbar -->
|
357 |
<nav class="navbar">
|
358 |
+
<img src="zama_logo.webp" alt="Zama logo" class="logo" />
|
359 |
<a href="https://www.zama.ai/contact" class="contact-btn" target="_blank" rel="noopener noreferrer">Contact us</a>
|
360 |
</nav>
|
361 |
|
362 |
<!-- Hero -->
|
363 |
<header class="hero" role="banner">
|
364 |
<div class="hero-copy">
|
365 |
+
<h1>Private AI Text Detection</h1>
|
366 |
<div class="explanation-text">
|
367 |
+
Private SynthID uses Google's SynthID technology to identify AI-generated text while preserving privacy through Fully Homomorphic Encryption (FHE). This means you can learn whether your text was produced by an AIβwithout anyone ever seeing the content. Learn more about <a href="https://deepmind.google/science/synthid/" target="_blank">SynthID</a> and <a href="https://www.zama.ai/" target="_blank">FHE applications</a>.
|
368 |
</div>
|
369 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
</header>
|
371 |
|
372 |
<!-- Wizard Steps -->
|
|
|
377 |
<h2 id="step1">1. Keys</h2>
|
378 |
<div class="card-content">
|
379 |
<div class="controls" style="margin-top: 0;">
|
380 |
+
<p id="keygenStatus" class="status" aria-live="polite">Generate new keys (a few minutes on first run)</p>
|
381 |
<span id="keygenSpin" class="loader" hidden aria-label="Generating keys"></span>
|
382 |
</div>
|
383 |
<div style="display:flex; gap:var(--spacing-unit); margin-top:auto">
|
384 |
+
<button id="btnKeygen" class="btn" aria-describedby="keygenStatus">π Generate new keys</button>
|
385 |
+
<button id="btnLoadSaved" class="btn" aria-describedby="keygenStatus">ποΈ Load saved keys</button>
|
386 |
</div>
|
387 |
</div>
|
388 |
</section>
|
|
|
398 |
<label for="tokenInput" class="visually-hidden">Text to encrypt</label>
|
399 |
<textarea id="tokenInput" rows="2" placeholder="Enter text to encrypt or use the example below" autocomplete="off"></textarea>
|
400 |
<div style="display: flex; gap: calc(var(--spacing-unit) * 1); margin-bottom: calc(var(--spacing-unit) * 2); flex-wrap: wrap; align-items: center;">
|
401 |
+
<button id="btnWatermarked" class="btn" style="min-width: auto; padding: calc(var(--spacing-unit) * 1) calc(var(--spacing-unit) * 1.5); font-size: 1rem;">β¨ Load sample AI text</button>
|
|
|
402 |
</div>
|
403 |
<div class="controls" style="margin-top: auto;">
|
404 |
<button id="btnEncrypt" class="btn" disabled>π‘οΈ Encrypt</button>
|
|
|
414 |
<h2 id="step3">3. Send to server</h2>
|
415 |
<div class="card-content">
|
416 |
<div>
|
417 |
+
<p id="srvStatus" class="status" aria-live="polite">Waiting for encrypted data⦠(server processing can take several minutes)</p>
|
418 |
+
<p id="srvComputing" class="status" aria-live="polite" hidden>Server computingβ¦</p>
|
419 |
</div>
|
420 |
<div class="controls" style="margin-top: auto;">
|
421 |
<button id="btnSend" class="btn" disabled>π‘ Send</button>
|
|
|
435 |
<button id="btnDecrypt" class="btn" disabled>π Decrypt</button>
|
436 |
</div>
|
437 |
<div class="disclaimer" style="margin-top: calc(var(--spacing-unit) * 3); font-size: 0.9rem; color: var(--black); opacity: 0.7; line-height: 1.5;">
|
438 |
+
<p><strong>Note about reliability:</strong> AI text detection works best with longer passages (100+ tokens). In this demo, input is limited to 16 tokens for performance, which may affect accuracy. Reliability improves significantly with 10+ tokens but is less reliable on very short snippets.</p>
|
439 |
</div>
|
440 |
</div>
|
441 |
</section>
|
wasm-demo.js
CHANGED
@@ -394,18 +394,36 @@ $('btnDecrypt').onclick = () => {
|
|
394 |
console.log('[Main] Starting decryption...');
|
395 |
const dec = decrypt_serialized_u64_radix_flat_wasm(encServerResult, clientKey);
|
396 |
const [flag, score_scaled, total_g] = Array.from(dec);
|
397 |
-
const
|
398 |
console.log('[Main] Decryption successful');
|
399 |
-
console.log(`[Main] Result - flag: ${flag},
|
400 |
|
401 |
-
//
|
402 |
-
const
|
403 |
-
|
404 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
405 |
|
406 |
$('decResult').innerHTML = `
|
407 |
-
<div class="watermark-flag">${
|
408 |
-
<div class="watermark-score">${
|
409 |
`;
|
410 |
} catch (e) {
|
411 |
console.error('[Main] Decryption error:', e);
|
|
|
394 |
console.log('[Main] Starting decryption...');
|
395 |
const dec = decrypt_serialized_u64_radix_flat_wasm(encServerResult, clientKey);
|
396 |
const [flag, score_scaled, total_g] = Array.from(dec);
|
397 |
+
const rawScore = Number(score_scaled) / 1e6;
|
398 |
console.log('[Main] Decryption successful');
|
399 |
+
console.log(`[Main] Result - flag: ${flag}, raw_score: ${rawScore}, total_g: ${total_g}`);
|
400 |
|
401 |
+
// Convert to confidence value between 0 and 1
|
402 |
+
const confidence = Math.max(0, Math.min(1, rawScore));
|
403 |
+
|
404 |
+
// Determine result based on confidence ranges
|
405 |
+
let resultText, confidenceText, resultClass;
|
406 |
+
|
407 |
+
if (confidence < 0.5) {
|
408 |
+
// Problematic range - should not be addressed according to user
|
409 |
+
resultText = 'β οΈ Inconclusive';
|
410 |
+
confidenceText = `Confidence: ${(confidence * 100).toFixed(1)}% (insufficient data)`;
|
411 |
+
resultClass = 'inconclusive';
|
412 |
+
} else if (confidence >= 0.5 && confidence < 0.6) {
|
413 |
+
// Very likely to be watermarked (close to 0.5)
|
414 |
+
resultText = 'β
AI-Generated (Watermarked)';
|
415 |
+
confidenceText = `Confidence: ${(confidence * 100).toFixed(1)}%`;
|
416 |
+
resultClass = 'watermarked';
|
417 |
+
} else {
|
418 |
+
// Between 0.6 and 1 - highly likely to be AI generated
|
419 |
+
resultText = 'π€ AI-Generated';
|
420 |
+
confidenceText = `Confidence: ${(confidence * 100).toFixed(1)}%`;
|
421 |
+
resultClass = 'ai-generated';
|
422 |
+
}
|
423 |
|
424 |
$('decResult').innerHTML = `
|
425 |
+
<div class="watermark-flag ${resultClass}">${resultText}</div>
|
426 |
+
<div class="watermark-score">${confidenceText}</div>
|
427 |
`;
|
428 |
} catch (e) {
|
429 |
console.error('[Main] Decryption error:', e);
|
zama_logo.webp
ADDED
![]() |