How Fuzzy Search Differs from Semantic Search in the Egonex Knowledge Graph

Fuzzy search in Egonex uses Fuse.js for approximate string matching against node text fields, while semantic search computes cosine similarity between dense vector embeddings to capture conceptual meaning.

The Egonex Understand-Anything plugin provides two distinct search modes for exploring the knowledge graph. Understanding how fuzzy search differs from semantic search in the Egonex knowledge graph helps developers choose the right approach for typo-tolerant lookups versus meaning-based discovery. Both engines are implemented in the core package, but they differ fundamentally in algorithms, data requirements, and use cases.

Algorithmic Foundations

The two search modes employ fundamentally different approaches to matching queries against graph nodes.

Fuzzy Search Implementation

Fuzzy search relies on Fuse.js to perform approximate string matching. The engine tokenizes the query, builds an extended "OR" query (e.g., converting auth contrl into auth | contrl), and scores results by textual similarity. This approach indexes the node fields name, tags, summary, and languageNotes with descending weights (0.4 → 0.1) according to the source code in packages/core/src/search.ts.

The search method returns a list of {nodeId, score} objects where score represents the Fuse-derived relevance (0 indicates a perfect match). This method requires no pre-computed embeddings and operates purely on textual data present in the graph.

Semantic Search Implementation

Semantic search computes cosine similarity between dense vector embeddings of graph nodes and the query embedding. Implemented in packages/core/src/embedding-search.ts, the custom SemanticSearchEngine stores node embeddings in a Map structure and calculates similarity using the cosineSimilarity function (lines 14-30).

Unlike fuzzy matching, this approach captures semantic relationships, synonyms, and paraphrases by comparing high-dimensional vectors. The engine returns the top-k nodes whose similarity exceeds a configurable threshold, enabling discovery of conceptually related nodes that share little lexical overlap.

Implementation Details and File Structure

The architecture separates concerns between text-based and vector-based search:

File Purpose
packages/core/src/search.ts Implements the fuzzy SearchEngine using Fuse.js (lines 14-25, 36-59)
packages/core/src/embedding-search.ts Implements SemanticSearchEngine and cosineSimilarity for vector-based search (lines 14-30, 37-78)
packages/dashboard/src/store.ts Holds the UI state (searchMode), creates the appropriate engine, and dispatches searches (lines 111-112, 519-531)
packages/dashboard/src/components/SearchBar.tsx UI component that lets the user type a query and switch between fuzzy/semantic modes (lines 217-289)

Data Requirements and Performance Characteristics

Each search mode presents distinct trade-offs in data preparation and computational overhead.

Fuzzy Search Advantages and Limitations

Strengths:

  • Fast, deterministic execution with no external model dependencies
  • Excellent for exact-ish name and tag lookups with typo tolerance
  • Zero preprocessing required—works immediately on graph text fields

Limitations:

  • Cannot capture relationships not expressed in searchable strings
  • Scores derive from string distance metrics, not semantic meaning
  • Misses conceptual connections between synonyms or related terms

Semantic Search Advantages and Limitations

Strengths:

  • Captures semantic similarity across languages and paraphrases
  • Surfaces conceptually related nodes despite minimal lexical overlap
  • Enables discovery based on meaning rather than exact text matching

Limitations:

  • Requires embedding generation, incurring computational cost
  • Quality depends entirely on the embedding model
  • Empty or low-quality embeddings produce poor or irrelevant results

Runtime Switching and UI Integration

The dashboard implements a runtime toggle between these modes using Zustand state management. In packages/dashboard/src/store.ts (lines 111-112), the store maintains searchMode: "fuzzy" | "semantic" with "fuzzy" as the default.

When users switch modes via the search bar UI (packages/dashboard/src/components/SearchBar.tsx), the application instantiates the appropriate engine. For semantic mode, the dashboard creates a SemanticSearchEngine instance (if embeddings exist) and calls its .search method; otherwise, it falls back to the fuzzy SearchEngine.

