Skip to main content

Overview

Neode supports semantic search using vector embeddings. Instead of matching exact keywords, semantic search finds content based on meaning and context.

How It Works

  1. Embedding Generation: Text is converted into a vector (array of numbers) that captures its meaning
  2. Similarity Search: Vectors are compared to find semantically similar content
  3. Results: Returns triples and entities with similar meaning to your query

Generating Embeddings

Convert text to embeddings for semantic search:

Single Embedding

curl -X POST "https://neode.ai/api/embeddings" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "values": "electric vehicle manufacturer",
    "type": "single"
  }'
Response:
{
  "success": true,
  "embedding": [0.123, -0.456, 0.789, ...],
  "usage": {
    "prompt_tokens": 4,
    "total_tokens": 4
  }
}

Batch Embeddings

Generate multiple embeddings at once:
curl -X POST "https://neode.ai/api/embeddings" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "values": ["Tesla", "SpaceX", "electric cars"],
    "type": "batch"
  }'
Response:
{
  "success": true,
  "embeddings": [
    [0.123, -0.456, ...],
    [0.234, -0.567, ...],
    [0.345, -0.678, ...]
  ],
  "usage": {
    "prompt_tokens": 8,
    "total_tokens": 8
  }
}

Semantic Search in the UI

The Neode web interface at neode.ai/explore uses semantic search:
  1. Enter a natural language query
  2. The system finds entities and triples with similar meaning
  3. Results are ranked by semantic similarity

Step 1: Generate Query Embedding

const queryResponse = await fetch('https://neode.ai/api/embeddings', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'
  },
  body: JSON.stringify({
    values: 'companies making electric cars',
    type: 'single'
  })
});

const { embedding: queryEmbedding } = await queryResponse.json();

Step 2: Compare with Stored Embeddings

Entities and triples in Neode have pre-computed embeddings. You can:
  1. Use the explore page: neode.ai/explore handles this automatically
  2. Build custom search: Store embeddings in a vector database and query with cosine similarity

Step 3: Rank Results

Sort results by similarity score (higher = more similar):
function cosineSimilarity(a, b) {
  let dotProduct = 0;
  let normA = 0;
  let normB = 0;
  
  for (let i = 0; i < a.length; i++) {
    dotProduct += a[i] * b[i];
    normA += a[i] * a[i];
    normB += b[i] * b[i];
  }
  
  return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
}

// Rank results
const rankedResults = results
  .map(r => ({
    ...r,
    similarity: cosineSimilarity(queryEmbedding, r.embedding)
  }))
  .sort((a, b) => b.similarity - a.similarity);

Embedding Model

Neode uses a 256-dimension embedding model optimized for knowledge graph content:
PropertyValue
Dimensions256
ModelOpenAI text-embedding
NormalizationL2 normalized

Use Cases

Search for entities related to a concept:
# Generate embedding for "renewable energy"
curl -X POST "https://neode.ai/api/embeddings" \
  -d '{"values": "renewable energy companies", "type": "single"}'

# Then use the embedding to find similar entities in your database

Question Answering

Find triples that answer a question:
# Query: "Who founded SpaceX?"
# Embedding of this question will be similar to triples like:
# "SpaceX" → "founded_by" → "Elon Musk"

Concept Exploration

Discover related concepts:
# Start with "artificial intelligence"
# Find related: "machine learning", "neural networks", "deep learning"

Duplicate Detection

Find potentially duplicate entities:
# Generate embeddings for all entity names
# Find pairs with high similarity scores
# "Tesla, Inc." and "Tesla Motors" would have high similarity

Best Practices

Embedding Quality

For best results, embed meaningful text:
// Good - descriptive
{
  "values": "Tesla electric vehicle manufacturer Elon Musk"
}

// Less effective - single word
{
  "values": "Tesla"
}

Caching

Embeddings are deterministic. Cache them to avoid repeated API calls:
const embeddingCache = new Map();

async function getEmbedding(text) {
  if (embeddingCache.has(text)) {
    return embeddingCache.get(text);
  }
  
  const response = await fetch('/api/embeddings', {
    method: 'POST',
    body: JSON.stringify({ values: text, type: 'single' })
  });
  
  const { embedding } = await response.json();
  embeddingCache.set(text, embedding);
  return embedding;
}

Batch for Efficiency

When embedding multiple items, use batch mode:
{
  "values": ["text1", "text2", "text3", ...],
  "type": "batch"
}
This is faster and uses fewer API calls than individual requests.

API Reference

See the complete Embeddings API documentation.