Class: Phronomy::VectorStore::Pgvector
- Defined in:
- lib/phronomy/vector_store/pgvector.rb
Overview
PostgreSQL-backed vector store using the pgvector extension.
Requires:
- The +pgvector+ gem (add to your Gemfile)
- An ActiveRecord model class with the following columns: id (string / uuid) embedding (vector — from the pgvector column type) metadata (text or jsonb — stores arbitrary metadata as JSON)
Instance Method Summary collapse
- #add(id:, embedding:, metadata: {}) ⇒ Object
- #clear ⇒ Object
-
#initialize(model_class:, dimension: nil) ⇒ Pgvector
constructor
A new instance of Pgvector.
- #remove(id:) ⇒ Object
-
#search(query_embedding:, k: 5) ⇒ Array<Hash>
Sorted by descending similarity score.
Constructor Details
#initialize(model_class:, dimension: nil) ⇒ Pgvector
Returns a new instance of Pgvector.
25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 25 def initialize(model_class:, dimension: nil) begin require "pgvector" rescue LoadError raise LoadError, "pgvector gem is required for Phronomy::VectorStore::Pgvector. " \ "Add `gem 'pgvector'` to your Gemfile." end @model_class = model_class @dimension = dimension end |
Instance Method Details
#add(id:, embedding:, metadata: {}) ⇒ Object
40 41 42 43 44 45 46 47 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 40 def add(id:, embedding:, metadata: {}) (, @dimension) @model_class.upsert( {id: id, embedding: safe_vector(), metadata: .to_json}, unique_by: :id ) self end |
#clear ⇒ Object
77 78 79 80 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 77 def clear @model_class.delete_all self end |
#remove(id:) ⇒ Object
72 73 74 75 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 72 def remove(id:) @model_class.where(id: id).delete_all self end |
#search(query_embedding:, k: 5) ⇒ Array<Hash>
Returns sorted by descending similarity score.
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 52 def search(query_embedding:, k: 5) (, @dimension) vec = safe_vector_literal() k_safe = Integer(k) conn = @model_class.connection quoted_vec = "#{conn.quote(vec)}::vector" @model_class .select("id, metadata, 1 - (embedding <=> #{quoted_vec}) AS score") .order("embedding <=> #{quoted_vec}") .limit(k_safe) .map do |r| { id: r.id.to_s, score: r.score.to_f, metadata: JSON.parse(r..to_s, symbolize_names: true) } end end |