Practical Code Examples

Fuzzy Search Implementation

import { SearchEngine } from "@understand-anything/core/search";

// `graph.nodes` is an array of GraphNode objects.
const fuzzyEngine = new SearchEngine(graph.nodes);

// Basic query – fuzzy-matches name / summary / tags.
const fuzzyResults = fuzzyEngine.search("auth contrl", {
  limit: 10,
  types: ["function"], // optional filter
});

Semantic Search Implementation

import {
  SemanticSearchEngine,
  cosineSimilarity,
} from "@understand-anything/core/embedding-search";

// `embeddings` is a Record<string, number[]> keyed by node ID.
const semanticEngine = new SemanticSearchEngine(graph.nodes, embeddings);

// Assume `queryEmbedding` is obtained from an LLM for the user query.
const semanticResults = semanticEngine.search(queryEmbedding, {
  limit: 10,
  threshold: 0.6,          // only return > 60% similarity
  types: ["function"],     // optional node-type filter
});

Toggle Implementation in Dashboard Store

// ... in the Zustand store definition
searchMode: "fuzzy", // default

// Switch mode (e.g. from UI)
setSearchMode: (mode) => set({ searchMode: mode }),

// When performing a search:
const engine = get().searchEngine!;
const mode = get().searchMode;

if (mode === "semantic" && engine instanceof SemanticSearchEngine) {
  const results = engine.search(queryEmbedding);
  // …
} else {
  const results = engine.search(queryString);
  // …
}

Summary

  • Fuzzy search in packages/core/src/search.ts uses Fuse.js for approximate string matching against node text fields (name, tags, summary, languageNotes), providing fast, typo-tolerant results without requiring embeddings.
  • Semantic search in packages/core/src/embedding-search.ts implements vector-based cosine similarity comparison to capture conceptual meaning, requiring pre-computed embeddings but enabling cross-lingual and synonym-aware discovery.
  • The dashboard store (packages/dashboard/src/store.ts) manages runtime switching between modes via Zustand, defaulting to fuzzy search for immediate results while allowing semantic mode for deeper meaning-based exploration.
  • Algorithmic choice depends on use case: fuzzy for exact lookups with tolerance for typos, semantic for conceptual relationships and language-agnostic similarity.

Frequently Asked Questions

How does the Egonex knowledge graph handle the transition between fuzzy and semantic search modes?

The transition occurs through the Zustand store defined in packages/dashboard/src/store.ts. The store maintains a searchMode state that toggles between "fuzzy" and "semantic" values. When the mode changes, the application instantiates the appropriate engine—either the Fuse.js-based SearchEngine or the vector-based SemanticSearchEngine—and routes queries accordingly, allowing seamless switching without page reloads.

What specific fields does the fuzzy search engine index in the Egonex knowledge graph?

According to the implementation in packages/core/src/search.ts, the fuzzy search engine indexes four specific node fields: name (weight 0.4), tags (weight 0.3), summary (weight 0.2), and languageNotes (weight 0.1). These descending weights ensure that matches in node names rank higher than matches in supplementary notes.

Why might semantic search return poor results in the Egonex Understand-Anything plugin?

Semantic search quality depends entirely on the availability and quality of pre-computed embeddings for each graph node. If nodes lack embeddings, were processed with a low-quality model, or contain empty vectors, the cosineSimilarity calculation in packages/core/src/embedding-search.ts cannot establish meaningful relationships. Additionally, the configurable threshold (typically 0.6) may filter out results if the query embedding diverges significantly from stored node vectors.

Can I use both search modes simultaneously in the Egonex dashboard?

The current implementation in packages/dashboard/src/store.ts treats these modes as mutually exclusive via the searchMode state. However, the architecture allows you to instantiate both SearchEngine and SemanticSearchEngine concurrently in custom implementations, merging results from both fuzzyEngine.search() and semanticEngine.search() calls to create hybrid ranking systems.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →