hermes-client-python 1.4.8__tar.gz → 1.4.9__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.4
2
2
  Name: hermes-client-python
3
- Version: 1.4.8
3
+ Version: 1.4.9
4
4
  Summary: Async Python client for Hermes search server
5
5
  Project-URL: Homepage, https://github.com/SpaceFrontiers/hermes
6
6
  Project-URL: Repository, https://github.com/SpaceFrontiers/hermes
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "hermes-client-python"
7
- version = "1.4.8"
7
+ version = "1.4.9"
8
8
  description = "Async Python client for Hermes search server"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -361,8 +361,34 @@ class HermesClient:
361
361
  # =============================================================================
362
362
 
363
363
 
364
+ def _is_sparse_vector(value: list) -> bool:
365
+ """Check if list is a sparse vector: list of (int, float) pairs."""
366
+ if not value:
367
+ return False
368
+ for item in value:
369
+ if not isinstance(item, (list, tuple)) or len(item) != 2:
370
+ return False
371
+ idx, val = item
372
+ if not isinstance(idx, int) or not isinstance(val, (int, float)):
373
+ return False
374
+ return True
375
+
376
+
377
+ def _is_dense_vector(value: list) -> bool:
378
+ """Check if list is a dense vector: flat list of numeric values."""
379
+ if not value:
380
+ return False
381
+ return all(isinstance(v, (int, float)) and not isinstance(v, bool) for v in value)
382
+
383
+
364
384
  def _to_field_value(value: Any) -> pb.FieldValue:
365
- """Convert Python value to protobuf FieldValue."""
385
+ """Convert Python value to protobuf FieldValue.
386
+
387
+ Special handling for vector types:
388
+ - list[(int, float)] -> SparseVector (list of (index, value) tuples)
389
+ - list[float] -> DenseVector (flat list of numeric values)
390
+ - Other lists/dicts -> JSON
391
+ """
366
392
  if isinstance(value, str):
367
393
  return pb.FieldValue(text=value)
368
394
  elif isinstance(value, bool):
@@ -376,8 +402,23 @@ def _to_field_value(value: Any) -> pb.FieldValue:
376
402
  return pb.FieldValue(f64=value)
377
403
  elif isinstance(value, bytes):
378
404
  return pb.FieldValue(bytes_value=value)
379
- elif isinstance(value, (list, dict)):
380
- # Assume JSON for complex types
405
+ elif isinstance(value, dict):
406
+ # Dicts are always JSON
407
+ return pb.FieldValue(json_value=json.dumps(value))
408
+ elif isinstance(value, list):
409
+ # Check if it's a sparse vector: list of (index, value) pairs
410
+ if _is_sparse_vector(value):
411
+ indices = [int(item[0]) for item in value]
412
+ values = [float(item[1]) for item in value]
413
+ return pb.FieldValue(
414
+ sparse_vector=pb.SparseVector(indices=indices, values=values)
415
+ )
416
+ # Check if it's a dense vector: flat list of numeric values
417
+ if _is_dense_vector(value):
418
+ return pb.FieldValue(
419
+ dense_vector=pb.DenseVector(values=[float(v) for v in value])
420
+ )
421
+ # Otherwise treat as JSON
381
422
  return pb.FieldValue(json_value=json.dumps(value))
382
423
  else:
383
424
  return pb.FieldValue(text=str(value))