Files
sure/app/models/family/vector_searchable.rb
2026-02-11 17:34:53 +00:00

86 lines
2.0 KiB
Ruby

module Family::VectorSearchable
extend ActiveSupport::Concern
included do
has_many :family_documents, dependent: :destroy
end
def ensure_vector_store!
return vector_store_id if vector_store_id.present?
adapter = vector_store_adapter
return nil unless adapter
response = adapter.create_store(name: "Family #{id} Documents")
return nil unless response.success?
if update(vector_store_id: response.data[:id])
vector_store_id
else
adapter.delete_store(store_id: response.data[:id]) rescue nil
nil
end
end
def search_documents(query, max_results: 10)
return [] unless vector_store_id.present?
adapter = vector_store_adapter
return [] unless adapter
response = adapter.search(
store_id: vector_store_id,
query: query,
max_results: max_results
)
response.success? ? response.data : []
end
def upload_document(file_content:, filename:, metadata: {})
adapter = vector_store_adapter
return nil unless adapter
store_id = ensure_vector_store!
return nil unless store_id
response = adapter.upload_file(
store_id: store_id,
file_content: file_content,
filename: filename
)
return nil unless response.success?
family_documents.create!(
filename: filename,
content_type: Marcel::MimeType.for(name: filename),
file_size: file_content.bytesize,
provider_file_id: response.data[:file_id],
status: "ready",
metadata: metadata || {}
)
end
def remove_document(family_document)
adapter = vector_store_adapter
return false unless adapter && vector_store_id.present? && family_document.provider_file_id.present?
response = adapter.remove_file(
store_id: vector_store_id,
file_id: family_document.provider_file_id
)
return false unless response.success?
family_document.destroy
true
end
private
def vector_store_adapter
VectorStore.adapter
end
end