projectdavid 1.33.20__py3-none-any.whl → 1.33.22__py3-none-any.whl

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.

Potentially problematic release.


This version of projectdavid might be problematic. Click here for more details.

@@ -7,10 +7,8 @@ details from the higher‑level SDK.
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
- import inspect
11
10
  import time
12
11
  import uuid
13
- from pathlib import Path
14
12
  from typing import Any, Dict, List, Optional
15
13
 
16
14
  from dotenv import load_dotenv
@@ -57,12 +55,14 @@ class VectorStoreManager(BaseVectorStore):
57
55
  vectors_config: Optional[Dict[str, qdrant.VectorParams]] = None,
58
56
  ) -> dict:
59
57
  """
60
- Create or recreate a Qdrant collection. By default creates a single-vector
61
- collection with `vector_size`. To define multi-vector schema, pass
62
- `vectors_config` mapping field names to VectorParams.
58
+ Create or recreate a Qdrant collection.
59
+
60
+ • If *vectors_config* is provided use it verbatim (multi-vector schema).
61
+ • Otherwise create a classic single-vector collection *without* naming the
62
+ vector field – so upserts can omit ``vector_name``.
63
63
  """
64
64
  try:
65
- # existence check
65
+ # ── pre-existence check ────────────────────────────────────────────
66
66
  if any(
67
67
  col.name == collection_name
68
68
  for col in self.client.get_collections().collections
@@ -73,27 +73,32 @@ class VectorStoreManager(BaseVectorStore):
73
73
  if dist not in qdrant.Distance.__members__:
74
74
  raise ValueError(f"Invalid distance metric '{distance}'")
75
75
 
76
- # choose schema
77
- if vectors_config:
78
- config = vectors_config
79
- else:
80
- config = {
81
- "_default": qdrant.VectorParams(
82
- size=vector_size, distance=qdrant.Distance[dist]
83
- )
84
- }
76
+ # ── choose schema ──────────────────────────────────────────────────
77
+ if vectors_config: # caller supplied full mapping
78
+ config = vectors_config # e.g. {"text_vec": ..., "img_vec": ...}
79
+ else: # default = single unnamed vector
80
+ config = qdrant.VectorParams(
81
+ size=vector_size,
82
+ distance=qdrant.Distance[dist],
83
+ )
85
84
 
86
- # recreate with full schema
85
+ # ── (re)create collection ─────────────────────────────────────────
87
86
  self.client.recreate_collection(
88
87
  collection_name=collection_name,
89
88
  vectors_config=config,
90
89
  )
91
- # record metadata for each field
90
+
91
+ # ── bookkeeping ───────────────────────────────────────────────────
92
+ if isinstance(config, dict):
93
+ fields = list(config.keys())
94
+ else: # unnamed field
95
+ fields = [None]
96
+
92
97
  self.active_stores[collection_name] = {
93
98
  "created_at": int(time.time()),
94
99
  "vector_size": vector_size,
95
100
  "distance": dist,
96
- "fields": list(config.keys()),
101
+ "fields": fields,
97
102
  }
98
103
  log.info("Created Qdrant collection %s", collection_name)
99
104
  return {"collection_name": collection_name, "status": "created"}
@@ -139,13 +144,17 @@ class VectorStoreManager(BaseVectorStore):
139
144
  metadata: List[dict],
140
145
  vector_name: Optional[str] = None,
141
146
  ) -> Dict[str, Any]:
142
- """Upsert vectors + payloads into *store_name*.
147
+ """
148
+ Upsert vectors + payloads into *store_name*.
149
+
150
+ If *vector_name* is omitted the manager:
143
151
 
