Module: SwarmSDK::V3::Memory::Adapters::FaissSupport

Included in:
FilesystemAdapter
Defined in:
lib/swarm_sdk/v3/memory/adapters/faiss_support.rb

Overview

Shared FAISS vector index support for adapters

Provides FAISS-based vector search and index management that can be included by any adapter that stores embeddings as Ruby arrays. The FAISS index (IndexFlatIP with L2-normalized vectors) handles efficient top-k nearest neighbor search.

## Requirements for including classes

The including class must:

  • Call #initialize_faiss! from its constructor

  • Define a ‘faiss_directory` method returning the path for FAISS files

  • Implement ‘list_cards` (used by #rebuild_index)

Examples:

Including in a custom adapter

class MyAdapter < Base
  include VectorUtils    # pairwise similarity
  include FaissSupport   # FAISS vector index

  def initialize(directory)
    super()
    @directory = directory
    initialize_faiss!
  end

  private

  def faiss_directory
    @directory
  end
end

Constant Summary collapse

EMBEDDING_DIMENSIONS =

Embedding dimensions for MiniLM-L6-v2 model

384

Instance Method Summary collapse

Instance Method Details

#rebuild_indexvoid

This method returns an undefined value.

Rebuild the FAISS index from all stored cards



80
81
82
83
84
85
86
87
88
# File 'lib/swarm_sdk/v3/memory/adapters/faiss_support.rb', line 80

def rebuild_index
  @faiss_index = create_faiss_index
  @id_to_index = {}
  @next_index_id = 0

  list_cards.each do |card|
    add_to_vector_index(card) if card.embedding
  end
end

#vector_search(embedding, top_k:, threshold: 0.0) ⇒ Array<Hash>

Search the FAISS index for similar vectors

Parameters:

  • embedding (Array<Float>)

    Query embedding

  • top_k (Integer)

    Maximum number of results

  • threshold (Float) (defaults to: 0.0)

    Minimum cosine similarity to include

Returns:

  • (Array<Hash>)

    Array of ‘{ id: String, similarity: Float }`



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/swarm_sdk/v3/memory/adapters/faiss_support.rb', line 48

def vector_search(embedding, top_k:, threshold: 0.0)
  return [] unless @faiss_index && @faiss_index.ntotal > 0

  normalized = normalize_vector(embedding)
  effective_k = [top_k, @faiss_index.ntotal].min
  # Explicit Numo conversion for safe FAISS C extension boundary crossing
  query_vector = Numo::SFloat.cast([normalized])
  distances, ids = @faiss_index.search(query_vector, effective_k)

  index_to_id = @id_to_index.invert
  # FAISS returns Numo::NArray — convert to Ruby arrays
  id_row = ids.to_a.flatten
  dist_row = distances.to_a.flatten
  results = []
  id_row.each_with_index do |idx, i|
    next if idx < 0

    card_id = index_to_id[idx]
    next unless card_id

    similarity = dist_row[i]
    next if similarity < threshold

    results << { id: card_id, similarity: similarity }
  end

  results
end