epsilla-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +0 -0
- data/README.md +81 -0
- data/Rakefile +4 -0
- data/examples/hello_epsilla.rb +66 -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 +74 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 02ec2167e8966de5929e21521bcd3640683d4ac7a4c27b42c811a85714d4d7bc
|
4
|
+
data.tar.gz: 1c665e9af8e44e1a5f16b965c0996075ad4aa5833f6c92207c3492488293dc70
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 72ad5416ad62fc593691288456294781a16aeb6aac85e12ef5257e133b2abd6df834963a3c2f40656d45235d7a5ea61b912716ba8b7250ad778192e403e09339
|
7
|
+
data.tar.gz: a805cb4f2ad872fbfeae05c7756bbb15f40d052cebc1c0fe68f4305e90078f0165095a104fec82de5759b5e43537bdf7544e65dd7f6ec899a4cc7ae8db4a05a5
|
data/CHANGELOG.md
ADDED
File without changes
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# Epsilla Ruby SDK
|
2
|
+
|
3
|
+
Welcome to Ruby SDK for Epsilla Vector Database!
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
```shell
|
7
|
+
bundle add epsilla-ruby
|
8
|
+
gem install epsilla-ruby
|
9
|
+
```
|
10
|
+
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
### Run Epsilla Vectordb using Docker
|
15
|
+
```shell
|
16
|
+
docker run --pull=always -d -p 8888:8888 epsilla/vectordb
|
17
|
+
```
|
18
|
+
|
19
|
+
### Use epsilla-ruby to connect to and interact with vector database
|
20
|
+
```ruby
|
21
|
+
|
22
|
+
require "epsilla"
|
23
|
+
|
24
|
+
# Connect to Epsilla VectorDB
|
25
|
+
client = Epsilla::Client.new(protocol="http", host="127.0.0.1", port="8888")
|
26
|
+
# puts client.live?
|
27
|
+
|
28
|
+
# Load DB with path
|
29
|
+
status_code, response = client.database.load_db(db_name="MyDB", db_path="/tmp/epsilla")
|
30
|
+
puts status_code, response
|
31
|
+
|
32
|
+
# Set DB to current DB
|
33
|
+
client.database.use_db(db_name="MyDB")
|
34
|
+
|
35
|
+
# Create a table with schema in current DB
|
36
|
+
table_fields= [
|
37
|
+
{"name" => "ID", "dataType" => "INT"},
|
38
|
+
{"name" => "Doc", "dataType" => "STRING"},
|
39
|
+
{"name" => "Embedding", "dataType" => "VECTOR_FLOAT", "dimensions" => 4}
|
40
|
+
]
|
41
|
+
# table_fields.each { |x| puts "==#{x}"}
|
42
|
+
status_code, response = client.database.create_table(table_name="MyTable", table_fields=table_fields)
|
43
|
+
puts status_code, response
|
44
|
+
|
45
|
+
# Insert new vector records into table
|
46
|
+
table_records = [
|
47
|
+
{"ID" => 1, "Doc" => "Berlin", "Embedding" => [0.05, 0.61, 0.76, 0.74]},
|
48
|
+
{"ID" => 2, "Doc" => "London", "Embedding" => [0.19, 0.81, 0.75, 0.11]},
|
49
|
+
{"ID" => 3, "Doc" => "Moscow", "Embedding" => [0.36, 0.55, 0.47, 0.94]},
|
50
|
+
{"ID" => 4, "Doc" => "San Francisco", "Embedding" => [0.18, 0.01, 0.85, 0.80]},
|
51
|
+
{"ID" => 5, "Doc" => "Shanghai", "Embedding" => [0.24, 0.18, 0.22, 0.44]}
|
52
|
+
]
|
53
|
+
|
54
|
+
status_code, response = client.database.insert(table_name="MyTable", table_records=table_records)
|
55
|
+
puts status_code, response
|
56
|
+
|
57
|
+
# Rebuild
|
58
|
+
status_code, response = client.database.rebuild()
|
59
|
+
puts status_code, response
|
60
|
+
|
61
|
+
# Query Vectors
|
62
|
+
query_field = "Embedding"
|
63
|
+
response_fields = ["Doc"]
|
64
|
+
query_vector=[0.35, 0.55, 0.47, 0.94]
|
65
|
+
limit=1
|
66
|
+
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)
|
67
|
+
puts status_code, response
|
68
|
+
|
69
|
+
|
70
|
+
# Drop table
|
71
|
+
status_code, response = client.database.drop_table("MyTable")
|
72
|
+
puts status_code, response
|
73
|
+
|
74
|
+
# Unload db
|
75
|
+
status_code, response = client.database.unload_db("MyDB")
|
76
|
+
puts status_code, response
|
77
|
+
|
78
|
+
```
|
79
|
+
|
80
|
+
## Contributing
|
81
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/epsilla-cloud/epsilla-ruby.
|
data/Rakefile
ADDED
@@ -0,0 +1,66 @@
|
|
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
|
+
# Connect to Epsilla VectorDB
|
12
|
+
client = Epsilla::Client.new(protocol="http", host="127.0.0.1", port="8888")
|
13
|
+
# puts client.live?
|
14
|
+
|
15
|
+
# Load DB with path
|
16
|
+
status_code, response = client.database.load_db(db_name="MyDB", db_path="/tmp/epsilla")
|
17
|
+
puts status_code, response
|
18
|
+
|
19
|
+
# Set DB to current DB
|
20
|
+
client.database.use_db(db_name="MyDB")
|
21
|
+
|
22
|
+
# Create a table with schema in current DB
|
23
|
+
table_fields= [
|
24
|
+
{"name" => "ID", "dataType" => "INT"},
|
25
|
+
{"name" => "Doc", "dataType" => "STRING"},
|
26
|
+
{"name" => "Embedding", "dataType" => "VECTOR_FLOAT", "dimensions" => 4}
|
27
|
+
]
|
28
|
+
# table_fields.each { |x| puts "==#{x}"}
|
29
|
+
status_code, response = client.database.create_table(table_name="MyTable", table_fields=table_fields)
|
30
|
+
puts status_code, response
|
31
|
+
|
32
|
+
# Insert new vector records into table
|
33
|
+
table_records = [
|
34
|
+
{"ID" => 1, "Doc" => "Berlin", "Embedding" => [0.05, 0.61, 0.76, 0.74]},
|
35
|
+
{"ID" => 2, "Doc" => "London", "Embedding" => [0.19, 0.81, 0.75, 0.11]},
|
36
|
+
{"ID" => 3, "Doc" => "Moscow", "Embedding" => [0.36, 0.55, 0.47, 0.94]},
|
37
|
+
{"ID" => 4, "Doc" => "San Francisco", "Embedding" => [0.18, 0.01, 0.85, 0.80]},
|
38
|
+
{"ID" => 5, "Doc" => "Shanghai", "Embedding" => [0.24, 0.18, 0.22, 0.44]}
|
39
|
+
]
|
40
|
+
|
41
|
+
status_code, response = client.database.insert(table_name="MyTable", table_records=table_records)
|
42
|
+
puts status_code, response
|
43
|
+
|
44
|
+
# Rebuild
|
45
|
+
status_code, response = client.database.rebuild()
|
46
|
+
puts status_code, response
|
47
|
+
|
48
|
+
# Query Vectors
|
49
|
+
query_field = "Embedding"
|
50
|
+
response_fields = ["Doc"]
|
51
|
+
query_vector=[0.35, 0.55, 0.47, 0.94]
|
52
|
+
limit=1
|
53
|
+
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)
|
54
|
+
puts status_code, response
|
55
|
+
|
56
|
+
|
57
|
+
# Drop table
|
58
|
+
status_code, response = client.database.drop_table("MyTable")
|
59
|
+
puts status_code, response
|
60
|
+
|
61
|
+
# Unload db
|
62
|
+
status_code, response = client.database.unload_db("MyDB")
|
63
|
+
puts status_code, response
|
64
|
+
|
65
|
+
|
66
|
+
|
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,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: epsilla-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Epsilla Team
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-08-13 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
|
+
- admin@epsilla.com
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- CHANGELOG.md
|
37
|
+
- README.md
|
38
|
+
- Rakefile
|
39
|
+
- examples/hello_epsilla.rb
|
40
|
+
- lib/epsilla.rb
|
41
|
+
- lib/epsilla/base.rb
|
42
|
+
- lib/epsilla/client.rb
|
43
|
+
- lib/epsilla/database.rb
|
44
|
+
- lib/epsilla/error.rb
|
45
|
+
- lib/epsilla/health.rb
|
46
|
+
- lib/epsilla/version.rb
|
47
|
+
- sig/epsilla.rbs
|
48
|
+
homepage: https://github.com/epsilla-cloud/vectordb
|
49
|
+
licenses:
|
50
|
+
- MIT
|
51
|
+
metadata:
|
52
|
+
homepage_uri: https://github.com/epsilla-cloud/vectordb
|
53
|
+
source_code_uri: https://github.com/epsilla-cloud/epsilla-ruby
|
54
|
+
changelog_uri: https://github.com/epsilla-cloud/epsilla-ruby/blob/main/CHANGELOG.md
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.6.0
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubygems_version: 3.4.18
|
71
|
+
signing_key:
|
72
|
+
specification_version: 4
|
73
|
+
summary: Ruby client for Epsilla Vector Database
|
74
|
+
test_files: []
|