vector-vault 7.2.6__tar.gz → 7.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: 7.2.6
3
+ Version: 7.2.7
4
4
  Summary: Quickly create RAG apps, Agents, and Unleash the full power of AI with Vector Vault
5
5
  Home-page: https://github.com/John-Rood/VectorVault
6
6
  Author: VectorVault.io
@@ -158,6 +158,37 @@ def agent_chat():
158
158
  )
159
159
  ```
160
160
 
161
+ ### Cross-Vault Retrieval
162
+ Search multiple vaults at once and get the absolute most similar results overall. Results are merged across all listed vaults and globally sorted by distance.
163
+
164
+ ```python
165
+ # Chat with cross-vault context
166
+ response = vault.get_chat(
167
+ "Where is the refund policy and API rate limits documented?",
168
+ get_context=True,
169
+ n_context=6,
170
+ vaults=["docs", "customer_support", "developer_portal"]
171
+ )
172
+
173
+ # Or use the low-level API directly
174
+ results = vault.get_similar_from_vaults(
175
+ "refund policy",
176
+ n=8,
177
+ vaults=["docs", "customer_support", "legal"]
178
+ )
179
+
180
+ # Enforce per-vault minimums (remaining slots fill from best overall)
181
+ results = vault.get_similar_from_vaults(
182
+ "refund policy",
183
+ n=5,
184
+ vaults={"legal": 2, "docs": 1}
185
+ )
186
+ ```
187
+
188
+ Notes:
189
+ - You can pass a single vault as a string to target only that vault
190
+ - You can enforce per-vault minimums with a dict: `vaults={"legal": 2, "docs": 1}`; if sum(minima) > n, n automatically expands to the sum of minima; otherwise the remainder fills from best overall
191
+
161
192
  ## 🌟 Why Vector Vault for Autonomous Agents?
162
193
 
163
194
  ### Build True Agents, Not Just Chatbots
@@ -141,6 +141,37 @@ def agent_chat():
141
141
  )
142
142
  ```
143
143
 
144
+ ### Cross-Vault Retrieval
145
+ Search multiple vaults at once and get the absolute most similar results overall. Results are merged across all listed vaults and globally sorted by distance.
146
+
147
+ ```python
148
+ # Chat with cross-vault context
149
+ response = vault.get_chat(
150
+ "Where is the refund policy and API rate limits documented?",
151
+ get_context=True,
152
+ n_context=6,
153
+ vaults=["docs", "customer_support", "developer_portal"]
154
+ )
155
+
156
+ # Or use the low-level API directly
157
+ results = vault.get_similar_from_vaults(
158
+ "refund policy",
159
+ n=8,
160
+ vaults=["docs", "customer_support", "legal"]
161
+ )
162
+
163
+ # Enforce per-vault minimums (remaining slots fill from best overall)
164
+ results = vault.get_similar_from_vaults(
165
+ "refund policy",
166
+ n=5,
167
+ vaults={"legal": 2, "docs": 1}
168
+ )
169
+ ```
170
+
171
+ Notes:
172
+ - You can pass a single vault as a string to target only that vault
173
+ - You can enforce per-vault minimums with a dict: `vaults={"legal": 2, "docs": 1}`; if sum(minima) > n, n automatically expands to the sum of minima; otherwise the remainder fills from best overall
174
+
144
175
  ## 🌟 Why Vector Vault for Autonomous Agents?
145
176
 
146
177
  ### Build True Agents, Not Just Chatbots
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="vector_vault",
5
- version="7.2.6",
5
+ version="7.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: 7.2.6
3
+ Version: 7.2.7
4
4
  Summary: Quickly create RAG apps, Agents, and Unleash the full power of AI with Vector Vault
5
5
  Home-page: https://github.com/John-Rood/VectorVault
6
6
  Author: VectorVault.io
@@ -158,6 +158,37 @@ def agent_chat():
158
158
  )
