Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
331
vendor/ruvector/examples/exo-ai-2025/crates/exo-wasm/examples/browser_demo.html
vendored
Normal file
331
vendor/ruvector/examples/exo-ai-2025/crates/exo-wasm/examples/browser_demo.html
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>EXO-WASM Browser Demo</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: system-ui, -apple-system, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background: #0a0a0a;
|
||||
color: #e0e0e0;
|
||||
}
|
||||
h1 {
|
||||
color: #00ff88;
|
||||
border-bottom: 2px solid #00ff88;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.controls {
|
||||
background: #1a1a1a;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
button {
|
||||
background: #00ff88;
|
||||
color: #0a0a0a;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
margin: 5px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
}
|
||||
button:hover {
|
||||
background: #00dd77;
|
||||
}
|
||||
.output {
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
margin: 10px 0;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 14px;
|
||||
white-space: pre-wrap;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.status {
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.status.success { background: #003322; color: #00ff88; }
|
||||
.status.error { background: #330000; color: #ff6666; }
|
||||
.status.info { background: #001133; color: #6688ff; }
|
||||
input {
|
||||
background: #2a2a2a;
|
||||
border: 1px solid #444;
|
||||
color: #e0e0e0;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>🧠 EXO-AI 2025 WASM Demo</h1>
|
||||
|
||||
<div class="status info" id="status">
|
||||
Initializing WASM module...
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<h2>Substrate Controls</h2>
|
||||
<div>
|
||||
<label>Dimensions: <input type="number" id="dimensions" value="128" min="1" max="1024"></label>
|
||||
<label>Metric:
|
||||
<select id="metric" style="background: #2a2a2a; color: #e0e0e0; padding: 8px; border: 1px solid #444; border-radius: 4px;">
|
||||
<option value="cosine">Cosine</option>
|
||||
<option value="euclidean">Euclidean</option>
|
||||
<option value="dotproduct">Dot Product</option>
|
||||
<option value="manhattan">Manhattan</option>
|
||||
</select>
|
||||
</label>
|
||||
<button onclick="initSubstrate()">Initialize Substrate</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px;">
|
||||
<label>Patterns to generate: <input type="number" id="numPatterns" value="100" min="1" max="10000"></label>
|
||||
<button onclick="generatePatterns()">Generate Random Patterns</button>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 15px;">
|
||||
<button onclick="querySubstrate()">Query Similar Patterns</button>
|
||||
<button onclick="showStats()">Show Statistics</button>
|
||||
<button onclick="benchmark()">Run Benchmark</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="output" id="output">
|
||||
Waiting for initialization...
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import init, { ExoSubstrate, Pattern, version, detect_simd } from './pkg/exo_wasm.js';
|
||||
|
||||
let substrate = null;
|
||||
let patternIds = [];
|
||||
|
||||
function log(message) {
|
||||
const output = document.getElementById('output');
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
output.textContent += `[${timestamp}] ${message}\n`;
|
||||
output.scrollTop = output.scrollHeight;
|
||||
}
|
||||
|
||||
function setStatus(message, type = 'info') {
|
||||
const status = document.getElementById('status');
|
||||
status.textContent = message;
|
||||
status.className = `status ${type}`;
|
||||
}
|
||||
|
||||
async function initialize() {
|
||||
try {
|
||||
await init();
|
||||
|
||||
const v = version();
|
||||
const simd = detect_simd();
|
||||
|
||||
log(`✓ EXO-WASM initialized successfully`);
|
||||
log(` Version: ${v}`);
|
||||
log(` SIMD Support: ${simd ? 'Yes' : 'No'}`);
|
||||
log('');
|
||||
|
||||
setStatus('Ready to create substrate', 'success');
|
||||
|
||||
// Auto-initialize with default settings
|
||||
window.initSubstrate();
|
||||
} catch (error) {
|
||||
log(`✗ Initialization failed: ${error}`);
|
||||
setStatus('Initialization failed', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
window.initSubstrate = function() {
|
||||
try {
|
||||
const dimensions = parseInt(document.getElementById('dimensions').value);
|
||||
const metric = document.getElementById('metric').value;
|
||||
|
||||
log(`Creating substrate with ${dimensions} dimensions and ${metric} metric...`);
|
||||
|
||||
substrate = new ExoSubstrate({
|
||||
dimensions: dimensions,
|
||||
distance_metric: metric,
|
||||
use_hnsw: true,
|
||||
enable_temporal: true,
|
||||
enable_causal: true
|
||||
});
|
||||
|
||||
log('✓ Substrate created successfully');
|
||||
setStatus(`Substrate ready (${dimensions}D, ${metric})`, 'success');
|
||||
} catch (error) {
|
||||
log(`✗ Failed to create substrate: ${error.message}`);
|
||||
setStatus('Substrate creation failed', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.generatePatterns = function() {
|
||||
if (!substrate) {
|
||||
log('✗ Please initialize substrate first');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const numPatterns = parseInt(document.getElementById('numPatterns').value);
|
||||
const dimensions = substrate.dimensions;
|
||||
|
||||
log(`Generating ${numPatterns} random patterns...`);
|
||||
const startTime = performance.now();
|
||||
|
||||
patternIds = [];
|
||||
for (let i = 0; i < numPatterns; i++) {
|
||||
const embedding = new Float32Array(dimensions);
|
||||
for (let j = 0; j < dimensions; j++) {
|
||||
embedding[j] = Math.random();
|
||||
}
|
||||
|
||||
const metadata = {
|
||||
index: i,
|
||||
type: i % 2 === 0 ? 'even' : 'odd',
|
||||
timestamp: Date.now()
|
||||
};
|
||||
|
||||
const pattern = new Pattern(embedding, metadata, []);
|
||||
const id = substrate.store(pattern);
|
||||
patternIds.push(id);
|
||||
}
|
||||
|
||||
const elapsed = performance.now() - startTime;
|
||||
const rate = (numPatterns / elapsed * 1000).toFixed(0);
|
||||
|
||||
log(`✓ Generated ${numPatterns} patterns in ${elapsed.toFixed(2)}ms`);
|
||||
log(` Rate: ${rate} patterns/second`);
|
||||
setStatus(`${numPatterns} patterns stored`, 'success');
|
||||
} catch (error) {
|
||||
log(`✗ Error generating patterns: ${error.message}`);
|
||||
setStatus('Pattern generation failed', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.querySubstrate = async function() {
|
||||
if (!substrate || patternIds.length === 0) {
|
||||
log('✗ Please generate patterns first');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const dimensions = substrate.dimensions;
|
||||
const queryVector = new Float32Array(dimensions);
|
||||
for (let i = 0; i < dimensions; i++) {
|
||||
queryVector[i] = Math.random();
|
||||
}
|
||||
|
||||
log('Executing similarity search...');
|
||||
const startTime = performance.now();
|
||||
|
||||
const results = await substrate.query(queryVector, 10);
|
||||
|
||||
const elapsed = performance.now() - startTime;
|
||||
|
||||
log(`✓ Search completed in ${elapsed.toFixed(2)}ms`);
|
||||
log(` Found ${results.length} results:`);
|
||||
|
||||
results.slice(0, 5).forEach((result, i) => {
|
||||
log(` ${i + 1}. ID: ${result.id.slice(0, 8)}... Score: ${result.score.toFixed(4)}`);
|
||||
});
|
||||
|
||||
setStatus(`Query returned ${results.length} results in ${elapsed.toFixed(2)}ms`, 'success');
|
||||
} catch (error) {
|
||||
log(`✗ Query failed: ${error.message}`);
|
||||
setStatus('Query failed', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
window.showStats = function() {
|
||||
if (!substrate) {
|
||||
log('✗ Please initialize substrate first');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const stats = substrate.stats();
|
||||
const length = substrate.len();
|
||||
const isEmpty = substrate.isEmpty();
|
||||
|
||||
log('Substrate Statistics:');
|
||||
log(` Dimensions: ${stats.dimensions}`);
|
||||
log(` Pattern Count: ${stats.pattern_count}`);
|
||||
log(` Distance Metric: ${stats.distance_metric}`);
|
||||
log(` Temporal Enabled: ${stats.temporal_enabled}`);
|
||||
log(` Causal Enabled: ${stats.causal_enabled}`);
|
||||
log(` Is Empty: ${isEmpty}`);
|
||||
log('');
|
||||
|
||||
setStatus(`${stats.pattern_count} patterns in substrate`, 'info');
|
||||
} catch (error) {
|
||||
log(`✗ Failed to get stats: ${error.message}`);
|
||||
}
|
||||
};
|
||||
|
||||
window.benchmark = async function() {
|
||||
if (!substrate) {
|
||||
log('✗ Please initialize substrate first');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
log('Running benchmark...');
|
||||
const dimensions = substrate.dimensions;
|
||||
const iterations = 100;
|
||||
|
||||
// Insert benchmark
|
||||
log(`Benchmarking ${iterations} inserts...`);
|
||||
let startTime = performance.now();
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
const embedding = new Float32Array(dimensions);
|
||||
for (let j = 0; j < dimensions; j++) {
|
||||
embedding[j] = Math.random();
|
||||
}
|
||||
const pattern = new Pattern(embedding, { index: i }, []);
|
||||
substrate.store(pattern);
|
||||
}
|
||||
|
||||
let elapsed = performance.now() - startTime;
|
||||
let rate = (iterations / elapsed * 1000).toFixed(0);
|
||||
log(` Insert: ${rate} ops/sec`);
|
||||
|
||||
// Search benchmark
|
||||
log(`Benchmarking ${iterations} searches...`);
|
||||
startTime = performance.now();
|
||||
|
||||
for (let i = 0; i < iterations; i++) {
|
||||
const queryVector = new Float32Array(dimensions);
|
||||
for (let j = 0; j < dimensions; j++) {
|
||||
queryVector[j] = Math.random();
|
||||
}
|
||||
await substrate.query(queryVector, 10);
|
||||
}
|
||||
|
||||
elapsed = performance.now() - startTime;
|
||||
rate = (iterations / elapsed * 1000).toFixed(0);
|
||||
log(` Search: ${rate} ops/sec`);
|
||||
log('');
|
||||
|
||||
setStatus('Benchmark complete', 'success');
|
||||
} catch (error) {
|
||||
log(`✗ Benchmark failed: ${error.message}`);
|
||||
setStatus('Benchmark failed', 'error');
|
||||
}
|
||||
};
|
||||
|
||||
// Initialize on page load
|
||||
initialize();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user