vector-vault 0.2.4__tar.gz → 0.2.7__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vector_vault
3
- Version: 0.2.4
3
+ Version: 0.2.7
4
4
  Summary: VectorVault: Simplified vector database management in the cloud for machine learning and generative ai workflows
5
5
  Home-page: https://github.com/John-Rood/VectorVault
6
6
  Author: VectorVault.io
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="vector_vault",
5
- version="0.2.4",
5
+ version="0.2.7",
6
6
  packages=find_packages(),
7
7
  author="VectorVault.io",
8
8
  author_email="john@johnrood.com",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vector-vault
3
- Version: 0.2.4
3
+ Version: 0.2.7
4
4
  Summary: VectorVault: Simplified vector database management in the cloud for machine learning and generative ai workflows
5
5
  Home-page: https://github.com/John-Rood/VectorVault
6
6
  Author: VectorVault.io
@@ -11,5 +11,6 @@ vectorvault/closedai.py
11
11
  vectorvault/cloudmanager.py
12
12
  vectorvault/creds.py
13
13
  vectorvault/download.py
14
+ vectorvault/itemize.py
14
15
  vectorvault/vault.py
15
16
  vectorvault/wrap.py
@@ -17,6 +17,7 @@ import tempfile
17
17
  import os
18
18
  import json
19
19
  from .creds import CustomCredentials
20
+ from .itemize import name
20
21
  from google.cloud import storage
21
22
  from concurrent.futures import ThreadPoolExecutor, as_completed
22
23
 
@@ -26,48 +27,46 @@ class CloudManager:
26
27
  self.user = user
27
28
  self.api = api_key
28
29
  self.vault = vault
29
-
30
- # Create the OAuth credentials
30
+ # Creates the credentials
31
31
  credentials = CustomCredentials(self.user, self.api)
32
-
33
- # Instantiates a client with the OAuth2 credentials
32
+ # Instantiates the client
34
33
  self.storage_client = storage.Client(project='vectorvault-361ab', credentials=credentials)
35
- self.gcloud = self.storage_client.bucket(self.user)
34
+ self.cloud = self.storage_client.bucket(self.user)
36
35
  print(f'Connected to Vault: {self.vault}')
37
36
 
38
37
  def vault_exists(self, vault_name):
39
- return storage.Blob(bucket=self.gcloud, name=vault_name).exists(self.storage_client)
38
+ return storage.Blob(bucket=self.cloud, name=vault_name).exists(self.storage_client)
40
39
 
41
40
  def upload_to_cloud(self, vault_name, content):
42
- blob = self.gcloud.blob(vault_name)
41
+ blob = self.cloud.blob(vault_name)
43
42
  blob.upload_from_string(content)
44
43
 
45
44
  def download_text_from_cloud(self, vault_name):
46
- blob = self.gcloud.blob(vault_name)
45
+ blob = self.cloud.blob(vault_name)
47
46
  return blob.download_as_text()
48
47
 
49
48
  def upload_temp_file(self, temp_file_path, vault_name):
50
- blob = self.gcloud.blob(vault_name)
49
+ blob = self.cloud.blob(vault_name)
51
50
  blob.upload_from_filename(temp_file_path)
52
51
  os.remove(temp_file_path)
53
52
 
54
53
  def download_to_temp_file(self, vault_name):
55
54
  with tempfile.NamedTemporaryFile(delete=False) as temp_file:
56
- blob = self.gcloud.blob(vault_name)
55
+ blob = self.cloud.blob(vault_name)
57
56
  blob.download_to_filename(temp_file.name)
58
57
  return temp_file.name
59
58
 
60
59
  def upload(self, item, text, meta):
61
60
  with ThreadPoolExecutor() as executor:
62
- executor.submit(self.upload_to_cloud, f'{self.vault}/{item}/item', text)
63
- executor.submit(self.upload_to_cloud, f'{self.vault}/{item}/meta', json.dumps(meta))
61
+ executor.submit(self.upload_to_cloud, name(self.vault, item, item=True), text)
62
+ executor.submit(self.upload_to_cloud, name(self.vault, item, meta=True), json.dumps(meta))
64
63
 
