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:) ⇒ 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:) ⇒ Pgvector
Returns a new instance of Pgvector.
22 23 24 25 26 27 28 29 30 31 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 22 def initialize(model_class:) 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 end |
Instance Method Details
#add(id:, embedding:, metadata: {}) ⇒ Object
36 37 38 39 40 41 42 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 36 def add(id:, embedding:, metadata: {}) @model_class.upsert( {id: id, embedding: safe_vector(), metadata: .to_json}, unique_by: :id ) self end |
#clear ⇒ Object
71 72 73 74 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 71 def clear @model_class.delete_all self end |
#remove(id:) ⇒ Object
66 67 68 69 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 66 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.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/phronomy/vector_store/pgvector.rb', line 47 def search(query_embedding:, k: 5) 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 |