Class: Leann::Rails::ActiveRecordBackend

Inherits:
Object
  • Object
show all
Defined in:
lib/leann/rails/storage/active_record_backend.rb

Overview

ActiveRecord-based storage backend for LEANN graphs

Stores graph structure (neighbor lists) in the passages table, avoiding the need for separate binary files.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(index) ⇒ ActiveRecordBackend

Returns a new instance of ActiveRecordBackend.

Parameters:



14
15
16
17
18
19
20
21
22
# File 'lib/leann/rails/storage/active_record_backend.rb', line 14

def initialize(index)
  @index = index
  @dimensions = index.dimensions
  config = index.config || {}
  @m = config["hnsw_m"] || Leann.configuration.hnsw_m
  @ef_construction = config["hnsw_ef_construction"] || Leann.configuration.hnsw_ef_construction
  @entry_point_id = nil
  @max_level = 0
end

Instance Attribute Details

#dimensionsObject (readonly)

Returns the value of attribute dimensions.



11
12
13
# File 'lib/leann/rails/storage/active_record_backend.rb', line 11

def dimensions
  @dimensions
end

#ef_constructionObject (readonly)

Returns the value of attribute ef_construction.



11
12
13
# File 'lib/leann/rails/storage/active_record_backend.rb', line 11

def ef_construction
  @ef_construction
end

#indexObject (readonly)

Returns the value of attribute index.



11
12
13
# File 'lib/leann/rails/storage/active_record_backend.rb', line 11

def index
  @index
end

#mObject (readonly)

Returns the value of attribute m.



11
12
13
# File 'lib/leann/rails/storage/active_record_backend.rb', line 11

def m
  @m
end

Instance Method Details

#build(documents, embeddings) ⇒ Object

Build the graph from documents and embeddings

Parameters:

  • documents (Array<Hash>)

    Documents with :id, :text, :metadata

  • embeddings (Array<Array<Float>>)

    Embedding vectors



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/leann/rails/storage/active_record_backend.rb', line 28

def build(documents, embeddings)
  return if documents.empty?

  puts "Building LEANN graph with #{documents.size} nodes (M=#{@m})..."

  # Build in-memory graph first using the core algorithm
  graph = build_graph(documents, embeddings)

  # Store passages with neighbor information
  store_passages(documents, graph)

  # Store graph metadata in the index
  (graph)

  puts "Graph built and stored in database: #{documents.size} passages"
end

#search(query_embedding, embedding_provider:, passages:, limit:) ⇒ Array<Array>

Search the graph

Parameters:

  • query_embedding (Array<Float>)

    Query vector

  • embedding_provider (Leann::Embedding::Base)

    Provider for recomputing embeddings

  • passages (Hash)

    Passage texts by ID (for embedding recomputation)

  • limit (Integer)

    Number of results

Returns:

  • (Array<Array>)

    Array of [id, score] pairs



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/leann/rails/storage/active_record_backend.rb', line 52

def search(query_embedding, embedding_provider:, passages:, limit:)
  return [] if @index.passages.empty?

  # Load graph metadata
  config = @index.config || {}
  entry_point_id = config["entry_point_id"]
  max_level = config["max_level"] || 0

  return [] unless entry_point_id

  # Perform HNSW search with on-the-fly embedding recomputation
  ef_search = [limit * 2, 50].max
  search_hnsw(query_embedding, entry_point_id, max_level, ef_search, embedding_provider, passages, limit)
end