qdrant: enforce int/UUID point ids; preserve original id in payload; add error handling

This commit is contained in:
2026-03-21 10:12:34 +01:00
parent 4218034d70
commit 8f758cf3b5

View File

@@ -148,7 +148,27 @@ def _build_filter(metadata: Dict[str, Any]) -> Optional[Filter]:
def _point_id(raw: Optional[str]) -> str:
return raw or uuid.uuid4().hex
"""Return a Qdrant-compatible point id.
Qdrant accepts either an unsigned integer or a UUID string (with hyphens).
If the provided `raw` value is an int or valid UUID we return it (as int or str).
Otherwise we generate a new UUID string and the caller should store the
original `raw` value in the point payload under `_original_id`.
"""
if not raw:
return str(uuid.uuid4())
# allow integer ids
try:
return int(raw)
except Exception:
pass
# allow UUID strings
try:
u = uuid.UUID(raw)
return str(u)
except Exception:
# fallback: generate a UUID
return str(uuid.uuid4())
# ---------------------------------------------------------------------------
@@ -223,12 +243,19 @@ async def upsert_url(req: UpsertUrlRequest):
vector = await _embed_url(req.url)
pid = _point_id(req.id)
payload = {**req.metadata, "source_url": req.url}
# preserve original user-provided id if it wasn't usable as a point id
if req.id is not None and str(pid) != str(req.id):
payload["_original_id"] = req.id
col = _col(req.collection)
client.upsert(
collection_name=col,
points=[PointStruct(id=pid, vector=vector, payload=payload)],
)
try:
client.upsert(
collection_name=col,
points=[PointStruct(id=pid, vector=vector, payload=payload)],
)
except Exception as e:
raise HTTPException(500, str(e))
return {"id": pid, "collection": col, "dim": len(vector)}
@@ -252,12 +279,19 @@ async def upsert_file(
payload = json.loads(metadata_json)
except json.JSONDecodeError:
raise HTTPException(400, "metadata_json must be valid JSON")
# preserve original user-provided id if it wasn't usable as a point id
if id is not None and str(pid) != str(id):
payload["_original_id"] = id
col = _col(collection)
client.upsert(
collection_name=col,
points=[PointStruct(id=pid, vector=vector, payload=payload)],
)
try:
client.upsert(
collection_name=col,
points=[PointStruct(id=pid, vector=vector, payload=payload)],
)
except Exception as e:
raise HTTPException(500, str(e))
return {"id": pid, "collection": col, "dim": len(vector)}
@@ -266,10 +300,16 @@ def upsert_vector(req: UpsertVectorRequest):
"""Store a pre-computed vector directly (skip CLIP embedding)."""
pid = _point_id(req.id)
col = _col(req.collection)
client.upsert(
collection_name=col,
points=[PointStruct(id=pid, vector=req.vector, payload=req.metadata)],
)
payload = dict(req.metadata or {})
if req.id is not None and str(pid) != str(req.id):
payload["_original_id"] = req.id
try:
client.upsert(
collection_name=col,
points=[PointStruct(id=pid, vector=req.vector, payload=payload)],
)
except Exception as e:
raise HTTPException(500, str(e))
return {"id": pid, "collection": col, "dim": len(req.vector)}