159
159
  ```
160
160
 
161
+ ### Cross-Vault Retrieval
162
+ Search multiple vaults at once and get the absolute most similar results overall. Results are merged across all listed vaults and globally sorted by distance.
163
+
164
+ ```python
165
+ # Chat with cross-vault context
166
+ response = vault.get_chat(
167
+ "Where is the refund policy and API rate limits documented?",
168
+ get_context=True,
169
+ n_context=6,
170
+ vaults=["docs", "customer_support", "developer_portal"]
171
+ )
172
+
173
+ # Or use the low-level API directly
174
+ results = vault.get_similar_from_vaults(
175
+ "refund policy",
176
+ n=8,
177
+ vaults=["docs", "customer_support", "legal"]
178
+ )
179
+
180
+ # Enforce per-vault minimums (remaining slots fill from best overall)
181
+ results = vault.get_similar_from_vaults(
182
+ "refund policy",
183
+ n=5,
184
+ vaults={"legal": 2, "docs": 1}
185
+ )
186
+ ```
187
+
188
+ Notes:
189
+ - You can pass a single vault as a string to target only that vault
190
+ - You can enforce per-vault minimums with a dict: `vaults={"legal": 2, "docs": 1}`; if sum(minima) > n, n automatically expands to the sum of minima; otherwise the remainder fills from best overall
191
+
161
192
  ## 🌟 Why Vector Vault for Autonomous Agents?
162
193
 
163
194
  ### Build True Agents, Not Just Chatbots
@@ -1181,36 +1181,103 @@ class Vault:
1181
1181
  return self.get_items_by_vector(vector, n, include_distances = include_distances, vault = vault if vault else self.vault)
1182
1182
 
1183
1183
 
1184
- def get_similar_from_vaults(self, text: str, n: int = 4, vaults: List[str] = None):
1184
+ def get_similar_from_vaults(self, text: str, n: int = 4, vaults = None):
1185
1185
  '''
1186
- Searches for the n most similar items in each of the provided vaults, combines the results,
1187
- sorts by distance, and returns the closest n items overall (with distances).
1186
+ Cross-vault similarity search with flexible selection behavior.
1187
+
1188
+ Behavior by type of `vaults`:
1189
+ - str: Treat as a single target vault and return top-n from that vault (with distances)
1190
+ - list[str]: Search each vault, merge, globally sort by distance, return top-n overall
1191
+ - dict[str, int]: Enforce a minimum number from each vault; fill any remaining slots with
1192
+ the best overall matches across all vaults.
1188
1193
 
1189
1194
  Args:
1190
1195
  text: The query text to embed and search with
1191
- n: The number of nearest items to retrieve per vault, and the number of items to return overall
1192
- vaults: A non-empty list of vault names to search
1196
+ n: Total number of items to return overall
1197
+ vaults: A string, list of vault names, or a dict mapping vault name -> minimum count
1193
1198
 
1194
1199
  Returns:
1195
1200
  A list of up to n items, each including a 'distance' field
1196
1201
  '''
1197
- if not vaults or not isinstance(vaults, list):
1198
- raise ValueError("A non-empty list of vaults must be provided.")
1202
+ if not vaults:
1203
+ raise ValueError("`vaults` must be provided as a str, list[str], or dict[str, int].")
1199
1204
 
1200
1205
  T(target=self.cloud_manager.build_update, args=(n,)).start()
1201
1206
  vector = self.process_batch([text], never_stop=False, loop_timeout=180)[0]
1202
1207
 
1203
- combined_results = []
1204
- for v in vaults:
1208
+ # Single vault (string): normal single-vault search with distances
1209
+ if isinstance(vaults, str):
1205
1210
  try:
1206
- results = self.get_items_by_vector(vector, n, include_distances=True, vault=v)
1207
- combined_results.extend(results)
1211
+ return self.get_items_by_vector(vector, n, include_distances=True, vault=vaults)
1208
1212
  except Exception:
1209
- # Skip vaults that cannot be loaded or queried
1210
- continue
1213
+ return []
1214
+
1215
+ # List of vaults: merge and take global top-n
1216
+ if isinstance(vaults, list) and all(isinstance(v, str) for v in vaults):
1217
+ combined_results = []
1218
+ for v in vaults:
1219
+ try:
1220
+ results = self.get_items_by_vector(vector, n, include_distances=True, vault=v)
1221
+ combined_results.extend(results)
1222
+ except Exception:
1223
+ continue
1224
+ combined_sorted = sorted(combined_results, key=lambda x: x.get('distance', float('inf')))
1225
+ return combined_sorted[:n]
1226
+
1227
+ # Dict of vault -> minimum count
1228
+ if isinstance(vaults, dict):
1229
+ minima = {k: int(v) for k, v in vaults.items() if isinstance(k, str)}
1230
+ total_min = sum(minima.values())
1231
+
1232
+ # 1. If total_min > n, override n to match total_min
1233
+ if total_min > n:
1234
+ n = total_min
1235
+
1236
+ # 2. If total_min == n, use the minimum for retrieval number, not n
1237
+ # 3. If n > total_min, fetch n from each vault for leftovers
1238
+ selected = []
1239
+ leftovers = []
1240
+
1241
+ # Determine how many to fetch from each vault
1242
+ # If n > total_min, fetch n from each vault for leftovers
1243
+ # If n <= total_min, fetch min_k from each vault (enough to satisfy minimums)
1244
+ fetch_per_vault = {}
1245
+ if n > total_min:
1246
+ for v, min_k in minima.items():
1247
+ fetch_per_vault[v] = n
1248
+ else:
1249
+ for v, min_k in minima.items():
1250
+ fetch_per_vault[v] = min_k
1251
+
1252
+ # Retrieve results from each vault
1253
+ vault_results = {}
1254
+ for v, min_k in minima.items():
1255
+ try:
1256
+ results = self.get_items_by_vector(vector, fetch_per_vault[v], include_distances=True, vault=v)
1257
+ except Exception:
1258
+ results = []
1259
+ vault_results[v] = results
1260
+
1261
+ # Take the top min_k from this vault (or fewer if unavailable)
1262
+ take_k = min(min_k, len(results))
1263
+ selected.extend(results[:take_k])
1264
+
1265
+ # Keep the rest as leftovers for global fill
1266
+ if len(results) > take_k:
1267
+ leftovers.extend(results[take_k:])
1268
+
1269
+ # Fill remaining with best overall from leftovers
1270
+ remaining_needed = max(0, n - len(selected))
1271
+ if remaining_needed > 0:
1272
+ leftovers_sorted = sorted(leftovers, key=lambda x: x.get('distance', float('inf')))
1273
+ selected.extend(leftovers_sorted[:remaining_needed])
1274
+
1275
+ # Final global sort for presentation consistency
1276
+ selected_sorted = sorted(selected, key=lambda x: x.get('distance', float('inf')))
1277
+ return selected_sorted[:n]
1211
1278
 
1212
- combined_sorted = sorted(combined_results, key=lambda x: x.get('distance', float('inf')))
1213
- return combined_sorted[:n]
1279
+ # Unsupported type
1280
+ raise ValueError("`vaults` must be a str, list[str], or dict[str, int].")
1214
1281
 
1215
1282
 
1216
1283
  def add_item(self, text: str, meta: dict = None, name: str = None):
@@ -1437,7 +1504,7 @@ class Vault:
1437
1504
  else:
1438
1505
  search_input = segment + history if history_search else segment
1439
1506
 
1440
- if vaults and isinstance(vaults, list) and all(isinstance(v, str) for v in vaults):
1507
+ if vaults:
1441
1508
  context = self.get_similar_from_vaults(search_input, n=n_context, vaults=vaults)
1442
1509
  else:
1443
1510
  context = self.get_similar(search_input, n=n_context)
@@ -1584,7 +1651,7 @@ class Vault:
1584
1651
  else:
1585
1652
  search_input = segment + history if history_search else segment
1586
1653
 
1587
- if vaults and isinstance(vaults, list) and all(isinstance(v, str) for v in vaults):
1654
+ if vaults:
1588
1655
  context = self.get_similar_from_vaults(search_input, n=n_context, vaults=vaults)
1589
1656
  else:
1590
1657
  context = self.get_similar(search_input, n=n_context)
File without changes
File without changes