65
64
  def delete_blob(self, blob):
66
65
  blob.delete()
67
66
 
68
67
  def delete(self):
69
68
  # Get all objects
70
- blobs = self.gcloud.list_blobs(prefix=self.vault)
69
+ blobs = self.cloud.list_blobs(prefix=self.vault)
71
70
 
72
71
  # Delete each object concurrently
73
72
  with ThreadPoolExecutor() as executor:
@@ -81,7 +80,7 @@ class CloudManager:
81
80
 
82
81
  def get_vaults(self, vault: str = None):
83
82
  vault = self.vault if vault is None else vault
84
- blobs = self.gcloud.list_blobs(prefix=f'{vault}')
83
+ blobs = self.cloud.list_blobs(prefix=f'{vault}')
85
84
 
86
85
  directories = set()
87
86
  for blob in blobs:
@@ -34,7 +34,7 @@ class CustomCredentials(Credentials):
34
34
  return False
35
35
  return datetime.datetime.now() < self.expiry
36
36
 
37
- def refresh(self, request):
37
+ def refresh(self):
38
38
  if not self.valid:
39
39
  data = {
40
40
  "user_id": self.user,
@@ -46,7 +46,7 @@ class CustomCredentials(Credentials):
46
46
  self.token = response_data['access_token']
47
47
  self.expiry = datetime.datetime.fromisoformat(response_data['expiry'])
48
48
 
49
- def before_request(self, request, method, url, headers):
49
+ def before_request(self, headers):
50
50
  self.apply(headers)
51
51
 
52
52
  def __getstate__(self):
@@ -0,0 +1,63 @@
1
+ import datetime
2
+ from annoy import AnnoyIndex
3
+
4
+ def itemize(vault, x, meta=None, text=None, name=None):
5
+ meta = {} if meta is None else meta
6
+
7
+ if 'name' not in meta and name is None:
8
+ name = f'{vault}-{x}'
9
+ elif name is not None:
10
+ name = __name__
11
+ metaize(meta, name, x)
12
+ return package(text, meta)
13
+
14
+ def metaize(meta, name, x):
15
+ meta['name'] = name
16
+ meta['item_id'] = x
17
+ if 'created_at' not in meta:
18
+ meta['created_at'] = datetime.datetime.utcnow().isoformat()
19
+ if 'updated_at' not in meta:
20
+ meta['updated_at'] = datetime.datetime.utcnow().isoformat()
21
+
22
+ def package(text, meta):
23
+ item = {
24
+ "text": text,
25
+ "meta": meta
26
+ }
27
+ return item
28
+
29
+ def build_base_path(v, x):
30
+ return f'{v}/{x}'
31
+
32
+ def append_path_suffix(base_path, is_item, is_meta):
33
+ if is_item:
34
+ suffix = 'item'
35
+ elif is_meta:
36
+ suffix = 'meta'
37
+ else:
38
+ suffix = ''
39
+ return f'{base_path}/{suffix}'
40
+
41
+ def name(v, x, item=False, meta=False):
42
+ base_path = build_base_path(v, x)
43
+ final_path = append_path_suffix(base_path, item, meta)
44
+ return final_path
45
+
46
+ def name_vecs(vault):
47
+ return f'{vault}.ann'
48
+
49
+ def get_vectors(dims):
50
+ return AnnoyIndex(dims, 'angular')
51
+
52
+ def get_item(item):
53
+ item_id = item["meta"]["item_id"]
54
+ item_text = item["text"]
55
+ item_meta = item["meta"]
56
+ return item_text, item_id, item_meta
57
+
58
+ def build_return(results, item_data, meta):
59
+ result = {
60
+ "data": item_data,
61
+ "metadata": meta
62
+ }
63
+ results.append(result)
@@ -16,21 +16,20 @@
16
16
  import numpy as np
17
17
  import tempfile
18
18
  import os
19
- import datetime
20
19
  import time
21
20
  import json
22
21
  import re
23
22
  import openai
24
- from annoy import AnnoyIndex
25
23
  from concurrent.futures import ThreadPoolExecutor
26
24
  from .cloudmanager import CloudManager
27
25
  from .closedai import ClosedAI
26
+ from .itemize import itemize, name, name_vecs, get_item, build_return, get_vectors
28
27
 
29
28
 
30
29
  class Vault:
31
30
  def __init__(self, user: str, api_key: str, vault: str = None, dims: int = 1536, verbose: bool = False):
32
31
  self.vault = vault.strip() if vault else 'home'
33
- self.vectors = AnnoyIndex(dims, 'angular')
32
+ self.vectors = get_vectors(dims)
34
33
  self.dims = dims
35
34
  self.cloud_manager = CloudManager(user, api_key, self.vault)
36
35
  self.x = 0
@@ -46,15 +45,14 @@ class Vault:
46
45
 
47
46
  def check_index(self):
48
47
  start_time = time.time()
49
- if self.cloud_manager.vault_exists(f'{self.vault}.ann'):
50
- print('vault exists')
48
+ if self.cloud_manager.vault_exists(name_vecs(self.vault)):
51
49
  self.load_vectors()
52
50
  num_existing_items = self.vectors.get_n_items()
53
- new_index = AnnoyIndex(self.dims, 'angular')
51
+ new_index = get_vectors(self.dims)
54
52
  for i in range(num_existing_items):
55
53
  vector = self.vectors.get_item_vector(i)
56
54
  new_index.add_item(i, vector)
57
- self.x = i
55
+ self.x = i + 1
58
56
  self.vectors = new_index
59
57
  else:
60
58
  pass
@@ -67,7 +65,7 @@ class Vault:
67
65
  def load_vectors(self):
68
66
  start_time = time.time()
69
67
  # Download the .ann file from google cloud storage to a temporary file
70
- temp_file_path = self.cloud_manager.download_to_temp_file(f'{self.vault}.ann')
68
+ temp_file_path = self.cloud_manager.download_to_temp_file(name_vecs(self.vault))
71
69
 
72
70
  # Load the AnnoyIndex object from the temporary file, then delete the temp file
73
71
  self.vectors.load(temp_file_path)
@@ -78,7 +76,7 @@ class Vault:
78
76
 
79
77
  def get_vaults(self, vault: str = None):
80
78
  vault = self.vault if vault is None else vault
81
- return self.cloud_manager.get_vaults(vault=f'{vault}')
79
+ return self.cloud_manager.get_vaults(vault)
82
80
 
83
81
 
84
82
  def get_total_vectors(self):
@@ -91,12 +89,12 @@ class Vault:
91
89
 
92
90
  with tempfile.NamedTemporaryFile(delete=False) as temp_file:
93
91
  self.vectors.save(temp_file.name)
94
- self.cloud_manager.upload_temp_file(temp_file.name, f'{self.vault}.ann')
92
+ self.cloud_manager.upload_temp_file(temp_file.name, name_vecs(self.vault))
95
93
 
96
94
  total_saved_items = 0
97
95
  for item in self.items:
98
- item_id = item["meta"]["item_id"]
99
- self.cloud_manager.upload(item_id, item["text"], item["meta"])
96
+ item_text, item_id, item_meta = get_item(item)
97
+ self.cloud_manager.upload(item_id, item_text, item_meta)
100
98
  total_saved_items += 1
101
99
 
102
100
  self.items.clear()
@@ -110,7 +108,7 @@ class Vault:
110
108
  if self.verbose == True:
111
109
  print('Deleting started. Note: this can take a while for large datasets')
112
110
  # Clear the local vector data
113
- self.vectors = AnnoyIndex(self.dims, 'angular')
111
+ self.vectors = get_vectors(self.dims)
114
112
  self.items.clear()
115
113
  self.x = 0
116
114
  self.cloud_manager.delete()
@@ -157,26 +155,15 @@ class Vault:
157
155
  self.load_vectors()
158
156
  start_time = time.time()
159
157
 
160
- # Create an empty list to store the results
161
158
  results = []
162
- indexes = self.vectors.get_nns_by_vector(vector, n)
163
- print(indexes)
164
- for index in indexes:
159
+ vecs = self.vectors.get_nns_by_vector(vector, n)
160
+ for vec in vecs:
165
161
  # Retrieve the item
166
- item_data = self.cloud_manager.download_text_from_cloud(f'{self.vault}/{index}/item')
167
-
162
+ item_data = self.cloud_manager.download_text_from_cloud(name(self.vault, vec, item=True))
168
163
  # Retrieve the metadata
169
- meta_data = self.cloud_manager.download_text_from_cloud(f'{self.vault}/{index}/meta')
164
+ meta_data = self.cloud_manager.download_text_from_cloud(name(self.vault, vec, meta=True))
170
165
  meta = json.loads(meta_data)
171
-
172
- # Create a dictionary with data and metadata
173
- result = {
174
- "data": item_data,
175
- "metadata": meta
176
- }
177
-
178
- # Append the result to the list
179
- results.append(result)
166
+ build_return(results, item_data, meta)
180
167
 
181
168
  # Create a return dictionary
182
169
  return_dict = {
@@ -203,29 +190,8 @@ class Vault:
203
190
  self.check_index()
204
191
  else:
205
192
  pass
206
-
207
- # set value if none exist
208
- meta = {} if meta is None else meta
209
-
210
- if 'name' not in meta and name is None:
211
- name = f'{self.vault}-{self.x}'
212
- elif name is not None:
213
- name = name
214
- meta['name'] = name
215
- meta['item_id'] = self.x # Store the item index in the metadata
216
-
217
- if 'created_at' not in meta:
218
- meta['created_at'] = datetime.datetime.utcnow().isoformat()
219
- if 'updated_at' not in meta:
220
- meta['updated_at'] = datetime.datetime.utcnow().isoformat()
221
-
222
- # Add item and its metadata to the items list
223
- item = {
224
- "text": text,
225
- "meta": meta
226
- }
227
- self.items.append(item)
228
193
 
194
+ self.items.append(itemize(self.vault, self.x, meta, text, name))
229
195
  self.x += 1
230
196
 
231
197
 
@@ -243,7 +209,7 @@ class Vault:
243
209
  texts = [text]
244
210
 
245
211
  for text in texts:
246
- self.add_item(text)
212
+ self.add_item(text, meta, name)
247
213
 
248
214
 
249
215
  def add_item_with_vector(self, text: str, vector: list, meta: dict = None, name: str = None):
@@ -260,30 +226,9 @@ class Vault:
260
226
  if len(text) > 36000:
261
227
  raise 'Text length too long. Use the "split_text() function to get a list of text segments'
262
228
 
263
- # set value if none exist
264
- meta = {} if meta is None else meta
265
-
266
- if 'name' not in meta and name is None:
267
- name = f'{self.vault}-{self.x}'
268
- elif name is not None:
269
- name = name
270
- meta['name'] = name
271
- meta['item_id'] = self.x # Store the item index in the metadata
272
-
273
- if 'created_at' not in meta:
274
- meta['created_at'] = datetime.datetime.utcnow().isoformat()
275
- if 'updated_at' not in meta:
276
- meta['updated_at'] = datetime.datetime.utcnow().isoformat()
277
-
278
229
  # Add vector to vectorspace
279
230
  self.vectors.add_item(self.x, vector)
280
-
281
- # Add item and its metadata to the items list
282
- item = {
283
- "text": text,
284
- "meta": meta
285
- }
286
- self.items.append(item)
231
+ self.items.append(itemize(self.vault, self.x, meta, text, name))
287
232
 
288
233
  self.x += 1
289
234
 
File without changes
File without changes
File without changes