Semantica HybridSearch Architecture: Vector and Graph Retrieval Explained

Semantica's HybridSearch orchestrates vector similarity searches with metadata filtering and Reciprocal Rank Fusion to deliver unified results from both dense embeddings and graph-structured knowledge.

The semantica-agi/semantica repository implements a modular HybridSearch architecture that unifies dense vector retrieval with graph-aware metadata filtering. This design enables semantic search across embeddings while applying structured constraints from knowledge graphs, making it suitable for complex decision-tracking and multi-hop reasoning scenarios.

Core Architecture Components

The architecture consists of three primary classes that coordinate the hybrid retrieval pipeline.

HybridSearch Orchestrator

The HybridSearch class in semantica/vector_store/hybrid_search.py serves as the central coordinator for the entire hybrid workflow. It abstracts the underlying storage layer, allowing operation on in-memory NumPy arrays or delegation to external vector stores including FAISS, Weaviate, Qdrant, Pinecone, Milvus, and PgVector. The class implements the search() method which executes the full pipeline: applying metadata filters, performing vector similarity searches, and delegating final ranking to a SearchRanker instance.

MetadataFilter for Graph Constraints

The MetadataFilter class implements a builder pattern for constructing expressive metadata predicates such as eq, gt, contains, and in. Located in the same module as HybridSearch, this component evaluates filter conditions against document metadata either before or after the vector search phase. This enables graph-level constraints—such as filtering for specific decision categories or node properties—effectively bridging vector similarity with graph structure.

SearchRanker and Result Fusion

The SearchRanker class handles result fusion from multiple sources or search phases. By default, it implements Reciprocal Rank Fusion (RRF), which merges ranked lists by calculating the sum of 1/(k+rank) scores for each document across all input lists. Alternatively, the ranker supports a Weighted Average strategy that accepts per-source weights for customized result blending.

HybridSimilarityCalculator for Semantic-Structural Fusion

For advanced decision-tracking scenarios, semantica/vector_store/hybrid_similarity.py provides the HybridSimilarityCalculator. This optional component combines dense semantic embeddings with structural graph embeddings (such as Node2Vec) using configurable weights. Higher-level APIs like DecisionQuery.find_precedents_hybrid() leverage this calculator to perform hybrid similarity scoring that considers both content meaning and graph topology.

Data Flow and Execution Pipeline

The hybrid retrieval process follows a strict seven-stage pipeline:

  1. Query Input – Accepts either a raw text string or a pre-computed NumPy vector.

  2. Embedding Generation – If the query is text, HybridSearch lazily instantiates an EmbeddingGenerator to produce the query vector.

  3. Metadata Filtering – The MetadataFilter predicates are evaluated against stored metadata; when using backend stores, filtering occurs after the backend returns raw results.

  4. Vector Similarity Search – Executes either in-memory cosine similarity via _vector_search or delegates to vector_store.search_vectors for backend-specific ANN algorithms (FAISS IVF/HNSW, Qdrant, etc.).

  5. Result Enrichment – Matching metadata is attached to each result record, including graph-derived fields.

  6. Fusion and Ranking – Intermediate result lists are passed to SearchRanker.rank(), which applies RRF or weighted strategies to produce a single ranked list limited to k items.

  7. Result Return – Returns a list of dictionaries containing id, score, distance, and metadata fields.

Knowledge Graph Integration

The hybrid architecture deeply integrates with Semantica's knowledge graph through metadata enrichment. Document metadata can include graph-derived fields such as decision categories, timestamps, and references to specific graph nodes. The DecisionQuery class in semantica/context/decision_query.py builds upon HybridSearch and HybridSimilarityCalculator to retrieve decision precedents using both semantic content and structural graph position. Additionally, graph analytics such as PageRank, community detection, and centrality measures can influence final ranking scores through custom weighting in DecisionQuery._calculate_combined_similarity or via the SearchRanker configuration.

Practical Implementation Examples

Basic Hybrid Search with Metadata Filtering

The following example demonstrates filtering for finance documents created after 2020, then performing semantic search:

from semantica.vector_store import HybridSearch, MetadataFilter

# Create a filter: category = "finance" and year > 2020

filter = MetadataFilter().eq("category", "finance").gt("year", 2020)

# Initialise the search (optionally pass a specific vector store)

search = HybridSearch()                       # uses default in‑memory store

results = search.search(
    query="loan approval decision",            # can be a string or np.ndarray

    vectors=my_vectors,                       # list or np.ndarray of stored vectors

    metadata=my_metadata,                     # list of dicts aligned with vectors

    vector_ids=my_ids,                        # optional IDs

    k=10,
    metadata_filter=filter
)

