vector_amp 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/README.md +32 -6
- data/lib/vector_amp/client.rb +4 -1
- data/lib/vector_amp/dataset.rb +8 -0
- data/lib/vector_amp/datasets.rb +47 -0
- data/lib/vector_amp/embedding.rb +6 -3
- data/lib/vector_amp/org_secrets.rb +58 -0
- data/lib/vector_amp/version.rb +1 -1
- data/lib/vector_amp.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 275fe25e338462efa98c327a40e334085c4cbad95e720fc3ca3adecb25afa31c
|
|
4
|
+
data.tar.gz: ec1e9abc640c9a76a2203550d277c20152828ff341bb91084594170cf572beae
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3fa5d4c3be9cae14083865ee02cfbe99bd72712ecd3ee461db487f10a51ac9c24c6810616b8d918154f1016d6971bb9d5412327221bb983ab39e821940da1595
|
|
7
|
+
data.tar.gz: 18267f1db75a0b97685a123be17caa021594fa09f6212b6f3f99bc52554a8423e963bac34d6e0f5a266467b017d981fec0f5f6f2c6dd42ef4151ab776dc205aa
|
data/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<a href="https://vectoramp.com/">
|
|
3
3
|
<picture>
|
|
4
|
-
<source media="(prefers-color-scheme: light)" srcset=".
|
|
5
|
-
<source media="(prefers-color-scheme: dark)" srcset=".
|
|
6
|
-
<img alt="VectorAmp Logo" src=".
|
|
4
|
+
<source media="(prefers-color-scheme: light)" srcset="https://vectoramp.com/logo-full-light.svg">
|
|
5
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://vectoramp.com/logo-full-dark.svg">
|
|
6
|
+
<img alt="VectorAmp Logo" src="https://vectoramp.com/logo-full-dark.svg" width="50%">
|
|
7
7
|
</picture>
|
|
8
8
|
</a>
|
|
9
9
|
</div>
|
|
@@ -64,14 +64,23 @@ answer = dataset.ask("What powers VectorAmp?")
|
|
|
64
64
|
### Creating datasets
|
|
65
65
|
|
|
66
66
|
```ruby
|
|
67
|
-
# Minimal: name only.
|
|
67
|
+
# Minimal: name only. Embedding config is omitted so VectorAmp uses
|
|
68
|
+
# the managed VectorAmp-Embedding-4B model and infers dim 2560.
|
|
68
69
|
client.datasets.create(name: "docs")
|
|
69
70
|
|
|
70
71
|
# Enable hybrid (dense + sparse) search.
|
|
71
72
|
client.datasets.create(name: "docs", hybrid: true)
|
|
72
73
|
|
|
73
|
-
#
|
|
74
|
-
|
|
74
|
+
# Optional BYOM: use OpenAI only when you intentionally want that provider.
|
|
75
|
+
# VectorAmp::Embedding.openai uses embedding.secret_ref "emb:openai:api_key" by default.
|
|
76
|
+
client.datasets.create(name: "openai-docs", embedding: VectorAmp::Embedding.openai("large"))
|
|
77
|
+
|
|
78
|
+
# Store/update the org OpenAI key, then create a dataset that references it.
|
|
79
|
+
client.datasets.create_with_openai_api_key(
|
|
80
|
+
name: "openai-docs",
|
|
81
|
+
api_key: ENV.fetch("OPENAI_API_KEY"),
|
|
82
|
+
size: "small"
|
|
83
|
+
)
|
|
75
84
|
|
|
76
85
|
# Custom/unknown model: pass dim explicitly.
|
|
77
86
|
client.datasets.create(name: "docs", embedding: { provider: "acme", model: "acme-embed" }, dim: 1024)
|
|
@@ -111,6 +120,7 @@ dataset.search(
|
|
|
111
120
|
rerank: true # expands to vectoramp / VectorAmp-Rerank-v1
|
|
112
121
|
)
|
|
113
122
|
dataset.insert(vectors: [{ id: "sku-1", values: [0.1, 0.2], metadata: { category: "electronics" } }])
|
|
123
|
+
dataset.delete_vectors(ids: ["sku-1"])
|
|
114
124
|
dataset.add_texts(["Wireless headphones"], metadata: { category: "electronics" })
|
|
115
125
|
dataset.ask("Which headphones should I buy?")
|
|
116
126
|
dataset.ingest_source("source-uuid")
|
|
@@ -123,10 +133,26 @@ dataset.search("wireless headphones", hybrid: true, sparse_query: "headphones",
|
|
|
123
133
|
client.datasets.stats("dataset-uuid")
|
|
124
134
|
client.datasets.search("dataset-uuid", "wireless headphones", top_k: 10)
|
|
125
135
|
client.datasets.insert("dataset-uuid", vectors: [])
|
|
136
|
+
client.datasets.delete_vectors("dataset-uuid", ids: ["sku-1", 42])
|
|
126
137
|
```
|
|
127
138
|
|
|
128
139
|
`client.datasets.create` intentionally does not accept `index_type`; all datasets are created with SABLE.
|
|
129
140
|
|
|
141
|
+
### Organization secrets
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
# Store or rotate the default OpenAI org secret used by OpenAI embedding datasets.
|
|
145
|
+
client.org_secrets.put_openai_api_key(api_key: ENV.fetch("OPENAI_API_KEY"))
|
|
146
|
+
|
|
147
|
+
# Optionally validate before storing, or use a custom secret_ref.
|
|
148
|
+
client.org_secrets.put_openai_api_key(
|
|
149
|
+
api_key: ENV.fetch("OPENAI_API_KEY"),
|
|
150
|
+
secret_ref: "emb:openai:api_key",
|
|
151
|
+
validate: true,
|
|
152
|
+
model: "text-embedding-3-small"
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
130
156
|
### Source documents
|
|
131
157
|
|
|
132
158
|
Dataset document listing is cursor-based: pass `next_cursor` into the next request and do not assume offsets or totals. Downloads return retained original bytes and follow API/storage redirects.
|
data/lib/vector_amp/client.rb
CHANGED
|
@@ -5,6 +5,7 @@ require_relative "datasets"
|
|
|
5
5
|
require_relative "error"
|
|
6
6
|
require_relative "ingestion"
|
|
7
7
|
require_relative "intelligence"
|
|
8
|
+
require_relative "org_secrets"
|
|
8
9
|
require_relative "schedules"
|
|
9
10
|
require_relative "source"
|
|
10
11
|
require_relative "transport/http"
|
|
@@ -19,7 +20,8 @@ module VectorAmp
|
|
|
19
20
|
# @return [IngestionResource] ingestion/source API resource.
|
|
20
21
|
# @return [IntelligenceResource] intelligence API resource.
|
|
21
22
|
# @return [ConnectionsResource] managed provider connections API resource.
|
|
22
|
-
|
|
23
|
+
# @return [OrgSecretsResource] organization-scoped secret helpers.
|
|
24
|
+
attr_reader :base_url, :datasets, :ingestion, :intelligence, :schedules, :sources, :connections, :org_secrets
|
|
23
25
|
|
|
24
26
|
# Create a VectorAmp API client.
|
|
25
27
|
# @param api_key [String] API key; defaults to ENV["VECTORAMP_API_KEY"].
|
|
@@ -38,6 +40,7 @@ module VectorAmp
|
|
|
38
40
|
@schedules = SchedulesResource.new(@transport)
|
|
39
41
|
@intelligence = IntelligenceResource.new(@transport)
|
|
40
42
|
@connections = ConnectionsResource.new(@transport)
|
|
43
|
+
@org_secrets = OrgSecretsResource.new(@transport)
|
|
41
44
|
@datasets = DatasetsResource.new(@transport, client: self)
|
|
42
45
|
end
|
|
43
46
|
|
data/lib/vector_amp/dataset.rb
CHANGED
|
@@ -71,6 +71,14 @@ module VectorAmp
|
|
|
71
71
|
service.insert(id, vectors: vectors)
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
# Delete one or more vectors from this dataset by id.
|
|
75
|
+
# @param ids [Array<String,Integer>] vector ids to delete.
|
|
76
|
+
# @param write_concern [String, nil] optional API write concern.
|
|
77
|
+
# @return [Hash] delete response.
|
|
78
|
+
def delete_vectors(ids:, write_concern: nil)
|
|
79
|
+
service.delete_vectors(id, ids: ids, write_concern: write_concern)
|
|
80
|
+
end
|
|
81
|
+
|
|
74
82
|
# Embed and insert texts into this dataset.
|
|
75
83
|
# @param texts_arg [Array<String>, nil] positional texts for convenience.
|
|
76
84
|
# @param texts [Array<String>, nil] keyword texts.
|
data/lib/vector_amp/datasets.rb
CHANGED
|
@@ -92,6 +92,29 @@ module VectorAmp
|
|
|
92
92
|
wrap_dataset(@transport.request(:post, "/datasets", body: body))
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
# Store/update an OpenAI API key in org secrets, then create an OpenAI-backed dataset
|
|
96
|
+
# whose embedding config references that secret.
|
|
97
|
+
# @param name [String] dataset name.
|
|
98
|
+
# @param api_key [String] OpenAI API key to store server-side.
|
|
99
|
+
# @param size [String, Symbol] "small" or "large".
|
|
100
|
+
# @param secret_ref [String] org secret reference to write and attach to the dataset.
|
|
101
|
+
# @param validate [Boolean] validate the key before storing.
|
|
102
|
+
# @param options [Hash] forwarded to {#create}, e.g. `hybrid: true` or `metadata:`.
|
|
103
|
+
# @return [Dataset] created dataset.
|
|
104
|
+
def create_with_openai_api_key(name:, api_key:, size: "small", secret_ref: "emb:openai:api_key", validate: false, **options)
|
|
105
|
+
secrets = @client&.org_secrets || begin
|
|
106
|
+
require_relative "org_secrets"
|
|
107
|
+
OrgSecretsResource.new(@transport)
|
|
108
|
+
end
|
|
109
|
+
secrets.put_openai_api_key(
|
|
110
|
+
api_key: api_key,
|
|
111
|
+
secret_ref: secret_ref,
|
|
112
|
+
validate: validate,
|
|
113
|
+
model: openai_model(size)
|
|
114
|
+
)
|
|
115
|
+
create(name: name, embedding: Embedding.openai(size, secret_ref: secret_ref), **options)
|
|
116
|
+
end
|
|
117
|
+
|
|
95
118
|
|
|
96
119
|
# List retained source documents for a dataset using cursor pagination.
|
|
97
120
|
# @param dataset_id [String] dataset id.
|
|
@@ -176,6 +199,21 @@ module VectorAmp
|
|
|
176
199
|
@transport.request(:post, "/datasets/#{dataset_id}/insert", body: { vectors: Utils.normalize_vectors(vectors) })
|
|
177
200
|
end
|
|
178
201
|
|
|
202
|
+
# Delete one or more vectors from a dataset by id.
|
|
203
|
+
# @param dataset_id [String] dataset id.
|
|
204
|
+
# @param ids [Array<String,Integer>] vector ids to delete.
|
|
205
|
+
# @param write_concern [String, nil] optional API write concern.
|
|
206
|
+
# @return [Hash] delete response with `deleted` and `dataset_id`.
|
|
207
|
+
def delete_vectors(dataset_id, ids:, write_concern: nil)
|
|
208
|
+
raise ArgumentError, "ids must not be empty" if ids.nil? || ids.empty?
|
|
209
|
+
|
|
210
|
+
@transport.request(
|
|
211
|
+
:delete,
|
|
212
|
+
"/datasets/#{dataset_id}/vectors",
|
|
213
|
+
body: Utils.compact_hash(ids: ids, write_concern: write_concern)
|
|
214
|
+
)
|
|
215
|
+
end
|
|
216
|
+
|
|
179
217
|
# Generate embeddings using the dataset embedding configuration.
|
|
180
218
|
# @param dataset_id [String] dataset id.
|
|
181
219
|
# @param text [String, nil] single text to embed.
|
|
@@ -221,6 +259,15 @@ module VectorAmp
|
|
|
221
259
|
|
|
222
260
|
private
|
|
223
261
|
|
|
262
|
+
def openai_model(size)
|
|
263
|
+
case size.to_s
|
|
264
|
+
when "small" then "text-embedding-3-small"
|
|
265
|
+
when "large" then "text-embedding-3-large"
|
|
266
|
+
else
|
|
267
|
+
raise ArgumentError, %(openai size must be "small" or "large", got #{size.inspect})
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
224
271
|
def wrap_dataset(data)
|
|
225
272
|
Dataset.new(data, service: self, client: @client)
|
|
226
273
|
end
|
data/lib/vector_amp/embedding.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative "utils"
|
|
4
|
+
|
|
3
5
|
module VectorAmp
|
|
4
6
|
# Embedding configuration defaults and helpers.
|
|
5
7
|
#
|
|
@@ -28,16 +30,17 @@ module VectorAmp
|
|
|
28
30
|
|
|
29
31
|
# Build an OpenAI embedding configuration.
|
|
30
32
|
# @param size [String, Symbol] `"small"` (text-embedding-3-small) or `"large"` (text-embedding-3-large).
|
|
31
|
-
# @
|
|
33
|
+
# @param secret_ref [String, nil] organization secret reference containing the OpenAI API key.
|
|
34
|
+
# @return [Hash] `{ provider: "openai", model: ..., secret_ref: ... }`
|
|
32
35
|
# @raise [ArgumentError] when size is not "small" or "large".
|
|
33
|
-
def openai(size = "small")
|
|
36
|
+
def openai(size = "small", secret_ref: "emb:openai:api_key")
|
|
34
37
|
model = case size.to_s
|
|
35
38
|
when "small" then "text-embedding-3-small"
|
|
36
39
|
when "large" then "text-embedding-3-large"
|
|
37
40
|
else
|
|
38
41
|
raise ArgumentError, %(openai size must be "small" or "large", got #{size.inspect})
|
|
39
42
|
end
|
|
40
|
-
|
|
43
|
+
Utils.compact_hash(provider: "openai", model: model, secret_ref: secret_ref)
|
|
41
44
|
end
|
|
42
45
|
|
|
43
46
|
# Normalize a user-supplied embedding value into a config hash.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "uri"
|
|
4
|
+
|
|
5
|
+
require_relative "utils"
|
|
6
|
+
|
|
7
|
+
module VectorAmp
|
|
8
|
+
# Organization-scoped secret helpers exposed by the public API.
|
|
9
|
+
class OrgSecretsResource
|
|
10
|
+
DEFAULT_OPENAI_SECRET_REF = "emb:openai:api_key"
|
|
11
|
+
|
|
12
|
+
# @param transport [#request] API transport.
|
|
13
|
+
# @return [OrgSecretsResource]
|
|
14
|
+
def initialize(transport)
|
|
15
|
+
@transport = transport
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Store or update an organization secret by name.
|
|
19
|
+
# @param name [String] org secret reference to write.
|
|
20
|
+
# @param value [String] plaintext value sent once to the API.
|
|
21
|
+
def put(name:, value:)
|
|
22
|
+
secret_name = name.to_s.strip
|
|
23
|
+
secret_value = value.to_s.strip
|
|
24
|
+
raise ArgumentError, "name is required" if secret_name.empty?
|
|
25
|
+
raise ArgumentError, "value is required" if secret_value.empty?
|
|
26
|
+
|
|
27
|
+
@transport.request(:put, "/org-secrets/#{URI.encode_www_form_component(secret_name)}", body: { value: secret_value })
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Check whether an organization secret exists.
|
|
31
|
+
def exists?(name:)
|
|
32
|
+
secret_name = name.to_s.strip
|
|
33
|
+
raise ArgumentError, "name is required" if secret_name.empty?
|
|
34
|
+
@transport.request(:get, "/org-secrets/#{URI.encode_www_form_component(secret_name)}")
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Store or update the organization OpenAI API key.
|
|
38
|
+
# @param api_key [String] OpenAI API key to store server-side.
|
|
39
|
+
# @param secret_ref [String] org secret reference to write.
|
|
40
|
+
# @param validate [Boolean] accepted for API compatibility; generic org-secret writes do not validate.
|
|
41
|
+
# @param model [String, nil] accepted for API compatibility.
|
|
42
|
+
# @return [Hash, nil] API response; normally nil/empty for 204.
|
|
43
|
+
def put_openai_api_key(api_key:, secret_ref: DEFAULT_OPENAI_SECRET_REF, validate: false, model: nil)
|
|
44
|
+
key = api_key.to_s.strip
|
|
45
|
+
raise ArgumentError, "api_key is required" if key.empty?
|
|
46
|
+
|
|
47
|
+
put(name: secret_ref, value: key)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
alias update_openai_api_key put_openai_api_key
|
|
51
|
+
|
|
52
|
+
# Check whether the default organization OpenAI API key exists.
|
|
53
|
+
# @return [Hash, nil] API response; normally nil/empty for 204.
|
|
54
|
+
def openai_api_key?
|
|
55
|
+
exists?(name: DEFAULT_OPENAI_SECRET_REF)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/vector_amp/version.rb
CHANGED
data/lib/vector_amp.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: vector_amp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- VectorAmp
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-14 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: minitest
|
|
@@ -114,6 +114,7 @@ files:
|
|
|
114
114
|
- lib/vector_amp/error.rb
|
|
115
115
|
- lib/vector_amp/ingestion.rb
|
|
116
116
|
- lib/vector_amp/intelligence.rb
|
|
117
|
+
- lib/vector_amp/org_secrets.rb
|
|
117
118
|
- lib/vector_amp/schedules.rb
|
|
118
119
|
- lib/vector_amp/source.rb
|
|
119
120
|
- lib/vector_amp/transport/base.rb
|