epsilla 0.0.2
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +0 -0
- data/README.md +83 -0
- data/Rakefile +4 -0
- data/examples/hello_epsilla.rb +67 -0
- data/lib/epsilla/base.rb +11 -0
- data/lib/epsilla/client.rb +48 -0
- data/lib/epsilla/database.rb +128 -0
- data/lib/epsilla/error.rb +6 -0
- data/lib/epsilla/health.rb +22 -0
- data/lib/epsilla/version.rb +5 -0
- data/lib/epsilla.rb +11 -0
- data/sig/epsilla.rbs +4 -0
- metadata +73 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d9735534acaf9e3a5999efd311c5196490ba03dc496c6cf58b3036aa6efa91a3
|
4
|
+
data.tar.gz: 510f3196a738e8a5b15e70dc2e08e760117ac03b460c73e9225182094d9760f7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 64233f486d746bbab551b38aeec8941eccd40df601387ebbb77429ae83a8a6f7666536552f4f4cc972b585a238d79ab6c04b22e4e4a4a43778ec0030d156a2a9
|
7
|
+
data.tar.gz: 3139f12945ac88a04f347d8944a8a0b68db957ce70c392868894e9119fb8b2ff10d125212bc049b9322de6dc10c75fe5fce66dbb8fba9d057f6bd70d34f17f6b
|
data/CHANGELOG.md
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# Epsilla Ruby SDK
|
2
|
+
|
3
|
+
Welcome to Ruby SDK for Epsilla Vector Database!
|
4
|
+
https://rubygems.org/gems/epsilla-ruby
|
5
|
+
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
```shell
|
9
|
+
bundle add epsilla-ruby
|
10
|
+
gem install epsilla-ruby
|
11
|
+
```
|
12
|
+
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
### Run Epsilla Vectordb using Docker
|
17
|
+
```shell
|
18
|
+
docker run --pull=always -d -p 8888:8888 epsilla/vectordb
|
19
|
+
```
|
20
|
+
|
21
|
+
### Use epsilla-ruby to connect to and interact with vector database
|
22
|
+
```ruby
|
23
|
+
|
24
|
+
require "epsilla"
|
25
|
+
|
26
|
+
# Connect to Epsilla VectorDB
|
27
|
+
client = Epsilla::Client.new(protocol="http", host="127.0.0.1", port="8888")
|
28
|
+
# puts client.live?
|
29
|
+
|
30
|
+
# Load DB with path
|
31
|
+
status_code, response = client.database.load_db(db_name="MyDB", db_path="/tmp/epsilla")
|
32
|
+
puts status_code, response
|
33
|
+
|
34
|
+
# Set DB to current DB
|
35
|
+
client.database.use_db(db_name="MyDB")
|
36
|
+
|
37
|
+
# Create a table with schema in current DB
|
38
|
+
table_fields= [
|
39
|
+
{"name" => "ID", "dataType" => "INT"},
|
40
|
+
{"name" => "Doc", "dataType" => "STRING"},
|
41
|
+
{"name" => "Embedding", "dataType" => "VECTOR_FLOAT", "dimensions" => 4}
|
42
|
+
]
|
43
|
+
# table_fields.each { |x| puts "==#{x}"}
|
44
|
+
status_code, response = client.database.create_table(table_name="MyTable", table_fields=table_fields)
|
45
|
+
puts status_code, response
|
46
|
+
|
47
|
+
# Insert new vector records into table
|
48
|
+
table_records = [
|
49
|
+
{"ID" => 1, "Doc" => "Berlin", "Embedding" => [0.05, 0.61, 0.76, 0.74]},
|
50
|
+
{"ID" => 2, "Doc" => "London", "Embedding" => [0.19, 0.81, 0.75, 0.11]},
|
51
|
+
{"ID" => 3, "Doc" => "Moscow", "Embedding" => [0.36, 0.55, 0.47, 0.94]},
|
52
|
+
{"ID" => 4, "Doc" => "San Francisco", "Embedding" => [0.18, 0.01, 0.85, 0.80]},
|
53
|
+
{"ID" => 5, "Doc" => "Shanghai", "Embedding" => [0.24, 0.18, 0.22, 0.44]}
|
54
|
+
]
|
55
|
+
|
56
|
+
status_code, response = client.database.insert(table_name="MyTable", table_records=table_records)
|
57
|
+
puts status_code, response
|
58
|
+
|
59
|
+
# Rebuild
|
60
|
+
status_code, response = client.database.rebuild()
|
61
|
+
puts status_code, response
|
62
|
+
|
63
|
+
# Query Vectors
|
64
|
+
query_field = "Embedding"
|
65
|
+
response_fields = ["Doc"]
|
66
|
+
query_vector=[0.35, 0.55, 0.47, 0.94]
|
67
|
+
limit=1
|
68
|
+
status_code, response = client.database.query(table_name="MyTable", query_field=query_field, query_vector=query_vector, response_fields=response_fields, limit=limit, with_distance=true)
|
69
|
+
puts status_code, response
|
70
|
+
|
71
|
+
|
72
|
+
# Drop table
|
73
|
+
#status_code, response = client.database.drop_table("MyTable")
|
74
|
+
#puts status_code, response
|
75
|
+
|
76
|
+
# Unload db
|
77
|
+
#status_code, response = client.database.unload_db("MyDB")
|
78
|
+
#puts status_code, response
|
79
|
+
|
80
|
+
```
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/epsilla-cloud/epsilla-ruby.
|
data/Rakefile
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Try this simple example
|
4
|
+
# 1. docker run --pull=always -d -p 8888:8888 epsilla/vectordb
|
5
|
+
# 2. gem install epsilla-ruby && gem update epsilla-ruby
|
6
|
+
# 3. ruby hello_epsilla.rb
|
7
|
+
|
8
|
+
|
9
|
+
require "epsilla"
|
10
|
+
|
11
|
+
|
12
|
+
# Connect to Epsilla VectorDB
|
13
|
+
client = Epsilla::Client.new(protocol="http", host="127.0.0.1", port="8888")
|
14
|
+
# puts client.live?
|
15
|
+
|
16
|
+
# Load DB with path
|
17
|
+
status_code, response = client.database.load_db(db_name="MyDB", db_path="/tmp/epsilla")
|
18
|
+
puts status_code, response
|
19
|
+
|
20
|
+
# Set DB to current DB
|
21
|
+
client.database.use_db(db_name="MyDB")
|
22
|
+
|
23
|
+
# Create a table with schema in current DB
|
24
|
+
table_fields= [
|
25
|
+
{"name" => "ID", "dataType" => "INT"},
|
26
|
+
{"name" => "Doc", "dataType" => "STRING"},
|
27
|
+
{"name" => "Embedding", "dataType" => "VECTOR_FLOAT", "dimensions" => 4}
|
28
|
+
]
|
29
|
+
# table_fields.each { |x| puts "==#{x}"}
|
30
|
+
status_code, response = client.database.create_table(table_name="MyTable", table_fields=table_fields)
|
31
|
+
puts status_code, response
|
32
|
+
|
33
|
+
# Insert new vector records into table
|
34
|
+
table_records = [
|
35
|
+
{"ID" => 1, "Doc" => "Berlin", "Embedding" => [0.05, 0.61, 0.76, 0.74]},
|
36
|
+
{"ID" => 2, "Doc" => "London", "Embedding" => [0.19, 0.81, 0.75, 0.11]},
|
37
|
+
{"ID" => 3, "Doc" => "Moscow", "Embedding" => [0.36, 0.55, 0.47, 0.94]},
|
38
|
+
{"ID" => 4, "Doc" => "San Francisco", "Embedding" => [0.18, 0.01, 0.85, 0.80]},
|
39
|
+
{"ID" => 5, "Doc" => "Shanghai", "Embedding" => [0.24, 0.18, 0.22, 0.44]}
|
40
|
+
]
|
41
|
+
|
42
|
+
status_code, response = client.database.insert(table_name="MyTable", table_records=table_records)
|
43
|
+
puts status_code, response
|
44
|
+
|
45
|
+
# Rebuild
|
46
|
+
status_code, response = client.database.rebuild()
|
47
|
+
puts status_code, response
|
48
|
+
|
49
|
+
# Query vectors
|
50
|
+
query_field = "Embedding"
|
51
|
+
query_vector=[0.35, 0.55, 0.47, 0.94]
|
52
|
+
response_fields = ["Doc"]
|
53
|
+
limit=2
|
54
|
+
status_code, response = client.database.query(table_name="MyTable", query_field=query_field, query_vector=query_vector, response_fields=response_fields, limit=limit, with_distance=true)
|
55
|
+
puts status_code, response
|
56
|
+
|
57
|
+
|
58
|
+
# Drop table
|
59
|
+
status_code, response = client.database.drop_table("MyTable")
|
60
|
+
puts status_code, response
|
61
|
+
|
62
|
+
# Unload db
|
63
|
+
status_code, response = client.database.unload_db("MyDB")
|
64
|
+
puts status_code, response
|
65
|
+
|
66
|
+
|
67
|
+
|
data/lib/epsilla/base.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "faraday"
|
4
|
+
|
5
|
+
|
6
|
+
module Epsilla
|
7
|
+
class Client
|
8
|
+
attr_reader :protocol, :host, :port, :adapter, :debug
|
9
|
+
|
10
|
+
def self.welcome
|
11
|
+
puts "WELCOME To EPSILLA VECTOR DATABASE!"
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(protocol, host, port, adapter: Faraday.default_adapter, debug: false)
|
15
|
+
@url = "#{protocol}://#{host}:#{port}"
|
16
|
+
@adapter = adapter
|
17
|
+
@debug = debug
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def connection
|
22
|
+
@conn ||= Faraday.new(url: "#{@url}", request: { timeout: 30 }) do |faraday|
|
23
|
+
faraday.request :json
|
24
|
+
faraday.response :logger if @debug
|
25
|
+
faraday.response :json, content_type: /\bjson$/
|
26
|
+
faraday.adapter @adapter
|
27
|
+
faraday.options.timeout = 30 # 30s
|
28
|
+
faraday.options.open_timeout = 30 # 30s
|
29
|
+
faraday.headers['Content-type'] = 'application/json'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def live?
|
34
|
+
@health ||= Epsilla::Health.new(client: self)
|
35
|
+
@health.live?
|
36
|
+
end
|
37
|
+
|
38
|
+
def state
|
39
|
+
@health ||= Epsilla::Health.new(client: self)
|
40
|
+
@health.state
|
41
|
+
end
|
42
|
+
|
43
|
+
def database
|
44
|
+
@database ||= Epsilla::DataBase.new(client: self)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Epsilla
|
4
|
+
class DataBase < Base
|
5
|
+
|
6
|
+
# use db
|
7
|
+
def use_db(db_name)
|
8
|
+
@db_name = db_name
|
9
|
+
end
|
10
|
+
|
11
|
+
# load db
|
12
|
+
def load_db(db_name, db_path, vector_scale: nil, wal_enabled: false)
|
13
|
+
response = client.connection.post do |req|
|
14
|
+
req.url "/api/load"
|
15
|
+
req.body = {"name": db_name, "path": db_path}.to_json
|
16
|
+
req.body["vectorScale"] = vector_scale if vector_scale
|
17
|
+
req.body["walEnabled"] = wal_enabled if wal_enabled
|
18
|
+
end
|
19
|
+
return response.status, response.body
|
20
|
+
end
|
21
|
+
|
22
|
+
# unload db
|
23
|
+
def unload_db(db_name)
|
24
|
+
@db_name = nil
|
25
|
+
response = client.connection.post do |req|
|
26
|
+
req.url "/api/#{db_name}/unload"
|
27
|
+
end
|
28
|
+
return response.status, response.body
|
29
|
+
end
|
30
|
+
|
31
|
+
# create table in the db
|
32
|
+
def create_table(table_name = "MyTable", table_fields = nil)
|
33
|
+
unless @db_name
|
34
|
+
raise Exception("[ERROR] Please use_db() first!")
|
35
|
+
end
|
36
|
+
unless table_fields
|
37
|
+
table_fields = Array.new
|
38
|
+
end
|
39
|
+
|
40
|
+
response = client.connection.post do |req|
|
41
|
+
req.url "/api/#{@db_name}/schema/tables"
|
42
|
+
req.body = {"name": table_name, "fields": table_fields}.to_json
|
43
|
+
end
|
44
|
+
|
45
|
+
return response.status, response.body
|
46
|
+
end
|
47
|
+
|
48
|
+
# insert data into table
|
49
|
+
def insert(table_name = "MyTable", table_records = nil)
|
50
|
+
unless @db_name
|
51
|
+
raise Exception("[ERROR] Please use_db() first!")
|
52
|
+
end
|
53
|
+
unless table_records
|
54
|
+
table_records = Array.new
|
55
|
+
end
|
56
|
+
response = client.connection.post do |req|
|
57
|
+
req.url "/api/#{@db_name}/data/insert"
|
58
|
+
req.body = {"table": table_name, "data": table_records}.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
return response.status, response.body
|
62
|
+
end
|
63
|
+
|
64
|
+
# rebuild the table
|
65
|
+
def rebuild
|
66
|
+
# puts "[INFO] waiting until rebuild is finished ..."
|
67
|
+
response = client.connection.post do |req|
|
68
|
+
req.url '/api/rebuild'
|
69
|
+
req.options.timeout = 7200 # 7200s
|
70
|
+
end
|
71
|
+
return response.status, response.body
|
72
|
+
end
|
73
|
+
|
74
|
+
# query
|
75
|
+
def query(table_name = "MyTable", query_field = "", query_vector = nil, response_fields = nil, limit = 1, with_distance = false)
|
76
|
+
unless @db_name
|
77
|
+
raise Exception("[ERROR] Please use_db() first!")
|
78
|
+
end
|
79
|
+
unless query_vector
|
80
|
+
query_vector = ""
|
81
|
+
end
|
82
|
+
unless response_fields
|
83
|
+
response_fields = Array.new
|
84
|
+
end
|
85
|
+
|
86
|
+
response = client.connection.post do |req|
|
87
|
+
req.url "/api/#{@db_name}/data/query"
|
88
|
+
req.body = {"table": table_name, "queryField": query_field, "queryVector": query_vector, "response": response_fields, "limit": limit, "withDistance": with_distance}.to_json
|
89
|
+
end
|
90
|
+
return response.status, response.body
|
91
|
+
end
|
92
|
+
|
93
|
+
# get
|
94
|
+
def get(table_name= "MyTable", response_fields = nil)
|
95
|
+
unless @db_name
|
96
|
+
raise Exception("[ERROR] Please use_db() first!")
|
97
|
+
end
|
98
|
+
unless response_fields
|
99
|
+
response_fields = Array.new
|
100
|
+
end
|
101
|
+
response = client.connection.post do |req|
|
102
|
+
req.url "/api/#{@db_name}/data/get"
|
103
|
+
req.body = {"table": table_name, "response": response_fields}.to_json
|
104
|
+
end
|
105
|
+
return response.status, response.body
|
106
|
+
end
|
107
|
+
|
108
|
+
# drop table
|
109
|
+
def drop_table(table_name)
|
110
|
+
unless @db_name
|
111
|
+
raise Exception("[ERROR] Please use_db() first!")
|
112
|
+
end
|
113
|
+
response = client.connection.delete do |req|
|
114
|
+
req.url "/api/#{@db_name}/schema/tables/#{table_name}"
|
115
|
+
end
|
116
|
+
return response.status, response.body
|
117
|
+
end
|
118
|
+
|
119
|
+
# drop db
|
120
|
+
def drop_db(db_name)
|
121
|
+
response = client.connection.delete do |req|
|
122
|
+
req.url "/api/#{@db_name}/drop"
|
123
|
+
end
|
124
|
+
return response.status, response.body
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Epsilla
|
4
|
+
class Health < Base
|
5
|
+
|
6
|
+
def live?
|
7
|
+
response = client.connection.get do |req|
|
8
|
+
req.url '/'
|
9
|
+
end
|
10
|
+
if response.status != 200
|
11
|
+
raise Exception.new "[ERROR] Failed to connect to #{@url}"
|
12
|
+
else
|
13
|
+
true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def state
|
18
|
+
response = client.connection.get("/state")
|
19
|
+
response.status == 200
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/epsilla.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "epsilla/version"
|
4
|
+
|
5
|
+
module Epsilla
|
6
|
+
autoload :Base, "epsilla/base"
|
7
|
+
autoload :Client, "epsilla/client"
|
8
|
+
autoload :DataBase, "epsilla/database"
|
9
|
+
autoload :Health, "epsilla/health"
|
10
|
+
autoload :Error, "epsilla/error"
|
11
|
+
end
|
data/sig/epsilla.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: epsilla
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Epsilla Team
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1'
|
27
|
+
description: EpsillaDB is a scalable, high-performance, and cost-effective vector
|
28
|
+
database
|
29
|
+
email:
|
30
|
+
- eric@epsilla.com
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- CHANGELOG.md
|
36
|
+
- README.md
|
37
|
+
- Rakefile
|
38
|
+
- examples/hello_epsilla.rb
|
39
|
+
- lib/epsilla.rb
|
40
|
+
- lib/epsilla/base.rb
|
41
|
+
- lib/epsilla/client.rb
|
42
|
+
- lib/epsilla/database.rb
|
43
|
+
- lib/epsilla/error.rb
|
44
|
+
- lib/epsilla/health.rb
|
45
|
+
- lib/epsilla/version.rb
|
46
|
+
- sig/epsilla.rbs
|
47
|
+
homepage: https://github.com/epsilla-cloud/vectordb
|
48
|
+
licenses:
|
49
|
+
- MIT
|
50
|
+
metadata:
|
51
|
+
homepage_uri: https://github.com/epsilla-cloud/vectordb
|
52
|
+
source_code_uri: https://github.com/epsilla-cloud/epsilla-ruby-client
|
53
|
+
changelog_uri: https://github.com/epsilla-cloud/epsilla-ruby-client/blob/main/CHANGELOG.md
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options: []
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 2.6.0
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
requirements: []
|
69
|
+
rubygems_version: 3.4.18
|
70
|
+
signing_key:
|
71
|
+
specification_version: 4
|
72
|
+
summary: Ruby client for Epsilla Vector Database
|
73
|
+
test_files: []
|