Class: SwarmSDK::V3::Memory::Adapters::Base
- Inherits:
-
Object
- Object
- SwarmSDK::V3::Memory::Adapters::Base
- Defined in:
- lib/swarm_sdk/v3/memory/adapters/base.rb
Overview
Abstract adapter interface for memory storage
Defines the contract that all storage backends must satisfy. SDK users can implement custom adapters (e.g., Postgres + pgvector) by subclassing this and implementing all methods.
## Why adapters own vector operations
The SDK code (ContextBuilder, IngestionPipeline, Retriever, etc.) never computes similarity directly. All vector math goes through the adapter so that each backend can use its native capabilities:
-
FilesystemAdapter: FAISS for indexed search, Ruby cosine similarity (via VectorUtils) for pairwise comparison
-
PgvectorAdapter: ‘<=>` operator for both indexed and pairwise
-
Qdrant/Pinecone: Client API for all similarity operations
There are two distinct vector operations:
### ‘vector_search(embedding, top_k:, threshold:)` Searches an index of card embeddings. Used by the Retriever for semantic search and by the Consolidator for dedup/conflict detection. The filesystem adapter uses FAISS for this. A pgvector adapter would use `ORDER BY embedding <=> query LIMIT k`.
### ‘similarity(embedding_a, embedding_b)` Computes pairwise similarity between **two arbitrary vectors**. This is needed when comparing vectors that aren’t both in the card index — for example:
-
Card embedding vs. cluster centroid (clusters aren’t indexed)
-
Two cards already in hand during dedup in the ContextBuilder
-
Query embedding vs. candidate cards in the exploration sprinkle
FAISS cannot do this — it only supports ‘index.search(, k)`, which searches vectors that have been `add`’d to the index.
For in-memory adapters, include VectorUtils to get a default Ruby implementation. For database adapters, implement it using your backend’s native operator.
## Implementing a custom adapter
Subclass Base and implement every method. Methods that raise NotImplementedError are required. For a starting point, see FilesystemAdapter which implements the full interface.
If your adapter doesn’t have native vector math, include VectorUtils to get a default #similarity implementation:
class MyAdapter < Base
include VectorUtils # provides similarity()
# ... implement the rest
end
Direct Known Subclasses
Instance Method Summary collapse
-
#delete_card(id) ⇒ void
Delete a card by ID.
-
#delete_edges_for(card_id) ⇒ void
Delete all edges involving a card (as source or target).
-
#edges_for(card_id, type: nil) ⇒ Array<Edge>
Get edges for a card (as source or target).
-
#list_cards(prefix: nil) ⇒ Array<Card>
List cards, optionally filtered by ID prefix.
-
#list_cards_for_compression(max_level: 3) ⇒ Array<Card>
List cards eligible for compression.
-
#list_clusters ⇒ Array<Cluster>
List all clusters.
-
#load ⇒ void
Load state from durable storage into memory.
-
#read_card(id) ⇒ Card?
Read a card by ID.
-
#read_cluster(id) ⇒ Cluster?
Read a cluster by ID.
-
#rebuild_index ⇒ void
Rebuild the vector index from all stored cards.
-
#save ⇒ void
Save all in-memory state to durable storage.
-
#similarity(embedding_a, embedding_b) ⇒ Float
Compute similarity between two arbitrary embedding vectors.
-
#transaction { ... } ⇒ Object
Execute a block within a transaction.
-
#vector_search(embedding, top_k:, threshold: 0.0) ⇒ Array<Hash>
Search the card embedding index for similar vectors.
-
#write_card(card) ⇒ void
Write a card to storage (insert or update).
-
#write_cluster(cluster) ⇒ void
Write a cluster to storage (insert or update).
-
#write_edge(edge) ⇒ void
Write an edge to storage.
Instance Method Details
#delete_card(id) ⇒ void
This method returns an undefined value.
Delete a card by ID
117 118 119 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 117 def delete_card(id) raise NotImplementedError, "#{self.class}#delete_card not implemented" end |
#delete_edges_for(card_id) ⇒ void
This method returns an undefined value.
Delete all edges involving a card (as source or target)
169 170 171 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 169 def delete_edges_for(card_id) raise NotImplementedError, "#{self.class}#delete_edges_for not implemented" end |
#edges_for(card_id, type: nil) ⇒ Array<Edge>
Get edges for a card (as source or target)
161 162 163 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 161 def edges_for(card_id, type: nil) raise NotImplementedError, "#{self.class}#edges_for not implemented" end |
#list_cards(prefix: nil) ⇒ Array<Card>
List cards, optionally filtered by ID prefix
125 126 127 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 125 def list_cards(prefix: nil) raise NotImplementedError, "#{self.class}#list_cards not implemented" end |
#list_cards_for_compression(max_level: 3) ⇒ Array<Card>
List cards eligible for compression
Default implementation loads all cards and filters in Ruby. Database adapters should override with a server-side query.
142 143 144 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 142 def list_cards_for_compression(max_level: 3) list_cards.select { |c| c.compression_level <= max_level } end |
#list_clusters ⇒ Array<Cluster>
List all clusters
194 195 196 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 194 def list_clusters raise NotImplementedError, "#{self.class}#list_clusters not implemented" end |
#load ⇒ void
This method returns an undefined value.
Load state from durable storage into memory
290 291 292 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 290 def load raise NotImplementedError, "#{self.class}#load not implemented" end |
#read_card(id) ⇒ Card?
Read a card by ID
109 110 111 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 109 def read_card(id) raise NotImplementedError, "#{self.class}#read_card not implemented" end |
#read_cluster(id) ⇒ Cluster?
Read a cluster by ID
187 188 189 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 187 def read_cluster(id) raise NotImplementedError, "#{self.class}#read_cluster not implemented" end |
#rebuild_index ⇒ void
This method returns an undefined value.
Rebuild the vector index from all stored cards
Called when the index needs to be reconstructed, e.g., after bulk imports or if the index file is missing/corrupted.
254 255 256 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 254 def rebuild_index raise NotImplementedError, "#{self.class}#rebuild_index not implemented" end |
#save ⇒ void
This method returns an undefined value.
Save all in-memory state to durable storage
283 284 285 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 283 def save raise NotImplementedError, "#{self.class}#save not implemented" end |
#similarity(embedding_a, embedding_b) ⇒ Float
Compute similarity between two arbitrary embedding vectors
Used by the SDK for pairwise comparisons where an indexed search doesn’t apply:
-
Card vs. cluster centroid (cluster assignment in IngestionPipeline)
-
Card vs. card (deduplication in ContextBuilder)
-
Query vs. card (exploration sprinkle in ContextBuilder)
For in-memory adapters, include VectorUtils to get a default cosine similarity implementation. For database adapters, implement using your backend’s native operator.
227 228 229 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 227 def similarity(, ) raise NotImplementedError, "#{self.class}#similarity not implemented" end |
#transaction { ... } ⇒ Object
Execute a block within a transaction
The default implementation is a no-op pass-through. Adapters with transactional backends (e.g., SQLite, Postgres) should override this to wrap the block in a real transaction.
274 275 276 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 274 def transaction yield end |
#vector_search(embedding, top_k:, threshold: 0.0) ⇒ Array<Hash>
Search the card embedding index for similar vectors
Used by the SDK for top-k retrieval:
-
Retriever: semantic search for relevant cards
-
Consolidator: finding near-duplicates and conflicts
This searches an index of card embeddings. The adapter decides how to implement the index (FAISS, pgvector, etc.).
244 245 246 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 244 def vector_search(, top_k:, threshold: 0.0) raise NotImplementedError, "#{self.class}#vector_search not implemented" end |
#write_card(card) ⇒ void
This method returns an undefined value.
Write a card to storage (insert or update)
101 102 103 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 101 def write_card(card) raise NotImplementedError, "#{self.class}#write_card not implemented" end |
#write_cluster(cluster) ⇒ void
This method returns an undefined value.
Write a cluster to storage (insert or update)
179 180 181 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 179 def write_cluster(cluster) raise NotImplementedError, "#{self.class}#write_cluster not implemented" end |
#write_edge(edge) ⇒ void
This method returns an undefined value.
Write an edge to storage
152 153 154 |
# File 'lib/swarm_sdk/v3/memory/adapters/base.rb', line 152 def write_edge(edge) raise NotImplementedError, "#{self.class}#write_edge not implemented" end |