<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vector Database Example</title>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: #f5f5f5;
}
.container {
background: white;
padding: 30px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
button {
background: #0066cc;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
button:hover {
background: #0052a3;
}
.output {
background: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 4px;
padding: 15px;
margin-top: 20px;
font-family: 'Courier New', monospace;
white-space: pre-wrap;
max-height: 400px;
overflow-y: auto;
}
.controls {
margin-bottom: 20px;
}
input {
padding: 8px;
margin: 5px;
border: 1px solid #ddd;
border-radius: 4px;
}
.status {
padding: 10px;
margin: 10px 0;
border-radius: 4px;
}
.status.success { background: #d4edda; color: #155724; }
.status.error { background: #f8d7da; color: #721c24; }
.status.info { background: #d1ecf1; color: #0c5460; }
</style>
</head>
<body>
<div class="container">
<h1>🚀 Vector Database Demo</h1>
<p>Client-side vector database using Rust/WASM + IndexedDB</p>
<div id="status" class="status info">Initializing...</div>
<div class="controls">
<h3>Operations</h3>
<button onclick="insertRandomVectors()">Insert 10 Random Vectors</button>
<button onclick="searchVectors()">Search Nearest Neighbors</button>
<button onclick="showStats()">Show Stats</button>
<button onclick="clearDatabase()">Clear Database</button>
</div>
<div class="controls">
<h3>Test Similarity</h3>
<input type="text" id="vec1" placeholder="Vector 1 (e.g., 1,0,0)" value="1,0,0">
<input type="text" id="vec2" placeholder="Vector 2 (e.g., 0,1,0)" value="0,1,0">
<button onclick="calculateSimilarity()">Calculate Similarity</button>
</div>
<div class="output" id="output">Output will appear here...</div>
</div>
<script type="module">
import init, { VectorDB, cosine_similarity, euclidean_distance } from './pkg/web/vector_db.js'
let db = null
async function initDB() {
try {
await init()
db = new VectorDB(3, 16, 100) setStatus('Database initialized!', 'success')
log('Vector database ready. Dimensions: 3')
} catch (err) {
setStatus('Failed to initialize: ' + err.message, 'error')
}
}
function setStatus(message, type = 'info') {
const statusEl = document.getElementById('status')
statusEl.textContent = message
statusEl.className = `status ${type}`
}
function log(message) {
const output = document.getElementById('output')
output.textContent += message + '\n'
output.scrollTop = output.scrollHeight
}
function clearOutput() {
document.getElementById('output').textContent = ''
}
window.insertRandomVectors = function() {
if (!db) return alert('Database not initialized')
clearOutput()
log('Inserting 10 random vectors...\n')
for (let i = 0; i < 10; i++) {
const vector = [Math.random(), Math.random(), Math.random()]
const id = `vec_${Date.now()}_${i}`
const metadata = { index: i.toString(), timestamp: Date.now().toString() }
db.insert(id, vector, metadata)
log(`Inserted ${id}: [${vector.map(v => v.toFixed(3)).join(', ')}]`)
}
log(`\nTotal vectors: ${db.size()}`)
setStatus('Vectors inserted successfully', 'success')
}
window.searchVectors = function() {
if (!db) return alert('Database not initialized')
if (db.size() === 0) return alert('No vectors in database')
clearOutput()
const query = [Math.random(), Math.random(), Math.random()]
log(`Search query: [${query.map(v => v.toFixed(3)).join(', ')}]\n`)
const results = db.search(query, 5, 50)
log(`Found ${results.length} nearest neighbors:\n`)
results.forEach((result, i) => {
log(`${i + 1}. ${result.id}`)
log(` Score: ${result.score.toFixed(4)}`)
if (result.metadata) {
log(` Metadata: ${JSON.stringify(result.metadata)}`)
}
log('')
})
setStatus('Search completed', 'success')
}
window.showStats = function() {
if (!db) return alert('Database not initialized')
clearOutput()
log('Database Statistics\n')
log(`Total vectors: ${db.size()}`)
log(`Dimensions: 3`)
log(`Max connections (M): 16`)
log(`Construction quality (ef): 100`)
setStatus('Stats displayed', 'success')
}
window.clearDatabase = function() {
if (!db) return alert('Database not initialized')
if (confirm('Clear all vectors?')) {
db = new VectorDB(3, 16, 100)
clearOutput()
log('Database cleared')
setStatus('Database cleared', 'success')
}
}
window.calculateSimilarity = async function() {
if (!db) return alert('Database not initialized')
const vec1Str = document.getElementById('vec1').value
const vec2Str = document.getElementById('vec2').value
try {
const vec1 = vec1Str.split(',').map(v => parseFloat(v.trim()))
const vec2 = vec2Str.split(',').map(v => parseFloat(v.trim()))
if (vec1.length !== 3 || vec2.length !== 3) {
throw new Error('Vectors must have 3 dimensions')
}
clearOutput()
log(`Vector 1: [${vec1.join(', ')}]`)
log(`Vector 2: [${vec2.join(', ')}]\n`)
const cosine = cosine_similarity(vec1, vec2)
const euclidean = euclidean_distance(vec1, vec2)
log(`Cosine Similarity: ${cosine.toFixed(6)}`)
log(`Euclidean Distance: ${euclidean.toFixed(6)}`)
setStatus('Similarity calculated', 'success')
} catch (err) {
setStatus('Error: ' + err.message, 'error')
}
}
initDB()
</script>
</body>
</html>