for r in results:
    print(r["id"], r["score"], r["metadata"]["category"])

Multi-Source Retrieval with Reciprocal Rank Fusion

When querying across multiple vector stores or indices, use SearchRanker to fuse results:

from semantica.vector_store import HybridSearch, SearchRanker

search = HybridSearch()
ranker = SearchRanker(strategy="reciprocal_rank_fusion")

# Assume we have two separate vector stores (e.g., FAISS and Qdrant)

source1 = {"vectors": vecs_a, "metadata": meta_a, "ids": ids_a}
source2 = {"vectors": vecs_b, "metadata": meta_b, "ids": ids_b}

# Perform hybrid search on each source

results1 = search.search(query_vec, **source1, k=20)
results2 = search.search(query_vec, **source2, k=20)

# Fuse the two ranked lists

fused = ranker.rank([results1, results2], k=10)

Decision-Precedent Retrieval with Combined Similarity

For retrieving similar decisions using both semantic and structural graph features:

from semantica.context.decision_query import DecisionQuery

dq = DecisionQuery(
    graph_store=my_kg,
    vector_store=my_vector_store,
    embedding_generator=my_emb_gen
)

precedents = dq.find_precedents_hybrid(
    scenario="Loan applicant denied due to credit score",
    category="mortgage",
    limit=5,
    similarity_weights={"semantic": 0.6, "structural": 0.3, "text": 0.1}
)

for d in precedents:
    print(d.decision_id, d.metadata["similarity_score"])

Extensibility and Backend Support

The architecture supports seamless extension through well-defined interfaces. New vector store backends integrate by implementing the VectorStore interface; HybridSearch automatically discovers these via the global method_registry. Developers can introduce custom fusion strategies by extending the SearchRanker class, or add new metadata operators by subclassing MetadataFilter.add_condition. This plugin-based approach ensures the hybrid search pipeline adapts to evolving retrieval requirements without modifying core orchestration logic.

Summary

  • Modular Design: The architecture separates concerns across HybridSearch, MetadataFilter, and SearchRanker, enabling independent optimization of retrieval, filtering, and ranking components.
  • Flexible Backends: Supports both in-memory cosine similarity and external ANN libraries (FAISS, Weaviate, Qdrant, Pinecone, Milvus, PgVector) through a unified interface.
  • Graph-Aware Filtering: Metadata predicates enable graph-structured constraints to constrain vector searches without requiring joint embedding spaces.
  • Advanced Fusion: Reciprocal Rank Fusion provides robust result merging across multiple sources, while HybridSimilarityCalculator enables fine-grained semantic-structural weighting for decision intelligence.

Frequently Asked Questions

How does Semantica's HybridSearch combine vector and graph retrieval?

The system combines these modalities through metadata bridging. Vector embeddings provide semantic similarity scores, while the MetadataFilter applies graph-derived constraints (such as node categories or relationship properties) to the result set. For deeper integration, the HybridSimilarityCalculator fuses dense semantic embeddings with structural graph embeddings (like Node2Vec) using configurable weights, enabling retrieval that considers both content meaning and topological graph position.

What ranking algorithms does the SearchRanker support?

The SearchRanker implements two primary strategies: Reciprocal Rank Fusion (RRF), which is the default and calculates document scores as the sum of 1/(k+rank) across all input lists, and Weighted Average, which allows explicit per-source weighting for linear combination of relevance scores. Both strategies operate on the intermediate result lists produced by HybridSearch and can be extended for custom fusion logic.

Can HybridSearch operate with existing vector databases?

Yes, the architecture abstracts storage through the VectorStore interface, enabling integration with FAISS, Weaviate, Qdrant, Pinecone, Milvus, and PgVector. When configured with a backend store, HybridSearch delegates the approximate nearest neighbor search to the backend's native algorithm (such as HNSW or IVF), then applies metadata filtering and result fusion on the returned candidates.

What is the difference between HybridSearch and HybridSimilarityCalculator?

HybridSearch is the high-level orchestration class that coordinates vector retrieval, metadata filtering, and result ranking across entire document collections. In contrast, HybridSimilarityCalculator is a specialized utility in semantica/vector_store/hybrid_similarity.py that computes combined similarity scores between individual pairs of items using both semantic embeddings and structural graph features. The calculator is typically used by higher-level APIs like DecisionQuery.find_precedents_hybrid() for fine-grained precedent matching, while HybridSearch handles broad-scale retrieval operations.

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 →