edgebert 0.4.0

Fast local text embeddings library for Rust and WASM for BERT inference on native and edge devices with no dependencies.
Documentation
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>EdgeBERT Embeddings Test</title>
    <style>
        body {
            font-family: 'Monaco', 'Menlo', 'Courier New', monospace;
            max-width: 900px;
            margin: 0 auto;
            padding: 20px;
            background: #1e1e1e;
            color: #d4d4d4;
        }
        h1 { color: #569cd6; }
        .input-section { display: flex; gap: 20px; margin-bottom: 20px; }
        input {
            flex: 1; padding: 10px;
            background: #2d2d30; color: #d4d4d4;
            border: 1px solid #3e3e42; font-family: inherit;
        }
        button {
            padding: 10px 20px;
            background: #007acc; color: white;
            border: none; cursor: pointer;
        }
        button:hover:not(:disabled) { background: #005a9e; }
        button:disabled { background: #3e3e42; cursor: not-allowed; }
        .output {
            background: #2d2d30; padding: 15px;
            border: 1px solid #3e3e42; white-space: pre-wrap;
            font-size: 14px; line-height: 1.5;
        }
    </style>
</head>
<body>
<h1>EdgeBERT Embeddings Test</h1>

<div class="input-section">
    <input type="text" id="text1" value="Hello world" placeholder="First text">
    <input type="text" id="text2" value="How are you?" placeholder="Second text">
</div>

<button id="encode-btn" disabled>Loading model...</button>

<div id="output" class="output"></div>

<script type="module">
    const EMBEDDING_SIZE = 384;
    const worker = new Worker('worker.js', { type: 'module' });
    const output = document.getElementById('output');
    const encodeBtn = document.getElementById('encode-btn');

    function cosineSim(a, b) {
        const dot = a.reduce((sum, val, i) => sum + val * b[i], 0);
        const normA = Math.sqrt(a.reduce((sum, val) => sum + val * val, 0));
        const normB = Math.sqrt(b.reduce((sum, val) => sum + val * val, 0));
        return dot / (normA * normB);
    }

    worker.onmessage = function(e) {
        const data = e.data;
        if (data.type === 'log') output.textContent += data.message + '\n';
        else if (data.type === 'ready') {
            encodeBtn.textContent = 'Generate Embeddings';
            encodeBtn.disabled = false;
            output.textContent += 'Model loaded successfully!\n';
        }
        else if (data.type === 'result') {
            const flatEmbeddings = data.embeddings;
            const texts = [document.getElementById('text1').value, document.getElementById('text2').value];
            const embeddings = [];
            for (let i = 0; i < 2; i++) {
                embeddings.push(flatEmbeddings.slice(i*EMBEDDING_SIZE, (i+1)*EMBEDDING_SIZE));
            }

            output.textContent += `Embeddings shape: [${embeddings.length}, ${embeddings[0].length}]\n`;

            const sim = cosineSim(embeddings[0], embeddings[1]);
            output.textContent += `'${texts[0]}' vs '${texts[1]}': ${sim.toFixed(3)}\n`;

            const norm = Math.sqrt(embeddings[0].reduce((sum, val) => sum + val*val, 0));
            output.textContent += `First embedding norm: ${norm.toFixed(6)}\n`;

            const first10 = embeddings[0].slice(0,10).map(v => v.toFixed(4));
            output.textContent += `First 10 values: [${first10.join(', ')}]\n`;

            encodeBtn.disabled = false;
            encodeBtn.textContent = 'Generate Embeddings';
        }
        else if (data.type === 'error') {
            output.textContent += `Error: ${data.error}\n`;
            encodeBtn.disabled = false;
        }
    };

    encodeBtn.addEventListener('click', () => {
        const texts = [document.getElementById('text1').value, document.getElementById('text2').value];
        output.textContent = 'Encoding texts: ' + JSON.stringify(texts) + '\n';
        encodeBtn.disabled = true;
        encodeBtn.textContent = 'Processing...';
        worker.postMessage({ type: 'encode', texts });
    });

    worker.postMessage({ type: 'init' });
</script>
</body>
</html>