Class: Ask::RAG::VectorStore::InMemory

Inherits:
VectorStore
  • Object
show all
Defined in:
lib/ask/rag/vector_store/in_memory.rb

Overview

In-memory vector store using cosine similarity.

Stores all documents and vectors in a Ruby Hash. Uses pure Ruby for cosine similarity — no external dependencies. Suitable for development, testing, and small-scale prototypes.

Examples:

store = Ask::RAG::VectorStore::InMemory.new
store.add(chunks, model: "text-embedding-3-small")
results = store.similarity_search("query", limit: 5)

With metadata filtering

results = store.similarity_search(
  "query",
  limit: 5,
  filter: { source: "api_docs.md" }
)

With MMR (diversified results)

results = store.similarity_search(
  "query",
  limit: 5,
  mmr: true,
  diversity_bonus: 0.5
)

Defined Under Namespace

Classes: Entry

Instance Method Summary collapse

Constructor Details

#initializeInMemory

Returns a new instance of InMemory.



35
36
37
38
39
40
# File 'lib/ask/rag/vector_store/in_memory.rb', line 35

def initialize
  @entries = {}
  @mutex = Mutex.new
  @embedding_model = nil
  @embedding_dimensions = nil
end

Instance Method Details

#add(documents, model:, batch_size: 20) ⇒ Array<String>

Add documents to the store.

Parameters:

  • documents (Array<Ask::Document>)

    documents to add

  • model (String)

    embedding model name

  • batch_size (Integer) (defaults to: 20)

    texts per embed API call

Returns:

  • (Array<String>)

    IDs of added documents



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/ask/rag/vector_store/in_memory.rb', line 48

def add(documents, model:, batch_size: 20)
  ids = documents.map { |d| d.id || SecureRandom.uuid }
  provider = resolve_embedding_provider(model)

  @embedding_model = model

  documents.each_slice(batch_size).flat_map do |batch|
    texts = batch.map(&:content)
    raw_vectors = provider.embed(texts, model: model)
    vectors = normalize_vectors(raw_vectors, texts)

    @mutex.synchronize do
      batch.each_with_index.map do |doc, idx|
        entry_id = ids[documents.index(doc)]
        @entries[entry_id] = Entry.new(
          id: entry_id,
          document: doc,
          vector: vectors[idx]
        )
        entry_id
      end
    end
  end
end

#clearObject



123
124
125
# File 'lib/ask/rag/vector_store/in_memory.rb', line 123

def clear
  @mutex.synchronize { @entries.clear }
end

#delete(ids) ⇒ Object



117
118
119
120
121
# File 'lib/ask/rag/vector_store/in_memory.rb', line 117

def delete(ids)
  @mutex.synchronize do
    ids.each { |id| @entries.delete(id) }
  end
end

#similarity_search(query, limit: 10, filter: nil, mmr: false, diversity_bonus: 0.3) ⇒ Array<Ask::Document>

Search for documents similar to the query.

Parameters:

  • query (String)

    the query text

  • limit (Integer) (defaults to: 10)

    maximum results (default: 10)

  • filter (Hash, nil) (defaults to: nil)

    metadata filter — only entries whose metadata matches all key/value pairs are considered

  • mmr (Boolean) (defaults to: false)

    apply Max Marginal Relevance for diversity

  • diversity_bonus (Float) (defaults to: 0.3)

    MMR diversity factor (0 = pure relevance, 1 = pure diversity)

Returns:

  • (Array<Ask::Document>)

    documents with :score and :mmr_score in metadata



82
83
84
85
86
# File 'lib/ask/rag/vector_store/in_memory.rb', line 82

def similarity_search(query, limit: 10, filter: nil, mmr: false, diversity_bonus: 0.3)
  query_vector = embed_query
  search_by_vector(query_vector, limit: limit, filter: filter,
                   mmr: mmr, diversity_bonus: diversity_bonus)
end

#similarity_search_by_vector(vector, limit: 10, filter: nil) ⇒ Object



88
89
90
# File 'lib/ask/rag/vector_store/in_memory.rb', line 88

def similarity_search_by_vector(vector, limit: 10, filter: nil)
  search_by_vector(vector, limit: limit, filter: filter)
end

#sizeObject



127
128
129
# File 'lib/ask/rag/vector_store/in_memory.rb', line 127

def size
  @mutex.synchronize { @entries.size }
end