hermes-client-python 1.7.14__tar.gz → 1.7.16__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.7.14
3
+ Version: 1.7.16
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.7.14"
7
+ version = "1.7.16"
8
8
  description = "Async Python client for Hermes search server"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,45 @@
1
+ """Async Python client for Hermes search server."""
2
+
3
+ from .client import HermesClient
4
+ from .types import (
5
+ AllQuery,
6
+ BooleanQuery,
7
+ BoostQuery,
8
+ Combiner,
9
+ DenseVectorQuery,
10
+ DocAddress,
11
+ Document,
12
+ Filter,
13
+ IndexInfo,
14
+ MatchQuery,
15
+ Reranker,
16
+ SearchHit,
17
+ SearchResponse,
18
+ SearchTimings,
19
+ SparseVectorQuery,
20
+ TermQuery,
21
+ VectorFieldStats,
22
+ )
23
+
24
+ __all__ = [
25
+ "HermesClient",
26
+ "AllQuery",
27
+ "BooleanQuery",
28
+ "BoostQuery",
29
+ "Combiner",
30
+ "DenseVectorQuery",
31
+ "DocAddress",
32
+ "Document",
33
+ "Filter",
34
+ "IndexInfo",
35
+ "MatchQuery",
36
+ "Reranker",
37
+ "SearchHit",
38
+ "SearchResponse",
39
+ "SearchTimings",
40
+ "SparseVectorQuery",
41
+ "TermQuery",
42
+ "VectorFieldStats",
43
+ ]
44
+
45
+ __version__ = "1.0.2"
@@ -1,4 +1,8 @@
1
- """Async Hermes client implementation."""
1
+ """Async Hermes client implementation.
2
+
3
+ All search types mirror the proto API structure exactly.
4
+ See types.py for Query, Reranker, Filter definitions.
5
+ """
2
6
 
3
7
  from __future__ import annotations
4
8
 
@@ -25,6 +29,8 @@ from .types import (
25
29
  class HermesClient:
26
30
  """Async client for Hermes search server.
27
31
 
32
+ All search types mirror the proto API structure exactly.
33
+
28
34
  Example:
29
35
  async with HermesClient("localhost:50051") as client:
30
36
  # Create index
@@ -43,9 +49,10 @@ class HermesClient:
43
49
  await client.commit("articles")
44
50
 
45
51
  # Search
46
- results = await client.search("articles", term=("title", "hello"))
52
+ results = await client.search("articles",
53
+ query={"match": {"field": "title", "text": "hello"}})
47
54
  for hit in results.hits:
48
- print(hit.doc_id, hit.score)
55
+ print(hit.address, hit.score)
49
56
  """
50
57
 
51
58
  def __init__(self, address: str = "localhost:50051"):
@@ -297,124 +304,95 @@ class HermesClient:
297
304
  self,
298
305
  index_name: str,
299
306
  *,
300
- term: tuple[str, str] | None = None,
301
- match: tuple[str, str] | None = None,
302
- boolean: dict[str, list[tuple[str, str]]] | None = None,
303
- sparse_vector: tuple[str, list[int], list[float]] | None = None,
304
- sparse_text: tuple[str, str] | None = None,
305
- dense_vector: tuple[str, list[float]] | None = None,
306
- nprobe: int = 0,
307
- rerank_factor: int = 0,
308
- heap_factor: float = 1.0,
309
- combiner: str = "sum",
307
+ query: dict[str, Any],
310
308
  limit: int = 10,
311
309
  offset: int = 0,
312
310
  fields_to_load: list[str] | None = None,
313
- reranker: tuple[str, list[float], int] | None = None,
314
- reranker_combiner: str = "weighted_top_k",
315
- matryoshka_dims: int = 0,
311
+ reranker: dict[str, Any] | None = None,
316
312
  filters: list[dict[str, Any]] | None = None,
317
313
  ) -> SearchResponse:
318
314
  """Search for documents.
319
315
 
316
+ All parameters mirror the proto SearchRequest structure exactly.
317
+ ``query`` is a dict with exactly one key matching the proto Query oneof.
318
+
320
319
  Args:
321
320
  index_name: Name of the index
322
- term: Term query as (field, term) tuple - exact single-term match
323
- match: Match query as (field, text) tuple - tokenizes text server-side
324
- and searches as OR of individual tokens (use for natural language)
325
- boolean: Boolean query with "must", "should", "must_not" keys
326
- sparse_vector: Sparse vector query as (field, indices, values) tuple
327
- sparse_text: Sparse vector query with server-side tokenization as (field, text) tuple
328
- dense_vector: Dense vector query as (field, vector) tuple
329
- nprobe: Number of clusters to probe for dense vector (IVF indexes)
330
- rerank_factor: Re-ranking factor for dense vector search
331
- heap_factor: Approximate search factor for sparse vectors (1.0=exact, 0.8=faster)
332
- combiner: Score combiner for multi-value fields: "sum", "max", or "avg"
321
+ query: Query dict with one key: "term", "match", "boolean",
322
+ "sparse_vector", "dense_vector", "boost", or "all".
333
323
  limit: Maximum number of results
334
324
  offset: Offset for pagination
335
325
  fields_to_load: List of fields to include in results
336
- reranker: L2 reranker as (field, query_vector, l1_limit) tuple.
337
- Reranks L1 candidates by exact dense vector distance.
338
- l1_limit=0 defaults to 10x the final limit.
339
- reranker_combiner: Score combiner for reranker multi-value fields:
340
- "log_sum_exp" (default), "max", "avg", "sum"
341
- matryoshka_dims: Matryoshka pre-filter dimensions for reranker.
342
- When > 0, scores candidates on leading N dimensions first,
343
- keeps top survivors, then does full-dimension exact scoring.
344
- 0 = disabled (default).
345
- filters: Fast-field filters. Each dict has "field" and one condition key:
346
- - {"field": "status", "eq_text": "active"}
347
- - {"field": "price", "eq_u64": 100}
348
- - {"field": "price", "range": {"min": 10.0, "max": 100.0}}
349
- - {"field": "category", "in_text": ["books", "movies"]}
350
- - {"field": "count", "in_u64": [1, 2, 3]}
326
+ reranker: Reranker dict matching proto Reranker message
327
+ filters: List of filter dicts matching proto Filter message
351
328
 
352
329
  Returns:
353
330
  SearchResponse with hits
354
331
 
355
332
  Examples:
356
333
  # Term query (exact single token)
357
- results = await client.search("articles", term=("title", "hello"))
334
+ results = await client.search("articles",
335
+ query={"term": {"field": "title", "term": "hello"}})
358
336
 
359
337
  # Match query (full-text, tokenized server-side)
360
- results = await client.search("articles", match=("title", "what is hemoglobin"))
338
+ results = await client.search("articles",
339
+ query={"match": {"field": "title", "text": "what is hemoglobin"}})
361
340
 
362
341
  # Boolean query
363
- results = await client.search("articles", boolean={
364
- "must": [("title", "hello")],
365
- "should": [("body", "world")],
366
- })
342
+ results = await client.search("articles",
343
+ query={"boolean": {
344
+ "must": [{"match": {"field": "title", "text": "hello"}}],
345
+ "should": [{"match": {"field": "body", "text": "world"}}],
346
+ }})
367
347
 
368
- # Sparse vector query (pre-tokenized)
348
+ # Sparse text query (server-side tokenization) with pruning
369
349
  results = await client.search("docs",
370
- sparse_vector=("embedding", [1, 5, 10], [0.5, 0.3, 0.2]),
371
- fields_to_load=["title", "body"]
372
- )
373
-
374
- # Sparse text query (server-side tokenization)
350
+ query={"sparse_vector": {
351
+ "field": "embedding",
352
+ "text": "machine learning",
353
+ "pruning": 0.5,
354
+ }},
355
+ fields_to_load=["title", "body"])
356
+
357
+ # Sparse vector query (pre-computed)
375
358
  results = await client.search("docs",
376
- sparse_text=("embedding", "what is machine learning?"),
377
- fields_to_load=["title", "body"]
378
- )
359
+ query={"sparse_vector": {
360
+ "field": "embedding",
361
+ "indices": [1, 5, 10],
362
+ "values": [0.5, 0.3, 0.2],
363
+ }})
379
364
 
380
- # Dense vector query
365
+ # Dense vector query with reranker
381
366
  results = await client.search("docs",
382
- dense_vector=("embedding", [0.1, 0.2, 0.3, ...]),
383
- fields_to_load=["title"]
384
- )
367
+ query={"dense_vector": {
368
+ "field": "embedding",
369
+ "vector": [0.1, 0.2, 0.3],
370
+ "nprobe": 10,
371
+ }},
372
+ reranker={
373
+ "field": "embedding",
374
+ "vector": [0.1, 0.2, 0.3],
375
+ "limit": 100,
376
+ },
377
+ fields_to_load=["title"])
378
+
379
+ # Filters
380
+ results = await client.search("docs",
381
+ query={"match": {"field": "title", "text": "hello"}},
382
+ filters=[
383
+ {"field": "status", "eq_text": "active"},
384
+ {"field": "price", "range": {"min": 10.0, "max": 100.0}},
385
+ ])
385
386
  """
386
387
  self._ensure_connected()
387
388
 
388
- query = _build_query(
389
- term=term,
390
- match=match,
391
- boolean=boolean,
392
- sparse_vector=sparse_vector,
393
- sparse_text=sparse_text,
394
- dense_vector=dense_vector,
395
- nprobe=nprobe,
396
- rerank_factor=rerank_factor,
397
- heap_factor=heap_factor,
398
- combiner=combiner,
399
- )
400
-
401
- pb_reranker = None
402
- if reranker is not None:
403
- field_name, query_vector, l1_limit = reranker
404
- reranker_combiner_value = _reranker_combiner_to_proto(reranker_combiner)
405
- pb_reranker = pb.Reranker(
406
- field=field_name,
407
- vector=query_vector,
408
- limit=l1_limit,
409
- combiner=reranker_combiner_value,
410
- matryoshka_dims=matryoshka_dims,
411
- )
412
-
413
- pb_filters = _build_filters(filters) if filters else []
389
+ pb_query = _build_query(query)
390
+ pb_reranker = _build_reranker(reranker) if reranker else None
391
+ pb_filters = [_build_filter(f) for f in filters] if filters else []
414
392
 