144
- If *vector_name* is omitted, the manager auto‑detects the sole vector
145
- field. If multiple fields exist it raises a clear error.
152
+ auto-detects the single vector field for classic (unnamed) collections
153
+ auto-detects the sole key for named-vector collections with exactly one field
154
+ • raises if multiple named fields exist.
146
155
  """
147
156
 
148
- # ---- validate input ------------------------------------------------
157
+ # ─── input validation ───────────────────────────────────────────────
149
158
  if not vectors:
150
159
  raise ValueError("Empty vectors list")
151
160
  expected = len(vectors[0])
@@ -153,22 +162,33 @@ class VectorStoreManager(BaseVectorStore):
153
162
  if len(vec) != expected or not all(isinstance(v, float) for v in vec):
154
163
  raise ValueError(f"Vector {i} malformed: expected {expected} floats")
155
164
 
156
- # ---- autodetect vector field --------------------------------------
165
+ # ─── auto-detect vector field ───────────────────────────────────────
157
166
  if vector_name is None:
158
167
  coll_info = self.client.get_collection(collection_name=store_name)
159
168
  v_cfg = coll_info.config.params.vectors
160
- vector_fields = list(v_cfg.keys()) if isinstance(v_cfg, dict) else [v_cfg]
161
- if len(vector_fields) == 1:
162
- vector_name = vector_fields[0]
163
- log.debug(
164
- "Auto‑detected vector_name=%r for store=%s", vector_name, store_name
165
- )
169
+
170
+ if isinstance(v_cfg, dict): # modern named-vector schema
171
+ vector_fields = list(v_cfg.keys())
172
+ if len(vector_fields) == 1: # exactly one → safe default
173
+ vector_name = vector_fields[0]
174
+ log.debug(
175
+ "Auto-detected vector_name=%r for store=%s",
176
+ vector_name,
177
+ store_name,
178
+ )
179
+ else: # >1 named fields → ambiguous
180
+ raise ValueError(
181
+ f"Multiple vector fields {vector_fields}; please specify vector_name"
182
+ )
166
183
  else:
167
- raise ValueError(
168
- f"Multiple vector fields {vector_fields}; please specify vector_name"
184
+ # legacy single-vector schema → leave vector_name as None
185
+ log.debug(
186
+ "Collection %s uses legacy single-vector schema; "
187
+ "upserting without vector_name",
188
+ store_name,
169
189
  )
170
190
 
171
- # ---- build points ---------------------------------------------------
191
+ # ─── build points payload ───────────────────────────────────────────
172
192
  points = [
173
193
  qdrant.PointStruct(
174
194
  id=self._generate_vector_id(),
@@ -178,7 +198,9 @@ class VectorStoreManager(BaseVectorStore):
178
198
  for txt, vec, meta in zip(texts, vectors, metadata)
179
199
  ]
180
200
 
181
- # ---- upsert with backwardcompat for old clients --------------------
201
+ # ─── upsert with backward-compat for old qdrant-client builds ───────
202
+ import inspect # keep local to avoid top-level dependency if absent elsewhere
203
+
182
204
  upsert_sig = inspect.signature(self.client.upsert)
183
205
  supports_vector_name = "vector_name" in upsert_sig.parameters
184
206
 
@@ -187,14 +209,14 @@ class VectorStoreManager(BaseVectorStore):
187
209
  "points": points,
188
210
  "wait": True,
189
211
  }
190
- if supports_vector_name:
212
+ if supports_vector_name and vector_name is not None:
191
213
  upsert_kwargs["vector_name"] = vector_name
192
214
 
193
215
  try:
194
216
  self.client.upsert(**upsert_kwargs)
195
217
  return {"status": "success", "points_inserted": len(points)}
196
218
  except Exception as exc: # noqa: BLE001
197
- log.error("Addtostore failed: %s", exc, exc_info=True)
219
+ log.error("Add-to-store failed: %s", exc, exc_info=True)
198
220
  raise VectorStoreError(f"Insertion failed: {exc}") from exc
199
221
 
200
222
  # ------------------------------------------------------------------ #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: projectdavid
3
- Version: 1.33.20
3
+ Version: 1.33.22
4
4
  Summary: Python SDK for interacting with the Entities Assistant API.
5
5
  Author-email: Francis Neequaye Armah <francis.neequaye@projectdavid.co.uk>
6
6
  License: PolyForm Noncommercial License 1.0.0
@@ -20,7 +20,7 @@ projectdavid/clients/synchronous_inference_wrapper.py,sha256=qh94rtNlLqgIxiA_ZbQ
20
20
  projectdavid/clients/threads_client.py,sha256=ekzU5w14zftmtmFkiec3NC90Of-_KVSUY1qH9cmfSFg,6771
21
21
  projectdavid/clients/tools_client.py,sha256=GkCVOmwpAoPqVt6aYmH0G1HIFha3iEwR9IIf9teR0j8,11487
22
22
  projectdavid/clients/users_client.py,sha256=eCuUb9qvyH1GUFhZu6TRL9zdoK-qzHSs8-Vmrk_0mmg,13729
23
- projectdavid/clients/vector_store_manager.py,sha256=4uedMZ7foNr7s4Lsq5-FSN5kl4lR-Y8-nUlkoO2ff8M,14119
23
+ projectdavid/clients/vector_store_manager.py,sha256=A-L1rhURKwiRs0EDd1HOuIShOtaC9Hb1yHB4He456Zc,15943
24
24
  projectdavid/clients/vectors.py,sha256=TcY-kMsFFbjZV3hIJ4qlRBZvaxtTbIAVzGS0GdQJNuI,31956
25
25
  projectdavid/clients/vision-file_processor.py,sha256=19ft9IUeY5x9_22vC4JqndiFlpDYyUn6z1ygv-EV2NE,16852
26
26
  projectdavid/clients/vision_vectors.py,sha256=cysPVbUzW3byB82MTqG2X1Iz5ZAe82WTS1JfQcoqVhE,40229
@@ -37,8 +37,8 @@ projectdavid/utils/monitor_launcher.py,sha256=3YAgJdeuaUvq3JGvpA4ymqFsAnk29nH5q9
37
37
  projectdavid/utils/peek_gate.py,sha256=5whMRnDOQjATRpThWDJkvY9ScXuJ7Sd_-9rvGgXeTAQ,2532
38
38
  projectdavid/utils/run_monitor.py,sha256=F_WkqIP-qnWH-4llIbileWWLfRj2Q1Cg-ni23SR1rec,3786
39
39
  projectdavid/utils/vector_search_formatter.py,sha256=YTe3HPGec26qGY7uxY8_GS8lc4QaN6aNXMzkl29nZpI,1735
40
- projectdavid-1.33.20.dist-info/licenses/LICENSE,sha256=_8yjiEGttpS284BkfhXxfERqTRZW_tUaHiBB0GTJTMg,4563
41
- projectdavid-1.33.20.dist-info/METADATA,sha256=pV7oSTxkZfCgK-GcJ1u2HZLvWr16vZssNGpQAmeJ1oY,11555
42
- projectdavid-1.33.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
- projectdavid-1.33.20.dist-info/top_level.txt,sha256=kil8GU4s7qYRfNnzGnFHhZnSNRSxgNG-J4HLgQMmMtw,13
44
- projectdavid-1.33.20.dist-info/RECORD,,
40
+ projectdavid-1.33.22.dist-info/licenses/LICENSE,sha256=_8yjiEGttpS284BkfhXxfERqTRZW_tUaHiBB0GTJTMg,4563
41
+ projectdavid-1.33.22.dist-info/METADATA,sha256=Q4TM1PmVUXpccxOLaRrKnx2qwZw48w7nt-XUOlUiJaE,11555
42
+ projectdavid-1.33.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
+ projectdavid-1.33.22.dist-info/top_level.txt,sha256=kil8GU4s7qYRfNnzGnFHhZnSNRSxgNG-J4HLgQMmMtw,13
44
+ projectdavid-1.33.22.dist-info/RECORD,,