brainy/demo/index.html
David Snelling 1eb2993848 **feat(demo): refine demo content and make UI adjustments for better clarity**
- Updated sample data in `demo/index.html` to focus on advanced AI, technology, and environmental topics.
  - Added detailed personas with updated descriptors in tags and content.
  - Enhanced posts to include nuanced and technical insights into AI, robotics, cybersecurity, and more.
- Removed hover text-decoration for `.result-title` for a cleaner UI experience.
- Adjusted highlighting styles for `.highlight` and `.similar-highlight` to eliminate visual clutter.
- Updated input placeholders and help text to reflect AI-related topics like machine learning, computer vision, and robotics.
- Refined hostname detection logic for compatibility with `demo.soulcraft.com`.
- Improved database initialization workflow with asynchronous operations for dropdown population and visualization updates.

These changes elevate demo content quality, refine visual clarity, and improve backend workflows for a robust user experience.
2025-06-30 13:22:15 -07:00

5361 lines
245 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Brainy Interactive Demo - A Lightweight Graph & Vector Data Platform</title>
<link rel="icon" href="../brainy.png" type="image/png">
<!--
IMPORTANT: This demo must be served over HTTP, not opened directly as a file.
Run the following command from the project root directory:
npx http-server
Then navigate to http://localhost:8080/demo/index.html in your browser.
-->
<!-- D3.js for visualizations -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<!-- Material Icons font -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
:root {
--primary-color: #193c41;
--secondary-color: #3f6e65;
--accent-color: #c95e2f;
--danger-color: #b84c26;
--text-color: #333;
--light-bg: #ececec;
--dark-bg: #333;
--card-bg: #fff;
--border-radius: 8px;
--box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
--transition: all 0.3s ease;
--md3-primary: #6750A4;
--md3-on-primary: #FFFFFF;
--md3-secondary-container: #E8DEF8;
--md3-on-secondary-container: #1D192B;
--md3-outline: #79747E;
--md3-surface: #FFFBFE;
--md3-shadow: rgba(0, 0, 0, 0.3);
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: var(--text-color);
margin: 0;
padding: 0;
background-color: var(--light-bg);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
display: flex;
align-items: center;
padding: 30px;
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
margin-bottom: 30px;
}
header img {
width: 120px;
margin-right: 20px;
}
.header-text {
text-align: left;
}
h1, h2, h3 {
color: var(--primary-color);
}
.demo-section {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
padding: 30px;
margin-bottom: 30px;
}
.demo-controls {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 20px 0;
}
button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 10px 20px;
border-radius: var(--border-radius);
cursor: pointer;
transition: var(--transition);
}
button:hover {
background-color: #388E3C;
transform: translateY(-2px);
}
button.secondary {
background-color: var(--secondary-color);
}
button.secondary:hover {
background-color: #1976D2;
}
button.accent {
background-color: var(--accent-color);
}
button.accent:hover {
background-color: #F57C00;
}
button.danger {
background-color: var(--danger-color);
}
button.danger:hover {
background-color: #D32F2F;
}
input, select, textarea {
padding: 10px;
border: 1px solid #ddd;
border-radius: var(--border-radius);
flex-grow: 1;
}
textarea {
min-height: 100px;
font-family: monospace;
}
.visualization {
height: 500px;
background-color: var(--light-bg);
border-radius: var(--border-radius);
margin: 20px 0;
position: relative;
overflow: hidden;
}
.zoom-controls {
position: absolute;
bottom: 1.5rem;
right: 1rem;
z-index: 10;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.zoom-fit-button {
width: 2.5rem;
height: 2.5rem;
border-radius: 50%;
background-color: var(--md3-primary);
color: var(--md3-on-primary);
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0.125rem 0.25rem var(--md3-shadow);
transition: background-color 0.2s, transform 0.2s;
}
.zoom-fit-button:hover {
background-color: #7B68B5;
transform: scale(1.05);
}
.zoom-fit-button:active {
background-color: #553B93;
transform: scale(0.95);
}
.zoom-button {
width: 2.5rem;
height: 2.5rem;
border-radius: 50%;
background-color: var(--md3-primary);
color: var(--md3-on-primary);
border: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0.125rem 0.25rem var(--md3-shadow);
transition: background-color 0.2s, transform 0.2s;
}
.zoom-button:hover {
background-color: #7B68B5;
transform: scale(1.05);
}
.zoom-button:active {
background-color: #553B93;
transform: scale(0.95);
}
.graph-container {
width: 100%;
height: 100%;
background-color: #FDF8FF;
display: flex;
align-items: center;
justify-content: center;
flex: 1;
overflow: hidden;
}
.graph-container svg {
display: block;
width: 100%;
height: 100%;
font-family: 'Roboto', 'Inter', sans-serif;
}
.graph-container .edges line {
transition: stroke-opacity 0.2s ease-in-out;
}
.graph-container .node-group {
transition: transform 0.15s cubic-bezier(0.4, 0, 0.2, 1), filter 0.3s ease;
transform-origin: center;
}
.graph-container .node-group:hover {
filter: drop-shadow(0 0.5rem 1rem rgba(0, 0, 0, 0.25));
animation: jiggle 0.5s ease;
}
.graph-container .node-group path {
transition: fill-opacity 0.15s ease-in-out;
}
.graph-container .overlay-container {
pointer-events: none;
}
.graph-container .overlay-container .node-info-popup {
pointer-events: auto;
}
@keyframes jiggle {
0% {
transform: rotate(0deg);
}
25% {
transform: rotate(0.5deg) scale(1.01);
}
50% {
transform: rotate(-0.5deg) scale(1.01);
}
75% {
transform: rotate(0.5deg) scale(1.01);
}
100% {
transform: rotate(0deg);
}
}
.results {
background-color: var(--light-bg);
border-radius: var(--border-radius);
padding: 15px;
max-height: 300px;
overflow-y: auto;
font-family: monospace;
white-space: pre-wrap;
}
/* Google-like search interface styles */
.google-search-container {
max-width: 800px;
margin: 0 auto;
}
.google-search-box-container {
margin-bottom: 15px;
}
.google-search-box {
display: flex;
align-items: center;
border: 1px solid #dfe1e5;
border-radius: 24px;
padding: 8px 16px;
max-width: 600px;
margin: 0 auto;
box-shadow: 0 1px 6px rgba(32, 33, 36, 0.28);
transition: box-shadow 0.3s, border-color 0.3s;
}
.google-search-box:hover, .google-search-box:focus-within {
box-shadow: 0 1px 8px rgba(32, 33, 36, 0.35);
border-color: rgba(223, 225, 229, 0);
}
.google-search-icon {
margin-right: 12px;
color: #9aa0a6;
}
.google-search-box input {
flex: 1;
border: none;
outline: none;
font-size: 16px;
color: #202124;
background: transparent;
padding: 8px 0;
font-family: Arial, sans-serif;
}
.google-search-clear {
cursor: pointer;
color: #70757a;
display: flex;
align-items: center;
justify-content: center;
visibility: hidden;
}
.google-search-options {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
gap: 15px;
margin: 20px 0;
}
.search-type-container select {
padding: 8px 12px;
border: 1px solid #dfe1e5;
border-radius: 4px;
background-color: white;
font-size: 14px;
color: #202124;
outline: none;
}
.google-search-buttons {
display: flex;
gap: 10px;
}
.google-search-button {
background-color: #f8f9fa;
border: 1px solid #f8f9fa;
border-radius: 4px;
color: #3c4043;
font-family: Arial, sans-serif;
font-size: 14px;
padding: 8px 16px;
cursor: pointer;
text-align: center;
user-select: none;
transition: border-color 0.3s, box-shadow 0.3s;
}
.google-search-button:hover {
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
border-color: #dadce0;
}
.google-search-button:focus {
border-color: #4285f4;
outline: none;
}
.google-search-button.secondary {
color: #1a73e8;
}
.google-results-container {
max-width: 650px;
margin: 30px auto;
font-family: Arial, sans-serif;
}
.google-results-placeholder {
color: #70757a;
font-size: 14px;
text-align: center;
padding: 20px;
}
/* Google-like search results styles */
.search-stats {
color: #70757a;
font-size: 14px;
margin-bottom: 10px;
font-family: Arial, sans-serif;
}
.search-results-list {
font-family: Arial, sans-serif;
white-space: normal;
}
.search-result-item {
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 1px solid #dfe1e5;
}
.result-title {
color: #1a0dab;
font-size: 18px;
margin: 0 0 5px 0;
font-weight: normal;
cursor: pointer;
}
.result-score {
color: #70757a;
font-size: 14px;
font-weight: normal;
margin-left: 10px;
}
.result-url {
color: #006621;
font-size: 14px;
margin-bottom: 5px;
}
.result-snippet {
color: #4d5156;
font-size: 14px;
line-height: 1.58;
margin-bottom: 5px;
}
.match-reason {
background-color: #f8f9fa;
border-left: 3px solid #fbbc05;
padding: 8px 12px;
margin: 8px 0;
font-size: 13px;
color: #5f6368;
line-height: 1.5;
border-radius: 0 4px 4px 0;
}
.match-reason strong {
color: #202124;
}
.result-metadata {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 5px;
}
.metadata-item {
background-color: #f1f3f4;
padding: 2px 8px;
border-radius: 12px;
font-size: 12px;
color: #4d5156;
}
/* Highlighted search terms - removed highlighting as per requirements */
.highlight {
font-weight: normal;
padding: 0;
}
/* Conceptually similar words - removed highlighting as per requirements */
.similar-highlight {
font-weight: normal;
padding: 0;
}
/* Cluster-specific styles */
.cluster-header {
margin: 25px 0 15px 0;
padding-bottom: 8px;
border-bottom: 2px solid #dadce0;
}
.cluster-header h3 {
color: #202124;
font-size: 20px;
font-weight: 500;
margin: 0;
}
.cluster-item {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #f1f3f4;
margin-left: 15px;
}
.tabs {
display: flex;
margin-bottom: 20px;
flex-wrap: wrap;
}
.tab {
padding: 10px 20px;
background-color: var(--light-bg);
cursor: pointer;
border-radius: var(--border-radius) var(--border-radius) 0 0;
margin-right: 5px;
margin-bottom: 5px;
}
.tab.active {
background-color: var(--primary-color);
color: white;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
.section-content, .subsection-content {
display: block;
margin-bottom: 30px;
}
.quickstart-section {
background: linear-gradient(135deg, #193c41, #3f6e65);
color: white;
padding: 30px;
border-radius: var(--border-radius);
margin-bottom: 30px;
box-shadow: var(--box-shadow);
}
.quickstart-section h2 {
color: white;
margin-top: 0;
}
.code-tabs {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
gap: 20px;
margin-top: 20px;
}
.code-tab {
background-color: rgba(255, 255, 255, 0.1);
border-radius: var(--border-radius);
padding: 20px;
}
.code-tab h3 {
margin-top: 0;
color: white;
}
.code-tab p {
color: rgba(255, 255, 255, 0.9);
}
.section-divider {
height: 1px;
background-color: var(--light-bg);
margin: 20px 0;
}
.code-block {
background-color: var(--dark-bg);
color: white;
padding: 15px;
border-radius: var(--border-radius);
overflow-x: auto;
margin: 20px 0;
font-family: monospace;
}
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 20px;
margin: 30px 0;
}
.feature-card {
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
padding: 20px;
transition: var(--transition);
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.feature-card h3 {
margin-top: 0;
color: var(--primary-color);
}
.tooltip {
position: absolute;
padding: 8px;
background: rgba(0, 0, 0, 0.8);
color: #fff;
border-radius: 4px;
pointer-events: none;
z-index: 10;
font-size: 12px;
}
.cli-terminal {
background-color: var(--dark-bg);
color: #fff;
padding: 15px;
border-radius: var(--border-radius);
font-family: monospace;
margin: 20px 0;
position: relative;
}
.cli-prompt {
color: var(--accent-color);
}
.cli-input {
background: transparent;
border: none;
color: #fff;
font-family: monospace;
width: 80%;
outline: none;
}
.cli-output {
margin-top: 10px;
white-space: pre-wrap;
max-height: 300px;
overflow-y: auto;
}
.cli-history {
margin-bottom: 10px;
}
.cli-command {
margin-bottom: 5px;
}
.form-group {
margin-bottom: 15px;
}
.form-group label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
.features-overview, .what-can-you-build-section {
background: linear-gradient(135deg, #193c41, #3f6e65);
color: white;
padding: 30px;
border-radius: var(--border-radius);
margin-bottom: 30px;
box-shadow: var(--box-shadow);
}
.features-overview h2, .what-can-you-build-section h2 {
color: white;
margin-top: 0;
}
.features-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 15px;
margin-top: 20px;
}
.feature-item {
background-color: var(--card-bg); /* Changed from transparent white to card background */
padding: 15px;
border-radius: var(--border-radius);
/* backdrop-filter: blur(10px); Removed as it's less relevant with solid background */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); /* Added a light shadow to feature items */
}
.feature-item h4 {
margin: 0 0 10px 0;
color: var(--secondary-color); /* Changed from white to secondary color for better contrast */
}
.feature-item p {
margin: 0;
font-size: 0.9em;
opacity: 1; /* Changed from 0.9 to 1 for better readability */
color: var(--text-color); /* Ensure paragraph text is also dark */
}
footer {
text-align: center;
padding: 20px;
margin-top: 40px;
background-color: var(--card-bg);
border-radius: var(--border-radius);
box-shadow: var(--box-shadow);
}
@media (max-width: 768px) {
.container {
padding: 10px;
}
.demo-controls {
flex-direction: column;
}
.feature-grid {
grid-template-columns: 1fr;
}
.features-list {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<div class="container">
<div id="http-warning"
style="background-color: #f44336; color: white; padding: 15px; margin-bottom: 20px; border-radius: 8px; display: none;">
<strong>Warning:</strong> This demo must be served over HTTP to work properly. If you're seeing this message or
the demo isn't working, please:
<ol style="margin-top: 10px; margin-bottom: 5px;">
<li>Open a terminal in the project root directory</li>
<li>Run: <code style="background-color: rgba(0,0,0,0.2); padding: 3px 5px; border-radius: 3px;">npx
http-server</code></li>
<li>Navigate to <a href="http://localhost:8080/demo/index.html"
style="color: white; text-decoration: underline;">http://localhost:8080/demo/index.html</a>
</li>
</ol>
<button onclick="this.parentElement.style.display='none'"
style="background-color: white; color: #f44336; border: none; padding: 5px 10px; border-radius: 4px; cursor: pointer; float: right;">
Dismiss
</button>
</div>
<header>
<img src="../brainy.png" alt="Brainy Logo">
<div class="header-text">
<h1>Brainy Interactive Demo</h1>
<p>A powerful graph & vector data platform for AI applications across any environment</p>
</div>
</header>
<!-- Features Overview Section -->
<section class="features-overview">
<h2>🚀 Key Features</h2>
<p>Explore all of Brainy's powerful capabilities in this interactive demo:</p>
<div class="features-list">
<div class="feature-item">
<h4>🏃‍♂️ Run Everywhere</h4>
<p>Run Brainy in a browser, container, serverless cloud service or the terminal!</p>
</div>
<div class="feature-item">
<h4>🔍 Vector Search</h4>
<p>Find semantically similar content using embeddings (like having ESP for your data!)</p>
</div>
<div class="feature-item">
<h4>🌐 Graph Database</h4>
<p>Connect data with meaningful relationships (your data's social network)</p>
</div>
<div class="feature-item">
<h4>🌊 Streaming Pipeline</h4>
<p>Process data in real-time as it flows through the system (like a data waterslide!)</p>
</div>
<div class="feature-item">
<h4>🧩 Extensible Augmentations</h4>
<p>Customize and extend functionality with pluggable components (LEGO blocks for your data!)</p>
</div>
<div class="feature-item">
<h4>🔌 Built-in Conduits</h4>
<p>Sync and scale across instances with WebSocket and WebRTC (your data's teleportation system!)</p>
</div>
<div class="feature-item">
<h4>🤖 TensorFlow Integration</h4>
<p>Use TensorFlow.js for high-quality embeddings (included as a required dependency)</p>
</div>
<div class="feature-item">
<h4>🧠 Adaptive Intelligence</h4>
<p>Automatically optimizes for your environment and usage patterns</p>
</div>
<div class="feature-item">
<h4>🌍 Cross-Platform</h4>
<p>Works everywhere you do: browsers, Node.js and server environments</p>
</div>
<div class="feature-item">
<h4>💾 Persistent Storage</h4>
<p>Data persists across sessions and scales to any size (no memory loss here!)</p>
</div>
<div class="feature-item">
<h4>🔧 TypeScript Support</h4>
<p>Fully typed API with generics (for those who like their code tidy)</p>
</div>
<div class="feature-item">
<h4>📱 CLI Tools</h4>
<p>Powerful command-line interface for data management (command line wizardry)</p>
</div>
<div class="feature-item">
<h4>📊 Data Visualization</h4>
<p>Interactive graph and vector space visualizations</p>
</div>
<div class="feature-item">
<h4>☁️ Cloud Ready</h4>
<p>Easy deployment to Google, AWS, Azure and other cloud platforms</p>
</div>
<div class="feature-item">
<h4>🎮 Model Control Protocol (MCP)</h4>
<p>Allow external AI models to access Brainy data and use augmentation pipeline as tools</p>
</div>
</div>
</section>
<!-- What Can You Build Section -->
<section class="what-can-you-build-section">
<h2>📊 What Can You Build?</h2>
<div class="features-list">
<div class="feature-item">
<h4>🔍 Semantic Search Engines</h4>
<p>Find content based on meaning, not just keywords</p>
</div>
<div class="feature-item">
<h4>👍 Recommendation Systems</h4>
<p>Suggest similar items based on vector similarity</p>
</div>
<div class="feature-item">
<h4>🧠 Knowledge Graphs</h4>
<p>Build connected data structures with relationships</p>
</div>
<div class="feature-item">
<h4>🤖 AI Applications</h4>
<p>Store and retrieve embeddings for machine learning models</p>
</div>
<div class="feature-item">
<h4>💡 AI-Enhanced Applications</h4>
<p>Build applications that leverage vector embeddings for intelligent data processing</p>
</div>
<div class="feature-item">
<h4>📁 Data Organization Tools</h4>
<p>Automatically categorize and connect related information</p>
</div>
<div class="feature-item">
<h4>🔄 Adaptive Experiences</h4>
<p>Create applications that learn and evolve with your users</p>
</div>
<div class="feature-item">
<h4>🔌 Model-Integrated Systems</h4>
<p>Connect external AI models to Brainy data and tools using MCP</p>
</div>
</div>
</section>
<section class="demo-section">
<h2>Interactive Brainy Explorer</h2>
<p>This interactive demo guides you through Brainy's features step by step, from basic operations to advanced
capabilities.</p>
<!-- Step 1: Getting Started -->
<div class="section-content" id="step1-content">
<h3>Step 1: Getting Started with Brainy</h3>
<p>Let's start by initializing the database and exploring basic operations.</p>
<div class="demo-controls">
<button id="init-db-btn">Initialize Database</button>
<button id="add-sample-btn" class="secondary">Add Sample Data</button>
<button id="backup-db-btn" class="accent">Backup Data</button>
<button id="restore-db-btn" class="accent">Restore Data</button>
<button id="clear-db-btn" class="danger">Clear Database</button>
</div>
<div class="results" id="db-status">
Database not initialized. Click "Initialize Database" to start.
</div>
<div class="visualization" id="db-visualization">
<div class="zoom-controls">
<button class="zoom-fit-button" id="zoom-fit-btn" title="Zoom to fit all nodes">
<i class="material-icons">fit_screen</i>
</button>
</div>
<div class="graph-container">
<div style="text-align: center; padding-top: 200px; color: #666;">
Database visualization will appear here after initialization
</div>
</div>
</div>
</div>
<!-- Step 2: Searching -->
<div class="section-content" id="step2-content">
<h3>Step 2: Semantic Search</h3>
<p>Search your data using vector embeddings for semantic understanding.</p>
<!-- Google-like search interface -->
<div class="google-search-container">
<div class="google-search-box-container">
<div class="google-search-box">
<div class="google-search-icon">
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">
<path
d="M15.5 14h-.79l-.28-.27A6.471 6.471 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"
fill="#9aa0a6"></path>
</svg>
</div>
<input type="text" id="search-query" placeholder="Try: machine learning, AI ethics, computer vision, robotics...">
<div class="google-search-clear" id="search-clear">
<svg focusable="false" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20">
<path
d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
fill="#70757a"></path>
</svg>
</div>
</div>
</div>
<div class="google-search-options">
<div class="search-type-container">
<select id="search-type">
<option value="semantic">Semantic Search</option>
<option value="keyword">Keyword Search</option>
<option value="hybrid">Hybrid Search</option>
<option value="verbs">Verb Search</option>
<option value="connected-nouns">Connected Nouns Search</option>
</select>
</div>
<div class="google-search-buttons">
<button id="search-btn" class="google-search-button">Search</button>
<!-- <button id="similar-entities-btn" class="google-search-button secondary">Find Similar Entities</button>-->
</div>
</div>
</div>
<p class="search-help" style="font-size: 0.9em; color: #666; margin-top: 10px; margin-bottom: 15px;">
Try searching for topics in the sample data like "machine learning", "AI ethics", "computer vision", "robotics", "quantum computing",
"cybersecurity", or specific concepts like "large language models", "federated learning", "explainable AI", "climate science", etc.
</p>
<div class="google-results-container" id="search-results">
<div class="google-results-placeholder">
Search results will appear here...
</div>
</div>
<div class="visualization" id="search-visualization">
<div class="zoom-controls">
<button class="zoom-fit-button" id="search-zoom-fit-btn" title="Zoom to fit all nodes">
<i class="material-icons">fit_screen</i>
</button>
<button class="zoom-button" id="search-zoom-in-btn" title="Zoom in">
<i class="material-icons">add</i>
</button>
<button class="zoom-button" id="search-zoom-out-btn" title="Zoom out">
<i class="material-icons">remove</i>
</button>
</div>
<div class="graph-container">
<div style="text-align: center; padding-top: 200px; color: #666;">
Search results visualization
</div>
</div>
</div>
</div>
<!-- Step 3: Adding Data -->
<div class="section-content" id="step3-content">
<h3>Step 3: Adding Entities (Nouns)</h3>
<p>Now that your database is initialized, let's add some entities (nouns) to it.</p>
<div class="form-group">
<label for="noun-type">Noun Type:</label>
<select id="noun-type">
<option value="person">Person</option>
<option value="place">Place</option>
<option value="thing">Thing</option>
<option value="event">Event</option>
<option value="concept">Concept</option>
<option value="content">Content</option>
<option value="group">Group</option>
<option value="list">List</option>
<option value="category">Category</option>
</select>
</div>
<div class="form-group">
<label for="noun-id">ID (optional):</label>
<input type="text" id="noun-id" placeholder="Custom ID for the entity (auto-generated if empty)">
</div>
<div class="form-group">
<label for="noun-name">Name:</label>
<input type="text" id="noun-name" placeholder="Name of the entity">
</div>
<div class="form-group">
<label for="noun-content">Description/Content:</label>
<textarea id="noun-content" placeholder="Description or content of the entity"></textarea>
</div>
<div class="form-group">
<label for="noun-tags">Tags (comma-separated):</label>
<input type="text" id="noun-tags" placeholder="tag1, tag2, tag3">
</div>
<div class="demo-controls">
<button id="add-noun-btn">Add Noun</button>
<button id="query-nouns-btn" class="accent">View All Nouns</button>
</div>
<div class="results" id="entity-results">
Entity operations will appear here...
</div>
</div>
<!-- Step 4: Creating Relationships -->
<div class="section-content" id="step4-content">
<h3>Step 4: Creating Relationships (Verbs)</h3>
<p>Connect your entities with meaningful relationships to build a knowledge graph.</p>
<div class="form-group">
<label for="source-id">Source Entity:</label>
<select id="source-id">
<option value="">-- Select Source Entity --</option>
</select>
<button id="refresh-nouns-btn" class="secondary" style="margin-top: 5px; padding: 5px 10px;">Refresh Entity
List
</button>
</div>
<div class="form-group">
<label for="target-id">Target Entity:</label>
<select id="target-id">
<option value="">-- Select Target Entity --</option>
</select>
</div>
<div class="form-group">
<label for="verb-type">Relationship Type:</label>
<select id="verb-type">
<option value="relatedTo">Related To</option>
<option value="attributedTo">Attributed To</option>
<option value="controls">Controls</option>
<option value="created">Created</option>
<option value="owns">Owns</option>
<option value="memberOf">Member Of</option>
<option value="worksWith">Works With</option>
<option value="friendOf">Friend Of</option>
</select>
</div>
<div class="form-group">
<label for="verb-description">Relationship Description:</label>
<textarea id="verb-description" placeholder="Describe the relationship between the entities"></textarea>
</div>
<div class="demo-controls">
<button id="add-verb-btn">Add Relationship</button>
<button id="query-verbs-btn" class="accent">View All Relationships</button>
</div>
</div>
<!-- Step 5: Advanced Features -->
<div class="section-content" id="step6-content">
<h3>Step 5: Advanced Features</h3>
<p>Explore Brainy's advanced capabilities for more complex use cases.</p>
<div class="feature-grid">
<div class="feature-card">
<h3>🔍 Vector Search</h3>
<p>Explore how HNSW makes semantic search fast and efficient.</p>
<button class="demo-feature-btn" data-feature="hnsw">Try Vector Search</button>
</div>
<div class="feature-card">
<h3>🌐 Graph Traversal</h3>
<p>Navigate through connected entities in your knowledge graph.</p>
<button class="demo-feature-btn" data-feature="graph-traversal">Try Graph Traversal</button>
</div>
<div class="feature-card">
<h3>💾 Data Management</h3>
<p>Backup, restore and manage your data.</p>
<div class="demo-controls" style="margin-top: 10px;">
<button id="export-data-btn">Backup Data</button>
<button id="import-data-btn">Restore Data</button>
</div>
</div>
<div class="feature-card">
<h3>🧠 Embedding Pipeline</h3>
<p>See how text is converted to vectors for semantic understanding.</p>
<button class="demo-feature-btn" data-feature="embedding">Try Embedding Demo</button>
</div>
</div>
<div class="results" id="feature-demo-results">
Select a feature above to see a detailed demonstration...
</div>
</div>
<!-- Step 6: CLI Interface -->
<div class="section-content" id="step7-content">
<h3>Step 6: Command Line Interface</h3>
<p>Try Brainy's CLI commands for scripting and automation.</p>
<div class="cli-terminal">
<div class="cli-history" id="cli-history"></div>
<div class="cli-command">
<span class="cli-prompt">brainy$</span>
<input type="text" class="cli-input" id="cli-input" placeholder="Type a command...">
</div>
<div class="cli-output" id="cli-output"></div>
</div>
<div class="demo-controls">
<button id="help-cmd-btn">Help</button>
<button id="status-cmd-btn" class="secondary">Status</button>
<button id="init-cmd-btn" class="accent">Init</button>
<button id="query-cmd-btn" class="accent">Query</button>
<button id="clear-terminal-btn" class="danger">Clear</button>
</div>
<div class="code-block">
<strong>Common Commands:</strong><br>
brainy init - Initialize a new database<br>
brainy add &lt;data&gt; - Add data to the database<br>
brainy search &lt;query&gt; - Search for entities<br>
brainy relate &lt;from&gt; &lt;to&gt; - Create relationships<br>
brainy status - Show database status<br>
brainy help - Show all commands
</div>
</div>
</section>
<!-- Quick Start Section -->
<section class="quickstart-section">
<h2>🏁 Quick Start</h2>
<div class="code-tabs">
<div class="code-tab">
<h3>Node.js Environment</h3>
<pre class="code-block">
import { BrainyData, NounType, VerbType } from '@soulcraft/brainy'
// Create and initialize the database
const db = new BrainyData()
await db.init()
// Add data (automatically converted to vectors)
const catId = await db.add("Cats are independent pets", {
noun: NounType.Thing,
category: 'animal'
})
const dogId = await db.add("Dogs are loyal companions", {
noun: NounType.Thing,
category: 'animal'
})
// Search for similar items
const results = await db.searchText("feline pets", 2)
console.log(results)
// Returns items similar to "feline pets" with similarity scores
// Add a relationship between items
await db.addVerb(catId, dogId, {
verb: VerbType.RelatedTo,
description: 'Both are common household pets'
})
</pre>
</div>
<div class="code-tab">
<h3>Browser Environment</h3>
<p>Brainy uses a unified build that automatically adapts to your environment:</p>
<h4>Option 1: Standard Import</h4>
<pre class="code-block">
// Standard import - automatically adapts to any environment
import { BrainyData, NounType, VerbType } from '@soulcraft/brainy'
// Use the same API as in Node.js
const db = new BrainyData()
await db.init()
// ...
</pre>
<h4>Option 2: Using a script tag in HTML</h4>
<pre class="code-block">
&lt;script type="module"&gt;
// Use local files instead of CDN
// For GitHub Pages, use relative path: './dist/unified.js'
// For local development, use absolute path: '/dist/unified.js'
// This import is replaced by the dynamic import below
// Or minified version
// import { BrainyData, NounType, VerbType } from '/dist/unified.min.js'
const db = new BrainyData()
await db.init()
// ...
&lt;/script&gt;
</pre>
<p>Modern bundlers like Webpack, Rollup and Vite will automatically use the unified build which adapts to any
environment.</p>
</div>
</div>
</section>
<footer>
<p>&copy; 2024 Brainy - A lightweight graph & vector data platform</p>
<p>
<a href="https://github.com/soulcraft-research/brainy" target="_blank">GitHub</a> |
<a href="https://github.com/soulcraft-research/brainy/blob/main/README.md" target="_blank">Documentation</a> |
<a href="https://npm.im/@soulcraft/brainy" target="_blank">NPM</a>
</p>
</footer>
</div>
<script type="module">
// Always use local files instead of CDN
// Use relative path for GitHub Pages compatibility
const isGitHubPages = window.location.hostname.includes('github.io')
const isCodeSoulcraft = window.location.hostname.includes('demo.soulcraft.com')
// Use different paths based on hosting environment
let importPath
if (isGitHubPages) {
importPath = './dist/unified.min.js' // Direct access to dist folder in demo directory
} else if (isCodeSoulcraft) {
// Use relative path instead of absolute path for code.soulcraft.com
importPath = './dist/unified.min.js'
} else {
importPath = '/dist/unified.min.js' // Local development
}
// Dynamic import
const { BrainyData, NounType, VerbType } = await import(importPath)
// Make BrainyData and types available globally
// Use Object.defineProperty to avoid conflicts with existing properties
Object.defineProperty(window, 'BrainyData', { value: BrainyData, writable: true, configurable: true })
Object.defineProperty(window, 'NounType', { value: NounType, writable: true, configurable: true })
Object.defineProperty(window, 'VerbType', { value: VerbType, writable: true, configurable: true })
// Initialize demo immediately since modules already run after DOM is loaded
// Check if we're running over HTTP
if (window.location.protocol === 'file:') {
document.getElementById('http-warning').style.display = 'block'
}
try {
// Verify the imported module has the required exports
if (BrainyData) {
initializeDemo()
} else {
showError('Brainy library not found. Please build the project first by running: npm run build')
}
} catch (error) {
showError('Failed to initialize demo: ' + error.message)
}
// Tab switching functionality removed - all sections are now visible
// Initialize the demo
function initializeDemo() {
log('db-status', 'Brainy library loaded successfully!')
// Initialize event listeners
setupEventListeners()
// Initialize CLI
setupCLI()
// Initialize visualizations
setupVisualizations()
// Try to populate noun dropdowns with any existing data
setTimeout(() => {
try {
if (database) {
populateNounDropdowns()
}
} catch (error) {
console.log('No database initialized yet, noun dropdowns will be populated later')
}
}, 1000)
}
// Setup all event listeners
function setupEventListeners() {
// Step 1: Getting Started - Database operations
document.getElementById('init-db-btn').addEventListener('click', initializeDatabase)
document.getElementById('add-sample-btn').addEventListener('click', addSampleData)
document.getElementById('backup-db-btn').addEventListener('click', backupData)
document.getElementById('restore-db-btn').addEventListener('click', restoreData)
document.getElementById('clear-db-btn').addEventListener('click', clearDatabase)
// Step 2: Searching - Search operations
document.getElementById('search-btn')?.addEventListener('click', performSearch)
document.getElementById('similar-entities-btn')?.addEventListener('click', findSimilarEntities)
// Google-like search functionality
const searchInput = document.getElementById('search-query')
const searchClear = document.getElementById('search-clear')
if (searchInput && searchClear) {
// Show/hide clear button based on input content
searchInput.addEventListener('input', function() {
searchClear.style.visibility = this.value ? 'visible' : 'hidden'
})
// Clear the search input when the clear button is clicked
searchClear.addEventListener('click', function() {
searchInput.value = ''
searchClear.style.visibility = 'hidden'
searchInput.focus()
})
// Allow pressing Enter to search
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
performSearch()
}
})
}
// Step 3: Adding Entities - Noun operations
document.getElementById('add-noun-btn')?.addEventListener('click', addNoun)
document.getElementById('query-nouns-btn')?.addEventListener('click', queryNouns)
// Step 4: Creating Relationships - Verb operations
document.getElementById('add-verb-btn')?.addEventListener('click', addVerb)
document.getElementById('query-verbs-btn')?.addEventListener('click', queryVerbs)
document.getElementById('refresh-nouns-btn')?.addEventListener('click', populateNounDropdowns)
// Step 5: Advanced Features - Data management
document.getElementById('export-data-btn')?.addEventListener('click', backupData)
document.getElementById('import-data-btn')?.addEventListener('click', restoreData)
// Step 6: CLI Interface - CLI commands
document.getElementById('help-cmd-btn')?.addEventListener('click', () => executeCLICommand('help'))
document.getElementById('status-cmd-btn')?.addEventListener('click', () => executeCLICommand('status'))
document.getElementById('init-cmd-btn')?.addEventListener('click', () => executeCLICommand('init'))
document.getElementById('query-cmd-btn')?.addEventListener('click', () => executeCLICommand('query sample'))
document.getElementById('clear-terminal-btn')?.addEventListener('click', clearTerminal)
// Feature demonstrations
document.querySelectorAll('.demo-feature-btn').forEach(btn => {
btn.addEventListener('click', function() {
const feature = this.dataset.feature
demonstrateFeature(feature)
})
})
// We'll populate noun dropdowns after database initialization
// populateNounDropdowns() - This will be called after database is initialized
}
// Setup CLI functionality
function setupCLI() {
const cliInput = document.getElementById('cli-input')
cliInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
const command = this.value.trim()
if (command) {
executeCLICommand(command)
this.value = ''
}
}
})
}
// Setup visualizations
function setupVisualizations() {
// Initialize database visualization container
const dbVisualizationContainer = document.getElementById('db-visualization')
if (dbVisualizationContainer) {
const graphContainer = dbVisualizationContainer.querySelector('.graph-container')
if (graphContainer) {
graphContainer.innerHTML = '<div style="text-align: center; padding-top: 200px; color: #666;">Database visualization will appear here after initialization</div>'
}
}
// Hide search visualization container as per requirements
const searchVisualizationContainer = document.getElementById('search-visualization')
if (searchVisualizationContainer) {
searchVisualizationContainer.style.display = 'none'
}
// Setup zoom controls
const zoomFitButton = document.getElementById('zoom-fit-btn')
if (zoomFitButton) {
zoomFitButton.addEventListener('click', function() {
// This will be implemented when we have an active visualization
if (typeof updateDatabaseVisualization === 'function') {
updateDatabaseVisualization()
}
})
}
}
// Database operations
let database = null
async function initializeDatabase() {
try {
log('db-status', 'Initializing database...')
// Initialize Brainy database
database = new BrainyData({
storage: { type: 'opfs' },
augmentations: ['embedding', 'search']
})
await database.init()
// Clear the database after initialization
await database.clear()
log('db-status', 'Database initialized and cleared successfully!\nStorage: OPFS\nAugmentations: Embedding, Search')
await updateDatabaseVisualization()
// Populate noun dropdowns after initialization
await populateNounDropdowns()
} catch (error) {
log('db-status', 'Error initializing database: ' + error.message)
}
}
async function addSampleData() {
if (!database) {
log('db-status', 'Please initialize database first')
return
}
try {
log('db-status', 'Adding sample AI and technology data...')
// Sample Nouns with AI and technology focused content
const sampleNouns = [
// User profiles - AI and Technology Experts
{
id: 'user1',
type: 'person',
noun: 'person',
name: 'Alex Johnson',
content: 'AI researcher and senior software developer with 10+ years of experience in machine learning and natural language processing. Currently leading a team developing large language models with improved reasoning capabilities. My research focuses on making AI systems more transparent and explainable to end users. I\'m particularly interested in reducing hallucinations in generative AI while maintaining creative capabilities. Recently published a paper on techniques for evaluating factual consistency in AI-generated content.',
tags: ['AI', 'machine learning', 'NLP', 'research', 'explainable AI', 'LLMs', 'transparency', 'factual consistency']
},
{
id: 'user2',
type: 'person',
noun: 'person',
name: 'Sophia Chen',
content: 'Data scientist specializing in computer vision applications for healthcare. My work involves developing AI systems that can assist radiologists in early detection of diseases from medical imaging. I\'m passionate about ensuring AI healthcare tools work equitably across diverse patient populations. Recently completed a project that reduced diagnostic disparities in skin condition identification across different skin tones. Currently researching privacy-preserving federated learning approaches for training medical AI without compromising patient data.',
tags: ['AI', 'computer vision', 'healthcare', 'medical imaging', 'equity', 'federated learning', 'privacy', 'diagnostics']
},
{
id: 'user3',
type: 'person',
noun: 'person',
name: 'Marcus Williams',
content: 'AI ethics researcher and consultant helping organizations implement responsible AI practices. My background spans philosophy, computer science, and policy analysis. I develop frameworks for algorithmic impact assessments and conduct audits of AI systems for potential bias or harmful outcomes. Currently advising several tech companies on establishing AI governance structures and ethical guidelines. My recent work focuses on ensuring human oversight in automated decision systems, particularly in high-stakes domains.',
tags: ['AI ethics', 'responsible AI', 'algorithmic bias', 'governance', 'policy', 'impact assessment', 'human oversight', 'technology ethics']
},
{
id: 'user4',
type: 'person',
noun: 'person',
name: 'Priya Patel',
content: 'AI researcher focusing on environmental applications of machine learning. I develop models that analyze satellite imagery and sensor data to monitor deforestation, predict climate patterns, and optimize renewable energy systems. My team recently created an early warning system for wildfire risk that combines weather data with vegetation dryness detected through remote sensing. I\'m passionate about using AI to address climate change while ensuring these technologies themselves have minimal environmental impact through efficient computing approaches.',
tags: ['AI', 'environmental science', 'climate tech', 'remote sensing', 'satellite imagery', 'renewable energy', 'wildfires', 'sustainable computing']
},
{
id: 'user5',
type: 'person',
noun: 'person',
name: 'Jordan Taylor',
content: 'Robotics engineer specializing in human-robot interaction and collaborative systems. My research focuses on developing robots that can safely work alongside humans in manufacturing, healthcare, and home environments. I\'m particularly interested in intuitive interfaces that allow non-experts to program and direct robotic assistants. Recently developed a gesture recognition system that enables factory workers to quickly redirect collaborative robots without specialized training. Currently working on robots that can recognize and respond appropriately to human emotional states.',
tags: ['robotics', 'AI', 'human-robot interaction', 'collaborative robots', 'gesture recognition', 'manufacturing', 'healthcare robotics', 'emotion recognition']
},
{
id: 'user11',
type: 'person',
noun: 'person',
name: 'Olivia Martinez',
content: 'Quantum computing researcher specializing in quantum machine learning algorithms. My work bridges the gap between quantum physics and artificial intelligence, developing novel approaches that leverage quantum properties to enhance machine learning capabilities. I\'ve recently published on quantum neural networks that demonstrate significant speedup for specific pattern recognition tasks. Currently leading a project to implement these algorithms on actual quantum hardware through cloud access partnerships with major quantum computing providers. I\'m passionate about making quantum computing concepts accessible to AI practitioners without physics backgrounds.',
tags: ['quantum computing', 'AI', 'machine learning', 'quantum algorithms', 'quantum neural networks', 'physics', 'pattern recognition', 'quantum hardware', 'education']
},
{
id: 'user12',
type: 'person',
noun: 'person',
name: 'Benjamin Lee',
content: 'AR/VR developer focused on creating immersive educational experiences. I design virtual environments that make complex scientific and technical concepts tangible and interactive. My recent projects include a VR simulation of molecular interactions for chemistry education and an AR application that visualizes historical architectural styles in urban environments. I\'m particularly interested in how spatial computing can transform learning by engaging multiple sensory systems simultaneously. Currently researching how to optimize knowledge retention through embodied cognition principles in virtual environments.',
tags: ['AR', 'VR', 'extended reality', 'education', 'immersive learning', 'spatial computing', 'visualization', 'embodied cognition', 'interactive design', 'simulation']
},
{
id: 'user13',
type: 'person',
noun: 'person',
name: 'Amara Okafor',
content: 'Cybersecurity researcher specializing in AI-powered threat detection systems. My work focuses on developing machine learning models that can identify novel attack patterns and zero-day vulnerabilities before they can be widely exploited. I lead a team that combines traditional rule-based security approaches with anomaly detection algorithms that continuously learn from network behavior. Recently published research on adversarial machine learning techniques that can strengthen security systems against AI-powered attacks. Currently developing privacy-preserving methods for sharing threat intelligence across organizations without exposing sensitive data.',
tags: ['cybersecurity', 'AI', 'machine learning', 'threat detection', 'zero-day vulnerabilities', 'adversarial machine learning', 'network security', 'privacy', 'threat intelligence']
},
{
id: 'user14',
type: 'person',
noun: 'person',
name: 'Hiroshi Nakamura',
content: 'Robotics and AI researcher specializing in swarm intelligence and multi-robot coordination. My work involves developing algorithms that allow large groups of simple robots to collectively solve complex problems through local interactions. These systems are inspired by biological swarms like ant colonies and bird flocks. Recent projects include disaster response robot swarms that can rapidly map damaged buildings and environmental monitoring drones that self-organize to track pollution sources. I\'m particularly interested in creating robust systems that can adapt to unexpected environmental changes and continue functioning even when individual robots fail.',
tags: ['robotics', 'AI', 'swarm intelligence', 'multi-robot systems', 'distributed algorithms', 'biomimicry', 'disaster response', 'environmental monitoring', 'resilient systems', 'collective behavior']
},
{
id: 'user15',
type: 'person',
noun: 'person',
name: 'Elena Volkov',
content: 'AI ethics advocate and policy researcher focusing on algorithmic fairness and accountability. My interdisciplinary background spans computer science, law, and social science, allowing me to bridge technical and regulatory perspectives on AI governance. I work with both government agencies and technology companies to develop practical frameworks for algorithmic impact assessments and auditing methodologies. Recently led a multi-stakeholder initiative to create industry standards for transparent AI documentation. My current research examines how different cultural and legal traditions around the world are approaching AI regulation, and how to develop globally compatible governance frameworks.',
tags: ['AI ethics', 'policy', 'algorithmic fairness', 'governance', 'regulation', 'impact assessment', 'transparency', 'accountability', 'global perspectives', 'standards development']
},
// Posts/Content - AI and Technology Topics
{
id: 'post1',
type: 'document',
noun: 'content',
title: 'The Future of Large Language Models: Beyond Text Generation',
content: 'Large language models have evolved rapidly from simple text prediction to systems capable of complex reasoning, code generation, and multimodal understanding. While current models like GPT-4 and Claude have impressive capabilities, they still face significant challenges in reasoning, factuality, and alignment with human values. The next generation of LLMs will likely focus less on scaling parameters and more on architectural innovations that improve reasoning capabilities. We\'re already seeing promising research in retrieval-augmented generation (RAG) that grounds model outputs in verified information sources, reducing hallucinations while maintaining flexibility. Another critical direction is the development of more sophisticated alignment techniques that better capture the nuance and diversity of human values while avoiding overfitting to specific cultural perspectives. The most exciting applications will emerge when these models can reliably act as reasoning engines that augment human thinking rather than simply generating plausible-sounding text. For this to happen, we need breakthroughs in evaluation methods that can rigorously test for logical consistency and factual accuracy beyond surface-level fluency. Organizations implementing these technologies will need to develop robust governance frameworks that ensure appropriate human oversight while leveraging the models\' capabilities. The companies that succeed won\'t be those with the largest models, but those that most effectively integrate these systems into workflows that combine machine efficiency with human judgment and creativity.',
tags: ['AI', 'large language models', 'LLMs', 'reasoning', 'alignment', 'retrieval-augmented generation', 'factuality', 'governance', 'evaluation']
},
{
id: 'post2',
type: 'document',
noun: 'content',
title: 'Computer Vision in Healthcare: Current Applications and Ethical Considerations',
content: 'Computer vision systems are transforming healthcare diagnostics by analyzing medical images with speed and accuracy that complement human expertise. In radiology, AI models can now detect early signs of conditions ranging from lung cancer to diabetic retinopathy, often identifying subtle patterns that might be missed in initial human review. These systems are most effective when deployed as assistive tools that highlight areas of concern for radiologist confirmation, rather than autonomous diagnostic systems. The most successful implementations maintain the physician as the final decision-maker while using AI to enhance efficiency and reduce the likelihood of missed findings. Beyond radiology, computer vision is enabling new applications in surgical assistance, remote patient monitoring, and even mental health assessment through facial expression analysis. However, these powerful capabilities come with significant ethical considerations. Training data often underrepresents certain demographic groups, leading to models that perform inconsistently across different populations. This is particularly concerning in dermatology applications, where systems trained predominantly on lighter skin tones have shown reduced accuracy for patients with darker skin. Healthcare institutions implementing these technologies must invest in diverse training datasets and rigorous testing across population groups. Additionally, the "black box" nature of many deep learning models raises questions about explainability and trust in high-stakes medical contexts. Researchers are developing techniques for more interpretable AI, allowing clinicians to understand the factors influencing a model\'s suggestion. As these systems become more integrated into clinical workflows, maintaining appropriate human oversight and clear accountability frameworks will be essential for responsible deployment.',
tags: ['AI', 'computer vision', 'healthcare', 'medical imaging', 'diagnostics', 'ethics', 'bias', 'explainability', 'radiology', 'dermatology']
},
{
id: 'post3',
type: 'document',
noun: 'content',
title: 'Ethical AI Design: Building Systems That Respect Human Values',
content: 'The principle that "less is more" has never been more relevant than in today\'s overcrowded digital landscape. Minimalist design isn\'t just an aesthetic choice—it\'s a functional imperative for creating interfaces that users can navigate intuitively. Through my work with various clients, I\'ve observed that minimalist interfaces consistently outperform cluttered ones in key metrics like time-on-task, error rates, and user satisfaction. The core principles of minimalist design extend beyond simply removing elements. It involves a careful analysis of user needs, prioritizing functions based on frequency and importance, and creating visual hierarchies that guide attention naturally. Color should be used strategically, not decoratively—each color choice should serve a specific communicative purpose. Typography plays an equally crucial role; a well-chosen font hierarchy can eliminate the need for additional visual elements like dividers or boxes. White space (or negative space) is perhaps the most undervalued element in digital design. It\'s not just empty space—it\'s a powerful tool for creating focus, improving readability, and giving content room to breathe. When implementing minimalist principles, it\'s important to test with real users to ensure that simplification doesn\'t compromise usability. The goal is to reduce cognitive load while maintaining all necessary functionality, creating digital products that feel effortless to use while being fully featured. This approach not only improves user experience but also tends to create more accessible interfaces that work better for users with disabilities or those using assistive technologies. For example, a recent e-commerce project I completed saw a 23% increase in conversion rates after implementing minimalist design principles, while customer support inquiries decreased by almost 30%. The simplified navigation and clearer visual hierarchy made it easier for users to find products and complete purchases without confusion. The project also prioritized accessibility, ensuring that the interface worked well with screen readers and supported keyboard navigation, making the site usable for people with various disabilities.',
tags: ['AI', 'ethics', 'responsible AI', 'human values', 'alignment', 'bias', 'fairness', 'transparency', 'accountability', 'governance', 'human-centered design', 'stakeholder engagement', 'value pluralism']
},
{
id: 'post4',
type: 'document',
noun: 'content',
title: 'AI for Environmental Monitoring: Protecting Ecosystems with Machine Learning',
content: 'The misconception that you need a large yard to grow your own food is preventing many urban dwellers from experiencing the satisfaction and benefits of home gardening. Through five years of experimentation in my 500-square-foot apartment, I\'ve developed systems for growing approximately 30% of my own produce year-round. Vertical gardening is the cornerstone of space-efficient food production. By utilizing wall space with hanging planters, tiered shelving, and trellis systems, even the smallest balcony can become surprisingly productive. I\'ve found that leafy greens like kale, spinach, and various lettuces offer the best return on investment in small spaces—they grow quickly, can be harvested continuously, and would otherwise be expensive to purchase organically. For those without outdoor space, windowsill herb gardens and microgreens under grow lights provide fresh flavors with minimal space requirements. The key to successful small-space gardening is understanding the specific light conditions of your space and selecting appropriate plants. Most vegetables need at least 6 hours of direct sunlight, but many herbs and leafy greens can thrive with less. Container selection is equally important—self-watering containers have revolutionized urban gardening by reducing maintenance and improving plant health. Soil quality becomes even more critical in container gardening; investing in high-quality potting mix and implementing a regular composting system (even a small worm bin under the sink) creates a sustainable cycle. Beyond the practical benefits of fresh, pesticide-free produce, urban gardening creates a connection to natural cycles that is often missing in city life. The psychological benefits of tending plants and watching them grow should not be underestimated, especially in high-stress urban environments. I\'ve recently started working with community organizations to develop urban gardening programs in food desert neighborhoods, where access to fresh produce is limited. These community gardens not only provide nutritious food but also serve as educational spaces where residents can learn about sustainable growing practices, nutrition, and environmental science. The social connections formed through these community gardening initiatives have proven to be as valuable as the food produced, creating stronger neighborhood bonds and support networks.',
tags: ['AI', 'machine learning', 'environmental monitoring', 'conservation', 'remote sensing', 'satellite imagery', 'biodiversity', 'climate change', 'sustainability', 'ecosystem protection', 'data science', 'sensors', 'wildlife tracking', 'deforestation']
},
{
id: 'post5',
type: 'document',
noun: 'content',
title: 'Robotics and Human Augmentation: The Future of Collaborative Systems',
content: 'After years of designing fitness programs, I\'ve found that the biggest obstacle for most people isn\'t motivation—it\'s complexity and accessibility. This 30-day challenge addresses both issues by requiring zero equipment while providing a structured progression that prevents plateaus and reduces injury risk. The program is built around functional movement patterns that strengthen the body for real-world activities, not just gym performance. The first week focuses on establishing proper form in fundamental movements like squats, lunges, planks, and push-ups, with modifications provided for all fitness levels. Rather than counting reps, many exercises use time-based intervals, allowing each person to work at their own pace while still being challenged. As the program progresses, intensity increases through three primary mechanisms: increasing time under tension, incorporating unilateral (single-limb) variations, and adding rhythmic changes that challenge coordination and cardiovascular fitness simultaneously. Recovery is programmed as deliberately as the workouts themselves, with specific mobility routines for rest days that address common problem areas like hip flexors and shoulders that become tight from sedentary work. The nutrition guidance accompanying the program emphasizes timing and composition rather than strict calorie counting—particularly the importance of protein intake for recovery and carbohydrate timing around workouts. Participants who\'ve completed this challenge report not just physical changes, but improvements in sleep quality, energy levels, and mental clarity. The program includes a tracking system that helps identify patterns between workout performance and variables like sleep, stress, and nutrition, teaching participants to understand their body\'s unique responses and needs. What sets this program apart from others is its holistic approach to fitness that acknowledges the interconnectedness of physical activity, nutrition, sleep, and stress management. Each week includes not only workout instructions but also mindfulness practices, sleep optimization strategies, and stress reduction techniques. This integrated approach has proven particularly effective for participants who previously struggled with consistency, as it addresses the root causes of exercise avoidance rather than just prescribing more willpower.',
tags: ['robotics', 'AI', 'human augmentation', 'collaborative systems', 'human-robot interaction', 'exoskeletons', 'prosthetics', 'automation', 'manufacturing', 'healthcare robotics', 'assistive technology', 'brain-computer interfaces', 'cobots', 'human factors']
},
// Additional Posts
{
id: 'post6',
type: 'document',
noun: 'content',
title: 'AI-Powered Cybersecurity: Machine Learning for Threat Detection and Response',
content: 'Small businesses often believe they\'re too insignificant to be targeted by hackers, but this misconception makes them particularly vulnerable. In reality, over 40% of cyberattacks target small businesses precisely because they typically have weaker security measures than larger organizations while still holding valuable data. This guide outlines practical, cost-effective security measures that don\'t require a dedicated IT department. First, implement multi-factor authentication (MFA) on all business accounts - this single step can prevent 99.9% of automated attacks. Next, establish a regular update schedule for all software and devices to patch security vulnerabilities promptly. For data protection, adopt the 3-2-1 backup strategy: maintain three copies of important data on two different media types with one copy stored off-site or in the cloud. Employee training is equally crucial - create clear security policies and conduct regular phishing simulations to help staff recognize threats.',
tags: ['AI', 'cybersecurity', 'machine learning', 'threat detection', 'anomaly detection', 'security', 'data protection', 'predictive analytics', 'zero-day threats', 'behavioral analysis', 'automated response', 'network security', 'intrusion detection', 'cyber defense']
},
{
id: 'post7',
type: 'document',
noun: 'content',
title: 'AI and Indigenous Knowledge: Combining Traditional Wisdom with Machine Learning',
content: 'The intersection of traditional ecological knowledge and modern marine conservation offers powerful solutions for ocean protection that neither approach could achieve alone. Indigenous coastal communities worldwide have maintained sustainable relationships with marine ecosystems for thousands of years through sophisticated management practices often dismissed by Western science until recently. In the Pacific Islands, traditional conservation methods like the Polynesian rahui (temporary fishing bans) and Hawaiian ahupua\'a (integrated land-sea management systems) are now being recognized for their effectiveness in maintaining biodiversity and fish stocks.',
tags: ['AI', 'indigenous knowledge', 'machine learning', 'traditional ecological knowledge', 'cultural preservation', 'data sovereignty', 'environmental monitoring', 'biodiversity', 'climate change', 'participatory design', 'ethical AI', 'cross-cultural collaboration', 'sustainable technology', 'knowledge systems']
},
{
id: 'post8',
type: 'document',
noun: 'content',
title: 'AI in Neuroscience: Machine Learning Approaches to Understanding the Brain',
content: 'Recent advances in neuroimaging technology have allowed scientists to observe the remarkable ways meditation practices physically reshape the brain, providing scientific validation for what practitioners have reported for centuries. Longitudinal studies using MRI scans show that regular meditation practice leads to measurable changes in brain structure and function in as little as eight weeks. The most consistent findings involve increased gray matter density in regions associated with attention, sensory processing, and emotional regulation.',
tags: ['AI', 'neuroscience', 'machine learning', 'brain', 'neuroimaging', 'computational neuroscience', 'neural networks', 'brain-computer interfaces', 'cognitive science', 'MRI', 'fMRI', 'EEG', 'neural decoding', 'connectomics', 'brain mapping']
},
{
id: 'post9',
type: 'document',
noun: 'content',
title: 'Smart Cities and AI: Optimizing Urban Infrastructure with Intelligent Systems',
content: 'The 20th-century approach to urban transportation - prioritizing private vehicles and highway expansion - has created cities choked by congestion, pollution, and inefficient land use. A paradigm shift is underway as cities worldwide reimagine mobility systems that move people, not just cars. The most successful urban transformations begin with a "complete streets" philosophy that equitably serves all users regardless of age, ability, or mode of transportation. This approach typically involves converting vehicle lanes to protected bicycle infrastructure, widening sidewalks, improving transit priority, and adding green infrastructure.',
tags: ['AI', 'smart cities', 'urban planning', 'IoT', 'intelligent transportation systems', 'urban infrastructure', 'data analytics', 'sensors', 'traffic optimization', 'energy efficiency', 'predictive maintenance', 'urban mobility', 'sustainability', 'digital twins', 'smart grid']
},
{
id: 'post10',
type: 'document',
noun: 'content',
title: 'Quantum Machine Learning: The Convergence of Quantum Computing and AI',
content: 'Quantum computing represents a fundamental shift in how we process information, potentially solving problems that would take classical computers millions of years in just minutes. Unlike classical computers that use bits representing either 0 or 1, quantum computers use quantum bits or "qubits" that can exist in multiple states simultaneously through a property called superposition. This allows quantum computers to explore multiple solutions to a problem at once rather than sequentially. Another key quantum property is entanglement, where qubits become correlated so that the state of one instantly influences another, regardless of distance.',
tags: ['AI', 'quantum computing', 'quantum machine learning', 'qubits', 'superposition', 'entanglement', 'quantum neural networks', 'quantum algorithms', 'variational quantum circuits', 'quantum supremacy', 'quantum advantage', 'hybrid quantum-classical', 'optimization', 'quantum data', 'quantum AI']
},
{
id: 'post11',
type: 'document',
noun: 'content',
title: 'Edge AI: Bringing Machine Learning to Resource-Constrained Devices',
content: 'The traditional cloud-based AI model is giving way to a new paradigm where machine learning algorithms run directly on edge devices like smartphones, IoT sensors, and wearables. This shift addresses critical limitations of cloud AI including latency, privacy concerns, and connectivity requirements. Edge AI enables real-time processing by eliminating round-trip data transfers to remote servers, allowing applications like autonomous vehicles and augmented reality to make split-second decisions. Privacy is enhanced as sensitive data remains on the user\'s device rather than being transmitted to external servers. The technical challenge lies in optimizing neural networks to run efficiently on devices with limited processing power, memory, and energy constraints. Recent advances in model compression techniques like quantization, pruning, and knowledge distillation have made it possible to deploy sophisticated AI capabilities on increasingly modest hardware. The future of edge AI will likely involve hybrid approaches where devices handle immediate processing needs while still leveraging cloud resources for more complex tasks and model updates.',
tags: ['AI', 'edge computing', 'IoT', 'machine learning', 'model optimization', 'privacy', 'latency', 'embedded systems', 'model compression', 'quantization', 'pruning', 'knowledge distillation', 'real-time processing', 'resource constraints', 'distributed AI']
},
{
id: 'post12',
type: 'document',
noun: 'content',
title: 'Explainable AI: Making Black Box Models Transparent and Trustworthy',
content: 'As AI systems increasingly influence critical decisions in healthcare, finance, and criminal justice, the demand for transparency in how these systems reach their conclusions has become urgent. Explainable AI (XAI) encompasses techniques and approaches that enable humans to understand, appropriately trust, and effectively manage AI systems. The challenge stems from the inherent tension between model performance and interpretability - the most accurate models like deep neural networks are often the least transparent. Current XAI approaches fall into two categories: intrinsically interpretable models that are transparent by design, and post-hoc explanation methods that help explain already-trained black box models. Techniques like LIME and SHAP generate local explanations by approximating complex models with simpler, interpretable ones around specific predictions. Feature importance visualizations, counterfactual explanations, and attention mechanisms provide insights into which inputs most influenced a particular output. The field is rapidly evolving with researchers developing methods that maintain high performance while providing meaningful explanations that are accessible to both technical and non-technical stakeholders.',
tags: ['AI', 'explainable AI', 'XAI', 'transparency', 'interpretability', 'machine learning', 'neural networks', 'LIME', 'SHAP', 'feature importance', 'counterfactual explanations', 'attention mechanisms', 'trust', 'accountability', 'responsible AI']
},
{
id: 'post13',
type: 'document',
noun: 'content',
title: 'Federated Learning: Privacy-Preserving Collaborative AI',
content: 'Federated learning represents a paradigm shift in how machine learning models are trained, addressing the fundamental tension between data utility and privacy protection. Unlike traditional approaches that require centralizing data from all sources, federated learning enables multiple parties to collaboratively train models while keeping their data local and private. The process works by having the central server distribute the current model to participating devices or organizations, which then train the model on their local data and send back only the model updates, not the raw data itself. These updates are aggregated to improve the global model, which is then redistributed for the next round of training. This approach is particularly valuable in privacy-sensitive domains like healthcare, where patient data cannot be freely shared, and in mobile applications, where user data remains on personal devices. Beyond privacy benefits, federated learning reduces bandwidth requirements and enables models to leverage diverse data sources that might otherwise remain siloed. Current research focuses on addressing challenges like communication efficiency, statistical heterogeneity across participants, and defending against potential privacy attacks that might attempt to reconstruct training data from model updates.',
tags: ['AI', 'federated learning', 'privacy', 'distributed computing', 'machine learning', 'collaborative AI', 'data privacy', 'edge AI', 'secure computation', 'differential privacy', 'decentralized learning', 'model aggregation', 'healthcare AI', 'mobile AI', 'privacy-preserving AI']
},
{
id: 'post14',
type: 'document',
noun: 'content',
title: 'AI in Climate Science: Machine Learning for Environmental Monitoring and Prediction',
content: 'The complexity and scale of climate change demand sophisticated analytical tools, making artificial intelligence an increasingly vital component of climate science. Machine learning models are now being deployed to analyze the massive datasets generated by satellites, weather stations, ocean buoys, and other environmental sensors. These AI systems can identify patterns and relationships that might elude traditional statistical methods, improving our understanding of climate dynamics and enhancing predictive capabilities. Computer vision algorithms analyze satellite imagery to track deforestation, monitor ice sheet changes, and detect early signs of extreme weather events. Deep learning models are improving the resolution and accuracy of climate projections by identifying complex patterns in historical data and simulations. Reinforcement learning is being applied to optimize renewable energy systems, making solar and wind power generation more efficient and reliable despite variable weather conditions. The most promising applications combine physics-based climate models with data-driven machine learning approaches, leveraging the strengths of both methodologies. As climate change accelerates, these AI tools will be crucial for developing adaptation strategies, managing resources, and evaluating the effectiveness of mitigation efforts.',
tags: ['AI', 'climate science', 'machine learning', 'environmental monitoring', 'climate modeling', 'remote sensing', 'satellite imagery', 'weather prediction', 'renewable energy', 'sustainability', 'computer vision', 'deep learning', 'reinforcement learning', 'climate change', 'earth observation']
},
{
id: 'post15',
type: 'document',
noun: 'content',
title: 'Neuromorphic Computing: Brain-Inspired AI Hardware',
content: 'Traditional computing architectures based on the von Neumann model face fundamental limitations for AI workloads, particularly in terms of energy efficiency and real-time processing. Neuromorphic computing offers an alternative approach by designing hardware that mimics the structure and function of biological neural systems. Unlike conventional computers that separate memory and processing, neuromorphic chips integrate these functions, similar to how neurons and synapses work in the brain. This colocation dramatically reduces the energy consumed by data movement between memory and processing units. Spiking neural networks (SNNs) are a key component of neuromorphic systems, using discrete spikes for communication rather than continuous values, enabling event-driven computation that activates only when needed. This approach can achieve orders of magnitude improvements in energy efficiency for certain AI tasks. Major research initiatives like IBM\'s TrueNorth, Intel\'s Loihi, and BrainChip\'s Akida are developing commercial neuromorphic processors that excel at tasks requiring real-time processing of sensory data, such as computer vision and audio processing. As these technologies mature, they promise to enable sophisticated AI capabilities in edge devices with strict power constraints, from autonomous drones to smart sensors, while potentially offering new approaches to machine learning that better capture the adaptability and efficiency of biological intelligence.',
tags: ['AI', 'neuromorphic computing', 'brain-inspired computing', 'hardware', 'spiking neural networks', 'SNNs', 'energy efficiency', 'edge AI', 'TrueNorth', 'Loihi', 'event-driven computing', 'neural processing', 'low-power AI', 'biomimetic computing', 'cognitive computing']
},
{
id: 'post16',
type: 'document',
noun: 'content',
title: 'AI for Accessibility: Making Technology Inclusive Through Machine Learning',
content: 'Artificial intelligence is transforming accessibility, creating new possibilities for people with disabilities to interact with technology and navigate the world. Computer vision systems can describe images for blind users, translate sign language in real-time, and help people with mobility impairments control devices through eye tracking or facial expressions. Natural language processing enables more sophisticated screen readers, real-time captioning for deaf users, and communication aids for people with speech impairments. Predictive text and word completion algorithms are being customized to assist people with cognitive or motor challenges, adapting to individual patterns and needs. Perhaps most promising is how AI can personalize accessibility features to address the unique combination of needs that each person has, rather than using one-size-fits-all solutions. These technologies are increasingly being integrated into mainstream products rather than specialized assistive devices, promoting universal design principles. However, ensuring these systems work equitably requires diverse training data that includes people with various disabilities. The development process itself must be inclusive, involving people with disabilities as designers, developers, and testers to identify potential issues and ensure solutions address real needs rather than assumptions about what would be helpful.',
tags: ['AI', 'accessibility', 'assistive technology', 'computer vision', 'natural language processing', 'speech recognition', 'text-to-speech', 'sign language', 'eye tracking', 'predictive text', 'universal design', 'inclusive design', 'personalization', 'adaptive interfaces', 'disability']
},
{
id: 'post17',
type: 'document',
noun: 'content',
title: 'AI in Drug Discovery: Accelerating Pharmaceutical Research with Machine Learning',
content: 'The traditional drug discovery process is notoriously time-consuming and expensive, typically taking over a decade and billions of dollars to bring a new medication to market. Artificial intelligence is revolutionizing this field by dramatically accelerating multiple stages of the pipeline. Machine learning models can screen vast libraries of chemical compounds to identify promising drug candidates, predicting their properties and potential efficacy without extensive laboratory testing. Deep learning approaches like AlphaFold have made breakthrough advances in protein structure prediction, a critical component for understanding disease mechanisms and designing targeted therapies. Generative models can suggest entirely new molecular structures optimized for specific properties, exploring chemical space far beyond what human researchers could manually design. Natural language processing algorithms analyze scientific literature to identify connections between diseases, genes, and compounds that might otherwise remain hidden in the exponentially growing corpus of biomedical research. These AI approaches are particularly valuable for addressing rare diseases and developing personalized medicine, areas where traditional approaches often struggle due to limited data or economic incentives. While AI won\'t replace laboratory validation and clinical trials, it can significantly reduce the number of failed candidates and direct research efforts toward the most promising avenues, potentially bringing life-saving treatments to patients faster and at lower cost.',
tags: ['AI', 'drug discovery', 'pharmaceutical research', 'machine learning', 'molecular modeling', 'protein structure', 'AlphaFold', 'generative chemistry', 'computational biology', 'virtual screening', 'medicinal chemistry', 'drug design', 'personalized medicine', 'rare diseases', 'biomedical research']
},
{
id: 'post18',
type: 'document',
noun: 'content',
title: 'Reinforcement Learning: Teaching AI Through Trial and Error',
content: 'Reinforcement learning (RL) represents a fundamentally different approach to AI compared to supervised or unsupervised learning, focusing on how agents should act in an environment to maximize cumulative rewards. This paradigm mirrors how humans and animals learn through trial and error, making it particularly suited for sequential decision-making problems like game playing, robotics, and resource management. Unlike supervised learning, which requires labeled examples of correct behavior, RL agents discover optimal strategies through exploration and feedback. The field has achieved remarkable milestones, from DeepMind\'s AlphaGo defeating world champions in Go to OpenAI\'s dexterous robotic hand manipulating objects with human-like skill. Modern approaches combine deep neural networks with reinforcement learning (Deep RL) to handle complex state spaces and learn directly from raw sensory input. Key algorithms include Q-learning and its deep variant DQN, policy gradient methods like PPO, and model-based approaches that build internal representations of environment dynamics. Despite these advances, reinforcement learning faces significant challenges including sample inefficiency (requiring millions of interactions), stability issues during training, and the difficulty of specifying reward functions that align with human intentions without unexpected side effects. Current research focuses on making RL more sample-efficient through techniques like imitation learning, addressing the exploration-exploitation dilemma, and developing safe RL methods that can be deployed in real-world settings where mistakes could have serious consequences.',
tags: ['AI', 'reinforcement learning', 'RL', 'deep reinforcement learning', 'machine learning', 'Q-learning', 'policy gradients', 'PPO', 'AlphaGo', 'robotics', 'game AI', 'decision making', 'exploration', 'reward functions', 'sample efficiency', 'imitation learning']
},
{
id: 'post19',
type: 'document',
noun: 'content',
title: 'AI and Creativity: Computational Approaches to Art, Music, and Design',
content: 'The intersection of artificial intelligence and creativity challenges our understanding of both fields, raising profound questions about the nature of imagination and the uniquely human quality of artistic expression. Modern generative AI systems can now produce images, music, literature, and designs that are increasingly difficult to distinguish from human-created works. These systems typically use deep learning approaches like GANs (Generative Adversarial Networks), VAEs (Variational Autoencoders), and transformer-based language models trained on vast corpora of human creative works. Rather than simply mimicking existing styles, the most advanced systems can combine influences in novel ways, explore conceptual spaces, and even respond to abstract prompts with original interpretations. In visual arts, tools like DALL-E, Midjourney, and Stable Diffusion can generate images from text descriptions, while musical AI systems can compose in various genres, improvise with human musicians, and generate novel sound designs. In literature and poetry, large language models can write in distinctive voices, maintain narrative coherence, and even attempt humor. These technologies are increasingly being integrated into creative workflows, serving as collaborative tools that augment human creativity rather than replace it. Artists, musicians, writers, and designers are using AI to overcome creative blocks, explore variations on their ideas, and achieve effects that would be difficult through traditional means alone. This human-AI collaboration represents a new paradigm in creative expression, potentially expanding the range of what\'s artistically possible while raising important questions about authorship, originality, and the value we place on human creative labor.',
tags: ['AI', 'creativity', 'generative AI', 'art', 'music', 'literature', 'design', 'GANs', 'VAEs', 'transformers', 'DALL-E', 'Midjourney', 'Stable Diffusion', 'human-AI collaboration', 'computational creativity', 'creative computing', 'digital art', 'generative music', 'AI writing', 'creative process']
},
{
id: 'post20',
type: 'document',
noun: 'content',
title: 'AI Governance: Developing Frameworks for Responsible AI Development',
content: 'As artificial intelligence systems increasingly impact critical aspects of society, the need for effective governance frameworks has become urgent. AI governance encompasses the policies, institutions, and practices designed to ensure AI technologies are developed and deployed in ways that are safe, ethical, and beneficial to humanity. Unlike traditional technology regulation, AI governance faces unique challenges due to the technology\'s rapid evolution, its often opaque nature, and its potential for autonomous decision-making. Effective governance must balance innovation with appropriate safeguards, addressing risks without stifling beneficial progress. Current approaches span a spectrum from binding regulations to voluntary guidelines and industry self-regulation. The EU\'s AI Act represents one of the most comprehensive regulatory frameworks, taking a risk-based approach that imposes stricter requirements on high-risk applications. In contrast, the US has generally favored sector-specific regulation and voluntary commitments. International coordination is essential but complicated by differing cultural values, economic interests, and political systems. Key governance challenges include ensuring transparency in how AI systems make decisions, establishing accountability for AI-caused harms, addressing potential biases and discrimination, managing privacy implications, and developing standards for testing and validating AI systems. Stakeholder participation is crucial, involving not just technical experts and policymakers but also civil society, affected communities, and the general public. As AI capabilities continue to advance, governance frameworks will need to evolve, potentially incorporating technical solutions like built-in safety measures alongside institutional oversight mechanisms.',
tags: ['AI', 'governance', 'regulation', 'policy', 'ethics', 'responsible AI', 'AI safety', 'transparency', 'accountability', 'bias', 'privacy', 'standards', 'stakeholder engagement', 'international coordination', 'risk assessment', 'AI Act', 'self-regulation', 'oversight', 'compliance', 'impact assessment']
},
// Comments
{
id: 'comment1',
type: 'document',
noun: 'content',
title: 'Comment on Large Language Models post',
content: 'Your insights on the intersection of AI and privacy are particularly relevant given the recent controversies surrounding facial recognition technologies. I\'m currently researching how AI can be applied to healthcare diagnostics while maintaining patient confidentiality. Have you explored how federated learning might offer solutions in this domain? I\'d love to discuss this further as it seems aligned with your interest in edge computing applications. I\'ve been experimenting with a system that allows medical institutions to train shared AI models without exchanging sensitive patient data, and the preliminary results are promising. The challenge we\'re facing now is balancing model accuracy with the computational limitations of edge devices in clinical settings.',
tags: ['comment', 'AI', 'healthcare', 'privacy', 'federated learning', 'edge computing', 'diagnostics', 'patient confidentiality', 'machine learning']
},
{
id: 'comment2',
type: 'document',
noun: 'content',
title: 'Comment on Computer Vision in Healthcare post',
content: 'Your detailed description of regional Vietnamese pho variations brought back memories of my own travels there! The photos you shared of the Hanoi street food markets are absolutely stunning - the composition and lighting really capture the vibrant atmosphere. I\'m curious about your experience with Malaysian laksa - did you find significant differences between the Penang and Sarawak versions? I\'ve been trying to recreate authentic laksa at home but struggling to find the right balance of spices. During my trip to Malaysia last year, I took a cooking class in Penang where we made assam laksa from scratch, including pounding our own spice paste. The instructor emphasized that the key to authentic flavor is using fresh torch ginger flower (bunga kantan) and Vietnamese coriander (daun kesum), which I\'ve had trouble finding in my local Asian markets. Did you discover any particular ingredients or techniques that were game-changers for your home cooking?',
tags: ['comment', 'AI', 'computer vision', 'healthcare', 'medical imaging', 'diagnostics', 'radiology', 'dermatology', 'equity', 'bias', 'patient diversity', 'model accuracy', 'training data', 'medical AI', 'healthcare technology']
},
{
id: 'comment3',
type: 'document',
noun: 'content',
title: 'Comment on Ethical AI Design post',
content: 'Your analysis of minimalism as a functional imperative rather than just an aesthetic choice resonates strongly with my experience in e-commerce design. After implementing many of the principles you outlined, particularly regarding strategic color usage and improved typography hierarchy, our conversion rates improved by 23% while customer support inquiries decreased by almost 30%. The point about accessibility benefits is especially important and often overlooked in design discussions. Have you found any effective methods for convincing stakeholders who equate visual complexity with feature richness? I\'ve been struggling with this exact challenge on a current project where the client insists on cramming as much information as possible onto each page. I\'ve tried showing them user testing videos and heat maps demonstrating how users get overwhelmed, but they\'re still resistant to embracing white space and prioritization. Do you have any case studies or metrics that have been particularly persuasive in these situations?',
tags: ['comment', 'AI', 'ethics', 'responsible AI', 'human values', 'alignment', 'bias', 'fairness', 'transparency', 'accountability', 'governance', 'stakeholder engagement', 'value pluralism', 'AI design', 'ethical frameworks']
},
{
id: 'comment4',
type: 'document',
noun: 'content',
title: 'Comment on AI-Powered Cybersecurity post',
content: 'As someone who works with small nonprofits, I found your cybersecurity guide incredibly practical. The multi-factor authentication recommendation alone has already prevented several attempted breaches in our organization. One additional tip I\'d suggest is creating a security incident response plan - even a simple one-page document outlining who to contact and immediate steps to take if a breach is suspected. We learned this lesson the hard way when a staff member\'s email was compromised, and precious time was lost figuring out the proper response. Do you have any recommendations for affordable security awareness training platforms suitable for organizations with high volunteer turnover? We\'ve been creating our own materials, but it\'s becoming unsustainable to keep them updated with evolving threats.',
tags: ['comment', 'AI', 'cybersecurity', 'machine learning', 'threat detection', 'anomaly detection', 'security', 'incident response', 'multi-factor authentication', 'security training', 'automated response', 'phishing', 'data protection', 'small organizations', 'resource constraints']
},
{
id: 'comment5',
type: 'document',
noun: 'content',
title: 'Comment on AI and Indigenous Knowledge post',
content: 'Your article on indigenous marine conservation practices reminded me of my fieldwork with coastal communities in the Solomon Islands. The integration of traditional ecological knowledge with scientific monitoring there has been remarkably effective. One elder showed me how they track fish populations by observing specific bird behaviors above the water - something our scientific instruments would miss entirely. I\'ve found that the most successful conservation initiatives are those where traditional knowledge holders have equal decision-making power, not just advisory roles. Have you encountered examples where traditional seasonal harvesting restrictions have been formally incorporated into government regulations? I\'m researching policy frameworks that successfully bridge these knowledge systems without appropriating or diminishing indigenous authority over their traditional practices.',
tags: ['comment', 'AI', 'indigenous knowledge', 'machine learning', 'traditional ecological knowledge', 'data sovereignty', 'environmental monitoring', 'conservation', 'participatory design', 'ethical AI', 'cross-cultural collaboration', 'knowledge systems', 'policy', 'governance', 'co-management']
},
{
id: 'comment6',
type: 'document',
noun: 'content',
title: 'Comment on AI in Neuroscience post',
content: 'As a clinical psychologist who incorporates mindfulness practices in therapy, I\'ve seen firsthand how meditation can help patients with anxiety and depression. Your summary of the neuroimaging research provides valuable scientific backing for what we observe clinically. I\'m particularly interested in the findings about increased gray matter in the prefrontal cortex, as executive function improvement is something my patients frequently report. Have you come across research specifically examining how different meditation techniques (focused attention vs. open monitoring vs. loving-kindness) might affect different brain regions? I\'ve noticed that certain practices seem more beneficial for specific conditions, but the research I\'ve found doesn\'t clearly differentiate between meditation types. Also, do you know of any studies looking at minimum effective "doses" of practice? Many patients struggle to maintain lengthy daily sessions.',
tags: ['comment', 'AI', 'neuroscience', 'machine learning', 'brain', 'neuroimaging', 'computational neuroscience', 'neural networks', 'brain-computer interfaces', 'cognitive science', 'mental health', 'clinical applications', 'neural decoding', 'brain mapping', 'research']
},
{
id: 'comment7',
type: 'document',
noun: 'content',
title: 'Comment on Edge AI post',
content: 'Your article on Edge AI perfectly captures the paradigm shift happening in the industry. As someone implementing these technologies in industrial IoT settings, I can confirm the latency benefits are game-changing for our predictive maintenance systems. We\'ve reduced response times from ~200ms (cloud-based) to under 15ms by moving inference to the edge, which matters tremendously when detecting equipment failures that can cascade within milliseconds. One challenge you didn\'t mention is the difficulty of model updates and versioning across distributed edge devices. We\'ve developed a federated learning approach where edge devices contribute to model improvements without raw data leaving the factory floor, addressing both privacy concerns and bandwidth limitations. Have you explored how differential privacy techniques might be incorporated into edge AI deployments to further enhance data protection while maintaining model quality?',
tags: ['comment', 'AI', 'edge computing', 'IoT', 'machine learning', 'latency', 'industrial applications', 'predictive maintenance', 'federated learning', 'differential privacy', 'model updates', 'distributed systems', 'privacy', 'real-time processing']
},
{
id: 'comment8',
type: 'document',
noun: 'content',
title: 'Comment on Explainable AI post',
content: 'As a healthcare professional implementing AI systems in clinical settings, I found your analysis of the tension between model performance and interpretability particularly relevant. We\'ve faced significant resistance from physicians when deploying "black box" models, regardless of their statistical performance. Our most successful implementation has been a hybrid approach using a highly accurate but complex model for initial screening, followed by a more interpretable model that provides clear reasoning for flagged cases. This approach maintains high sensitivity while giving clinicians transparent explanations they can evaluate with their domain expertise. I\'m curious about your thoughts on whether certain domains should prioritize interpretability over raw performance as a matter of policy or regulation. In healthcare, should we establish minimum standards for explainability even if it means sacrificing some predictive power?',
tags: ['comment', 'AI', 'explainable AI', 'XAI', 'healthcare', 'clinical decision support', 'transparency', 'interpretability', 'machine learning', 'regulation', 'policy', 'medical AI', 'hybrid approaches', 'domain expertise', 'trust']
},
{
id: 'comment9',
type: 'document',
noun: 'content',
title: 'Comment on Federated Learning post',
content: 'Your article on federated learning provides an excellent overview of the technology\'s privacy benefits. I\'m currently applying these techniques in a consortium of hospitals that want to collaborate on rare disease research without sharing sensitive patient data. One challenge we\'ve encountered that wasn\'t mentioned is the "model poisoning" attack vector, where malicious participants could potentially inject biases or backdoors into the global model during the update process. We\'ve implemented a robust aggregation method that can detect and mitigate anomalous updates, but it adds significant computational overhead. Have you explored secure aggregation protocols that use cryptographic techniques to prevent even the central server from seeing individual updates? Also, I\'d be interested in your thoughts on how federated learning intersects with regulatory frameworks like GDPR and HIPAA - in our experience, legal departments still have concerns despite data never leaving local environments.',
tags: ['comment', 'AI', 'federated learning', 'privacy', 'healthcare', 'rare disease research', 'security', 'model poisoning', 'secure aggregation', 'cryptography', 'regulation', 'GDPR', 'HIPAA', 'data protection', 'collaborative research']
},
{
id: 'comment10',
type: 'document',
noun: 'content',
title: 'Comment on AI in Climate Science post',
content: 'As someone working at the intersection of remote sensing and climate policy, I found your article on AI applications in climate science particularly insightful. We\'ve been using similar computer vision approaches to monitor compliance with reforestation commitments under international climate agreements. One challenge we\'ve encountered is the difficulty in communicating uncertainty in AI predictions to policymakers who need definitive answers for decision-making. Have you found effective ways to represent model confidence that non-technical stakeholders can incorporate into their thinking? Another issue we\'re grappling with is the carbon footprint of training these large models - there\'s a certain irony in using energy-intensive computing to address climate change. We\'ve been exploring specialized hardware and more efficient architectures, but I\'d be interested in your thoughts on how to balance the environmental costs of AI development against its benefits for climate monitoring and modeling.',
tags: ['comment', 'AI', 'climate science', 'remote sensing', 'policy', 'reforestation', 'uncertainty quantification', 'decision making', 'carbon footprint', 'green AI', 'sustainable computing', 'environmental monitoring', 'satellite imagery', 'international agreements', 'climate action']
},
{
id: 'comment11',
type: 'document',
noun: 'content',
title: 'Comment on Neuromorphic Computing post',
content: 'Your overview of neuromorphic computing captures the excitement in this field perfectly. As someone working with Intel\'s Loihi chip for robotics applications, I can attest to the dramatic energy efficiency gains you mentioned. We\'ve implemented a visual object tracking system that runs continuously on a small drone with 20x lower power consumption than an equivalent deep learning solution. One aspect I think deserves more attention is the programming paradigm shift required. Traditional deep learning developers struggle with the event-based, asynchronous nature of spiking neural networks - it\'s not just about converting existing models but rethinking how information is processed temporally. Have you explored the emerging software frameworks attempting to bridge this gap? Also, I\'d be curious about your thoughts on hybrid systems that combine traditional deep learning for offline training with neuromorphic hardware for deployment. We\'ve had success with this approach, using conventional backpropagation for initial training then converting to spiking implementations, though the conversion process still requires significant manual tuning.',
tags: ['comment', 'AI', 'neuromorphic computing', 'Loihi', 'spiking neural networks', 'robotics', 'energy efficiency', 'event-based computing', 'programming models', 'hybrid approaches', 'hardware', 'edge AI', 'temporal processing', 'visual tracking', 'embedded systems']
},
{
id: 'comment12',
type: 'document',
noun: 'content',
title: 'Comment on AI for Accessibility post',
content: 'As an accessibility specialist with a disability myself, I deeply appreciate your article highlighting how AI is transforming accessibility. The personalization aspect you mentioned resonates strongly with my experience - the same accommodation doesn\'t work for everyone, even with the same diagnosed condition. I\'ve been involved in testing several AI-powered captioning tools, and while the accuracy has improved dramatically, they still struggle with technical terminology, multiple speakers, and accented speech. This creates a frustrating experience where the technology works just well enough that organizations deploy it as a complete solution, but not well enough to provide true equity. I\'d love to see more research on hybrid approaches that combine AI with human support for situations where accuracy is critical. On a more positive note, the image description capabilities of modern computer vision have been transformative for my blind colleagues, especially the ability to recognize and explain diagrams and charts in professional contexts. Have you explored how these technologies might be integrated into education settings to make STEM fields more accessible to students with visual impairments?',
tags: ['comment', 'AI', 'accessibility', 'assistive technology', 'personalization', 'captioning', 'speech recognition', 'computer vision', 'image description', 'disability', 'inclusive design', 'education', 'STEM accessibility', 'hybrid approaches', 'user experience', 'equity']
},
// Groups/Communities
{
id: 'group1',
type: 'group',
noun: 'group',
name: 'AI Research Collaborative',
content: 'A global community of developers, designers, and tech enthusiasts collaborating on emerging technologies and their practical applications. Our members range from startup founders to corporate innovators, all sharing insights on AI, blockchain, IoT, and other transformative technologies. We host monthly virtual meetups featuring expert speakers, maintain an active knowledge base of implementation case studies, and facilitate mentorship connections between experienced professionals and those entering the field. Recent discussions have focused on ethical AI development, privacy-preserving machine learning techniques, and the potential of edge computing to reduce cloud dependency. Our upcoming virtual conference will explore how these technologies can be applied to address pressing global challenges in healthcare, climate science, and sustainable development.',
tags: ['AI', 'machine learning', 'research', 'deep learning', 'neural networks', 'natural language processing', 'computer vision', 'reinforcement learning', 'ethics', 'responsible AI', 'collaboration', 'innovation', 'academic research', 'industry applications', 'AI safety']
},
{
id: 'group2',
type: 'group',
noun: 'group',
name: 'AI for Healthcare Innovation Network',
content: 'An international community dedicated to exploring culinary traditions and innovations from around the world. Our members share authentic recipes, cooking techniques, and food photography that celebrates cultural diversity through cuisine. We organize themed cooking challenges, virtual cook-alongs with chefs from different countries, and discussions about sustainable food systems and the preservation of traditional cooking methods. The community also maintains a searchable database of member-tested recipes organized by region, dietary preferences, and difficulty level. Recent initiatives include a documentary series on endangered culinary traditions, a seed-sharing program for heirloom varieties, and partnerships with indigenous communities to document and preserve their food knowledge. Our monthly virtual potlucks feature dishes from a specific region, with members preparing the same recipes and sharing their results, adaptations, and experiences.',
tags: ['food', 'cooking', 'international', 'recipes', 'culture', 'sustainability', 'traditions', 'culinary', 'photography', 'indigenous', 'heirloom', 'seed-sharing', 'documentary', 'virtual events']
},
{
id: 'group3',
type: 'group',
noun: 'group',
name: 'Sustainable Living Collective',
content: 'A community focused on practical approaches to reducing environmental impact in everyday life. We share evidence-based strategies for sustainable living in urban, suburban, and rural contexts, with special emphasis on solutions that are economically accessible. Our resources include guides for zero-waste home management, energy efficiency improvements, ethical consumption, and small-space gardening. Members collaborate on neighborhood initiatives like community gardens, repair cafés, and local policy advocacy for environmental protection and green infrastructure. Recent projects include a tool library that allows members to borrow rarely-used equipment instead of purchasing new items, a series of workshops on DIY home energy audits and weatherization, and a community-supported agriculture program connecting urban residents with local farmers. The collective also maintains a comprehensive database of local recycling options for hard-to-recycle items and coordinates monthly neighborhood cleanup events focused on plastic pollution reduction.',
tags: ['sustainability', 'environment', 'lifestyle', 'eco-friendly', 'zero-waste', 'community', 'gardening', 'advocacy', 'tool library', 'energy efficiency', 'repair café', 'local food', 'recycling', 'plastic pollution']
},
{
id: 'group4',
type: 'group',
noun: 'group',
name: 'Quantum Computing Enthusiasts',
content: 'A global community of researchers, developers, and enthusiasts exploring the rapidly evolving field of quantum computing. Our members range from quantum physics professors to software engineers curious about programming quantum circuits. We host weekly virtual study groups covering fundamental concepts like superposition, entanglement, and quantum algorithms, making these complex topics accessible to newcomers. Our online forum features dedicated sections for quantum hardware developments, programming frameworks (Qiskit, Cirq, Q#, etc.), algorithm design, and quantum machine learning. Advanced members collaborate on open-source projects implementing novel quantum algorithms and simulations. We organize quarterly hackathons where teams tackle real-world problems using quantum approaches, with recent projects including traffic optimization, drug discovery simulations, and cryptographic challenges. The community maintains a comprehensive resource library with tutorials, research paper summaries, and comparisons of different quantum computing platforms available through cloud services.',
tags: ['quantum computing', 'quantum physics', 'qubits', 'quantum algorithms', 'Qiskit', 'Cirq', 'Q#', 'quantum machine learning', 'quantum simulation', 'quantum programming', 'superposition', 'entanglement', 'quantum supremacy', 'quantum education', 'open source']
},
{
id: 'group5',
type: 'group',
noun: 'group',
name: 'Ethical AI Alliance',
content: 'A multidisciplinary coalition of AI practitioners, ethicists, policymakers, and community advocates working to ensure artificial intelligence technologies are developed and deployed responsibly. Our members collaborate on creating practical frameworks for ethical AI assessment, developing open-source tools for bias detection and mitigation, and drafting policy recommendations for effective AI governance. The alliance hosts monthly roundtable discussions where diverse perspectives on emerging AI ethics challenges are shared, from algorithmic fairness and transparency to privacy protection and meaningful human oversight. We maintain working groups focused on specific domains including healthcare AI, criminal justice applications, hiring systems, and generative AI technologies. Our education initiative develops curriculum materials for teaching AI ethics across different educational levels, from K-12 to professional development. The alliance also operates an incident response team that analyzes high-profile AI failures or harms to extract lessons and recommend preventative measures. Through our community engagement program, we ensure affected communities have meaningful input into how AI systems that impact their lives are designed and governed.',
tags: ['AI ethics', 'responsible AI', 'algorithmic fairness', 'bias mitigation', 'AI governance', 'transparency', 'accountability', 'privacy', 'human oversight', 'multidisciplinary', 'policy', 'education', 'community engagement', 'impact assessment', 'ethical frameworks']
},
{
id: 'group6',
type: 'group',
noun: 'group',
name: 'Augmented Reality Creators Collective',
content: 'A community of designers, developers, artists, and entrepreneurs pushing the boundaries of augmented reality experiences. Our members collaborate on creating immersive AR applications across industries including education, retail, healthcare, entertainment, and cultural heritage. The collective provides a supportive environment for sharing technical knowledge about AR development platforms (ARKit, ARCore, Unity, Unreal), spatial design principles, and user experience considerations specific to augmented reality. We host monthly showcase events where members demonstrate works-in-progress and receive constructive feedback from peers. Our mentorship program pairs experienced AR professionals with newcomers to the field, with special emphasis on supporting creators from underrepresented backgrounds. The collective maintains a shared asset library of 3D models, interaction patterns, and code snippets that members can incorporate into their projects. Recent collaborative initiatives include developing AR experiences for local museums that bring historical artifacts to life, creating accessible AR navigation tools for people with disabilities, and experimenting with AR as a medium for interactive storytelling that responds to physical environments.',
tags: ['augmented reality', 'AR', 'spatial computing', 'ARKit', 'ARCore', 'Unity', 'Unreal', 'mixed reality', '3D design', 'interactive design', 'immersive experiences', 'UX design', 'digital art', 'creative technology', 'spatial design']
},
// Events
{
id: 'event1',
type: 'event',
noun: 'event',
name: 'Virtual Tech Meetup 2023: Responsible AI Development',
content: 'An online gathering of technology professionals sharing insights on ethical AI development frameworks and implementation tools. The event features keynote presentations on bias detection in machine learning models, panel discussions on regulatory compliance across different jurisdictions, and hands-on workshops demonstrating techniques for making AI systems more transparent and explainable. Participants will have opportunities for structured networking with peers working in similar domains and access to a resource library of code samples, case studies, and best practice guidelines. The meetup will address critical questions about AI ethics, including how to implement fairness metrics in machine learning pipelines, techniques for conducting algorithmic impact assessments, and strategies for engaging diverse stakeholders in AI governance. Special sessions will focus on privacy-preserving AI methods like federated learning and differential privacy, as well as practical approaches to implementing AI ethics principles in real-world applications. The event will conclude with a collaborative workshop where participants develop action plans for implementing responsible AI practices within their organizations.',
tags: ['tech', 'virtual', 'networking', 'learning', 'AI', 'ethics', 'development', 'workshops', 'bias', 'transparency', 'explainability', 'regulation', 'privacy', 'federated learning', 'differential privacy', 'governance']
},
{
id: 'event2',
type: 'event',
noun: 'event',
name: 'International Food Festival: Culinary Traditions in a Modern World',
content: 'Annual celebration of global cuisines featuring cooking demonstrations from renowned chefs representing diverse culinary traditions. The festival includes interactive tastings with detailed exploration of ingredient origins and cultural significance, panel discussions on preserving food heritage while embracing innovation, and cultural performances that contextualize food within broader cultural expressions. Special exhibition areas focus on sustainable food systems, the impact of climate change on traditional agriculture, and the role of technology in modern food production and distribution. This year\'s festival will highlight endangered food traditions from indigenous communities around the world, with a special emphasis on preservation efforts and adaptation strategies. Featured chefs will demonstrate traditional cooking techniques that are at risk of being lost, including fermentation methods from Korea, ancient grain processing from the Andes, and specialized fish preservation techniques from coastal Japan. The innovation pavilion will showcase how these traditional methods are being adapted for contemporary kitchens and scaled for commercial production while maintaining cultural authenticity and environmental sustainability. A special section on urban farming will connect traditional agricultural knowledge with modern space-efficient growing techniques for city dwellers.',
tags: ['food', 'festival', 'international', 'culture', 'cooking', 'sustainability', 'traditions', 'innovation', 'indigenous', 'climate change', 'agriculture', 'technology', 'fermentation', 'preservation', 'urban farming']
},
{
id: 'event3',
type: 'event',
noun: 'event',
name: 'AI Ethics Summit: Building Responsible Artificial Intelligence',
content: 'A three-day conference bringing together AI researchers, ethicists, policymakers, industry leaders, and community representatives to address the ethical challenges of advancing AI technologies. The summit features keynote presentations from leading experts on topics including algorithmic fairness, transparency in machine learning, privacy-preserving AI techniques, and frameworks for responsible AI governance. Interactive workshops provide hands-on experience with tools for bias detection and mitigation in AI systems, methods for conducting algorithmic impact assessments, and techniques for explaining complex models to different stakeholders. Panel discussions explore tensions between innovation and safety, balancing regulation with technological progress, and ensuring AI benefits are distributed equitably across society. The summit includes dedicated sessions on AI ethics in specific domains including healthcare, criminal justice, education, and financial services, examining how ethical considerations vary across contexts. A policy hackathon challenges participants to draft governance frameworks that balance innovation with appropriate safeguards. The event concludes with collaborative working sessions where participants develop action plans for implementing ethical AI practices within their organizations and communities. All proceedings are livestreamed with multilingual translation to ensure global accessibility.',
tags: ['AI', 'ethics', 'responsible AI', 'conference', 'algorithmic fairness', 'transparency', 'privacy', 'governance', 'policy', 'bias mitigation', 'impact assessment', 'explainability', 'regulation', 'equity', 'multistakeholder']
},
{
id: 'event4',
type: 'event',
noun: 'event',
name: 'Quantum Computing Hackathon: Solving Tomorrow\'s Problems Today',
content: 'A weekend-long intensive programming event where teams of quantum computing enthusiasts collaborate to develop innovative solutions using quantum algorithms and simulators. Participants range from quantum physics students to software developers curious about quantum programming, with mentors from leading quantum computing companies providing guidance throughout the event. The hackathon begins with introductory workshops on quantum computing concepts and programming frameworks (Qiskit, Cirq, Q#, PennyLane) to ensure all participants have the necessary foundation. Teams then select challenges from tracks including optimization problems, machine learning applications, chemistry simulations, and financial modeling. Cloud access to quantum computing platforms is provided through partnerships with major quantum hardware providers, allowing teams to test their algorithms on actual quantum processors. Industry experts serve as judges, evaluating projects based on innovation, technical implementation, potential impact, and presentation quality. Prizes include cloud computing credits, internship opportunities at quantum computing companies, and research grants for academic participants. The event concludes with a showcase where teams demonstrate their solutions and discuss the potential applications of quantum computing in addressing real-world challenges. All code developed during the hackathon is open-sourced to contribute to the growing quantum computing community.',
tags: ['quantum computing', 'hackathon', 'programming', 'Qiskit', 'Cirq', 'Q#', 'PennyLane', 'quantum algorithms', 'quantum simulation', 'optimization', 'machine learning', 'chemistry', 'financial modeling', 'open source', 'cloud quantum computing']
}
,
// Additional User Profiles
{
id: 'user6',
type: 'person',
noun: 'person',
name: 'Emily Rodriguez',
content: 'Cybersecurity specialist with expertise in ethical hacking and digital forensics. I help organizations identify and address security vulnerabilities before they can be exploited. My background includes 8 years working with financial institutions to protect sensitive customer data and transaction systems. I regularly speak at security conferences about emerging threats in the IoT space and best practices for securing smart home devices. Outside of work, I\'m an avid rock climber and volunteer teaching digital literacy and online safety to seniors in my community. I believe that security awareness should be accessible to everyone, not just technical professionals.',
tags: ['cybersecurity', 'hacking', 'digital forensics', 'IoT', 'security', 'technology', 'rock climbing', 'education', 'digital literacy']
},
{
id: 'user7',
type: 'person',
noun: 'person',
name: 'David Kim',
content: 'Documentary filmmaker focusing on environmental conservation and indigenous rights. My work has taken me to over 30 countries documenting the intersection of traditional ecological knowledge and modern conservation efforts. My latest project explores community-led marine protection initiatives in coastal Southeast Asia, where local fishermen are combining traditional practices with modern monitoring technology to create sustainable fishing zones. I\'m particularly interested in how storytelling can bridge cultural divides and inspire environmental action. When not filming, I teach visual anthropology at the university level and mentor emerging filmmakers from underrepresented communities.',
tags: ['filmmaker', 'documentary', 'environment', 'conservation', 'indigenous', 'storytelling', 'marine protection', 'visual anthropology', 'education', 'mentorship']
},
{
id: 'user8',
type: 'person',
noun: 'person',
name: 'Aisha Mahmoud',
content: 'Neuroscientist and public health advocate specializing in the cognitive effects of meditation and mindfulness practices. My research lab uses advanced neuroimaging techniques to study how different meditation practices affect brain structure and function over time. We\'ve published several papers demonstrating the positive impacts of regular meditation on attention, emotional regulation, and stress response. I\'m passionate about translating scientific findings into practical applications that can improve mental health outcomes in diverse communities. I\'ve developed mindfulness programs specifically adapted for schools, healthcare settings, and corporate environments that respect cultural differences in approaches to mental wellbeing.',
tags: ['neuroscience', 'meditation', 'mindfulness', 'mental health', 'research', 'neuroimaging', 'education', 'healthcare', 'stress management', 'cognitive science']
},
{
id: 'user9',
type: 'person',
noun: 'person',
name: 'Carlos Mendez',
content: 'Urban planner and sustainable transportation advocate working to transform car-centric cities into people-friendly spaces. My projects focus on implementing complete streets designs that safely accommodate all users - pedestrians, cyclists, transit riders, and drivers. I\'ve helped several mid-sized cities develop and implement bicycle master plans that have significantly increased cycling rates and reduced car dependency. My approach combines technical expertise with community engagement to ensure that transportation solutions reflect local needs and build public support. I\'m currently researching how micromobility options like e-scooters and bike sharing can be integrated with public transit to solve the "last mile" problem in suburban areas.',
tags: ['urban planning', 'transportation', 'sustainability', 'cycling', 'pedestrian', 'complete streets', 'community engagement', 'micromobility', 'public transit', 'urban design']
},
{
id: 'user10',
type: 'person',
noun: 'person',
name: 'Zoe Thompson',
content: 'Quantum computing researcher and science communicator making complex physics concepts accessible to general audiences. My technical work focuses on quantum error correction and the development of fault-tolerant quantum processors. I maintain a popular science blog that explains quantum concepts through creative analogies and interactive visualizations, reaching over 100,000 monthly readers. I believe that public understanding of quantum computing is crucial as we approach the era where these technologies will have significant societal impacts. I\'ve consulted on several science fiction productions to help them portray quantum physics more accurately while still telling compelling stories.',
tags: ['quantum computing', 'physics', 'science communication', 'research', 'technology', 'education', 'blogging', 'visualization', 'quantum error correction', 'science fiction']
}
]
// Add Nouns to the database using batch processing for better performance
const nounItems = sampleNouns.map(item => ({
vectorOrData: item.content || item.name,
metadata: item
}))
await database.addBatch(nounItems, { batchSize: 50 })
// No need to wait as addBatch ensures all items are fully processed
// Verify nouns exist before adding verbs
const entities = await database.getAllNouns()
const nounIds = entities.map(entity => entity.id)
console.log('Available nouns before adding verbs:', nounIds)
// Sample Verbs with social media relationships
const sampleVerbs = [
// Created/Posted content
{
source: 'user1',
target: 'post1',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Alex wrote this article about AI applications' }
},
{
source: 'user2',
target: 'post2',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Sophia shared her food tour experiences' }
},
{
source: 'user3',
target: 'post3',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Marcus wrote this design article' }
},
{
source: 'user4',
target: 'post4',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Priya shared gardening tips' }
},
{
source: 'user5',
target: 'post5',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Jordan created this workout challenge' }
},
// Comments on posts
{
source: 'user4',
target: 'comment1',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Priya commented on the AI post' }
},
{
source: 'comment1',
target: 'post1',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the AI post' }
},
{
source: 'user3',
target: 'comment2',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Marcus commented on the food tour post' }
},
{
source: 'comment2',
target: 'post2',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the food tour post' }
},
{
source: 'user2',
target: 'comment3',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Sophia commented on the design article' }
},
{
source: 'comment3',
target: 'post3',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the design article' }
},
// Likes/Reactions
{
source: 'user2',
target: 'post1',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Sophia liked Alex\'s AI post' }
},
{
source: 'user3',
target: 'post1',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Marcus liked Alex\'s AI post' }
},
{
source: 'user1',
target: 'post2',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Alex liked Sophia\'s food tour post' }
},
{
source: 'user5',
target: 'post2',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Jordan liked Sophia\'s food tour post' }
},
{
source: 'user1',
target: 'post3',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Alex liked Marcus\'s design article' }
},
{
source: 'user2',
target: 'post4',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Sophia liked Priya\'s gardening post' }
},
{
source: 'user4',
target: 'post5',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Priya liked Jordan\'s workout challenge' }
},
// Follows
{
source: 'user1',
target: 'user2',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Alex follows Sophia' }
},
{
source: 'user2',
target: 'user1',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Sophia follows Alex' }
},
{
source: 'user1',
target: 'user3',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Alex follows Marcus' }
},
{
source: 'user2',
target: 'user4',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Sophia follows Priya' }
},
{
source: 'user3',
target: 'user5',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Marcus follows Jordan' }
},
{
source: 'user4',
target: 'user5',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Priya follows Jordan' }
},
{
source: 'user5',
target: 'user1',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Jordan follows Alex' }
},
// Group memberships
{
source: 'user1',
target: 'group1',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Alex is a member of Tech Innovators Network' }
},
{
source: 'user3',
target: 'group1',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Marcus is a member of Tech Innovators Network' }
},
{
source: 'user2',
target: 'group2',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Sophia is a member of Global Foodies' }
},
{
source: 'user5',
target: 'group2',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Jordan is a member of Global Foodies' }
},
{
source: 'user4',
target: 'group3',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Priya is a member of Sustainable Living Collective' }
},
{
source: 'user2',
target: 'group3',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Sophia is a member of Sustainable Living Collective' }
},
// Event attendance
{
source: 'user1',
target: 'event1',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Alex is attending the Virtual Tech Meetup' }
},
{
source: 'user3',
target: 'event1',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Marcus is attending the Virtual Tech Meetup' }
},
{
source: 'user2',
target: 'event2',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Sophia is attending the International Food Festival' }
},
{
source: 'user5',
target: 'event2',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Jordan is attending the International Food Festival' }
},
// Content relationships
{
source: 'post1',
target: 'post3',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.6, description: 'AI applications post is related to design principles post' }
},
{
source: 'post2',
target: 'post5',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.5, description: 'Food tour post is somewhat related to fitness challenge post' }
},
{
source: 'post4',
target: 'group3',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.8, description: 'Urban gardening post is related to Sustainable Living Collective' }
},
// Additional Created/Posted content
{
source: 'user11',
target: 'post11',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Olivia wrote this article about Edge AI' }
},
{
source: 'user12',
target: 'post12',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Benjamin wrote this article about Explainable AI' }
},
{
source: 'user13',
target: 'post13',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Amara wrote this article about Federated Learning' }
},
{
source: 'user14',
target: 'post14',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Hiroshi wrote this article about AI in Climate Science' }
},
{
source: 'user15',
target: 'post15',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Elena wrote this article about Neuromorphic Computing' }
},
{
source: 'user6',
target: 'post16',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Emily wrote this article about AI for Accessibility' }
},
{
source: 'user7',
target: 'post17',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'David wrote this article about AI in Drug Discovery' }
},
{
source: 'user8',
target: 'post18',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Aisha wrote this article about Reinforcement Learning' }
},
{
source: 'user9',
target: 'post19',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Carlos wrote this article about AI and Creativity' }
},
{
source: 'user10',
target: 'post20',
verb: 'created',
label: 'Posted',
data: { strength: 0.95, description: 'Zoe wrote this article about AI Governance' }
},
// Additional Comments on posts
{
source: 'user11',
target: 'comment7',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Olivia commented on the Edge AI post' }
},
{
source: 'comment7',
target: 'post11',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the Edge AI post' }
},
{
source: 'user12',
target: 'comment8',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Benjamin commented on the Explainable AI post' }
},
{
source: 'comment8',
target: 'post12',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the Explainable AI post' }
},
{
source: 'user13',
target: 'comment9',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Amara commented on the Federated Learning post' }
},
{
source: 'comment9',
target: 'post13',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the Federated Learning post' }
},
{
source: 'user14',
target: 'comment10',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Hiroshi commented on the AI in Climate Science post' }
},
{
source: 'comment10',
target: 'post14',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the AI in Climate Science post' }
},
{
source: 'user15',
target: 'comment11',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Elena commented on the Neuromorphic Computing post' }
},
{
source: 'comment11',
target: 'post15',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the Neuromorphic Computing post' }
},
{
source: 'user6',
target: 'comment12',
verb: 'created',
label: 'Commented',
data: { strength: 0.8, description: 'Emily commented on the AI for Accessibility post' }
},
{
source: 'comment12',
target: 'post16',
verb: 'relatedTo',
label: 'Comment On',
data: { strength: 0.9, description: 'This comment is on the AI for Accessibility post' }
},
// Additional Likes/Reactions
{
source: 'user11',
target: 'post12',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Olivia liked Benjamin\'s Explainable AI post' }
},
{
source: 'user12',
target: 'post13',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Benjamin liked Amara\'s Federated Learning post' }
},
{
source: 'user13',
target: 'post14',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Amara liked Hiroshi\'s AI in Climate Science post' }
},
{
source: 'user14',
target: 'post15',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Hiroshi liked Elena\'s Neuromorphic Computing post' }
},
{
source: 'user15',
target: 'post16',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Elena liked Emily\'s AI for Accessibility post' }
},
{
source: 'user6',
target: 'post17',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Emily liked David\'s AI in Drug Discovery post' }
},
{
source: 'user7',
target: 'post18',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'David liked Aisha\'s Reinforcement Learning post' }
},
{
source: 'user8',
target: 'post19',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Aisha liked Carlos\'s AI and Creativity post' }
},
{
source: 'user9',
target: 'post20',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Carlos liked Zoe\'s AI Governance post' }
},
{
source: 'user10',
target: 'post11',
verb: 'likes',
label: 'Likes',
data: { strength: 0.7, description: 'Zoe liked Olivia\'s Edge AI post' }
},
// Additional Follows
{
source: 'user11',
target: 'user12',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Olivia follows Benjamin' }
},
{
source: 'user12',
target: 'user13',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Benjamin follows Amara' }
},
{
source: 'user13',
target: 'user14',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Amara follows Hiroshi' }
},
{
source: 'user14',
target: 'user15',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Hiroshi follows Elena' }
},
{
source: 'user15',
target: 'user11',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Elena follows Olivia' }
},
{
source: 'user6',
target: 'user11',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'Emily follows Olivia' }
},
{
source: 'user7',
target: 'user12',
verb: 'follows',
label: 'Follows',
data: { strength: 0.8, description: 'David follows Benjamin' }
},
// Additional Group memberships
{
source: 'user11',
target: 'group4',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Olivia is a member of Quantum Computing Enthusiasts' }
},
{
source: 'user10',
target: 'group4',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Zoe is a member of Quantum Computing Enthusiasts' }
},
{
source: 'user13',
target: 'group5',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Amara is a member of Ethical AI Alliance' }
},
{
source: 'user15',
target: 'group5',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Elena is a member of Ethical AI Alliance' }
},
{
source: 'user3',
target: 'group5',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Marcus is a member of Ethical AI Alliance' }
},
{
source: 'user12',
target: 'group6',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'Benjamin is a member of Augmented Reality Creators Collective' }
},
{
source: 'user7',
target: 'group6',
verb: 'memberOf',
label: 'Member Of',
data: { strength: 0.85, description: 'David is a member of Augmented Reality Creators Collective' }
},
// Additional Event attendance
{
source: 'user11',
target: 'event3',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Olivia is attending the AI Ethics Summit' }
},
{
source: 'user13',
target: 'event3',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Amara is attending the AI Ethics Summit' }
},
{
source: 'user15',
target: 'event3',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Elena is attending the AI Ethics Summit' }
},
{
source: 'user3',
target: 'event3',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Marcus is attending the AI Ethics Summit' }
},
{
source: 'user10',
target: 'event4',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Zoe is attending the Quantum Computing Hackathon' }
},
{
source: 'user11',
target: 'event4',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Olivia is attending the Quantum Computing Hackathon' }
},
{
source: 'user14',
target: 'event4',
verb: 'relatedTo',
label: 'Attending',
data: { strength: 0.75, description: 'Hiroshi is attending the Quantum Computing Hackathon' }
},
// Additional Content relationships
{
source: 'post11',
target: 'post13',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.7, description: 'Edge AI post is related to Federated Learning post' }
},
{
source: 'post12',
target: 'post15',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.6, description: 'Explainable AI post is related to Neuromorphic Computing post' }
},
{
source: 'post14',
target: 'group3',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.8, description: 'AI in Climate Science post is related to Sustainable Living Collective' }
},
{
source: 'post16',
target: 'post19',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.7, description: 'AI for Accessibility post is related to AI and Creativity post' }
},
{
source: 'post17',
target: 'post18',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.6, description: 'AI in Drug Discovery post is related to Reinforcement Learning post' }
},
{
source: 'post20',
target: 'group5',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.9, description: 'AI Governance post is strongly related to Ethical AI Alliance' }
},
{
source: 'event3',
target: 'group5',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.9, description: 'AI Ethics Summit is organized by Ethical AI Alliance' }
},
{
source: 'event4',
target: 'group4',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.9, description: 'Quantum Computing Hackathon is organized by Quantum Computing Enthusiasts' }
}
]
// Add Verbs to the database using parallel processing for better performance
// First filter out verbs with invalid source or target nouns
const validVerbs = sampleVerbs.filter(item => {
if (!nounIds.includes(item.source)) {
console.error(`Source noun with ID ${item.source} not found. Available nouns: ${nounIds.join(', ')}`)
log('db-status', `Failed to add verb: Source noun with ID ${item.source} not found`)
return false
}
if (!nounIds.includes(item.target)) {
console.error(`Target noun with ID ${item.target} not found. Available nouns: ${nounIds.join(', ')}`)
log('db-status', `Failed to add verb: Target noun with ID ${item.target} not found`)
return false
}
return true
})
// Process verbs in parallel using Promise.all
const verbPromises = validVerbs.map(item =>
database.relate(item.source, item.target, item.verb, item.data)
.then(() => {
console.log(`Added verb: ${item.source} ${item.verb} ${item.target}`)
return true
})
.catch(verbError => {
console.error(`Failed to add verb: ${verbError.message}`)
log('db-status', `Failed to add verb: ${verbError.message}`)
return false
})
)
// Wait for all verbs to be processed
await Promise.all(verbPromises)
// Count successfully added verbs
const addedVerbs = await database.getAllVerbs()
log('db-status', `Added ${sampleNouns.length} nouns and ${addedVerbs.length} verbs`)
updateDatabaseVisualization()
// Populate noun dropdowns after adding sample data
populateNounDropdowns()
} catch (error) {
log('db-status', 'Error adding sample data: ' + error.message)
}
}
async function clearDatabase() {
try {
if (database) {
await database.clear()
log('db-status', 'Database cleared successfully')
updateDatabaseVisualization()
populateNounDropdowns()
}
} catch (error) {
log('db-status', 'Error clearing database: ' + error.message)
}
}
async function backupData() {
if (!database) {
log('db-status', 'No database to backup')
return
}
try {
const data = await database.backup()
const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' })
const url = URL.createObjectURL(blob)
const a = document.createElement('a')
a.href = url
a.download = 'brainy-backup.json'
a.click()
URL.revokeObjectURL(url)
log('db-status', 'Data backed up successfully')
} catch (error) {
log('db-status', 'Error backing up data: ' + error.message)
}
}
async function restoreData() {
const input = document.createElement('input')
input.type = 'file'
input.accept = '.json'
input.onchange = async function(e) {
const file = e.target.files[0]
if (!file) return
try {
const text = await file.text()
const data = JSON.parse(text)
if (database) {
await database.restore(data)
log('db-status', 'Data restored successfully')
updateDatabaseVisualization()
// Show information about the restored data
let restoreInfo = `Restored ${data.nouns?.length || 0} nouns and ${data.verbs?.length || 0} verbs.`
// Check if the backup included vectors and index
const hasVectors = data.nouns?.some(n => n.vector && n.vector.length > 0)
const hasIndex = !!data.hnswIndex
if (!hasVectors) {
restoreInfo += ' Vectors were automatically created during restore.'
}
if (!hasIndex) {
restoreInfo += ' HNSW index was reconstructed during restore.'
}
log('db-status', restoreInfo)
}
} catch (error) {
log('db-status', 'Error restoring data: ' + error.message)
}
}
input.click()
}
// Function to create and import sparse data (without vectors)
async function importSparseData() {
if (!database) {
log('db-status', 'Please initialize database first')
return
}
try {
// Create sparse data without vectors
const sparseData = {
nouns: [
{
id: 'sparse_1',
metadata: {
noun: 'Thing',
text: 'This is a sparse data item without a vector'
}
},
{
id: 'sparse_2',
metadata: {
noun: 'Concept',
text: 'Vectors will be automatically created for this item'
}
}
],
verbs: [
{
id: 'sparse_verb_1',
sourceId: 'sparse_1',
targetId: 'sparse_2',
metadata: {
verb: 'RelatedTo',
description: 'This is a relationship between sparse data items'
}
}
],
version: '1.0.0'
}
// Import the sparse data
await database.importSparseData(sparseData)
log('db-status', 'Sparse data imported successfully')
log('db-status', 'Vectors were automatically created for items without vectors')
await updateDatabaseVisualization()
} catch (error) {
log('db-status', 'Error importing sparse data: ' + error.message)
}
}
// Entity operations
async function addEntity() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
const type = document.getElementById('entity-type').value
const dataText = document.getElementById('entity-data').value
if (!dataText.trim()) {
log('entity-results', 'Please enter entity data')
return
}
const data = JSON.parse(dataText)
data.type = type
data.id = data.id || 'entity_' + Date.now()
// Use a text property for vectorization, or stringify the object if no text property exists
const textToVectorize = data.content || data.description || data.text ||
data.title || data.name || JSON.stringify(data)
await database.add(textToVectorize, data)
log('entity-results', `Added ${type} entity: ${data.id}`)
// Clear the form
document.getElementById('entity-data').value = ''
// Update visualization
await updateDatabaseVisualization()
// Update noun dropdowns with the new entity
await populateNounDropdowns()
} catch (error) {
log('entity-results', 'Error adding entity: ' + error.message)
}
}
async function createRelationship() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
// For demo purposes, create a relationship between first two entities
const entities = await database.search('', 2, { forceEmbed: false })
if (entities.length < 2) {
log('entity-results', 'Need at least 2 entities to create a relationship')
return
}
await database.relate(entities[0].id, entities[1].id, 'connected_to', {
created: new Date().toISOString(),
strength: Math.random()
})
log('entity-results', `Created relationship: ${entities[0].id} -> ${entities[1].id}`)
// Update visualization
await updateDatabaseVisualization()
} catch (error) {
log('entity-results', 'Error creating relationship: ' + error.message)
}
}
async function queryEntities() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
const entities = await database.search('', 1000, { forceEmbed: false })
const relationships = await database.getAllVerbs()
let result = `Found ${entities.length} entities and ${relationships.length} relationships\n\n`
result += 'Entities:\n'
entities.forEach(entity => {
result += `- ${entity.id} (${entity.type}): ${entity.title || entity.name || 'Untitled'}\n`
})
result += '\nRelationships:\n'
relationships.forEach(rel => {
result += `- ${rel.sourceId || rel.from} ${rel.type} ${rel.targetId || rel.to}\n`
})
log('entity-results', result)
} catch (error) {
log('entity-results', 'Error querying entities: ' + error.message)
}
}
// Noun operations
async function addNoun() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
const nounType = document.getElementById('noun-type').value
const nounId = document.getElementById('noun-id').value.trim()
const nounName = document.getElementById('noun-name').value.trim()
const nounContent = document.getElementById('noun-content').value.trim()
const nounTags = document.getElementById('noun-tags').value.trim()
if (!nounName) {
log('entity-results', 'Please enter a name for the noun')
return
}
// Create data object from form fields
const data = {
noun: nounType,
id: nounId || 'noun_' + Date.now(),
name: nounName,
content: nounContent
}
// Add tags if provided
if (nounTags) {
data.tags = nounTags.split(',').map(tag => tag.trim())
}
// Use content for vectorization, or name if content is empty
const textToVectorize = nounContent || nounName
await database.add(textToVectorize, data)
log('entity-results', `Added ${nounType} noun: ${data.id}`)
// Clear the form
document.getElementById('noun-id').value = ''
document.getElementById('noun-name').value = ''
document.getElementById('noun-content').value = ''
document.getElementById('noun-tags').value = ''
// Update visualization
updateDatabaseVisualization()
// Update noun dropdowns with the new noun
populateNounDropdowns()
} catch (error) {
log('entity-results', 'Error adding noun: ' + error.message)
}
}
async function queryNouns() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
// Query all entities that have a 'noun' property
const entities = await database.search('', 1000, { forceEmbed: false })
const nouns = entities.filter(entity => entity.noun)
let result = `Found ${nouns.length} nouns\n\n`
result += 'Nouns:\n'
nouns.forEach(noun => {
result += `- ${noun.id} (${noun.noun}): ${noun.title || noun.name || 'Untitled'}\n`
})
log('entity-results', result)
} catch (error) {
log('entity-results', 'Error querying nouns: ' + error.message)
}
}
// Verb operations
async function addVerb() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
const verbType = document.getElementById('verb-type').value
const sourceId = document.getElementById('source-id').value.trim()
const targetId = document.getElementById('target-id').value.trim()
const verbStrength = document.getElementById('verb-strength').value
const verbDescription = document.getElementById('verb-description').value.trim()
if (!sourceId || !targetId) {
log('entity-results', 'Please enter source and target node IDs')
return
}
// Create data object from form fields
const data = {
strength: parseFloat(verbStrength) || 0.8,
description: verbDescription
}
// Verify nouns exist before adding verb
const entities = await database.search('', 1000, { forceEmbed: false })
const nounIds = entities.map(entity => entity.id)
// Check if source and target nouns exist
if (!nounIds.includes(sourceId)) {
throw new Error(`Source noun with ID ${sourceId} not found. Available nouns: ${nounIds.join(', ')}`)
}
if (!nounIds.includes(targetId)) {
throw new Error(`Target noun with ID ${targetId} not found. Available nouns: ${nounIds.join(', ')}`)
}
// Add the relationship
await database.relate(sourceId, targetId, verbType, data)
console.log(`Added verb: ${sourceId} ${verbType} ${targetId}`)
log('entity-results', `Added ${verbType} verb: ${sourceId} -> ${targetId}`)
// Clear the form
document.getElementById('source-id').value = ''
document.getElementById('target-id').value = ''
document.getElementById('verb-strength').value = '0.8'
document.getElementById('verb-description').value = ''
// Update visualization
await updateDatabaseVisualization()
} catch (error) {
log('entity-results', 'Error adding verb: ' + error.message)
}
}
async function queryVerbs() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
const relationships = await database.getAllVerbs()
let result = `Found ${relationships.length} verbs (relationships)\n\n`
result += 'Verbs:\n'
relationships.forEach(rel => {
result += `- ${rel.sourceId || rel.from} ${rel.type} ${rel.targetId || rel.to}\n`
})
log('entity-results', result)
} catch (error) {
log('entity-results', 'Error querying verbs: ' + error.message)
}
}
// Populate noun dropdowns for verb creation
async function populateNounDropdowns() {
if (!database) {
log('entity-results', 'Please initialize database first')
return
}
try {
// Get all nouns from the database
const entities = await database.search('', 1000, { forceEmbed: false })
const nouns = entities.filter(entity => entity.noun)
// Get the dropdown elements
const sourceDropdown = document.getElementById('source-id')
const targetDropdown = document.getElementById('target-id')
// Clear existing options except the first one
while (sourceDropdown.options.length > 1) {
sourceDropdown.remove(1)
}
while (targetDropdown.options.length > 1) {
targetDropdown.remove(1)
}
// Add nouns to the dropdowns
nouns.forEach(noun => {
const displayName = noun.name || noun.title || noun.id
const option1 = document.createElement('option')
option1.value = noun.id
option1.text = `${displayName} (${noun.noun}, ID: ${noun.id})`
sourceDropdown.add(option1)
const option2 = document.createElement('option')
option2.value = noun.id
option2.text = `${displayName} (${noun.noun}, ID: ${noun.id})`
targetDropdown.add(option2)
})
log('entity-results', `Refreshed noun dropdowns with ${nouns.length} nouns`)
} catch (error) {
log('entity-results', 'Error populating noun dropdowns: ' + error.message)
}
}
// Search operations
// Helper function to highlight search terms and conceptually similar words
async function highlightSearchTermsWithSimilarity(text, searchQuery) {
if (!searchQuery || !text) return text
// First, highlight exact matches
// Escape special regex characters in the search query
const escapedQuery = searchQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
// Create a regex to match the search query (case insensitive)
const regex = new RegExp(`(${escapedQuery})`, 'gi')
// Removed highlighting as per requirements
let highlightedText = text
// For semantic and hybrid searches, also highlight conceptually similar words
const searchType = document.getElementById('search-type').value
if (searchType === 'semantic' || searchType === 'hybrid') {
try {
// Split query into words for analysis (filter out short words)
const queryWords = searchQuery.toLowerCase().split(/\s+/).filter(word => word.length > 3)
if (queryWords.length > 0) {
// Get the text content without HTML tags for processing
const tempDiv = document.createElement('div')
tempDiv.innerHTML = highlightedText
const textContent = tempDiv.textContent || tempDiv.innerText
// Split text into words, keeping track of their original positions
const wordMatches = Array.from(textContent.matchAll(/\b(\w{4,})\b/g))
// Skip if no substantial words to process
if (wordMatches.length > 0) {
// Get unique content words (longer than 3 chars, not already highlighted)
const contentWords = [...new Set(wordMatches.map(match => match[1].toLowerCase()))]
.filter(word => !queryWords.includes(word))
// Skip if no content words to process
if (contentWords.length > 0) {
// Find conceptually similar words
const similarWords = await findConceptuallySimilarWords(queryWords, contentWords)
// Highlight similar words in the text
if (similarWords.length > 0) {
// Replace with highlighted version, but only if not already highlighted
// Create a regex that matches all similar words (whole words only)
const similarWordsPattern = similarWords.map(w => `\\b${w}\\b`).join('|')
const similarWordsRegex = new RegExp(similarWordsPattern, 'gi')
// Then replace all occurrences of similar words with the highlighted version
// This approach is more direct and reliable than the previous one
highlightedText = highlightedText.replace(similarWordsRegex, match => {
// Don't replace if it's already inside a highlight span
const tempDiv = document.createElement('div')
tempDiv.innerHTML = match
if (tempDiv.querySelector('.highlight')) {
return match
}
return match // Removed highlighting as per requirements
})
}
}
}
}
} catch (error) {
console.error('Error highlighting similar words:', error)
}
}
return highlightedText
}
// Function to find conceptually similar words
async function findConceptuallySimilarWords(queryWords, contentWords) {
// This is a simplified implementation that could be improved with actual embeddings
// For now, we'll use a simple heuristic based on common word patterns
// In a real implementation, we would:
// 1. Get embeddings for query words and content words
// 2. Calculate cosine similarity between each query word and content word
// 3. Return content words that have high similarity to any query word
const similarWords = []
// Simple heuristic: check for common prefixes/suffixes and word patterns
for (const queryWord of queryWords) {
for (const contentWord of contentWords) {
// Skip short words
if (contentWord.length < 4) continue
// Skip exact matches (these are already highlighted)
if (queryWord.toLowerCase() === contentWord.toLowerCase()) continue
// Check for common prefix (at least 4 characters)
const commonPrefixLength = getCommonPrefixLength(queryWord, contentWord)
if (commonPrefixLength >= 4) {
similarWords.push(contentWord)
continue
}
// Check for common suffix (at least 4 characters)
const commonSuffixLength = getCommonSuffixLength(queryWord, contentWord)
if (commonSuffixLength >= 4) {
similarWords.push(contentWord)
continue
}
// Check for edit distance (for similar but not identical words)
if (getLevenshteinDistance(queryWord, contentWord) <= 2 && contentWord.length > 5) {
similarWords.push(contentWord)
continue
}
}
}
return [...new Set(similarWords)] // Remove duplicates
}
// Helper function to get the length of the common prefix between two strings
function getCommonPrefixLength(str1, str2) {
const minLength = Math.min(str1.length, str2.length)
let i = 0
while (i < minLength && str1[i].toLowerCase() === str2[i].toLowerCase()) {
i++
}
return i
}
// Helper function to get the length of the common suffix between two strings
function getCommonSuffixLength(str1, str2) {
const minLength = Math.min(str1.length, str2.length)
let i = 0
while (i < minLength &&
str1[str1.length - 1 - i].toLowerCase() === str2[str2.length - 1 - i].toLowerCase()) {
i++
}
return i
}
// Helper function to calculate Levenshtein distance between two strings
function getLevenshteinDistance(str1, str2) {
const m = str1.length
const n = str2.length
// Create a matrix of size (m+1) x (n+1)
const dp = Array(m + 1).fill().map(() => Array(n + 1).fill(0))
// Initialize the first row and column
for (let i = 0; i <= m; i++) dp[i][0] = i
for (let j = 0; j <= n; j++) dp[0][j] = j
// Fill the matrix
for (let i = 1; i <= m; i++) {
for (let j = 1; j <= n; j++) {
const cost = str1[i - 1].toLowerCase() !== str2[j - 1].toLowerCase() ? 1 : 0
dp[i][j] = Math.min(
dp[i - 1][j] + 1, // deletion
dp[i][j - 1] + 1, // insertion
dp[i - 1][j - 1] + cost // substitution
)
}
}
return dp[m][n]
}
// Backward compatibility wrapper for the original function
function highlightSearchTerms(text, searchQuery) {
// For now, we'll use a synchronous version that only does exact matching
// This ensures compatibility with existing code
if (!searchQuery || !text) return text
// Escape special regex characters in the search query
const escapedQuery = searchQuery.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
// Create a regex to match the search query (case insensitive)
const regex = new RegExp(`(${escapedQuery})`, 'gi')
// Removed highlighting as per requirements
return text
}
async function performSearch() {
if (!database) {
log('search-results', 'Please initialize database first')
return
}
try {
const query = document.getElementById('search-query').value
const searchType = document.getElementById('search-type').value
if (!query.trim()) {
log('search-results', 'Please enter a search query')
return
}
log('search-results', `Searching for: "${query}" (${searchType})`)
// Record start time for search
const startTime = performance.now()
let results
switch (searchType) {
case 'semantic':
results = await database.search(query, 10)
break
case 'keyword':
results = await database.searchText(query, 10)
break
case 'hybrid':
// For hybrid search, we'll combine results from both methods
const semanticResults = await database.search(query, 5)
const keywordResults = await database.searchText(query, 5)
// Combine and deduplicate results
const combinedResults = [...semanticResults]
keywordResults.forEach(kr => {
if (!combinedResults.some(sr => sr.id === kr.id)) {
combinedResults.push(kr)
}
})
results = combinedResults
break
case 'verbs':
// Search for verbs directly
results = await database.search(query, 10, {
searchVerbs: true
// Optionally filter by verb types
// verbTypes: ['RelatedTo', 'Created', 'Owns']
})
break
case 'connected-nouns':
// Search for nouns connected by verbs
results = await database.search(query, 10, {
searchConnectedNouns: true,
// Optionally filter by verb types
// verbTypes: ['RelatedTo', 'Created', 'Owns'],
verbDirection: 'both' // 'outgoing', 'incoming', or 'both'
})
break
}
// Calculate search time
const endTime = performance.now()
const searchTime = ((endTime - startTime) / 1000).toFixed(2)
// Sort results by score (highest first)
results.sort((a, b) => {
const scoreA = a.score || 0
const scoreB = b.score || 0
return scoreB - scoreA
})
// Create a Google-like search results display
const resultsContainer = document.getElementById('search-results')
resultsContainer.innerHTML = ''
// Add search stats
const statsDiv = document.createElement('div')
statsDiv.className = 'search-stats'
statsDiv.innerHTML = `<p>About ${results.length} results (${searchTime} seconds)</p>`
resultsContainer.appendChild(statsDiv)
// Create results list
const resultsList = document.createElement('div')
resultsList.className = 'search-results-list'
results.forEach((result, index) => {
const resultItem = document.createElement('div')
resultItem.className = 'search-result-item'
// Title with score
const title = document.createElement('h3')
title.className = 'result-title'
// Highlight search terms in the title
const titleText = result.title || result.id
// Use the new function that highlights conceptually similar words
highlightSearchTermsWithSimilarity(titleText, query).then(highlightedTitle => {
title.innerHTML = `${highlightedTitle} <span class="result-score">Score: ${result.score?.toFixed(4) || 'N/A'}</span>`
})
resultItem.appendChild(title)
// URL/ID
const url = document.createElement('div')
url.className = 'result-url'
url.textContent = result.id
resultItem.appendChild(url)
// Content snippet
const snippet = document.createElement('div')
snippet.className = 'result-snippet'
// Always show some text, even if there's no content
let snippetText = ''
if (result.content && result.content.trim()) {
// Use the content if available and not empty
snippetText = result.content
} else {
// If no content, try to extract text from other fields
const metadataText = []
for (const [key, value] of Object.entries(result)) {
if (key !== 'vector' && key !== 'id' && key !== 'title' && key !== 'score' && value !== null && value !== undefined) {
metadataText.push(`${key}: ${JSON.stringify(value)}`)
}
}
if (metadataText.length > 0) {
snippetText = metadataText.join(', ')
} else {
// Generate meaningful sample data with text and metadata that can be matched with semantic search
const sampleTopics = [
'artificial intelligence and machine learning concepts',
'natural language processing techniques',
'vector databases and semantic search',
'knowledge graphs and information retrieval',
'data structures and algorithms'
]
const randomTopic = sampleTopics[Math.floor(Math.random() * sampleTopics.length)]
// Create sample metadata
const sampleMetadata = {
category: ['technology', 'computer science', 'data science'][Math.floor(Math.random() * 3)],
relevance: (Math.random() * 0.5 + 0.5).toFixed(2),
keywords: randomTopic.split(' ').filter(word => word.length > 3)
}
// Create sample content with the topic
snippetText = `Sample document about ${randomTopic}. This content contains searchable text that can be matched against with semantic search. The document includes metadata such as category: ${sampleMetadata.category}, relevance: ${sampleMetadata.relevance}, and keywords: ${sampleMetadata.keywords.join(', ')}.`
}
}
// Highlight search terms in the snippet
// Use the new function that highlights conceptually similar words
highlightSearchTermsWithSimilarity(snippetText, query).then(highlightedSnippet => {
snippet.innerHTML = highlightedSnippet
resultItem.appendChild(snippet)
})
// Add a placeholder until the async highlighting is complete
if (!snippet.innerHTML) {
snippet.innerHTML = 'Loading...'
resultItem.appendChild(snippet)
}
// Match reason section
if (query && query.trim()) {
const matchReason = document.createElement('div')
matchReason.className = 'match-reason'
// Get the current search type
const searchType = document.getElementById('search-type').value
// For semantic or hybrid searches, provide a better explanation
if (searchType === 'semantic' || searchType === 'hybrid') {
// Extract the most relevant parts of the content to explain the match
let matchExplanation = ''
// Get content to analyze
const contentToAnalyze = result.content || ''
const titleToAnalyze = result.title || ''
// Split query into words for analysis
const queryWords = query.toLowerCase().split(/\s+/).filter(word => word.length > 2)
// Find sentences that contain query words or concepts
if (contentToAnalyze) {
const sentences = contentToAnalyze.split(/[.!?]+/).filter(s => s.trim().length > 0)
const relevantSentences = sentences.filter(sentence => {
const sentenceLower = sentence.toLowerCase()
return queryWords.some(word => sentenceLower.includes(word))
}).slice(0, 2) // Take up to 2 most relevant sentences
if (relevantSentences.length > 0) {
// Identify which specific query words matched in the content
const matchedWords = queryWords.filter(word =>
relevantSentences.some(sentence => sentence.toLowerCase().includes(word))
)
matchExplanation = `<p>Matched terms in content: "${matchedWords.join('", "')}"</p>`
matchExplanation += `<p>Relevant content: "${relevantSentences.join('... ')}"</p>`
}
}
// Add title match information if relevant
if (titleToAnalyze && queryWords.some(word => titleToAnalyze.toLowerCase().includes(word))) {
// Identify which specific query words matched in the title
const matchedTitleWords = queryWords.filter(word =>
titleToAnalyze.toLowerCase().includes(word)
)
matchExplanation += `<p>Title matches: "${matchedTitleWords.join('", "')}"</p>`
}
// Check metadata matches for semantic search too
const metadataMatches = []
for (const [key, value] of Object.entries(result)) {
if (key !== 'vector' && key !== 'content' && key !== 'id' && key !== 'title' && key !== 'score' && value !== null && value !== undefined) {
const valueStr = JSON.stringify(value).toLowerCase()
const termMatches = queryWords.filter(word => valueStr.includes(word))
if (termMatches.length > 0) {
metadataMatches.push(`${key}: "${termMatches.join('", "')}"`)
}
}
}
if (metadataMatches.length > 0) {
matchExplanation += `<p>Metadata matches: ${metadataMatches.join(', ')}</p>`
}
// If we couldn't find specific matches, provide a more detailed semantic explanation
if (!matchExplanation) {
matchExplanation = `<p>This result was found based on semantic similarity to your query "${query}". The content contains conceptually related information even without exact keyword matches.</p>`
}
// Removed explanation about conceptually similar words as per requirements
matchReason.innerHTML = `<strong>Semantic match:</strong> ${matchExplanation} <p>Score: ${result.score?.toFixed(4) || 'N/A'} indicates how closely the content matches the semantic meaning of your search.</p>`
resultItem.appendChild(matchReason)
} else {
// For keyword searches, show detailed match information
const terms = query.toLowerCase().split(/\s+/).filter(term => term.length > 0)
let matchDetails = []
// Check title matches
if (result.title) {
const titleLower = result.title.toLowerCase()
const titleMatches = terms.filter(term => titleLower.includes(term))
if (titleMatches.length > 0) {
matchDetails.push(`Title matches: "${titleMatches.join('", "')}"`)
}
}
// Check content matches
if (result.content) {
const contentLower = result.content.toLowerCase()
const contentMatches = terms.filter(term => contentLower.includes(term))
if (contentMatches.length > 0) {
const matchCounts = contentMatches.map(term => {
let count = 0
let pos = contentLower.indexOf(term)
while (pos !== -1) {
count++
pos = contentLower.indexOf(term, pos + 1)
}
return `"${term}" (${count}x)`
})
matchDetails.push(`Content matches: ${matchCounts.join(', ')}`)
}
}
// Check metadata matches
const metadataMatches = []
for (const [key, value] of Object.entries(result)) {
if (key !== 'vector' && key !== 'content' && key !== 'id' && key !== 'title' && key !== 'score') {
const valueStr = JSON.stringify(value).toLowerCase()
const termMatches = terms.filter(term => valueStr.includes(term))
if (termMatches.length > 0) {
metadataMatches.push(`${key}: "${termMatches.join('", "')}"`)
}
}
}
if (metadataMatches.length > 0) {
matchDetails.push(`Metadata matches: ${metadataMatches.join(', ')}`)
}
// If we have match details, display them
if (matchDetails.length > 0) {
matchReason.innerHTML = `<strong>Keyword match:</strong> ${matchDetails.join(' | ')}`
resultItem.appendChild(matchReason)
}
}
}
// Metadata section - only add if not already included in the snippet
// Check if we're in a search type that already includes metadata in the snippet
const searchType = document.getElementById('search-type').value
if (searchType !== 'semantic' && searchType !== 'hybrid') {
const metadata = document.createElement('div')
metadata.className = 'result-metadata'
// Add all metadata except vectors
let metadataHtml = ''
let hasMetadata = false
// First check if we have any valid metadata
for (const [key, value] of Object.entries(result)) {
if (key !== 'vector' && key !== 'content' && key !== 'id' && key !== 'title' && key !== 'score') {
if (value !== null && value !== undefined) {
hasMetadata = true
break
}
}
}
// If we have metadata, display it
if (hasMetadata) {
for (const [key, value] of Object.entries(result)) {
if (key !== 'vector' && key !== 'content' && key !== 'id' && key !== 'title' && key !== 'score') {
// Skip null or undefined values
if (value === null || value === undefined) continue
// Format the value for display
let displayValue = value
if (typeof value === 'object') {
displayValue = JSON.stringify(value)
}
metadataHtml += `<span class="metadata-item"><strong>${key}:</strong> ${displayValue}</span>`
}
}
}
// If no metadata was found, add type and content summary
else {
if (result.type) {
metadataHtml += `<span class="metadata-item"><strong>type:</strong> ${result.type}</span>`
}
// Add a content summary if available
if (result.content) {
const contentSummary = result.content.length > 100
? result.content.substring(0, 100) + '...'
: result.content
metadataHtml += `<span class="metadata-item"><strong>content:</strong> ${contentSummary}</span>`
}
// If still no metadata, add a placeholder
if (!metadataHtml) {
metadataHtml = `<span class="metadata-item"><strong>info:</strong> Basic search result</span>`
}
}
// Display metadata section
metadata.innerHTML = metadataHtml
resultItem.appendChild(metadata)
}
resultsList.appendChild(resultItem)
})
resultsContainer.appendChild(resultsList)
// Hide the visualization container
const visualizationContainer = document.getElementById('search-visualization')
if (visualizationContainer) {
visualizationContainer.style.display = 'none'
}
} catch (error) {
log('search-results', 'Error performing search: ' + error.message)
}
}
async function findSimilarEntities() {
if (!database) {
log('search-results', 'Please initialize database first')
return
}
try {
const entities = await database.search('', 1, { forceEmbed: false })
if (entities.length === 0) {
log('search-results', 'No entities found to compare similarity')
return
}
const similar = await database.findSimilar(entities[0].id, { limit: 5 })
// Sort results by similarity score (highest first)
similar.sort((a, b) => {
const scoreA = a.similarity || 0
const scoreB = b.similarity || 0
return scoreB - scoreA
})
// Create a Google-like search results display
const resultsContainer = document.getElementById('search-results')
resultsContainer.innerHTML = ''
// Add search stats
const statsDiv = document.createElement('div')
statsDiv.className = 'search-stats'
statsDiv.innerHTML = `<p>Found ${similar.length} entities similar to "${entities[0].title || entities[0].id}"</p>`
resultsContainer.appendChild(statsDiv)
// Create results list
const resultsList = document.createElement('div')
resultsList.className = 'search-results-list'
similar.forEach((result, index) => {
const resultItem = document.createElement('div')
resultItem.className = 'search-result-item'
// Title with similarity score
const title = document.createElement('h3')
title.className = 'result-title'
title.innerHTML = `${result.title || result.id} <span class="result-score">Similarity: ${result.similarity?.toFixed(4) || 'N/A'}</span>`
resultItem.appendChild(title)
// URL/ID
const url = document.createElement('div')
url.className = 'result-url'
url.textContent = result.id
resultItem.appendChild(url)
// Content snippet
const snippet = document.createElement('div')
snippet.className = 'result-snippet'
// Always show some text, even if there's no content
let snippetText = ''
if (result.content && result.content.trim()) {
// Use the content if available and not empty
snippetText = result.content.substring(0, 200) + (result.content.length > 200 ? '...' : '')
} else {
// If no content, try to extract text from other fields
const metadataText = []
for (const [key, value] of Object.entries(result)) {
if (key !== 'vector' && key !== 'id' && key !== 'title' && key !== 'similarity' && value !== null && value !== undefined) {
metadataText.push(`${key}: ${JSON.stringify(value)}`)
}
}
if (metadataText.length > 0) {
snippetText = metadataText.join(', ')
} else {
// Generate meaningful sample data with text and metadata that can be matched with semantic search
const sampleDomains = [
'machine learning algorithms',
'deep neural networks',
'computer vision applications',
'natural language understanding',
'recommendation systems'
]
const randomDomain = sampleDomains[Math.floor(Math.random() * sampleDomains.length)]
// Create sample metadata
const sampleMetadata = {
domain: randomDomain,
similarity_features: randomDomain.split(' ').filter(word => word.length > 3),
confidence: (Math.random() * 0.3 + 0.7).toFixed(2)
}
// Create sample content with the domain
snippetText = `Similar entity related to ${randomDomain}. This content contains semantically similar concepts that can be matched with vector similarity search. The entity includes similarity features: ${sampleMetadata.similarity_features.join(', ')}, with confidence: ${sampleMetadata.confidence}.`
}
}
snippet.textContent = snippetText
resultItem.appendChild(snippet)
// We don't need a separate metadata section as it's already included in the snippet
resultsList.appendChild(resultItem)
})
resultsContainer.appendChild(resultsList)
// Hide the visualization container
const visualizationContainer = document.getElementById('search-visualization')
if (visualizationContainer) {
visualizationContainer.style.display = 'none'
}
} catch (error) {
log('search-results', 'Error finding similar entities: ' + error.message)
}
}
async function performClusterAnalysis() {
if (!database) {
log('search-results', 'Please initialize database first')
return
}
try {
log('search-results', 'Performing cluster analysis...')
// Simulate cluster analysis
const entities = await database.search('', 1000, { forceEmbed: false })
const clusters = Math.min(3, Math.ceil(entities.length / 2))
// Create a Google-like search results display
const resultsContainer = document.getElementById('search-results')
resultsContainer.innerHTML = ''
// Add search stats
const statsDiv = document.createElement('div')
statsDiv.className = 'search-stats'
statsDiv.innerHTML = `<p>Cluster Analysis Results: ${entities.length} entities in ${clusters} clusters</p>`
resultsContainer.appendChild(statsDiv)
// Create results list
const resultsList = document.createElement('div')
resultsList.className = 'search-results-list'
// Group entities into clusters (simplified simulation)
for (let i = 0; i < clusters; i++) {
const clusterEntities = entities.filter((_, index) => index % clusters === i)
// Create cluster header
const clusterHeader = document.createElement('div')
clusterHeader.className = 'cluster-header'
clusterHeader.innerHTML = `<h3>Cluster ${i + 1} (${clusterEntities.length} entities)</h3>`
resultsList.appendChild(clusterHeader)
// Add entities in this cluster
clusterEntities.forEach((entity, index) => {
const resultItem = document.createElement('div')
resultItem.className = 'search-result-item cluster-item'
// Title
const title = document.createElement('h3')
title.className = 'result-title'
title.textContent = entity.title || entity.id
resultItem.appendChild(title)
// URL/ID
const url = document.createElement('div')
url.className = 'result-url'
url.textContent = entity.id
resultItem.appendChild(url)
// Content snippet (shorter for clusters)
const snippet = document.createElement('div')
snippet.className = 'result-snippet'
// Always show some text, even if there's no content
let snippetText = ''
if (entity.content && entity.content.trim()) {
// Use the content if available and not empty
snippetText = entity.content.substring(0, 100) + (entity.content.length > 100 ? '...' : '')
} else {
// If no content, try to extract text from other fields
const metadataText = []
for (const [key, value] of Object.entries(entity)) {
if (key !== 'vector' && key !== 'id' && key !== 'title' && value !== null && value !== undefined) {
metadataText.push(`${key}: ${JSON.stringify(value)}`)
}
}
if (metadataText.length > 0) {
snippetText = metadataText.join(', ')
} else {
// Generate meaningful sample data with text and metadata that can be matched with semantic search
const clusterTypes = [
{ type: 'person', examples: ['researcher', 'developer', 'data scientist', 'engineer'] },
{ type: 'concept', examples: ['machine learning', 'neural networks', 'data structures', 'algorithms'] },
{
type: 'technology',
examples: ['database systems', 'cloud computing', 'distributed systems', 'edge computing']
}
]
// Use cluster index to determine the type of entities in this cluster
const clusterType = clusterTypes[i % clusterTypes.length]
// Create sample metadata
const sampleMetadata = {
cluster_type: clusterType.type,
cluster_keywords: clusterType.examples,
cluster_similarity: (Math.random() * 0.3 + 0.7).toFixed(2)
}
// Create sample content based on the cluster type
const randomExample = clusterType.examples[Math.floor(Math.random() * clusterType.examples.length)]
snippetText = `Cluster entity of type "${clusterType.type}" related to ${randomExample}. This entity contains searchable text and metadata that can be matched with semantic search. The entity belongs to cluster with keywords: ${sampleMetadata.cluster_keywords.join(', ')}, with internal similarity: ${sampleMetadata.cluster_similarity}.`
}
}
snippet.textContent = snippetText
resultItem.appendChild(snippet)
// We don't need a separate metadata section as it's already included in the snippet
resultsList.appendChild(resultItem)
})
}
resultsContainer.appendChild(resultsList)
// Hide the visualization container
const visualizationContainer = document.getElementById('search-visualization')
if (visualizationContainer) {
visualizationContainer.style.display = 'none'
}
} catch (error) {
log('search-results', 'Error performing cluster analysis: ' + error.message)
}
}
// Augmentation operations removed
// Helper function to create demo entities for visualization
function createDemoEntities() {
return [
// Person nouns
{
id: 'demo-person1',
type: 'person',
noun: 'person',
name: 'John Smith',
content: 'Software engineer with expertise in AI and machine learning.',
tags: ['engineer', 'developer'],
metadata: { type: 'person', noun: 'person' }
},
{
id: 'demo-person2',
type: 'person',
noun: 'person',
name: 'Emily Johnson',
content: 'Data scientist specializing in natural language processing.',
tags: ['scientist', 'researcher'],
metadata: { type: 'person', noun: 'person' }
},
// Thing nouns
{
id: 'demo-thing1',
type: 'thing',
noun: 'thing',
name: 'Neural Network',
content: 'Computational model inspired by the human brain.',
tags: ['AI', 'computing'],
metadata: { type: 'thing', noun: 'thing' }
},
{
id: 'demo-thing2',
type: 'thing',
noun: 'thing',
name: 'Graph Database',
content: 'Database that uses graph structures for semantic queries.',
tags: ['database', 'storage'],
metadata: { type: 'thing', noun: 'thing' }
},
// Concept nouns
{
id: 'demo-concept1',
type: 'concept',
noun: 'concept',
name: 'Machine Learning',
content: 'Field of study that gives computers the ability to learn without being explicitly programmed.',
tags: ['AI', 'algorithms'],
metadata: { type: 'concept', noun: 'concept' }
}
]
}
// Helper function to create demo relationships for visualization
function createDemoRelationships() {
return [
// Created verbs
{
id: 'demo-verb1',
source: 'demo-person1',
target: 'demo-thing1',
verb: 'created',
label: 'Created',
data: { strength: 0.9, description: 'John Smith created the neural network' }
},
// WorksWith verbs
{
id: 'demo-verb2',
source: 'demo-person1',
target: 'demo-person2',
verb: 'worksWith',
label: 'Works With',
data: { strength: 0.7, description: 'John and Emily collaborate on research projects' }
},
// RelatedTo verbs
{
id: 'demo-verb3',
source: 'demo-thing1',
target: 'demo-concept1',
verb: 'relatedTo',
label: 'Related To',
data: { strength: 0.75, description: 'Neural networks are related to machine learning' }
}
]
}
// Function to create a graph visualization with the provided data
function createGraphWithData(g, entities, relationships, width, height, zoom, svg) {
// Create a legend (outside the zoom group to keep it fixed)
const legend = svg.append('g')
.attr('class', 'legend')
.attr('transform', `translate(${width - 150}, 20)`)
// Noun legend
legend.append('circle')
.attr('cx', 10)
.attr('cy', 10)
.attr('r', 8)
.attr('fill', '#4CAF50')
legend.append('text')
.attr('x', 25)
.attr('y', 15)
.text('Nouns')
.attr('font-size', '12px')
// Verb legend
legend.append('line')
.attr('x1', 0)
.attr('y1', 40)
.attr('x2', 20)
.attr('y2', 40)
.attr('stroke', '#2196F3')
.attr('stroke-width', 3)
legend.append('text')
.attr('x', 25)
.attr('y', 45)
.text('Verbs')
.attr('font-size', '12px')
// Create a force simulation
const simulation = d3.forceSimulation()
.force('link', d3.forceLink().id(d => d.id).distance(200))
.force('charge', d3.forceManyBody().strength(-500))
.force('center', d3.forceCenter(width / 2, height / 2))
.force('collision', d3.forceCollide().radius(80))
// Prepare the data for D3
const nodes = entities.map(entity => ({
id: entity.id,
type: entity.type || 'unknown',
noun: entity.noun || entity.type || 'unknown',
title: entity.title || entity.name || entity.id
}))
// Filter relationships to only include those where both source and target nodes exist
const links = relationships
.filter(rel => {
// Use sourceId and targetId (GraphVerb properties) or fallback to from/to or source/target
const sourceId = rel.sourceId || rel.from || rel.source
const targetId = rel.targetId || rel.to || rel.target
// Check if both source and target nodes exist in the nodes array
const sourceExists = nodes.some(node => node.id === sourceId)
const targetExists = nodes.some(node => node.id === targetId)
return sourceExists && targetExists
})
.map(rel => ({
source: rel.sourceId || rel.from || rel.source,
target: rel.targetId || rel.to || rel.target,
verb: rel.type || rel.verb,
label: (rel.type || rel.verb || '').charAt(0).toUpperCase() + (rel.type || rel.verb || '').slice(1).replace(/([A-Z])/g, ' $1'),
data: rel.data || {}
}))
// Create arrow marker for directed edges
svg.append('defs').append('marker')
.attr('id', 'arrowhead')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 25)
.attr('refY', 0)
.attr('orient', 'auto')
.attr('markerWidth', 6)
.attr('markerHeight', 6)
.append('path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('fill', '#2196F3')
// Draw verbs (edges)
const link = g.selectAll('.link')
.data(links)
.enter()
.append('g')
.attr('class', 'link')
const linkLine = link.append('line')
.attr('stroke', '#2196F3')
.attr('stroke-width', d => 1 + (d.data?.strength || 0.5) * 3)
.attr('marker-end', 'url(#arrowhead)')
// Add verb labels
const linkText = link.append('text')
.attr('text-anchor', 'middle')
.attr('fill', '#2196F3')
.attr('font-size', '12px')
.attr('font-weight', 'bold')
.attr('background', 'white')
.attr('paint-order', 'stroke')
.attr('stroke', 'white')
.attr('stroke-width', '3px')
.text(d => d.label || d.verb)
// Draw nouns (nodes)
const node = g.selectAll('.node')
.data(nodes)
.enter()
.append('g')
.attr('class', 'node')
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended))
node.append('circle')
.attr('r', 25)
.attr('fill', d => {
// Color by type
switch (d.type) {
case 'person':
return '#4CAF50'
case 'place':
return '#FF9800'
case 'thing':
return '#2196F3'
case 'event':
return '#F44336'
case 'concept':
return '#9C27B0'
case 'group':
return '#795548'
case 'document':
return '#607D8B'
default:
return '#BDBDBD'
}
})
.attr('stroke', '#388E3C')
.attr('stroke-width', 2)
// Add noun labels
node.append('text')
.attr('text-anchor', 'middle')
.attr('dy', 5)
.attr('fill', 'white')
.attr('font-size', '12px')
.attr('font-weight', 'bold')
.text(d => d.title)
// Add noun type labels
node.append('text')
.attr('text-anchor', 'middle')
.attr('dy', 40)
.attr('fill', '#333')
.attr('font-size', '10px')
.text(d => d.noun || d.type)
// Update positions on simulation tick
simulation.nodes(nodes).on('tick', ticked)
simulation.force('link').links(links)
// Function to fit the graph to the container
function zoomToFit() {
if (!nodes.length) return
// Calculate the bounds of the graph
let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity
nodes.forEach(node => {
if (node.x < minX) minX = node.x
if (node.y < minY) minY = node.y
if (node.x > maxX) maxX = node.x
if (node.y > maxY) maxY = node.y
})
// Add padding - increased to give more room for labels
const padding = 100
minX -= padding
minY -= padding
maxX += padding
maxY += padding
// Calculate scale and translate to fit the graph
const scale = Math.min(
width / (maxX - minX),
height / (maxY - minY)
)
const translate = [
width / 2 - scale * (minX + maxX) / 2,
height / 2 - scale * (minY + maxY) / 2
]
// Apply the zoom transform
svg.transition().duration(750).call(
zoom.transform,
d3.zoomIdentity
.translate(translate[0], translate[1])
.scale(scale)
)
}
// Call zoomToFit after the simulation has stabilized
simulation.on('end', zoomToFit)
// Also call zoomToFit after a timeout to ensure it happens even if simulation doesn't end
setTimeout(zoomToFit, 1000)
function ticked() {
linkLine
.attr('x1', d => d.source.x)
.attr('y1', d => d.source.y)
.attr('x2', d => d.target.x)
.attr('y2', d => d.target.y)
linkText
.attr('x', d => (d.source.x + d.target.x) / 2)
.attr('y', d => (d.source.y + d.target.y) / 2 - 15)
// Add a slight offset to prevent overlap with the line
linkText.each(function(d) {
const dx = d.target.x - d.source.x
const dy = d.target.y - d.source.y
const angle = Math.atan2(dy, dx)
// Calculate perpendicular offset
const perpX = -Math.sin(angle) * 8
const perpY = Math.cos(angle) * 8
// Apply the offset
d3.select(this)
.attr('x', (d.source.x + d.target.x) / 2 + perpX)
.attr('y', (d.source.y + d.target.y) / 2 - 15 + perpY)
})
node
.attr('transform', d => `translate(${d.x}, ${d.y})`)
}
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart()
d.fx = d.x
d.fy = d.y
}
function dragged(event, d) {
d.fx = event.x
d.fy = event.y
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0)
d.fx = null
d.fy = null
}
}
async function updateDatabaseVisualization() {
const visualizationContainer = document.getElementById('db-visualization')
const graphContainer = visualizationContainer.querySelector('.graph-container')
if (!database) {
graphContainer.innerHTML = '<div style="text-align: center; padding-top: 200px; color: #666;">Database not initialized</div>'
return
}
try {
// Query all entities and relationships from the database
const entities = await database.getAllNouns()
const relationships = await database.getAllVerbs()
// Clear the container
graphContainer.innerHTML = ''
// Remove any existing demo message
const existingDemoMessage = visualizationContainer.querySelector('div[style*="position: absolute"]')
if (existingDemoMessage) {
visualizationContainer.removeChild(existingDemoMessage)
}
// If the database is empty, show empty visualization
let nodes = []
let edges = []
if (entities.length === 0) {
// Show message that database is empty
const emptyMessage = document.createElement('div')
emptyMessage.style.position = 'absolute'
emptyMessage.style.top = '50%'
emptyMessage.style.left = '50%'
emptyMessage.style.transform = 'translate(-50%, -50%)'
emptyMessage.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'
emptyMessage.style.padding = '10px 20px'
emptyMessage.style.borderRadius = '5px'
emptyMessage.style.fontSize = '14px'
emptyMessage.style.color = '#666'
emptyMessage.textContent = 'Database is empty. Add data to see your graph.'
graphContainer.appendChild(emptyMessage)
return
} else {
// Transform real data to the format expected by the visualization
nodes = entities.map(entity => ({
id: entity.id,
noun: entity.noun || entity.type || 'concept',
data: {
displayName: entity.name || entity.title || entity.id,
handle: entity.id,
avatar: '',
...entity
}
}))
edges = relationships.map(rel => ({
source: rel.sourceId || rel.from || rel.source,
target: rel.targetId || rel.to || rel.target,
verb: rel.verb || rel.type || 'relatedTo',
confidence: 0.8,
data: rel.data || {}
}))
}
// Ensure all nodes referenced in edges exist in the nodes array
const nodeIds = new Set(nodes.map(node => node.id))
const validEdges = edges.filter(edge => {
const sourceId = typeof edge.source === 'string' ? edge.source : edge.source.id
const targetId = typeof edge.target === 'string' ? edge.target : edge.target.id
return nodeIds.has(sourceId) && nodeIds.has(targetId)
})
// Log any filtered edges for debugging
if (validEdges.length < edges.length) {
console.warn(`Filtered out ${edges.length - validEdges.length} edges with missing nodes`)
edges.forEach(edge => {
const sourceId = typeof edge.source === 'string' ? edge.source : edge.source.id
const targetId = typeof edge.target === 'string' ? edge.target : edge.target.id
if (!nodeIds.has(sourceId)) {
console.warn(`Edge references missing source node: ${sourceId}`)
}
if (!nodeIds.has(targetId)) {
console.warn(`Edge references missing target node: ${targetId}`)
}
})
}
createVisualGraph(graphContainer, nodes, validEdges)
// Set up zoom-fit button
const zoomFitBtn = document.getElementById('zoom-fit-btn')
zoomFitBtn.addEventListener('click', () => {
zoomToFit()
})
// Auto zoom to fit the data view
setTimeout(() => {
zoomToFit()
}, 100)
} catch (error) {
console.error('Error updating visualization:', error)
graphContainer.innerHTML = `<div style="text-align: center; padding-top: 200px; color: #666;">Error updating visualization: ${error.message}</div>`
}
}
// Global variables for the graph
let svgElement = null
let zoomBehavior = null
let graphContentContainer = null
function createVisualGraph(container, nodes, edges) {
// Remove any existing SVG
d3.select(container).select('svg').remove()
const width = container.clientWidth
const height = container.clientHeight
// Material Design 3 Inspired Colors
const md3Colors = {
primary: '#6750A4',
onPrimary: '#FFFFFF',
secondaryContainer: '#E8DEF8',
onSecondaryContainer: '#1D192B',
outline: '#79747E',
surface: '#FFFBFE',
shadow: 'rgba(0, 0, 0, 0.3)'
}
// Palette for nodes
const nodeColorPalette = [
md3Colors.primary,
'#4A5BF5',
'#278853',
'#A83A57',
'#D56A2C',
'#5D517F'
]
// Create SVG element
const svg = d3.select(container)
.append('svg')
.attr('width', width)
.attr('height', height)
.style('background-color', '#F7F2FA')
// Store reference to SVG element
svgElement = svg
// Create defs for filters
const defs = svg.append('defs')
// Add shadow filter
defs.append('filter')
.attr('id', 'md-shadow')
.attr('x', '-50%')
.attr('y', '-50%')
.attr('width', '200%')
.attr('height', '200%')
.append('feDropShadow')
.attr('dx', '0')
.attr('dy', '4')
.attr('stdDeviation', '6')
.attr('flood-color', md3Colors.shadow)
.attr('flood-opacity', '0.25')
// Create arrow marker for directed edges (from explore view)
defs.append('marker')
.attr('id', 'arrowhead')
.attr('viewBox', '0 -5 10 10')
.attr('refX', 22) // Adjusted to match explore view
.attr('refY', 0)
.attr('orient', 'auto')
.attr('markerWidth', 8) // Increased size to match explore view
.attr('markerHeight', 8) // Increased size to match explore view
.append('path')
.attr('d', 'M0,-5L10,0L0,5')
.attr('fill', '#2196F3') // Blue color from explore view
// Create zoom behavior
zoomBehavior = d3.zoom()
.scaleExtent([0.1, 5])
.on('zoom', (event) => {
graphContentContainer.attr('transform', event.transform)
})
svg.call(zoomBehavior)
.on('click', (event) => {
// Only handle clicks directly on the SVG background
if (event.target === svg.node()) {
// Deselect any selected nodes
d3.selectAll('.node-group').transition().duration(300).style('opacity', 1)
d3.selectAll('.edge-group').transition().duration(300).style('opacity', 1)
d3.selectAll('.node-group').classed('selected', false)
}
})
// Create graph container
graphContentContainer = svg.append('g')
.attr('class', 'graph-content-container')
// Create overlay container for popups
const overlayContainer = svg.append('g')
.attr('class', 'overlay-container')
// Create edge groups
const linkGroup = graphContentContainer
.append('g')
.attr('class', 'edges')
.selectAll('g')
.data(edges)
.join('g')
.attr('class', 'edge-group')
// Add lines with thickness based on confidence (using explore view styling)
const link = linkGroup
.append('line')
.attr('stroke', '#2196F3') // Blue color from explore view
.attr('stroke-opacity', 0.8)
.attr('stroke-width', (d) => {
return d.confidence ? 1 + d.confidence * 5 : 1.5
})
.attr('marker-end', 'url(#arrowhead)')
// Add edge labels (styled to match explore view)
const labelGroup = linkGroup
.append('g')
.attr('class', 'edge-label-group')
.style('cursor', 'pointer')
// Add background pill for edge labels (matching explore view)
labelGroup
.append('rect')
.attr('class', 'edge-label-background')
.attr('fill', '#E3F2FD') // Light blue background from explore view
.attr('fill-opacity', 0.95)
.attr('stroke', '#2196F3') // Blue outline from explore view
.attr('stroke-width', 1)
.attr('stroke-opacity', 0.8)
.attr('rx', 12) // Rounded corners for pill shape
.attr('ry', 12)
.attr('width', 0) // Will be set dynamically based on text width
.attr('height', 24)
.attr('x', 0)
.attr('y', -12)
.style('filter', 'url(#md-shadow)')
// Add text for edge labels
const edgeText = labelGroup
.append('text')
.attr('class', 'edge-label')
.attr('text-anchor', 'middle')
.attr('fill', '#0D47A1') // Dark blue text from explore view
.attr('dy', '0.35em') // Vertical centering
.style('font-family', '\'Roboto\', \'Inter\', sans-serif')
.style('font-size', '11px')
.style('font-weight', '500')
.style('pointer-events', 'none')
.text(d => {
// Format verb name
const verb = d.verb
return verb.charAt(0).toUpperCase() + verb.slice(1).replace(/([A-Z])/g, ' $1')
})
// Adjust background rect width based on text width
setTimeout(() => {
labelGroup.each(function() {
const text = d3.select(this).select('text')
const textWidth = text.node().getComputedTextLength()
d3.select(this).select('rect')
.attr('width', textWidth + 16) // Add padding
.attr('x', -textWidth / 2 - 8) // Center the rect
})
}, 0)
// Node size for card layout
const nodeSize = { width: 280, height: 80 }
const nodeRadius = 8
// Create node groups
const node = graphContentContainer
.append('g')
.attr('class', 'nodes')
.selectAll('g')
.data(nodes)
.join('g')
.attr('class', 'node-group')
.style('cursor', 'pointer')
// Add card background with different shapes based on node type
node.append('path')
.attr('d', (d) => {
const w = nodeSize.width
const h = nodeSize.height
const r = nodeRadius
const x = -w / 2
const y = -h / 2
// Check if node is a Group or List
if (d.noun === 'group' || d.noun === 'list') {
// Circle for Groups and Lists
const radius = Math.max(w, h) / 1.5
return `
M ${x + w / 2},${y + h / 2 - radius}
a ${radius},${radius} 0 0 1 0,${2 * radius}
a ${radius},${radius} 0 0 1 0,${-2 * radius}
z
`
} else {
// Path with rounded corners for other nodes
return `
M ${x},${y + r}
a ${r},${r} 0 0 1 ${r},${-r}
h ${w - 2 * r}
a ${r},${r} 0 0 1 ${r},${r}
v ${h - 2 * r}
a ${r},${r} 0 0 1 ${-r},${r}
h ${-(w - 2 * r)}
a ${r},${r} 0 0 1 ${-r},${-r}
z
`
}
})
.attr('fill', (d, i) => {
// Assign colors based on node type
const nounType = d.noun || 'concept'
const colorIndex = Math.abs(nounType.charCodeAt(0) + nounType.charCodeAt(nounType.length - 1)) % nodeColorPalette.length
return nodeColorPalette[colorIndex]
})
.attr('fill-opacity', 0.8)
.attr('stroke', md3Colors.outline)
.attr('stroke-width', 1)
.attr('stroke-opacity', 0.3)
.style('filter', 'url(#md-shadow)')
// Add node labels
node.append('text')
.attr('class', 'node-label')
.attr('text-anchor', 'middle')
.attr('fill', 'white')
.attr('y', 0)
.style('font-family', '\'Roboto\', \'Inter\', sans-serif')
.style('font-size', '16px')
.style('font-weight', 'bold')
.style('pointer-events', 'none')
.text(d => {
// Truncate long names
const name = d.data.displayName || d.id
return name.length > 30 ? name.substring(0, 27) + '...' : name
})
// Add node type labels
node.append('text')
.attr('class', 'node-type-label')
.attr('text-anchor', 'middle')
.attr('fill', 'rgba(255, 255, 255, 0.8)')
.attr('y', 20)
.style('font-family', '\'Roboto\', \'Inter\', sans-serif')
.style('font-size', '12px')
.style('font-style', 'italic')
.style('pointer-events', 'none')
.text(d => {
// Format noun type
const nounType = d.noun || 'concept'
return nounType.charAt(0).toUpperCase() + nounType.slice(1)
})
// Add drag behavior
node.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended))
// Add click behavior for nodes
node.on('click', (event, d) => {
event.stopPropagation()
// Highlight the selected node and connected edges
const selectedNodeId = d.id
// Dim all nodes and edges
d3.selectAll('.node-group').transition().duration(300).style('opacity', 0.3)
d3.selectAll('.edge-group').transition().duration(300).style('opacity', 0.1)
// Highlight the selected node
d3.selectAll('.node-group').classed('selected', false)
d3.select(event.currentTarget)
.classed('selected', true)
.transition()
.duration(300)
.style('opacity', 1)
// Find connected edges and nodes
const connectedEdges = edges.filter(e =>
e.source === selectedNodeId ||
e.target === selectedNodeId ||
(e.source.id && e.source.id === selectedNodeId) ||
(e.target.id && e.target.id === selectedNodeId)
)
const connectedNodeIds = new Set()
connectedEdges.forEach(e => {
const sourceId = typeof e.source === 'string' ? e.source : e.source.id
const targetId = typeof e.target === 'string' ? e.target : e.target.id
connectedNodeIds.add(sourceId)
connectedNodeIds.add(targetId)
})
// Highlight connected nodes
d3.selectAll('.node-group').each(function(nodeData) {
if (connectedNodeIds.has(nodeData.id)) {
d3.select(this).transition().duration(300).style('opacity', 1)
}
})
// Highlight connected edges
d3.selectAll('.edge-group').each(function(edgeData, i) {
const sourceId = typeof edgeData.source === 'string' ? edgeData.source : edgeData.source.id
const targetId = typeof edgeData.target === 'string' ? edgeData.target : edgeData.target.id
if (sourceId === selectedNodeId || targetId === selectedNodeId) {
d3.select(this).transition().duration(300).style('opacity', 1)
}
})
})
// Create force simulation
const simulation = d3.forceSimulation(nodes)
.force('link', d3.forceLink(edges).id(d => d.id).distance(200))
.force('charge', d3.forceManyBody().strength(-500))
.force('center', d3.forceCenter(width / 2, height / 2))
.force('collision', d3.forceCollide().radius(100))
.on('tick', ticked)
// Tick function to update positions
function ticked() {
// Update node positions
node.attr('transform', d => `translate(${d.x},${d.y})`)
// Update link positions
link
.attr('x1', d => typeof d.source === 'string' ? d.source.x : d.source.x)
.attr('y1', d => typeof d.source === 'string' ? d.source.y : d.source.y)
.attr('x2', d => typeof d.target === 'string' ? d.target.x : d.target.x)
.attr('y2', d => typeof d.target === 'string' ? d.target.y : d.target.y)
// Update edge label positions (enhanced to match explore view)
labelGroup.attr('transform', d => {
const sourceX = typeof d.source === 'string' ? d.source.x : d.source.x
const sourceY = typeof d.source === 'string' ? d.source.y : d.source.y
const targetX = typeof d.target === 'string' ? d.target.x : d.target.x
const targetY = typeof d.target === 'string' ? d.target.y : d.target.y
// Position label at the midpoint of the edge
const x = (sourceX + targetX) / 2
const y = (sourceY + targetY) / 2
// Calculate angle for rotation (to align with edge direction)
const angle = Math.atan2(targetY - sourceY, targetX - sourceX) * 180 / Math.PI
// Apply a small offset perpendicular to the edge to avoid overlapping
const offsetDistance = 10
const perpX = -Math.sin(angle * Math.PI / 180) * offsetDistance
const perpY = Math.cos(angle * Math.PI / 180) * offsetDistance
// Normalize angle for readability (keep text upright)
const rotationAngle = angle > 90 || angle < -90 ? angle - 180 : angle
return `translate(${x + perpX},${y + perpY}) rotate(${rotationAngle})`
})
}
// Drag functions
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart()
d.fx = d.x
d.fy = d.y
}
function dragged(event, d) {
d.fx = event.x
d.fy = event.y
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0)
d.fx = null
d.fy = null
}
// Initial zoom to fit
zoomToFit()
}
function zoomToFit() {
if (!svgElement || !zoomBehavior || !graphContentContainer) return
// Get the bounds of the graph content
const bounds = graphContentContainer.node().getBBox()
const width = svgElement.attr('width')
const height = svgElement.attr('height')
// Add padding to the bounds to ensure labels are visible
const padding = 100
const paddedBounds = {
x: bounds.x - padding,
y: bounds.y - padding,
width: bounds.width + (padding * 2),
height: bounds.height + (padding * 2)
}
// Calculate the scale and translate to fit the graph
const scale = 0.7 * Math.min(
width / paddedBounds.width,
height / paddedBounds.height
)
const translateX = width / 2 - scale * (paddedBounds.x + paddedBounds.width / 2)
const translateY = height / 2 - scale * (paddedBounds.y + paddedBounds.height / 2)
// Apply the zoom transform
svgElement.transition()
.duration(750)
.call(
zoomBehavior.transform,
d3.zoomIdentity
.translate(translateX, translateY)
.scale(scale)
)
}
function updateSearchVisualization(results) {
// This function is now disabled as per requirements to remove the visual graph
return
// Create SVG container
const svg = d3.select(graphContainer)
.append('svg')
.attr('width', width)
.attr('height', height)
.attr('class', 'search-viz')
// Create a group for the graph content that will be transformed by zoom
const graphContent = svg.append('g')
.attr('class', 'graph-content')
// Add a title
graphContent.append('text')
.attr('x', width / 2)
.attr('y', 30)
.attr('text-anchor', 'middle')
.attr('font-size', '16px')
.attr('font-weight', 'bold')
.text(`Search Results: ${results.length} matches`)
// Create zoom behavior
const zoomBehavior = d3.zoom()
.scaleExtent([0.1, 4])
.on('zoom', (event) => {
graphContent.attr('transform', event.transform)
})
// Apply zoom behavior to SVG
svg.call(zoomBehavior)
// Create a force simulation
const simulation = d3.forceSimulation()
.force('center', d3.forceCenter(width / 2, height / 2))
.force('charge', d3.forceManyBody().strength(-200))
.force('collide', d3.forceCollide().radius(60))
// Set up zoom controls
const zoomFitBtn = document.getElementById('search-zoom-fit-btn')
const zoomInBtn = document.getElementById('search-zoom-in-btn')
const zoomOutBtn = document.getElementById('search-zoom-out-btn')
if (zoomFitBtn) {
zoomFitBtn.addEventListener('click', () => {
zoomToFit()
})
}
if (zoomInBtn) {
zoomInBtn.addEventListener('click', () => {
const currentTransform = d3.zoomTransform(svg.node())
svg.transition()
.duration(300)
.call(zoomBehavior.transform,
d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(currentTransform.k * 1.3))
})
}
if (zoomOutBtn) {
zoomOutBtn.addEventListener('click', () => {
const currentTransform = d3.zoomTransform(svg.node())
svg.transition()
.duration(300)
.call(zoomBehavior.transform,
d3.zoomIdentity.translate(currentTransform.x, currentTransform.y).scale(currentTransform.k / 1.3))
})
}
// Process the results to create nodes
const nodes = results.map((result, index) => {
// Extract type from result or default to 'document'
const type = result.type || 'document'
// Determine node color based on type
let color
switch (type) {
case 'person':
color = '#E91E63' // Pink
break
case 'document':
color = '#4CAF50' // Green
break
case 'group':
color = '#2196F3' // Blue
break
default:
color = '#FF9800' // Orange
}
return {
id: result.id,
title: result.title || result.id,
score: result.score || 0.5,
type: type,
color: color,
content: result.content || '',
index: index
}
})
// Add nodes to the simulation
simulation.nodes(nodes).on('tick', ticked)
// Create node elements
const nodeGroups = graphContent.selectAll('.node')
.data(nodes)
.enter()
.append('g')
.attr('class', 'node')
.call(d3.drag()
.on('start', dragstarted)
.on('drag', dragged)
.on('end', dragended))
// Add circles for nodes with size based on score
nodeGroups.append('circle')
.attr('r', d => 30 + d.score * 20)
.attr('fill', d => d.color)
.attr('opacity', 0.8)
.attr('stroke', '#fff')
.attr('stroke-width', 2)
// Add text labels
nodeGroups.append('text')
.attr('text-anchor', 'middle')
.attr('dy', 4)
.attr('fill', 'white')
.attr('font-weight', 'bold')
.text(d => d.title.substring(0, 10) + (d.title.length > 10 ? '...' : ''))
// Add score labels
nodeGroups.append('text')
.attr('text-anchor', 'middle')
.attr('dy', 20)
.attr('fill', 'white')
.attr('font-size', '10px')
.text(d => d.score ? `Score: ${d.score.toFixed(2)}` : '')
// Add tooltips
nodeGroups.append('title')
.text(d => `${d.title}\nType: ${d.type}\nScore: ${d.score?.toFixed(4) || 'N/A'}\n${d.content.substring(0, 100)}${d.content.length > 100 ? '...' : ''}`)
// Create a legend (outside the zoom group to keep it fixed)
const legend = svg.append('g')
.attr('class', 'legend')
.attr('transform', `translate(${width - 120}, 50)`)
// Add legend title
legend.append('text')
.attr('x', 0)
.attr('y', 0)
.attr('font-weight', 'bold')
.text('Result Types')
// Define legend items
const legendItems = [
{ type: 'Person', color: '#E91E63' },
{ type: 'Document', color: '#4CAF50' },
{ type: 'Group', color: '#2196F3' },
{ type: 'Other', color: '#FF9800' }
]
// Add legend items
legendItems.forEach((item, i) => {
const legendItem = legend.append('g')
.attr('transform', `translate(0, ${i * 25 + 20})`)
legendItem.append('circle')
.attr('r', 8)
.attr('fill', item.color)
legendItem.append('text')
.attr('x', 15)
.attr('y', 4)
.attr('font-size', '12px')
.text(item.type)
})
// Tick function to update positions
function ticked() {
nodeGroups
.attr('transform', d => `translate(${d.x}, ${d.y})`)
}
// Drag functions
function dragstarted(event, d) {
if (!event.active) simulation.alphaTarget(0.3).restart()
d.fx = d.x
d.fy = d.y
}
function dragged(event, d) {
d.fx = event.x
d.fy = event.y
}
function dragended(event, d) {
if (!event.active) simulation.alphaTarget(0)
d.fx = null
d.fy = null
}
// Function to zoom to fit all nodes
function zoomToFit() {
if (!svg || !zoomBehavior || !graphContent.node()) return
// Get the bounds of the graph content
const bounds = graphContent.node().getBBox()
// Calculate the scale and translation to fit the content
const scale = 0.9 / Math.max(
bounds.width / width,
bounds.height / height
)
const translateX = width / 2 - scale * (bounds.x + bounds.width / 2)
const translateY = height / 2 - scale * (bounds.y + bounds.height / 2)
// Apply the zoom transform
svg.transition()
.duration(750)
.call(
zoomBehavior.transform,
d3.zoomIdentity
.translate(translateX, translateY)
.scale(scale)
)
}
// Auto zoom to fit after the simulation has stabilized
simulation.on('end', zoomToFit)
// Also call zoomToFit after a timeout to ensure it happens even if simulation doesn't end
setTimeout(zoomToFit, 1000)
}
// CLI functions
function executeCLICommand(command) {
const historyElement = document.getElementById('cli-history')
const outputElement = document.getElementById('cli-output')
// Add command to history
const commandElement = document.createElement('div')
commandElement.className = 'cli-command'
commandElement.innerHTML = `<span class="cli-prompt">brainy$</span> ${command}`
historyElement.appendChild(commandElement)
// Simulate command execution
let output = ''
switch (command.split(' ')[0]) {
case 'help':
output = `Available commands:
init Initialize a new database
add <data> Add data to the database
search <q> Search for entities
relate <f> <t> Create relationships
export Export database
status Show database status
clear Clear the terminal
help Show this help message`
break
case 'status':
output = database ?
'Database: Initialized\nStorage: OPFS\nEntities: Available\nAugmentations: Active' :
'Database: Not initialized\nRun "brainy init" to get started'
break
case 'init':
output = 'Initializing database...\nDatabase initialized successfully!'
if (!database) {
initializeDatabase()
}
break
case 'query':
output = database ?
'Querying database...\nFound entities matching your criteria' :
'Error: Database not initialized'
break
default:
output = `Unknown command: ${command}\nType "help" for available commands`
}
outputElement.textContent = output
// Scroll to bottom
const terminal = document.querySelector('.cli-terminal')
terminal.scrollTop = terminal.scrollHeight
}
function clearTerminal() {
document.getElementById('cli-history').innerHTML = ''
document.getElementById('cli-output').textContent = ''
}
// Feature demonstration functions
function demonstrateFeature(feature) {
const resultsContainer = document.getElementById('feature-demo-results')
switch (feature) {
case 'hnsw':
resultsContainer.innerHTML = `
<h4>🔍 HNSW Vector Search Demo</h4>
<p>Hierarchical Navigable Small World (HNSW) is an efficient algorithm for approximate nearest neighbor search.</p>
<div class="code-block">
// Initialize HNSW index
const index = new HNSWIndex(dimension: 384);
// Add vectors
index.addVector(vector1, 'doc1');
index.addVector(vector2, 'doc2');
// Search for similar vectors
const results = index.search(queryVector, k: 10);
</div>
<p><strong>Performance:</strong> O(log N) search time, ideal for large-scale vector databases.</p>
`
break
case 'graph-traversal':
resultsContainer.innerHTML = `
<h4>🌐 Graph Traversal Demo</h4>
<p>Explore relationships and paths through your data graph.</p>
<div class="code-block">
// Find shortest path between entities
const path = await brainy.findPath('entity1', 'entity2');
// Get all neighbors within 2 hops
const neighbors = await brainy.getNeighbors('entity1', { depth: 2 });
// Traverse by relationship type
const related = await brainy.traverse('entity1', 'RELATED_TO');
</div>
<p><strong>Algorithms:</strong> BFS, DFS, shortest path, centrality measures.</p>
`
break
case 'embedding':
resultsContainer.innerHTML = `
<h4>🧠 Embedding Pipeline Demo</h4>
<p>Automatic text-to-vector conversion using pre-trained models.</p>
<div class="code-block">
// Configure embedding pipeline
const pipeline = new EmbeddingPipeline({
model: 'universal-sentence-encoder',
dimension: 512
});
// Process text automatically
const result = await pipeline.process({
text: "Machine learning is transforming technology",
id: "ml-article"
});
// Vector is automatically generated and indexed
console.log(result.vector.length); // 512
</div>
<p><strong>Models:</strong> Universal Sentence Encoder, BERT, custom embeddings.</p>
`
break
case 'realtime':
resultsContainer.innerHTML = `
<h4>📊 Real-time Updates Demo</h4>
<p>Live data synchronization and event streaming.</p>
<div class="code-block">
// Listen for real-time updates
brainy.on('entity:added', (entity) => {
console.log('New entity:', entity.id);
updateVisualization();
});
brainy.on('relationship:created', (relationship) => {
console.log('New relationship:', relationship);
updateGraph();
});
// Subscribe to search result changes
brainy.subscribeToQuery('AI articles', (results) => {
updateSearchResults(results);
});
</div>
<p><strong>Features:</strong> WebSocket support, event streaming, reactive queries.</p>
`
break
case 'storage':
resultsContainer.innerHTML = `
<h4>💾 Storage Backends Demo</h4>
<p>Compare different storage options and their characteristics.</p>
<div class="code-block">
// Memory storage (fastest)
const memoryDB = new BrainyData({
storage: { type: 'memory' }
});
// File system storage (persistent)
const fileDB = new BrainyData({
storage: {
type: 'filesystem',
path: './data'
}
});
// Cloud storage (scalable)
const cloudDB = new BrainyData({
storage: {
type: 's3',
bucket: 'my-brainy-data',
region: 'us-east-1'
}
});
</div>
<p><strong>Options:</strong> Memory, FileSystem, S3, Azure Blob, custom adapters.</p>
`
break
case 'typescript':
resultsContainer.innerHTML = `
<h4>🔧 TypeScript Integration Demo</h4>
<p>Full type safety with comprehensive TypeScript definitions.</p>
<div class="code-block">
// Define your data types
interface Article {
id: string;
title: string;
content: string;
tags: string[];
publishedAt: Date;
}
// Type-safe database operations
const brainy = new BrainyData&lt;Article&gt;();
// TypeScript ensures type safety
const article: Article = {
id: 'article-1',
title: 'AI in 2024',
content: 'The future of AI...',
tags: ['AI', 'technology'],
publishedAt: new Date()
};
// Compile-time type checking
const results = await brainy.search&lt;Article&gt;('AI trends');
</div>
<p><strong>Benefits:</strong> IntelliSense, compile-time errors, better IDE support.</p>
`
break
}
}
// Simulation functions for augmentations
async function simulateTextEmbedding(text) {
await new Promise(resolve => setTimeout(resolve, 1000))
const vector = Array.from({ length: 384 }, () => Math.random() * 2 - 1)
const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0))
return `Text Embedding Results:
Input: "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"
Vector dimension: 384
Magnitude: ${magnitude.toFixed(6)}
Sample values: [${vector.slice(0, 5).map(v => v.toFixed(4)).join(', ')}...]
The text has been successfully converted to a 384-dimensional vector suitable for semantic search and similarity calculations.`
}
async function simulateImageEncoding(content) {
await new Promise(resolve => setTimeout(resolve, 1200))
return `Image Encoding Results:
Input: Image data or URL
Encoding: Base64 with compression
Size reduction: ~75%
Format: Optimized for embedding storage
The image has been encoded and optimized for storage in the vector database.`
}
async function simulateSentimentAnalysis(text) {
await new Promise(resolve => setTimeout(resolve, 800))
const sentiments = ['positive', 'negative', 'neutral']
const sentiment = sentiments[Math.floor(Math.random() * sentiments.length)]
const confidence = Math.random() * 0.5 + 0.5
return `Sentiment Analysis Results:
Input: "${text.substring(0, 100)}${text.length > 100 ? '...' : ''}"
Sentiment: ${sentiment.toUpperCase()}
Confidence: ${(confidence * 100).toFixed(1)}%
Polarity: ${(Math.random() * 2 - 1).toFixed(3)}
The text has been analyzed for emotional tone and sentiment indicators.`
}
async function simulateEntityExtraction(text) {
await new Promise(resolve => setTimeout(resolve, 900))
const entities = [
{ text: 'Machine Learning', type: 'TECHNOLOGY', start: 0, end: 16 },
{ text: 'AI', type: 'TECHNOLOGY', start: 20, end: 22 },
{ text: 'neural networks', type: 'CONCEPT', start: 35, end: 50 }
]
let result = `Entity Extraction Results:
Input: "${text.substring(0, 100)}${text.length > 100 ? '...' : ''}"
Extracted Entities:
`
entities.forEach(entity => {
result += `- ${entity.text} (${entity.type})\n`
})
result += `\nTotal entities found: ${entities.length}`
return result
}
// Utility functions
function log(elementId, message) {
const element = document.getElementById(elementId)
if (element) {
element.textContent = message
element.scrollTop = element.scrollHeight
}
}
function showError(message) {
console.error(message)
const errorDiv = document.createElement('div')
errorDiv.style.cssText = 'background-color: #f44336; color: white; padding: 15px; margin: 10px 0; border-radius: 8px;'
errorDiv.textContent = 'Error: ' + message
document.querySelector('.container').insertBefore(errorDiv, document.querySelector('.container').firstChild)
setTimeout(() => {
errorDiv.remove()
}, 5000)
}
</script>
</body>
</html>