415
393
  request = pb.SearchRequest(
416
394
  index_name=index_name,
417
- query=query,
395
+ query=pb_query,
418
396
  limit=limit,
419
397
  offset=offset,
420
398
  fields_to_load=fields_to_load or [],
@@ -625,129 +603,134 @@ def _from_field_value(fv: pb.FieldValue) -> Any:
625
603
  return None
626
604
 
627
605
 
628
- def _combiner_to_proto(combiner: str) -> int:
629
- """Convert combiner string to proto enum value."""
630
- return {"sum": 0, "max": 1, "avg": 2}.get(combiner.lower(), 0)
631
-
632
-
633
- def _reranker_combiner_to_proto(combiner: str) -> int:
634
- """Convert reranker combiner string to proto MultiValueCombiner enum."""
635
- return {
636
- "log_sum_exp": 0,
637
- "max": 1,
638
- "avg": 2,
639
- "sum": 3,
640
- "weighted_top_k": 4,
641
- }.get(combiner.lower(), 0)
642
-
643
-
644
- def _build_filters(filters: list[dict[str, Any]]) -> list[pb.Filter]:
645
- """Convert filter dicts to protobuf Filter messages."""
646
- result = []
647
- for f in filters:
648
- field = f["field"]
649
- kwargs: dict[str, Any] = {"field": field}
650
- if "eq_u64" in f:
651
- kwargs["eq_u64"] = int(f["eq_u64"])
652
- elif "eq_i64" in f:
653
- kwargs["eq_i64"] = int(f["eq_i64"])
654
- elif "eq_f64" in f:
655
- kwargs["eq_f64"] = float(f["eq_f64"])
656
- elif "eq_text" in f:
657
- kwargs["eq_text"] = str(f["eq_text"])
658
- elif "range" in f:
659
- r = f["range"]
660
- range_kwargs = {}
661
- if "min" in r:
662
- range_kwargs["min"] = float(r["min"])
663
- if "max" in r:
664
- range_kwargs["max"] = float(r["max"])
665
- kwargs["range"] = pb.RangeFilter(**range_kwargs)
666
- elif "in_text" in f:
667
- kwargs["in_values"] = pb.InFilter(text_values=list(f["in_text"]))
668
- elif "in_u64" in f:
669
- kwargs["in_values"] = pb.InFilter(u64_values=[int(v) for v in f["in_u64"]])
670
- elif "in_i64" in f:
671
- kwargs["in_values"] = pb.InFilter(i64_values=[int(v) for v in f["in_i64"]])
672
- result.append(pb.Filter(**kwargs))
673
- return result
674
-
675
-
676
- def _build_query(
677
- *,
678
- term: tuple[str, str] | None = None,
679
- match: tuple[str, str] | None = None,
680
- boolean: dict[str, list[tuple[str, str]]] | None = None,
681
- sparse_vector: tuple[str, list[int], list[float]] | None = None,
682
- sparse_text: tuple[str, str] | None = None,
683
- dense_vector: tuple[str, list[float]] | None = None,
684
- nprobe: int = 0,
685
- rerank_factor: int = 0,
686
- heap_factor: float = 1.0,
687
- combiner: str = "sum",
688
- ) -> pb.Query:
689
- """Build a protobuf Query from parameters."""
690
- if term is not None:
691
- field, value = term
692
- return pb.Query(term=pb.TermQuery(field=field, term=value))
693
-
694
- if match is not None:
695
- field, text = match
696
- return pb.Query(match=pb.MatchQuery(field=field, text=text))
697
-
698
- if boolean is not None:
699
- must = [
700
- pb.Query(match=pb.MatchQuery(field=f, text=t))
701
- for f, t in boolean.get("must", [])
702
- ]
703
- should = [
704
- pb.Query(match=pb.MatchQuery(field=f, text=t))
705
- for f, t in boolean.get("should", [])
706
- ]
707
- must_not = [
708
- pb.Query(match=pb.MatchQuery(field=f, text=t))
709
- for f, t in boolean.get("must_not", [])
710
- ]
711
- return pb.Query(
712
- boolean=pb.BooleanQuery(must=must, should=should, must_not=must_not)
713
- )
606
+ _COMBINER_MAP: dict[str, int] = {
607
+ "log_sum_exp": 0,
608
+ "max": 1,
609
+ "avg": 2,
610
+ "sum": 3,
611
+ "weighted_top_k": 4,
612
+ }
613
+
614
+
615
+ def _combiner_to_proto(combiner: str | None) -> int:
616
+ """Convert combiner string to proto MultiValueCombiner enum value."""
617
+ if combiner is None:
618
+ return 0 # LOG_SUM_EXP default
619
+ return _COMBINER_MAP.get(combiner.lower(), 0)
620
+
714
621
 
715
- combiner_value = _combiner_to_proto(combiner)
622
+ def _build_query(q: dict[str, Any]) -> pb.Query:
623
+ """Recursively convert a Query dict to protobuf Query.
716
624
 
717
- if sparse_vector is not None:
718
- field, indices, values = sparse_vector
625
+ The dict must have exactly one key matching the proto Query oneof:
626
+ "term", "match", "boolean", "sparse_vector", "dense_vector", "boost", "all".
627
+ """
628
+ if "term" in q:
629
+ t = q["term"]
630
+ return pb.Query(term=pb.TermQuery(field=t["field"], term=t["term"]))
631
+
632
+ if "match" in q:
633
+ m = q["match"]
634
+ return pb.Query(match=pb.MatchQuery(field=m["field"], text=m["text"]))
635
+
636
+ if "boolean" in q:
637
+ b = q["boolean"]
719
638
  return pb.Query(
720
- sparse_vector=pb.SparseVectorQuery(
721
- field=field,
722
- indices=indices,
723
- values=values,
724
- combiner=combiner_value,
725
- heap_factor=heap_factor,
639
+ boolean=pb.BooleanQuery(
640
+ must=[_build_query(sq) for sq in b.get("must", [])],
641
+ should=[_build_query(sq) for sq in b.get("should", [])],
642
+ must_not=[_build_query(sq) for sq in b.get("must_not", [])],
726
643
  )
727
644
  )
728
645
 
729
- if sparse_text is not None:
730
- field, text = sparse_text
646
+ if "sparse_vector" in q:
647
+ sv = q["sparse_vector"]
731
648
  return pb.Query(
732
649
  sparse_vector=pb.SparseVectorQuery(
733
- field=field,
734
- text=text,
735
- combiner=combiner_value,
736
- heap_factor=heap_factor,
650
+ field=sv["field"],
651
+ indices=sv.get("indices", []),
652
+ values=sv.get("values", []),
653
+ text=sv.get("text", ""),
654
+ combiner=_combiner_to_proto(sv.get("combiner")),
655
+ heap_factor=sv.get("heap_factor", 0),
656
+ combiner_temperature=sv.get("combiner_temperature", 0),
657
+ combiner_top_k=sv.get("combiner_top_k", 0),
658
+ combiner_decay=sv.get("combiner_decay", 0),
659
+ weight_threshold=sv.get("weight_threshold", 0),
660
+ max_query_dims=sv.get("max_query_dims", 0),
661
+ pruning=sv.get("pruning", 0),
737
662
  )
738
663
  )
739
664
 
740
- if dense_vector is not None:
741
- field, vector = dense_vector
665
+ if "dense_vector" in q:
666
+ dv = q["dense_vector"]
742
667
  return pb.Query(
743
668
  dense_vector=pb.DenseVectorQuery(
744
- field=field,
745
- vector=vector,
746
- nprobe=nprobe,
747
- rerank_factor=rerank_factor,
748
- combiner=combiner_value,
669
+ field=dv["field"],
670
+ vector=dv["vector"],
671
+ nprobe=dv.get("nprobe", 0),
672
+ rerank_factor=dv.get("rerank_factor", 0),
673
+ combiner=_combiner_to_proto(dv.get("combiner")),
674
+ combiner_temperature=dv.get("combiner_temperature", 0),
675
+ combiner_top_k=dv.get("combiner_top_k", 0),
676
+ combiner_decay=dv.get("combiner_decay", 0),
749
677
  )
750
678
  )
751
679
 
752
- # Default: match all (empty boolean query)
680
+ if "boost" in q:
681
+ bq = q["boost"]
682
+ return pb.Query(
683
+ boost=pb.BoostQuery(
684
+ query=_build_query(bq["query"]),
685
+ boost=bq["boost"],
686
+ )
687
+ )
688
+
689
+ if "all" in q:
690
+ return pb.Query(all=pb.AllQuery())
691
+
692
+ # Default: match all
753
693
  return pb.Query(boolean=pb.BooleanQuery())
694
+
695
+
696
+ def _build_reranker(r: dict[str, Any]) -> pb.Reranker:
697
+ """Convert a Reranker dict to protobuf Reranker."""
698
+ return pb.Reranker(
699
+ field=r["field"],
700
+ vector=r["vector"],
701
+ limit=r.get("limit", 0),
702
+ combiner=_combiner_to_proto(r.get("combiner")),
703
+ combiner_temperature=r.get("combiner_temperature", 0),
704
+ combiner_top_k=r.get("combiner_top_k", 0),
705
+ combiner_decay=r.get("combiner_decay", 0),
706
+ matryoshka_dims=r.get("matryoshka_dims", 0),
707
+ )
708
+
709
+
710
+ def _build_filter(f: dict[str, Any]) -> pb.Filter:
711
+ """Convert a Filter dict to protobuf Filter."""
712
+ kwargs: dict[str, Any] = {"field": f["field"]}
713
+ if "eq_u64" in f:
714
+ kwargs["eq_u64"] = int(f["eq_u64"])
715
+ elif "eq_i64" in f:
716
+ kwargs["eq_i64"] = int(f["eq_i64"])
717
+ elif "eq_f64" in f:
718
+ kwargs["eq_f64"] = float(f["eq_f64"])
719
+ elif "eq_text" in f:
720
+ kwargs["eq_text"] = str(f["eq_text"])
721
+ elif "range" in f:
722
+ r = f["range"]
723
+ range_kwargs = {}
724
+ if "min" in r:
725
+ range_kwargs["min"] = float(r["min"])
726
+ if "max" in r:
727
+ range_kwargs["max"] = float(r["max"])
728
+ kwargs["range"] = pb.RangeFilter(**range_kwargs)
729
+ elif "in_values" in f:
730
+ iv = f["in_values"]
731
+ kwargs["in_values"] = pb.InFilter(
732
+ text_values=iv.get("text_values", []),
733
+ u64_values=[int(v) for v in iv.get("u64_values", [])],
734
+ i64_values=[int(v) for v in iv.get("i64_values", [])],
735
+ )
736
+ return pb.Filter(**kwargs)
@@ -0,0 +1,142 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # NO CHECKED-IN PROTOBUF GENCODE
4
+ # source: hermes.proto
5
+ # Protobuf Python Version: 6.31.1
6
+ """Generated protocol buffer code."""
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import descriptor_pool as _descriptor_pool
9
+ from google.protobuf import runtime_version as _runtime_version
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ _runtime_version.ValidateProtobufRuntimeVersion(
13
+ _runtime_version.Domain.PUBLIC,
14
+ 6,
15
+ 31,
16
+ 1,
17
+ '',
18
+ 'hermes.proto'
19
+ )
20
+ # @@protoc_insertion_point(imports)
21
+
22
+ _sym_db = _symbol_database.Default()
23
+
24
+
25
+
26
+
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0chermes.proto\x12\x06hermes\"\xad\x02\n\x05Query\x12!\n\x04term\x18\x01 \x01(\x0b\x32\x11.hermes.TermQueryH\x00\x12\'\n\x07\x62oolean\x18\x02 \x01(\x0b\x32\x14.hermes.BooleanQueryH\x00\x12#\n\x05\x62oost\x18\x03 \x01(\x0b\x32\x12.hermes.BoostQueryH\x00\x12\x1f\n\x03\x61ll\x18\x04 \x01(\x0b\x32\x10.hermes.AllQueryH\x00\x12\x32\n\rsparse_vector\x18\x05 \x01(\x0b\x32\x19.hermes.SparseVectorQueryH\x00\x12\x30\n\x0c\x64\x65nse_vector\x18\x06 \x01(\x0b\x32\x18.hermes.DenseVectorQueryH\x00\x12#\n\x05match\x18\x07 \x01(\x0b\x32\x12.hermes.MatchQueryH\x00\x42\x07\n\x05query\"\xa5\x02\n\x11SparseVectorQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0f\n\x07indices\x18\x02 \x03(\r\x12\x0e\n\x06values\x18\x03 \x03(\x02\x12\x0c\n\x04text\x18\x04 \x01(\t\x12,\n\x08\x63ombiner\x18\x05 \x01(\x0e\x32\x1a.hermes.MultiValueCombiner\x12\x13\n\x0bheap_factor\x18\x06 \x01(\x02\x12\x1c\n\x14\x63ombiner_temperature\x18\x07 \x01(\x02\x12\x16\n\x0e\x63ombiner_top_k\x18\x08 \x01(\r\x12\x16\n\x0e\x63ombiner_decay\x18\t \x01(\x02\x12\x18\n\x10weight_threshold\x18\n \x01(\x02\x12\x16\n\x0emax_query_dims\x18\x0b \x01(\r\x12\x0f\n\x07pruning\x18\x0c \x01(\x02\"\xd4\x01\n\x10\x44\x65nseVectorQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0e\n\x06vector\x18\x02 \x03(\x02\x12\x0e\n\x06nprobe\x18\x03 \x01(\r\x12\x15\n\rrerank_factor\x18\x04 \x01(\x02\x12,\n\x08\x63ombiner\x18\x05 \x01(\x0e\x32\x1a.hermes.MultiValueCombiner\x12\x1c\n\x14\x63ombiner_temperature\x18\x06 \x01(\x02\x12\x16\n\x0e\x63ombiner_top_k\x18\x07 \x01(\r\x12\x16\n\x0e\x63ombiner_decay\x18\x08 \x01(\x02\"(\n\tTermQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0c\n\x04term\x18\x02 \x01(\t\"k\n\x0c\x42ooleanQuery\x12\x1b\n\x04must\x18\x01 \x03(\x0b\x32\r.hermes.Query\x12\x1d\n\x06should\x18\x02 \x03(\x0b\x32\r.hermes.Query\x12\x1f\n\x08must_not\x18\x03 \x03(\x0b\x32\r.hermes.Query\"9\n\nBoostQuery\x12\x1c\n\x05query\x18\x01 \x01(\x0b\x32\r.hermes.Query\x12\r\n\x05\x62oost\x18\x02 \x01(\x02\"\n\n\x08\x41llQuery\")\n\nMatchQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\"\xcd\x01\n\x08Reranker\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0e\n\x06vector\x18\x02 \x03(\x02\x12\r\n\x05limit\x18\x03 \x01(\r\x12,\n\x08\x63ombiner\x18\x04 \x01(\x0e\x32\x1a.hermes.MultiValueCombiner\x12\x1c\n\x14\x63ombiner_temperature\x18\x05 \x01(\x02\x12\x16\n\x0e\x63ombiner_top_k\x18\x06 \x01(\r\x12\x16\n\x0e\x63ombiner_decay\x18\x07 \x01(\x02\x12\x17\n\x0fmatryoshka_dims\x18\x08 \x01(\r\"\xba\x01\n\x06\x46ilter\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x10\n\x06\x65q_u64\x18\x02 \x01(\x04H\x00\x12\x10\n\x06\x65q_i64\x18\x03 \x01(\x03H\x00\x12\x10\n\x06\x65q_f64\x18\x04 \x01(\x01H\x00\x12\x11\n\x07\x65q_text\x18\x05 \x01(\tH\x00\x12$\n\x05range\x18\x06 \x01(\x0b\x32\x13.hermes.RangeFilterH\x00\x12%\n\tin_values\x18\x07 \x01(\x0b\x32\x10.hermes.InFilterH\x00\x42\x0b\n\tcondition\"A\n\x0bRangeFilter\x12\x10\n\x03min\x18\x01 \x01(\x01H\x00\x88\x01\x01\x12\x10\n\x03max\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\x06\n\x04_minB\x06\n\x04_max\"G\n\x08InFilter\x12\x13\n\x0btext_values\x18\x01 \x03(\t\x12\x12\n\nu64_values\x18\x02 \x03(\x04\x12\x12\n\ni64_values\x18\x03 \x03(\x03\"\xbd\x01\n\rSearchRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\x1c\n\x05query\x18\x02 \x01(\x0b\x32\r.hermes.Query\x12\r\n\x05limit\x18\x03 \x01(\r\x12\x0e\n\x06offset\x18\x04 \x01(\r\x12\x16\n\x0e\x66ields_to_load\x18\x05 \x03(\t\x12\"\n\x08reranker\x18\x06 \x01(\x0b\x32\x10.hermes.Reranker\x12\x1f\n\x07\x66ilters\x18\x07 \x03(\x0b\x32\x0e.hermes.Filter\"0\n\nDocAddress\x12\x12\n\nsegment_id\x18\x01 \x01(\t\x12\x0e\n\x06\x64oc_id\x18\x02 \x01(\r\"\xdf\x01\n\tSearchHit\x12#\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x12.hermes.DocAddress\x12\r\n\x05score\x18\x02 \x01(\x02\x12-\n\x06\x66ields\x18\x03 \x03(\x0b\x32\x1d.hermes.SearchHit.FieldsEntry\x12,\n\x0eordinal_scores\x18\x04 \x03(\x0b\x32\x14.hermes.OrdinalScore\x1a\x41\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.hermes.FieldValue:\x02\x38\x01\".\n\x0cOrdinalScore\x12\x0f\n\x07ordinal\x18\x01 \x01(\r\x12\r\n\x05score\x18\x02 \x01(\x02\"\xdb\x01\n\nFieldValue\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12\r\n\x03u64\x18\x02 \x01(\x04H\x00\x12\r\n\x03i64\x18\x03 \x01(\x03H\x00\x12\r\n\x03\x66\x36\x34\x18\x04 \x01(\x01H\x00\x12\x15\n\x0b\x62ytes_value\x18\x05 \x01(\x0cH\x00\x12-\n\rsparse_vector\x18\x06 \x01(\x0b\x32\x14.hermes.SparseVectorH\x00\x12+\n\x0c\x64\x65nse_vector\x18\x07 \x01(\x0b\x32\x13.hermes.DenseVectorH\x00\x12\x14\n\njson_value\x18\x08 \x01(\tH\x00\x42\x07\n\x05value\"/\n\x0cSparseVector\x12\x0f\n\x07indices\x18\x01 \x03(\r\x12\x0e\n\x06values\x18\x02 \x03(\x02\"\x1d\n\x0b\x44\x65nseVector\x12\x0e\n\x06values\x18\x01 \x03(\x02\"~\n\x0eSearchResponse\x12\x1f\n\x04hits\x18\x01 \x03(\x0b\x32\x11.hermes.SearchHit\x12\x12\n\ntotal_hits\x18\x02 \x01(\r\x12\x0f\n\x07took_ms\x18\x03 \x01(\x04\x12&\n\x07timings\x18\x04 \x01(\x0b\x32\x15.hermes.SearchTimings\"X\n\rSearchTimings\x12\x11\n\tsearch_us\x18\x01 \x01(\x04\x12\x11\n\trerank_us\x18\x02 \x01(\x04\x12\x0f\n\x07load_us\x18\x03 \x01(\x04\x12\x10\n\x08total_us\x18\x04 \x01(\x04\"M\n\x12GetDocumentRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12#\n\x07\x61\x64\x64ress\x18\x02 \x01(\x0b\x32\x12.hermes.DocAddress\"\x91\x01\n\x13GetDocumentResponse\x12\x37\n\x06\x66ields\x18\x01 \x03(\x0b\x32\'.hermes.GetDocumentResponse.FieldsEntry\x1a\x41\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.hermes.FieldValue:\x02\x38\x01\")\n\x13GetIndexInfoRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"\xbd\x01\n\x14GetIndexInfoResponse\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\x10\n\x08num_docs\x18\x02 \x01(\r\x12\x14\n\x0cnum_segments\x18\x03 \x01(\r\x12\x0e\n\x06schema\x18\x04 \x01(\t\x12)\n\x0cmemory_stats\x18\x05 \x01(\x0b\x32\x13.hermes.MemoryStats\x12.\n\x0cvector_stats\x18\x06 \x03(\x0b\x32\x18.hermes.VectorFieldStats\"e\n\x10VectorFieldStats\x12\x12\n\nfield_name\x18\x01 \x01(\t\x12\x13\n\x0bvector_type\x18\x02 \x01(\t\x12\x15\n\rtotal_vectors\x18\x03 \x01(\x04\x12\x11\n\tdimension\x18\x04 \x01(\r\"\x8c\x01\n\x0bMemoryStats\x12\x13\n\x0btotal_bytes\x18\x01 \x01(\x04\x12\x34\n\x0findexing_buffer\x18\x02 \x01(\x0b\x32\x1b.hermes.IndexingBufferStats\x12\x32\n\x0esegment_reader\x18\x03 \x01(\x0b\x32\x1a.hermes.SegmentReaderStats\"\xdf\x01\n\x13IndexingBufferStats\x12\x13\n\x0btotal_bytes\x18\x01 \x01(\x04\x12\x16\n\x0epostings_bytes\x18\x02 \x01(\x04\x12\x1c\n\x14sparse_vectors_bytes\x18\x03 \x01(\x04\x12\x1b\n\x13\x64\x65nse_vectors_bytes\x18\x04 \x01(\x04\x12\x16\n\x0einterner_bytes\x18\x05 \x01(\x04\x12\x1c\n\x14position_index_bytes\x18\x06 \x01(\x04\x12\x14\n\x0cpending_docs\x18\x07 \x01(\r\x12\x14\n\x0cunique_terms\x18\x08 \x01(\r\"\xb7\x01\n\x12SegmentReaderStats\x12\x13\n\x0btotal_bytes\x18\x01 \x01(\x04\x12\x1d\n\x15term_dict_cache_bytes\x18\x02 \x01(\x04\x12\x19\n\x11store_cache_bytes\x18\x03 \x01(\x04\x12\x1a\n\x12sparse_index_bytes\x18\x04 \x01(\x04\x12\x19\n\x11\x64\x65nse_index_bytes\x18\x05 \x01(\x04\x12\x1b\n\x13num_segments_loaded\x18\x06 \x01(\r\"8\n\x12\x43reateIndexRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\x0e\n\x06schema\x18\x02 \x01(\t\"&\n\x13\x43reateIndexResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"=\n\nFieldEntry\x12\x0c\n\x04name\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.hermes.FieldValue\"3\n\rNamedDocument\x12\"\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x12.hermes.FieldEntry\"Z\n\x1a\x42\x61tchIndexDocumentsRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12(\n\tdocuments\x18\x02 \x03(\x0b\x32\x15.hermes.NamedDocument\"I\n\x1b\x42\x61tchIndexDocumentsResponse\x12\x15\n\rindexed_count\x18\x01 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\x02 \x01(\r\"N\n\x14IndexDocumentRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\"\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x12.hermes.FieldEntry\"/\n\x16IndexDocumentsResponse\x12\x15\n\rindexed_count\x18\x01 \x01(\r\"#\n\rCommitRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"3\n\x0e\x43ommitResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x10\n\x08num_docs\x18\x02 \x01(\r\"\'\n\x11\x46orceMergeRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\";\n\x12\x46orceMergeResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x14\n\x0cnum_segments\x18\x02 \x01(\r\"(\n\x12\x44\x65leteIndexRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"&\n\x13\x44\x65leteIndexResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\x14\n\x12ListIndexesRequest\"*\n\x13ListIndexesResponse\x12\x13\n\x0bindex_names\x18\x01 \x03(\t\"/\n\x19RetrainVectorIndexRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"-\n\x1aRetrainVectorIndexResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*\x81\x01\n\x12MultiValueCombiner\x12\x18\n\x14\x43OMBINER_LOG_SUM_EXP\x10\x00\x12\x10\n\x0c\x43OMBINER_MAX\x10\x01\x12\x10\n\x0c\x43OMBINER_AVG\x10\x02\x12\x10\n\x0c\x43OMBINER_SUM\x10\x03\x12\x1b\n\x17\x43OMBINER_WEIGHTED_TOP_K\x10\x04\x32\xdb\x01\n\rSearchService\x12\x37\n\x06Search\x12\x15.hermes.SearchRequest\x1a\x16.hermes.SearchResponse\x12\x46\n\x0bGetDocument\x12\x1a.hermes.GetDocumentRequest\x1a\x1b.hermes.GetDocumentResponse\x12I\n\x0cGetIndexInfo\x12\x1b.hermes.GetIndexInfoRequest\x1a\x1c.hermes.GetIndexInfoResponse2\xf3\x04\n\x0cIndexService\x12\x46\n\x0b\x43reateIndex\x12\x1a.hermes.CreateIndexRequest\x1a\x1b.hermes.CreateIndexResponse\x12P\n\x0eIndexDocuments\x12\x1c.hermes.IndexDocumentRequest\x1a\x1e.hermes.IndexDocumentsResponse(\x01\x12^\n\x13\x42\x61tchIndexDocuments\x12\".hermes.BatchIndexDocumentsRequest\x1a#.hermes.BatchIndexDocumentsResponse\x12\x37\n\x06\x43ommit\x12\x15.hermes.CommitRequest\x1a\x16.hermes.CommitResponse\x12\x43\n\nForceMerge\x12\x19.hermes.ForceMergeRequest\x1a\x1a.hermes.ForceMergeResponse\x12\x46\n\x0b\x44\x65leteIndex\x12\x1a.hermes.DeleteIndexRequest\x1a\x1b.hermes.DeleteIndexResponse\x12\x46\n\x0bListIndexes\x12\x1a.hermes.ListIndexesRequest\x1a\x1b.hermes.ListIndexesResponse\x12[\n\x12RetrainVectorIndex\x12!.hermes.RetrainVectorIndexRequest\x1a\".hermes.RetrainVectorIndexResponseb\x06proto3')
28
+
29
+ _globals = globals()
30
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'hermes_pb2', _globals)
32
+ if not _descriptor._USE_C_DESCRIPTORS:
33
+ DESCRIPTOR._loaded_options = None
34
+ _globals['_SEARCHHIT_FIELDSENTRY']._loaded_options = None
35
+ _globals['_SEARCHHIT_FIELDSENTRY']._serialized_options = b'8\001'
36
+ _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._loaded_options = None
37
+ _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._serialized_options = b'8\001'
38
+ _globals['_MULTIVALUECOMBINER']._serialized_start=4744
39
+ _globals['_MULTIVALUECOMBINER']._serialized_end=4873
40
+ _globals['_QUERY']._serialized_start=25
41
+ _globals['_QUERY']._serialized_end=326
42
+ _globals['_SPARSEVECTORQUERY']._serialized_start=329
43
+ _globals['_SPARSEVECTORQUERY']._serialized_end=622
44
+ _globals['_DENSEVECTORQUERY']._serialized_start=625
45
+ _globals['_DENSEVECTORQUERY']._serialized_end=837
46
+ _globals['_TERMQUERY']._serialized_start=839
47
+ _globals['_TERMQUERY']._serialized_end=879
48
+ _globals['_BOOLEANQUERY']._serialized_start=881
49
+ _globals['_BOOLEANQUERY']._serialized_end=988
50
+ _globals['_BOOSTQUERY']._serialized_start=990
51
+ _globals['_BOOSTQUERY']._serialized_end=1047
52
+ _globals['_ALLQUERY']._serialized_start=1049
53
+ _globals['_ALLQUERY']._serialized_end=1059
54
+ _globals['_MATCHQUERY']._serialized_start=1061
55
+ _globals['_MATCHQUERY']._serialized_end=1102
56
+ _globals['_RERANKER']._serialized_start=1105
57
+ _globals['_RERANKER']._serialized_end=1310
58
+ _globals['_FILTER']._serialized_start=1313
59
+ _globals['_FILTER']._serialized_end=1499
60
+ _globals['_RANGEFILTER']._serialized_start=1501
61
+ _globals['_RANGEFILTER']._serialized_end=1566
62
+ _globals['_INFILTER']._serialized_start=1568
63
+ _globals['_INFILTER']._serialized_end=1639
64
+ _globals['_SEARCHREQUEST']._serialized_start=1642
65
+ _globals['_SEARCHREQUEST']._serialized_end=1831
66
+ _globals['_DOCADDRESS']._serialized_start=1833
67
+ _globals['_DOCADDRESS']._serialized_end=1881
68
+ _globals['_SEARCHHIT']._serialized_start=1884
69
+ _globals['_SEARCHHIT']._serialized_end=2107
70
+ _globals['_SEARCHHIT_FIELDSENTRY']._serialized_start=2042
71
+ _globals['_SEARCHHIT_FIELDSENTRY']._serialized_end=2107
72
+ _globals['_ORDINALSCORE']._serialized_start=2109
73
+ _globals['_ORDINALSCORE']._serialized_end=2155
74
+ _globals['_FIELDVALUE']._serialized_start=2158
75
+ _globals['_FIELDVALUE']._serialized_end=2377
76
+ _globals['_SPARSEVECTOR']._serialized_start=2379
77
+ _globals['_SPARSEVECTOR']._serialized_end=2426
78
+ _globals['_DENSEVECTOR']._serialized_start=2428
79
+ _globals['_DENSEVECTOR']._serialized_end=2457
80
+ _globals['_SEARCHRESPONSE']._serialized_start=2459
81
+ _globals['_SEARCHRESPONSE']._serialized_end=2585
82
+ _globals['_SEARCHTIMINGS']._serialized_start=2587
83
+ _globals['_SEARCHTIMINGS']._serialized_end=2675
84
+ _globals['_GETDOCUMENTREQUEST']._serialized_start=2677
85
+ _globals['_GETDOCUMENTREQUEST']._serialized_end=2754
86
+ _globals['_GETDOCUMENTRESPONSE']._serialized_start=2757
87
+ _globals['_GETDOCUMENTRESPONSE']._serialized_end=2902
88
+ _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._serialized_start=2042
89
+ _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._serialized_end=2107
90
+ _globals['_GETINDEXINFOREQUEST']._serialized_start=2904
91
+ _globals['_GETINDEXINFOREQUEST']._serialized_end=2945
92
+ _globals['_GETINDEXINFORESPONSE']._serialized_start=2948
93
+ _globals['_GETINDEXINFORESPONSE']._serialized_end=3137
94
+ _globals['_VECTORFIELDSTATS']._serialized_start=3139
95
+ _globals['_VECTORFIELDSTATS']._serialized_end=3240
96
+ _globals['_MEMORYSTATS']._serialized_start=3243
97
+ _globals['_MEMORYSTATS']._serialized_end=3383
98
+ _globals['_INDEXINGBUFFERSTATS']._serialized_start=3386
99
+ _globals['_INDEXINGBUFFERSTATS']._serialized_end=3609
100
+ _globals['_SEGMENTREADERSTATS']._serialized_start=3612
101
+ _globals['_SEGMENTREADERSTATS']._serialized_end=3795
102
+ _globals['_CREATEINDEXREQUEST']._serialized_start=3797
103
+ _globals['_CREATEINDEXREQUEST']._serialized_end=3853
104
+ _globals['_CREATEINDEXRESPONSE']._serialized_start=3855
105
+ _globals['_CREATEINDEXRESPONSE']._serialized_end=3893
106
+ _globals['_FIELDENTRY']._serialized_start=3895
107
+ _globals['_FIELDENTRY']._serialized_end=3956
108
+ _globals['_NAMEDDOCUMENT']._serialized_start=3958
109
+ _globals['_NAMEDDOCUMENT']._serialized_end=4009
110
+ _globals['_BATCHINDEXDOCUMENTSREQUEST']._serialized_start=4011
111
+ _globals['_BATCHINDEXDOCUMENTSREQUEST']._serialized_end=4101
112
+ _globals['_BATCHINDEXDOCUMENTSRESPONSE']._serialized_start=4103
113
+ _globals['_BATCHINDEXDOCUMENTSRESPONSE']._serialized_end=4176
114
+ _globals['_INDEXDOCUMENTREQUEST']._serialized_start=4178
115
+ _globals['_INDEXDOCUMENTREQUEST']._serialized_end=4256
116
+ _globals['_INDEXDOCUMENTSRESPONSE']._serialized_start=4258
117
+ _globals['_INDEXDOCUMENTSRESPONSE']._serialized_end=4305
118
+ _globals['_COMMITREQUEST']._serialized_start=4307
119
+ _globals['_COMMITREQUEST']._serialized_end=4342
120
+ _globals['_COMMITRESPONSE']._serialized_start=4344
121
+ _globals['_COMMITRESPONSE']._serialized_end=4395
122
+ _globals['_FORCEMERGEREQUEST']._serialized_start=4397
123
+ _globals['_FORCEMERGEREQUEST']._serialized_end=4436
124
+ _globals['_FORCEMERGERESPONSE']._serialized_start=4438
125
+ _globals['_FORCEMERGERESPONSE']._serialized_end=4497
126
+ _globals['_DELETEINDEXREQUEST']._serialized_start=4499
127
+ _globals['_DELETEINDEXREQUEST']._serialized_end=4539
128
+ _globals['_DELETEINDEXRESPONSE']._serialized_start=4541
129
+ _globals['_DELETEINDEXRESPONSE']._serialized_end=4579
130
+ _globals['_LISTINDEXESREQUEST']._serialized_start=4581
131
+ _globals['_LISTINDEXESREQUEST']._serialized_end=4601
132
+ _globals['_LISTINDEXESRESPONSE']._serialized_start=4603
133
+ _globals['_LISTINDEXESRESPONSE']._serialized_end=4645
134
+ _globals['_RETRAINVECTORINDEXREQUEST']._serialized_start=4647
135
+ _globals['_RETRAINVECTORINDEXREQUEST']._serialized_end=4694
136
+ _globals['_RETRAINVECTORINDEXRESPONSE']._serialized_start=4696
137
+ _globals['_RETRAINVECTORINDEXRESPONSE']._serialized_end=4741
138
+ _globals['_SEARCHSERVICE']._serialized_start=4876
139
+ _globals['_SEARCHSERVICE']._serialized_end=5095
140
+ _globals['_INDEXSERVICE']._serialized_start=5098
141
+ _globals['_INDEXSERVICE']._serialized_end=5725
142
+ # @@protoc_insertion_point(module_scope)
@@ -0,0 +1,185 @@
1
+ """Type definitions for Hermes client.
2
+
3
+ All search-related types mirror the proto API structure exactly.
4
+ Query is a dict with exactly one key matching the proto Query oneof variant.
5
+ """
6
+
7
+ from dataclasses import dataclass, field
8
+ from typing import Any, Literal, TypedDict
9
+
10
+ # =============================================================================
11
+ # Multi-value score combiner (mirrors proto MultiValueCombiner)
12
+ # =============================================================================
13
+
14
+ Combiner = Literal["log_sum_exp", "max", "avg", "sum", "weighted_top_k"]
15
+
16
+ # =============================================================================
17
+ # Query types (mirrors proto Query oneof)
18
+ # =============================================================================
19
+
20
+
21
+ class TermQuery(TypedDict):
22
+ field: str
23
+ term: str
24
+
25
+
26
+ class MatchQuery(TypedDict):
27
+ field: str
28
+ text: str
29
+
30
+
31
+ class BooleanQuery(TypedDict, total=False):
32
+ must: list["Query"]
33
+ should: list["Query"]
34
+ must_not: list["Query"]
35
+
36
+
37
+ class BoostQuery(TypedDict):
38
+ query: "Query"
39
+ boost: float
40
+
41
+
42
+ class AllQuery(TypedDict):
43
+ pass
44
+
45
+
46
+ class SparseVectorQuery(TypedDict, total=False):
47
+ field: str # required but total=False for optional fields
48
+ indices: list[int]
49
+ values: list[float]
50
+ text: str
51
+ combiner: Combiner
52
+ heap_factor: float
53
+ combiner_temperature: float
54
+ combiner_top_k: int
55
+ combiner_decay: float
56
+ weight_threshold: float
57
+ max_query_dims: int
58
+ pruning: float
59
+
60
+
61
+ class DenseVectorQuery(TypedDict, total=False):
62
+ field: str # required but total=False for optional fields
63
+ vector: list[float]
64
+ nprobe: int
65
+ rerank_factor: float
66
+ combiner: Combiner
67
+ combiner_temperature: float
68
+ combiner_top_k: int
69
+ combiner_decay: float
70
+
71
+
72
+ # Query is a dict with exactly one key: "term", "match", "boolean",
73
+ # "sparse_vector", "dense_vector", "boost", or "all".
74
+ Query = dict[str, Any]
75
+
76
+ # =============================================================================
77
+ # Reranker (mirrors proto Reranker)
78
+ # =============================================================================
79
+
80
+
81
+ class Reranker(TypedDict, total=False):
82
+ field: str
83
+ vector: list[float]
84
+ limit: int
85
+ combiner: Combiner
86
+ combiner_temperature: float
87
+ combiner_top_k: int
88
+ combiner_decay: float
89
+ matryoshka_dims: int
90
+
91
+
92
+ # =============================================================================
93
+ # Filter (mirrors proto Filter)
94
+ # =============================================================================
95
+
96
+
97
+ class Filter(TypedDict, total=False):
98
+ field: str
99
+ eq_u64: int
100
+ eq_i64: int
101
+ eq_f64: float
102
+ eq_text: str
103
+ range: dict[str, float] # {"min": ..., "max": ...}
104
+ in_values: dict[
105
+ str, list
106
+ ] # {"text_values": [...], "u64_values": [...], "i64_values": [...]}
107
+
108
+
109
+ # =============================================================================
110
+ # Response types
111
+ # =============================================================================
112
+
113
+
114
+ @dataclass
115
+ class Document:
116
+ """A document with field values."""
117
+
118
+ fields: dict[str, Any] = field(default_factory=dict)
119
+
120
+ def __getitem__(self, key: str) -> Any:
121
+ return self.fields[key]
122
+
123
+ def __setitem__(self, key: str, value: Any) -> None:
124
+ self.fields[key] = value
125
+
126
+ def get(self, key: str, default: Any = None) -> Any:
127
+ return self.fields.get(key, default)
128
+
129
+
130
+ @dataclass
131
+ class DocAddress:
132
+ """Unique document address: segment + local doc_id."""
133
+
134
+ segment_id: str
135
+ doc_id: int
136
+
137
+
138
+ @dataclass
139
+ class SearchHit:
140
+ """A single search result."""
141
+
142
+ address: DocAddress
143
+ score: float
144
+ fields: dict[str, Any] = field(default_factory=dict)
145
+
146
+
147
+ @dataclass
148
+ class SearchTimings:
149
+ """Detailed timing breakdown for search phases (all values in microseconds)."""
150
+
151
+ search_us: int
152
+ rerank_us: int
153
+ load_us: int
154
+ total_us: int
155
+
156
+
157
+ @dataclass
158
+ class SearchResponse:
159
+ """Search response with hits and metadata."""
160
+
161
+ hits: list[SearchHit]
162
+ total_hits: int
163
+ took_ms: int
164
+ timings: SearchTimings | None = None
165
+
166
+
167
+ @dataclass
168
+ class VectorFieldStats:
169
+ """Per-field vector statistics."""
170
+
171
+ field_name: str
172
+ vector_type: str # "dense" or "sparse"
173
+ total_vectors: int
174
+ dimension: int
175
+
176
+
177
+ @dataclass
178
+ class IndexInfo:
179
+ """Information about an index."""
180
+
181
+ index_name: str
182
+ num_docs: int
183
+ num_segments: int
184
+ schema: str
185
+ vector_stats: list[VectorFieldStats] = field(default_factory=list)
@@ -1,23 +0,0 @@
1
- """Async Python client for Hermes search server."""
2
-
3
- from .client import HermesClient
4
- from .types import (
5
- DocAddress,
6
- Document,
7
- IndexInfo,
8
- SearchHit,
9
- SearchResponse,
10
- VectorFieldStats,
11
- )
12
-
13
- __all__ = [
14
- "HermesClient",
15
- "DocAddress",
16
- "Document",
17
- "SearchHit",
18
- "SearchResponse",
19
- "IndexInfo",
20
- "VectorFieldStats",
21
- ]
22
-
23
- __version__ = "1.0.2"
@@ -1,142 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- # Generated by the protocol buffer compiler. DO NOT EDIT!
3
- # NO CHECKED-IN PROTOBUF GENCODE
4
- # source: hermes.proto
5
- # Protobuf Python Version: 6.31.1
6
- """Generated protocol buffer code."""
7
- from google.protobuf import descriptor as _descriptor
8
- from google.protobuf import descriptor_pool as _descriptor_pool
9
- from google.protobuf import runtime_version as _runtime_version
10
- from google.protobuf import symbol_database as _symbol_database
11
- from google.protobuf.internal import builder as _builder
12
- _runtime_version.ValidateProtobufRuntimeVersion(
13
- _runtime_version.Domain.PUBLIC,
14
- 6,
15
- 31,
16
- 1,
17
- '',
18
- 'hermes.proto'
19
- )
20
- # @@protoc_insertion_point(imports)
21
-
22
- _sym_db = _symbol_database.Default()
23
-
24
-
25
-
26
-
27
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0chermes.proto\x12\x06hermes\"\xad\x02\n\x05Query\x12!\n\x04term\x18\x01 \x01(\x0b\x32\x11.hermes.TermQueryH\x00\x12\'\n\x07\x62oolean\x18\x02 \x01(\x0b\x32\x14.hermes.BooleanQueryH\x00\x12#\n\x05\x62oost\x18\x03 \x01(\x0b\x32\x12.hermes.BoostQueryH\x00\x12\x1f\n\x03\x61ll\x18\x04 \x01(\x0b\x32\x10.hermes.AllQueryH\x00\x12\x32\n\rsparse_vector\x18\x05 \x01(\x0b\x32\x19.hermes.SparseVectorQueryH\x00\x12\x30\n\x0c\x64\x65nse_vector\x18\x06 \x01(\x0b\x32\x18.hermes.DenseVectorQueryH\x00\x12#\n\x05match\x18\x07 \x01(\x0b\x32\x12.hermes.MatchQueryH\x00\x42\x07\n\x05query\"\xa5\x02\n\x11SparseVectorQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0f\n\x07indices\x18\x02 \x03(\r\x12\x0e\n\x06values\x18\x03 \x03(\x02\x12\x0c\n\x04text\x18\x04 \x01(\t\x12,\n\x08\x63ombiner\x18\x05 \x01(\x0e\x32\x1a.hermes.MultiValueCombiner\x12\x13\n\x0bheap_factor\x18\x06 \x01(\x02\x12\x1c\n\x14\x63ombiner_temperature\x18\x07 \x01(\x02\x12\x16\n\x0e\x63ombiner_top_k\x18\x08 \x01(\r\x12\x16\n\x0e\x63ombiner_decay\x18\t \x01(\x02\x12\x18\n\x10weight_threshold\x18\n \x01(\x02\x12\x16\n\x0emax_query_dims\x18\x0b \x01(\r\x12\x0f\n\x07pruning\x18\x0c \x01(\x02\"\xd4\x01\n\x10\x44\x65nseVectorQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0e\n\x06vector\x18\x02 \x03(\x02\x12\x0e\n\x06nprobe\x18\x03 \x01(\r\x12\x15\n\rrerank_factor\x18\x04 \x01(\r\x12,\n\x08\x63ombiner\x18\x05 \x01(\x0e\x32\x1a.hermes.MultiValueCombiner\x12\x1c\n\x14\x63ombiner_temperature\x18\x06 \x01(\x02\x12\x16\n\x0e\x63ombiner_top_k\x18\x07 \x01(\r\x12\x16\n\x0e\x63ombiner_decay\x18\x08 \x01(\x02\"(\n\tTermQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0c\n\x04term\x18\x02 \x01(\t\"k\n\x0c\x42ooleanQuery\x12\x1b\n\x04must\x18\x01 \x03(\x0b\x32\r.hermes.Query\x12\x1d\n\x06should\x18\x02 \x03(\x0b\x32\r.hermes.Query\x12\x1f\n\x08must_not\x18\x03 \x03(\x0b\x32\r.hermes.Query\"9\n\nBoostQuery\x12\x1c\n\x05query\x18\x01 \x01(\x0b\x32\r.hermes.Query\x12\r\n\x05\x62oost\x18\x02 \x01(\x02\"\n\n\x08\x41llQuery\")\n\nMatchQuery\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0c\n\x04text\x18\x02 \x01(\t\"\xcd\x01\n\x08Reranker\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x0e\n\x06vector\x18\x02 \x03(\x02\x12\r\n\x05limit\x18\x03 \x01(\r\x12,\n\x08\x63ombiner\x18\x04 \x01(\x0e\x32\x1a.hermes.MultiValueCombiner\x12\x1c\n\x14\x63ombiner_temperature\x18\x05 \x01(\x02\x12\x16\n\x0e\x63ombiner_top_k\x18\x06 \x01(\r\x12\x16\n\x0e\x63ombiner_decay\x18\x07 \x01(\x02\x12\x17\n\x0fmatryoshka_dims\x18\x08 \x01(\r\"\xba\x01\n\x06\x46ilter\x12\r\n\x05\x66ield\x18\x01 \x01(\t\x12\x10\n\x06\x65q_u64\x18\x02 \x01(\x04H\x00\x12\x10\n\x06\x65q_i64\x18\x03 \x01(\x03H\x00\x12\x10\n\x06\x65q_f64\x18\x04 \x01(\x01H\x00\x12\x11\n\x07\x65q_text\x18\x05 \x01(\tH\x00\x12$\n\x05range\x18\x06 \x01(\x0b\x32\x13.hermes.RangeFilterH\x00\x12%\n\tin_values\x18\x07 \x01(\x0b\x32\x10.hermes.InFilterH\x00\x42\x0b\n\tcondition\"A\n\x0bRangeFilter\x12\x10\n\x03min\x18\x01 \x01(\x01H\x00\x88\x01\x01\x12\x10\n\x03max\x18\x02 \x01(\x01H\x01\x88\x01\x01\x42\x06\n\x04_minB\x06\n\x04_max\"G\n\x08InFilter\x12\x13\n\x0btext_values\x18\x01 \x03(\t\x12\x12\n\nu64_values\x18\x02 \x03(\x04\x12\x12\n\ni64_values\x18\x03 \x03(\x03\"\xbd\x01\n\rSearchRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\x1c\n\x05query\x18\x02 \x01(\x0b\x32\r.hermes.Query\x12\r\n\x05limit\x18\x03 \x01(\r\x12\x0e\n\x06offset\x18\x04 \x01(\r\x12\x16\n\x0e\x66ields_to_load\x18\x05 \x03(\t\x12\"\n\x08reranker\x18\x06 \x01(\x0b\x32\x10.hermes.Reranker\x12\x1f\n\x07\x66ilters\x18\x07 \x03(\x0b\x32\x0e.hermes.Filter\"0\n\nDocAddress\x12\x12\n\nsegment_id\x18\x01 \x01(\t\x12\x0e\n\x06\x64oc_id\x18\x02 \x01(\r\"\xdf\x01\n\tSearchHit\x12#\n\x07\x61\x64\x64ress\x18\x01 \x01(\x0b\x32\x12.hermes.DocAddress\x12\r\n\x05score\x18\x02 \x01(\x02\x12-\n\x06\x66ields\x18\x03 \x03(\x0b\x32\x1d.hermes.SearchHit.FieldsEntry\x12,\n\x0eordinal_scores\x18\x04 \x03(\x0b\x32\x14.hermes.OrdinalScore\x1a\x41\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.hermes.FieldValue:\x02\x38\x01\".\n\x0cOrdinalScore\x12\x0f\n\x07ordinal\x18\x01 \x01(\r\x12\r\n\x05score\x18\x02 \x01(\x02\"\xdb\x01\n\nFieldValue\x12\x0e\n\x04text\x18\x01 \x01(\tH\x00\x12\r\n\x03u64\x18\x02 \x01(\x04H\x00\x12\r\n\x03i64\x18\x03 \x01(\x03H\x00\x12\r\n\x03\x66\x36\x34\x18\x04 \x01(\x01H\x00\x12\x15\n\x0b\x62ytes_value\x18\x05 \x01(\x0cH\x00\x12-\n\rsparse_vector\x18\x06 \x01(\x0b\x32\x14.hermes.SparseVectorH\x00\x12+\n\x0c\x64\x65nse_vector\x18\x07 \x01(\x0b\x32\x13.hermes.DenseVectorH\x00\x12\x14\n\njson_value\x18\x08 \x01(\tH\x00\x42\x07\n\x05value\"/\n\x0cSparseVector\x12\x0f\n\x07indices\x18\x01 \x03(\r\x12\x0e\n\x06values\x18\x02 \x03(\x02\"\x1d\n\x0b\x44\x65nseVector\x12\x0e\n\x06values\x18\x01 \x03(\x02\"~\n\x0eSearchResponse\x12\x1f\n\x04hits\x18\x01 \x03(\x0b\x32\x11.hermes.SearchHit\x12\x12\n\ntotal_hits\x18\x02 \x01(\r\x12\x0f\n\x07took_ms\x18\x03 \x01(\x04\x12&\n\x07timings\x18\x04 \x01(\x0b\x32\x15.hermes.SearchTimings\"X\n\rSearchTimings\x12\x11\n\tsearch_us\x18\x01 \x01(\x04\x12\x11\n\trerank_us\x18\x02 \x01(\x04\x12\x0f\n\x07load_us\x18\x03 \x01(\x04\x12\x10\n\x08total_us\x18\x04 \x01(\x04\"M\n\x12GetDocumentRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12#\n\x07\x61\x64\x64ress\x18\x02 \x01(\x0b\x32\x12.hermes.DocAddress\"\x91\x01\n\x13GetDocumentResponse\x12\x37\n\x06\x66ields\x18\x01 \x03(\x0b\x32\'.hermes.GetDocumentResponse.FieldsEntry\x1a\x41\n\x0b\x46ieldsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.hermes.FieldValue:\x02\x38\x01\")\n\x13GetIndexInfoRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"\xbd\x01\n\x14GetIndexInfoResponse\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\x10\n\x08num_docs\x18\x02 \x01(\r\x12\x14\n\x0cnum_segments\x18\x03 \x01(\r\x12\x0e\n\x06schema\x18\x04 \x01(\t\x12)\n\x0cmemory_stats\x18\x05 \x01(\x0b\x32\x13.hermes.MemoryStats\x12.\n\x0cvector_stats\x18\x06 \x03(\x0b\x32\x18.hermes.VectorFieldStats\"e\n\x10VectorFieldStats\x12\x12\n\nfield_name\x18\x01 \x01(\t\x12\x13\n\x0bvector_type\x18\x02 \x01(\t\x12\x15\n\rtotal_vectors\x18\x03 \x01(\x04\x12\x11\n\tdimension\x18\x04 \x01(\r\"\x8c\x01\n\x0bMemoryStats\x12\x13\n\x0btotal_bytes\x18\x01 \x01(\x04\x12\x34\n\x0findexing_buffer\x18\x02 \x01(\x0b\x32\x1b.hermes.IndexingBufferStats\x12\x32\n\x0esegment_reader\x18\x03 \x01(\x0b\x32\x1a.hermes.SegmentReaderStats\"\xdf\x01\n\x13IndexingBufferStats\x12\x13\n\x0btotal_bytes\x18\x01 \x01(\x04\x12\x16\n\x0epostings_bytes\x18\x02 \x01(\x04\x12\x1c\n\x14sparse_vectors_bytes\x18\x03 \x01(\x04\x12\x1b\n\x13\x64\x65nse_vectors_bytes\x18\x04 \x01(\x04\x12\x16\n\x0einterner_bytes\x18\x05 \x01(\x04\x12\x1c\n\x14position_index_bytes\x18\x06 \x01(\x04\x12\x14\n\x0cpending_docs\x18\x07 \x01(\r\x12\x14\n\x0cunique_terms\x18\x08 \x01(\r\"\xb7\x01\n\x12SegmentReaderStats\x12\x13\n\x0btotal_bytes\x18\x01 \x01(\x04\x12\x1d\n\x15term_dict_cache_bytes\x18\x02 \x01(\x04\x12\x19\n\x11store_cache_bytes\x18\x03 \x01(\x04\x12\x1a\n\x12sparse_index_bytes\x18\x04 \x01(\x04\x12\x19\n\x11\x64\x65nse_index_bytes\x18\x05 \x01(\x04\x12\x1b\n\x13num_segments_loaded\x18\x06 \x01(\r\"8\n\x12\x43reateIndexRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\x0e\n\x06schema\x18\x02 \x01(\t\"&\n\x13\x43reateIndexResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"=\n\nFieldEntry\x12\x0c\n\x04name\x18\x01 \x01(\t\x12!\n\x05value\x18\x02 \x01(\x0b\x32\x12.hermes.FieldValue\"3\n\rNamedDocument\x12\"\n\x06\x66ields\x18\x01 \x03(\x0b\x32\x12.hermes.FieldEntry\"Z\n\x1a\x42\x61tchIndexDocumentsRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12(\n\tdocuments\x18\x02 \x03(\x0b\x32\x15.hermes.NamedDocument\"I\n\x1b\x42\x61tchIndexDocumentsResponse\x12\x15\n\rindexed_count\x18\x01 \x01(\r\x12\x13\n\x0b\x65rror_count\x18\x02 \x01(\r\"N\n\x14IndexDocumentRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\x12\"\n\x06\x66ields\x18\x02 \x03(\x0b\x32\x12.hermes.FieldEntry\"/\n\x16IndexDocumentsResponse\x12\x15\n\rindexed_count\x18\x01 \x01(\r\"#\n\rCommitRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"3\n\x0e\x43ommitResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x10\n\x08num_docs\x18\x02 \x01(\r\"\'\n\x11\x46orceMergeRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\";\n\x12\x46orceMergeResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\x12\x14\n\x0cnum_segments\x18\x02 \x01(\r\"(\n\x12\x44\x65leteIndexRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"&\n\x13\x44\x65leteIndexResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08\"\x14\n\x12ListIndexesRequest\"*\n\x13ListIndexesResponse\x12\x13\n\x0bindex_names\x18\x01 \x03(\t\"/\n\x19RetrainVectorIndexRequest\x12\x12\n\nindex_name\x18\x01 \x01(\t\"-\n\x1aRetrainVectorIndexResponse\x12\x0f\n\x07success\x18\x01 \x01(\x08*\x81\x01\n\x12MultiValueCombiner\x12\x18\n\x14\x43OMBINER_LOG_SUM_EXP\x10\x00\x12\x10\n\x0c\x43OMBINER_MAX\x10\x01\x12\x10\n\x0c\x43OMBINER_AVG\x10\x02\x12\x10\n\x0c\x43OMBINER_SUM\x10\x03\x12\x1b\n\x17\x43OMBINER_WEIGHTED_TOP_K\x10\x04\x32\xdb\x01\n\rSearchService\x12\x37\n\x06Search\x12\x15.hermes.SearchRequest\x1a\x16.hermes.SearchResponse\x12\x46\n\x0bGetDocument\x12\x1a.hermes.GetDocumentRequest\x1a\x1b.hermes.GetDocumentResponse\x12I\n\x0cGetIndexInfo\x12\x1b.hermes.GetIndexInfoRequest\x1a\x1c.hermes.GetIndexInfoResponse2\xf3\x04\n\x0cIndexService\x12\x46\n\x0b\x43reateIndex\x12\x1a.hermes.CreateIndexRequest\x1a\x1b.hermes.CreateIndexResponse\x12P\n\x0eIndexDocuments\x12\x1c.hermes.IndexDocumentRequest\x1a\x1e.hermes.IndexDocumentsResponse(\x01\x12^\n\x13\x42\x61tchIndexDocuments\x12\".hermes.BatchIndexDocumentsRequest\x1a#.hermes.BatchIndexDocumentsResponse\x12\x37\n\x06\x43ommit\x12\x15.hermes.CommitRequest\x1a\x16.hermes.CommitResponse\x12\x43\n\nForceMerge\x12\x19.hermes.ForceMergeRequest\x1a\x1a.hermes.ForceMergeResponse\x12\x46\n\x0b\x44\x65leteIndex\x12\x1a.hermes.DeleteIndexRequest\x1a\x1b.hermes.DeleteIndexResponse\x12\x46\n\x0bListIndexes\x12\x1a.hermes.ListIndexesRequest\x1a\x1b.hermes.ListIndexesResponse\x12[\n\x12RetrainVectorIndex\x12!.hermes.RetrainVectorIndexRequest\x1a\".hermes.RetrainVectorIndexResponseb\x06proto3')
28
-
29
- _globals = globals()
30
- _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
- _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'hermes_pb2', _globals)
32
- if not _descriptor._USE_C_DESCRIPTORS:
33
- DESCRIPTOR._loaded_options = None
34
- _globals['_SEARCHHIT_FIELDSENTRY']._loaded_options = None
35
- _globals['_SEARCHHIT_FIELDSENTRY']._serialized_options = b'8\001'
36
- _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._loaded_options = None
37
- _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._serialized_options = b'8\001'
38
- _globals['_MULTIVALUECOMBINER']._serialized_start=4744
39
- _globals['_MULTIVALUECOMBINER']._serialized_end=4873
40
- _globals['_QUERY']._serialized_start=25
41
- _globals['_QUERY']._serialized_end=326
42
- _globals['_SPARSEVECTORQUERY']._serialized_start=329
43
- _globals['_SPARSEVECTORQUERY']._serialized_end=622
44
- _globals['_DENSEVECTORQUERY']._serialized_start=625
45
- _globals['_DENSEVECTORQUERY']._serialized_end=837
46
- _globals['_TERMQUERY']._serialized_start=839
47
- _globals['_TERMQUERY']._serialized_end=879
48
- _globals['_BOOLEANQUERY']._serialized_start=881
49
- _globals['_BOOLEANQUERY']._serialized_end=988
50
- _globals['_BOOSTQUERY']._serialized_start=990
51
- _globals['_BOOSTQUERY']._serialized_end=1047
52
- _globals['_ALLQUERY']._serialized_start=1049
53
- _globals['_ALLQUERY']._serialized_end=1059
54
- _globals['_MATCHQUERY']._serialized_start=1061
55
- _globals['_MATCHQUERY']._serialized_end=1102
56
- _globals['_RERANKER']._serialized_start=1105
57
- _globals['_RERANKER']._serialized_end=1310
58
- _globals['_FILTER']._serialized_start=1313
59
- _globals['_FILTER']._serialized_end=1499
60
- _globals['_RANGEFILTER']._serialized_start=1501
61
- _globals['_RANGEFILTER']._serialized_end=1566
62
- _globals['_INFILTER']._serialized_start=1568
63
- _globals['_INFILTER']._serialized_end=1639
64
- _globals['_SEARCHREQUEST']._serialized_start=1642
65
- _globals['_SEARCHREQUEST']._serialized_end=1831
66
- _globals['_DOCADDRESS']._serialized_start=1833
67
- _globals['_DOCADDRESS']._serialized_end=1881
68
- _globals['_SEARCHHIT']._serialized_start=1884
69
- _globals['_SEARCHHIT']._serialized_end=2107
70
- _globals['_SEARCHHIT_FIELDSENTRY']._serialized_start=2042
71
- _globals['_SEARCHHIT_FIELDSENTRY']._serialized_end=2107
72
- _globals['_ORDINALSCORE']._serialized_start=2109
73
- _globals['_ORDINALSCORE']._serialized_end=2155
74
- _globals['_FIELDVALUE']._serialized_start=2158
75
- _globals['_FIELDVALUE']._serialized_end=2377
76
- _globals['_SPARSEVECTOR']._serialized_start=2379
77
- _globals['_SPARSEVECTOR']._serialized_end=2426
78
- _globals['_DENSEVECTOR']._serialized_start=2428
79
- _globals['_DENSEVECTOR']._serialized_end=2457
80
- _globals['_SEARCHRESPONSE']._serialized_start=2459
81
- _globals['_SEARCHRESPONSE']._serialized_end=2585
82
- _globals['_SEARCHTIMINGS']._serialized_start=2587
83
- _globals['_SEARCHTIMINGS']._serialized_end=2675
84
- _globals['_GETDOCUMENTREQUEST']._serialized_start=2677
85
- _globals['_GETDOCUMENTREQUEST']._serialized_end=2754
86
- _globals['_GETDOCUMENTRESPONSE']._serialized_start=2757
87
- _globals['_GETDOCUMENTRESPONSE']._serialized_end=2902
88
- _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._serialized_start=2042
89
- _globals['_GETDOCUMENTRESPONSE_FIELDSENTRY']._serialized_end=2107
90
- _globals['_GETINDEXINFOREQUEST']._serialized_start=2904
91
- _globals['_GETINDEXINFOREQUEST']._serialized_end=2945
92
- _globals['_GETINDEXINFORESPONSE']._serialized_start=2948
93
- _globals['_GETINDEXINFORESPONSE']._serialized_end=3137
94
- _globals['_VECTORFIELDSTATS']._serialized_start=3139
95
- _globals['_VECTORFIELDSTATS']._serialized_end=3240
96
- _globals['_MEMORYSTATS']._serialized_start=3243
97
- _globals['_MEMORYSTATS']._serialized_end=3383
98
- _globals['_INDEXINGBUFFERSTATS']._serialized_start=3386
99
- _globals['_INDEXINGBUFFERSTATS']._serialized_end=3609
100
- _globals['_SEGMENTREADERSTATS']._serialized_start=3612
101
- _globals['_SEGMENTREADERSTATS']._serialized_end=3795
102
- _globals['_CREATEINDEXREQUEST']._serialized_start=3797
103
- _globals['_CREATEINDEXREQUEST']._serialized_end=3853
104
- _globals['_CREATEINDEXRESPONSE']._serialized_start=3855
105
- _globals['_CREATEINDEXRESPONSE']._serialized_end=3893
106
- _globals['_FIELDENTRY']._serialized_start=3895
107
- _globals['_FIELDENTRY']._serialized_end=3956
108
- _globals['_NAMEDDOCUMENT']._serialized_start=3958
109
- _globals['_NAMEDDOCUMENT']._serialized_end=4009
110
- _globals['_BATCHINDEXDOCUMENTSREQUEST']._serialized_start=4011
111
- _globals['_BATCHINDEXDOCUMENTSREQUEST']._serialized_end=4101
112
- _globals['_BATCHINDEXDOCUMENTSRESPONSE']._serialized_start=4103
113
- _globals['_BATCHINDEXDOCUMENTSRESPONSE']._serialized_end=4176
114
- _globals['_INDEXDOCUMENTREQUEST']._serialized_start=4178
115
- _globals['_INDEXDOCUMENTREQUEST']._serialized_end=4256
116
- _globals['_INDEXDOCUMENTSRESPONSE']._serialized_start=4258
117
- _globals['_INDEXDOCUMENTSRESPONSE']._serialized_end=4305
118
- _globals['_COMMITREQUEST']._serialized_start=4307
119
- _globals['_COMMITREQUEST']._serialized_end=4342
120
- _globals['_COMMITRESPONSE']._serialized_start=4344
121
- _globals['_COMMITRESPONSE']._serialized_end=4395
122
- _globals['_FORCEMERGEREQUEST']._serialized_start=4397
123
- _globals['_FORCEMERGEREQUEST']._serialized_end=4436
124
- _globals['_FORCEMERGERESPONSE']._serialized_start=4438
125
- _globals['_FORCEMERGERESPONSE']._serialized_end=4497
126
- _globals['_DELETEINDEXREQUEST']._serialized_start=4499
127
- _globals['_DELETEINDEXREQUEST']._serialized_end=4539
128
- _globals['_DELETEINDEXRESPONSE']._serialized_start=4541
129
- _globals['_DELETEINDEXRESPONSE']._serialized_end=4579
130
- _globals['_LISTINDEXESREQUEST']._serialized_start=4581
131
- _globals['_LISTINDEXESREQUEST']._serialized_end=4601
132
- _globals['_LISTINDEXESRESPONSE']._serialized_start=4603
133
- _globals['_LISTINDEXESRESPONSE']._serialized_end=4645
134
- _globals['_RETRAINVECTORINDEXREQUEST']._serialized_start=4647
135
- _globals['_RETRAINVECTORINDEXREQUEST']._serialized_end=4694
136
- _globals['_RETRAINVECTORINDEXRESPONSE']._serialized_start=4696
137
- _globals['_RETRAINVECTORINDEXRESPONSE']._serialized_end=4741
138
- _globals['_SEARCHSERVICE']._serialized_start=4876
139
- _globals['_SEARCHSERVICE']._serialized_end=5095
140
- _globals['_INDEXSERVICE']._serialized_start=5098
141
- _globals['_INDEXSERVICE']._serialized_end=5725
142
- # @@protoc_insertion_point(module_scope)
@@ -1,78 +0,0 @@
1
- """Type definitions for Hermes client."""
2
-
3
- from dataclasses import dataclass, field
4
- from typing import Any
5
-
6
-
7
- @dataclass
8
- class Document:
9
- """A document with field values."""
10
-
11
- fields: dict[str, Any] = field(default_factory=dict)
12
-
13
- def __getitem__(self, key: str) -> Any:
14
- return self.fields[key]
15
-
16
- def __setitem__(self, key: str, value: Any) -> None:
17
- self.fields[key] = value
18
-
19
- def get(self, key: str, default: Any = None) -> Any:
20
- return self.fields.get(key, default)
21
-
22
-
23
- @dataclass
24
- class DocAddress:
25
- """Unique document address: segment + local doc_id."""
26
-
27
- segment_id: str
28
- doc_id: int
29
-
30
-
31
- @dataclass
32
- class SearchHit:
33
- """A single search result."""
34
-
35
- address: DocAddress
36
- score: float
37
- fields: dict[str, Any] = field(default_factory=dict)
38
-
39
-
40
- @dataclass
41
- class SearchTimings:
42
- """Detailed timing breakdown for search phases (all values in microseconds)."""
43
-
44
- search_us: int
45
- rerank_us: int
46
- load_us: int
47
- total_us: int
48
-
49
-
50
- @dataclass
51
- class SearchResponse:
52
- """Search response with hits and metadata."""
53
-
54
- hits: list[SearchHit]
55
- total_hits: int
56
- took_ms: int
57
- timings: SearchTimings | None = None
58
-
59
-
60
- @dataclass
61
- class VectorFieldStats:
62
- """Per-field vector statistics."""
63
-
64
- field_name: str
65
- vector_type: str # "dense" or "sparse"
66
- total_vectors: int
67
- dimension: int
68
-
69
-
70
- @dataclass
71
- class IndexInfo:
72
- """Information about an index."""
73
-
74
- index_name: str
75
- num_docs: int
76
- num_segments: int
77
- schema: str
78
- vector_stats: list[VectorFieldStats] = field(default_factory=list)