roseflow-pinecone 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roseflow
4
+ module Pinecone
5
+ module Vectors
6
+ module Common
7
+ def self.extended(base_class)
8
+ base_class.extend ClassMethods
9
+ end
10
+
11
+ def self.included(base_class)
12
+ base_class.extend ClassMethods
13
+ end
14
+
15
+ module ClassMethods
16
+ def self.new(input)
17
+ validation = self.contract_object.new.call(input)
18
+ if validation.success?
19
+ super(input)
20
+ else
21
+ raise ArgumentError.new(validation.errors.to_h.inspect)
22
+ end
23
+ end
24
+ end
25
+
26
+ def to_json
27
+ to_h.map do |key, value|
28
+ [key.to_s.split("_").map.with_index do |word, index|
29
+ index == 0 ? word : word.capitalize
30
+ end.join.to_sym, value]
31
+ end.to_h.to_json
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-validation"
5
+
6
+ require "roseflow/pinecone/object"
7
+ require "roseflow/pinecone/vectors/filter"
8
+ require "roseflow/pinecone/vectors/common"
9
+
10
+ module Types
11
+ include Dry.Types()
12
+ end
13
+
14
+ module Roseflow
15
+ module Pinecone
16
+ class Vector
17
+ class Deletion < PineconeObject
18
+ include Roseflow::Pinecone::Vectors::Common
19
+
20
+ class DeletionContract < Dry::Validation::Contract
21
+ params do
22
+ optional(:ids).filled(:array)
23
+ optional(:namespace).filled(:string)
24
+ optional(:filter).filled
25
+ optional(:delete_all).filled(:bool)
26
+ end
27
+ end
28
+
29
+ contract_object DeletionContract
30
+
31
+ attribute? :ids, Dry::Types['array'].of(Dry::Types['string'])
32
+ attribute? :namespace, Dry::Types['string']
33
+ attribute? :filter, Types.Instance(Filter)
34
+ attribute? :delete_all, Dry::Types['bool'].default(false)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-validation"
5
+
6
+ module Types
7
+ include Dry.Types()
8
+
9
+ StringOrNumberOrBoolean = Dry::Types['string'] | Dry::Types['integer'] | Dry::Types['float'] | Dry::Types['bool']
10
+ StringOrNumber = Dry::Types['string'] | Dry::Types['integer'] | Dry::Types['float']
11
+ Number = Dry::Types['integer'] | Dry::Types['float']
12
+ end
13
+
14
+ module Roseflow
15
+ module Pinecone
16
+ class Vector
17
+ class Filter < Hash
18
+ class FilterContract < Dry::Validation::Contract
19
+ schema do
20
+ optional(:$and).filled(:array)
21
+ optional(:$or).filled(:array)
22
+ optional(:$eq).filled(Types::StringOrNumberOrBoolean)
23
+ optional(:$ne).filled(Types::StringOrNumberOrBoolean)
24
+ optional(:$gt).filled(Types::Number)
25
+ optional(:$gte).filled(Types::Number)
26
+ optional(:$lt).filled(Types::Number)
27
+ optional(:$lte).filled(Types::Number)
28
+ optional(:$in).filled(:array).each(Types::StringOrNumber)
29
+ optional(:$nin).filled(:array).each(Types::StringOrNumber)
30
+ end
31
+
32
+ rule(:$and) do
33
+ if key?
34
+ key(:$and).failure("'$any' must be an array") unless value.is_a?(Array)
35
+
36
+ value.each do |v|
37
+ key(:$and).failure("'$any' must be an array of filters") unless v.is_a?(Filter) || to_filter(v).is_a?(Filter)
38
+ end
39
+ end
40
+ end
41
+
42
+ rule(:$or) do
43
+ if key?
44
+ key(:$or).failure("'$or' must be an array") unless value.is_a?(Array)
45
+
46
+ value.each do |v|
47
+ key(:$or).failure("'$or' must be an array of filters") unless v.is_a?(Filter) || to_filter(v).is_a?(Filter)
48
+ end
49
+ end
50
+ end
51
+
52
+ def to_filter(input)
53
+ return false unless input.is_a?(Hash)
54
+ return Filter.new(input)
55
+ end
56
+ end
57
+
58
+ def self.new(input)
59
+ validation = FilterContract.new.call(input)
60
+ if validation.success?
61
+ super(input)
62
+ else
63
+ raise ArgumentError.new(validation.errors.to_h.inspect)
64
+ end
65
+ end
66
+
67
+ def self.default?
68
+ nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-validation"
5
+
6
+ require "roseflow/pinecone/vectors/filter"
7
+ require "roseflow/pinecone/vectors/sparse_vector"
8
+
9
+ module Types
10
+ include Dry.Types()
11
+ end
12
+
13
+ module Roseflow
14
+ module Pinecone
15
+ class Vector
16
+ class Query < PineconeObject
17
+ include Roseflow::Pinecone::Vectors::Common
18
+
19
+ class QueryContract < Dry::Validation::Contract
20
+ params do
21
+ optional(:vector).filled(:array)
22
+ optional(:id).filled(:string)
23
+ end
24
+
25
+ rule(:vector, :id) do
26
+ if !values[:vector].nil? && !values[:id].nil?
27
+ key(:vector).failure("Only one of vector or id can be specified")
28
+ key(:id).failure("Only one of vector or id can be specified")
29
+ end
30
+ end
31
+ end
32
+
33
+ contract_object QueryContract
34
+
35
+ schema schema.strict
36
+
37
+ attribute :namespace, Dry::Types['string'].default("")
38
+ attribute :include_values, Dry::Types['bool'].default(false)
39
+ attribute :include_metadata, Dry::Types['bool'].default(true)
40
+ attribute :top_k, Dry::Types['integer'].default(10)
41
+ attribute? :vector, Dry::Types['array'].of(Dry::Types['float'] | Dry::Types['integer'])
42
+ attribute? :filter, Filter
43
+ attribute? :sparse_vector, SparseVector
44
+ attribute? :id, Dry::Types['string']
45
+
46
+ def self.new(input)
47
+ validation = self.contract_object.new.call(input)
48
+ if validation.success?
49
+ super(input)
50
+ else
51
+ raise ArgumentError.new(validation.errors.to_h.inspect)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-validation"
5
+
6
+ require "roseflow/pinecone/object"
7
+ require "roseflow/pinecone/vectors/common"
8
+
9
+ module Types
10
+ include Dry.Types()
11
+ end
12
+
13
+ module Roseflow
14
+ module Pinecone
15
+ class Vector
16
+ class SparseVector < PineconeObject
17
+ include Roseflow::Pinecone::Vectors::Common
18
+
19
+ class SparseVectorContract < Dry::Validation::Contract
20
+ params do
21
+ required(:indices).filled(:array)
22
+ required(:values).filled(:array)
23
+ end
24
+
25
+ rule(:indices, :values) do
26
+ unless values[:indices].size === values[:values].size
27
+ key(:indices).failure("Indices and values must be the same size")
28
+ key(:values).failure("Indices and values must be the same size")
29
+ end
30
+ end
31
+ end
32
+
33
+ contract_object SparseVectorContract
34
+
35
+ attribute :indices, Dry::Types['array'].of(Dry::Types['integer'])
36
+ attribute :values, Dry::Types['array'].of(Dry::Types['float'] | Dry::Types['integer'])
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-validation"
5
+
6
+ require "roseflow/pinecone/object"
7
+ require "roseflow/pinecone/vectors/sparse_vector"
8
+ require "roseflow/pinecone/vectors/common"
9
+
10
+ module Types
11
+ include Dry.Types()
12
+ end
13
+
14
+ module Roseflow
15
+ module Pinecone
16
+ class Vector
17
+ class Update < PineconeObject
18
+ include Roseflow::Pinecone::Vectors::Common
19
+
20
+ class UpdateContract < Dry::Validation::Contract
21
+ params do
22
+ required(:id).filled(:string)
23
+ optional(:namespace).filled(:string)
24
+ optional(:values).filled(:array)
25
+ optional(:sparse_values).filled
26
+ optional(:metadata).filled(:hash)
27
+ end
28
+ end
29
+
30
+ contract_object UpdateContract
31
+
32
+ attribute :id, Dry::Types['string']
33
+ attribute? :namespace, Dry::Types['string'].optional
34
+ attribute? :values, Dry::Types['array'].of(Dry::Types['float']).optional
35
+ attribute? :sparse_values, SparseVector.optional
36
+ attribute? :metadata, Dry::Types['hash'].optional
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+
5
+ require "roseflow/pinecone/object"
6
+ require "roseflow/pinecone/vectors/sparse_vector"
7
+ require "roseflow/pinecone/vectors/vector_object"
8
+ require "roseflow/pinecone/vectors/common"
9
+
10
+ module Types
11
+ include Dry.Types()
12
+ end
13
+
14
+ module Roseflow
15
+ module Pinecone
16
+ class Vector
17
+ class Upsert < PineconeObject
18
+ include Roseflow::Pinecone::Vectors::Common
19
+
20
+ class UpsertContract < Dry::Validation::Contract
21
+ params do
22
+ required(:vectors).filled(:array)
23
+ optional(:namespace).filled(:string)
24
+ end
25
+ end
26
+
27
+ contract_object UpsertContract
28
+
29
+ attribute :vectors, Dry::Types['array'].of(VectorObject)
30
+ attribute? :namespace, Dry::Types['string'].optional
31
+
32
+ def self.from(data)
33
+ raise ArgumentError, "Data must be a valid upsert hash" unless data.is_a?(Hash) && data.keys.include?(:vectors)
34
+ new(
35
+ vectors: data[:vectors].map { |vector| VectorObject.new(id: vector[:id], values: vector[:values]) },
36
+ namespace: data[:namespace]
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-struct"
4
+ require "dry-validation"
5
+
6
+ require "roseflow/pinecone/object"
7
+ require "roseflow/pinecone/vectors/sparse_vector"
8
+ require "roseflow/pinecone/vectors/common"
9
+
10
+ module Types
11
+ include Dry.Types()
12
+
13
+ Number = Types::Coercible::Float
14
+ # SparseVector = Roseflow::Pinecone::Vector::SparseVector
15
+ end
16
+
17
+ module Roseflow
18
+ module Pinecone
19
+ class Vector
20
+ class VectorObject < PineconeObject
21
+ include Roseflow::Pinecone::Vectors::Common
22
+ transform_keys(&:to_sym)
23
+
24
+ class VectorObjectContract < Dry::Validation::Contract
25
+ params do
26
+ required(:id).filled(:string)
27
+ required(:values).filled(:array)
28
+ optional(:sparse_values).filled
29
+ optional(:metadata).filled(:hash)
30
+ end
31
+ end
32
+
33
+ contract_object VectorObjectContract
34
+
35
+ attribute :id, Dry::Types['string']
36
+ attribute :values, Dry::Types['array'].of(Types::Number)
37
+ attribute? :score, Types::Number.optional
38
+ attribute? :sparse_values, SparseVector.optional
39
+ attribute? :metadata, Dry::Types['hash'].optional
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Roseflow
4
+ module Pinecone
5
+ def self.gem_version
6
+ Gem::Version.new VERSION::STRING
7
+ end
8
+
9
+ module VERSION
10
+ MAJOR = 0
11
+ MINOR = 1
12
+ PATCH = 0
13
+ PRE = nil
14
+
15
+ STRING = [MAJOR, MINOR, PATCH, PRE].compact.join(".")
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "pinecone/version"
4
+
5
+ require "roseflow/pinecone/client"
6
+ require "roseflow/pinecone/collection"
7
+ require "roseflow/pinecone/config"
8
+ require "roseflow/pinecone/response"
9
+
10
+ require "dry-struct"
11
+
12
+ module Types
13
+ include Dry.Types()
14
+ end
15
+
16
+ module Roseflow
17
+ module Pinecone
18
+ class Error < StandardError; end
19
+ class IndexURLNotSetError < Error; end
20
+ end
21
+ end
22
+
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/roseflow/pinecone/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "roseflow-pinecone"
7
+ spec.version = Roseflow::Pinecone.gem_version
8
+ spec.authors = ["Lauri Jutila"]
9
+ spec.email = ["git@laurijutila.com"]
10
+
11
+ spec.summary = "Roseflow meets Pinecone"
12
+ spec.description = "Pinecone vector database integration and support for Roseflow."
13
+ spec.homepage = "https://github.com/roseflow-ai/roseflow-pinecone"
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 3.2.0"
16
+
17
+ spec.metadata["homepage_uri"] = spec.homepage
18
+ spec.metadata["source_code_uri"] = "https://github.com/roseflow-ai/roseflow-pinecone"
19
+ spec.metadata["changelog_uri"] = "https://github.com/roseflow-ai/roseflow-pinecone/blob/master/CHANGELOG.md"
20
+
21
+ # Specify which files should be added to the gem when it is released.
22
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
+ spec.files = Dir.chdir(__dir__) do
24
+ `git ls-files -z`.split("\x0").reject do |f|
25
+ (File.expand_path(f) == __FILE__) || f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor])
26
+ end
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ # Uncomment to register a new dependency of your gem
33
+ spec.add_dependency "activesupport"
34
+ spec.add_dependency "anyway_config", "~> 2.0"
35
+ spec.add_dependency "dry-struct"
36
+ spec.add_dependency "dry-validation"
37
+ spec.add_dependency "faraday"
38
+ spec.add_dependency "faraday-retry"
39
+
40
+ spec.add_development_dependency "awesome_print"
41
+ spec.add_development_dependency "pry"
42
+ spec.add_development_dependency "roseflow"
43
+ spec.add_development_dependency "webmock"
44
+ spec.add_development_dependency "vcr"
45
+
46
+ # For more information and examples about making a new gem, check out our
47
+ # guide at: https://bundler.io/guides/creating_gem.html
48
+ end
@@ -0,0 +1,6 @@
1
+ module Roseflow
2
+ module Pinecone
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end