Class: SwarmSDK::V3::Memory::Retriever

Inherits:
Object
  • Object
show all
Defined in:
lib/swarm_sdk/v3/memory/retriever.rb

Overview

Hybrid search retriever combining semantic and keyword search

Uses reciprocal rank fusion (RRF) to combine results from:

  1. Semantic search via FAISS vector similarity

  2. Keyword search via text matching

  3. Graph expansion via 1-hop edge traversal

Examples:

retriever = Retriever.new(adapter: adapter, embedder: embedder)
results = retriever.search("JWT authentication", top_k: 10)

Instance Method Summary collapse

Constructor Details

#initialize(adapter:, embedder:, semantic_weight: 0.5, keyword_weight: 0.5) ⇒ Retriever

Returns a new instance of Retriever.

Parameters:

  • adapter (Adapters::Base)

    Storage adapter

  • embedder (Embedder)

    Text embedder

  • semantic_weight (Float) (defaults to: 0.5)

    Weight for semantic results (0.0-1.0)

  • keyword_weight (Float) (defaults to: 0.5)

    Weight for keyword results (0.0-1.0)



21
22
23
24
25
26
27
# File 'lib/swarm_sdk/v3/memory/retriever.rb', line 21

def initialize(adapter:, embedder:, semantic_weight: 0.5, keyword_weight: 0.5)
  @adapter = adapter
  @embedder = embedder
  @semantic_weight = semantic_weight
  @keyword_weight = keyword_weight
  @config = Configuration.instance
end

Instance Method Details

#search(query, top_k: 15) ⇒ Array<Card>

Search for relevant memory cards

Examples:

cards = retriever.search("How does auth work?", top_k: 10)

Parameters:

  • query (String)

    Search query

  • top_k (Integer) (defaults to: 15)

    Number of results to return

Returns:

  • (Array<Card>)

    Ranked cards



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/swarm_sdk/v3/memory/retriever.rb', line 37

def search(query, top_k: 15)
  DebugLog.log("retriever", "search: query=#{query[0..60].inspect}, top_k=#{top_k}")

  semantic_results = DebugLog.time("retriever", "semantic_search(#{top_k * 2})") do
    semantic_search(query, top_k: top_k * 2)
  end

  keyword_results = DebugLog.time("retriever", "keyword_search(#{top_k * 2})") do
    keyword_search(query, top_k: top_k * 2)
  end

  DebugLog.log("retriever", "semantic=#{semantic_results.size} keyword=#{keyword_results.size}")

  # Reciprocal rank fusion
  fused = DebugLog.time("retriever", "rrf") do
    reciprocal_rank_fusion(semantic_results, keyword_results)
  end

  # Graph expansion: add 1-hop neighbors of top results
  expanded = DebugLog.time("retriever", "graph_expand") do
    graph_expand(fused.take(top_k), top_k: top_k)
  end

  DebugLog.log("retriever", "fused=#{fused.size} expanded=#{expanded.size} returning=#{[expanded.size, top_k].min}")

  # Return unique cards, limited to top_k
  expanded.take(top_k)
end