Skip to main content

Hermes Python client

Async Python client for the Hermes gRPC search server.

Installation

pip install hermes-client-python

Python 3.10 or newer is required.

Quick start

import asyncio

from hermes_client_python import HermesClient


async def main():
    async with HermesClient("localhost:50051") as client:
        await client.create_index(
            "articles",
            """
            index articles {
                field title: text<simple> [indexed, stored]
                field body: text<simple> [indexed, stored]
            }
            """,
        )

        indexed, error_count, errors = await client.index_documents(
            "articles",
            [
                {"title": "Hello World", "body": "First article"},
                {"title": "Hermes Search", "body": "Fast retrieval"},
            ],
        )
        if error_count:
            raise RuntimeError(errors)
        print(f"Indexed {indexed} documents")

        await client.commit("articles")

        results = await client.search(
            "articles",
            query={"match": {"field": "title", "text": "hello"}},
            fields_to_load=["title", "body"],
        )
        for hit in results.hits:
            print(hit.address, hit.score, hit.fields)

        if results.hits:
            document = await client.get_document("articles", results.hits[0].address)
            print(document.fields if document else "document not found")

        await client.delete_index("articles")


asyncio.run(main())

The context manager calls connect() and close() automatically. For manual lifecycle management:

client = HermesClient("localhost:50051")
await client.connect()
try:
    ...
finally:
    await client.close()

Index management

await client.create_index("articles", schema_sdl)
names = await client.list_indexes()
info = await client.get_index_info("articles")
print(info.num_docs, info.num_segments, info.vector_stats)

await client.force_merge("articles")
await client.reorder("articles")
await client.retrain_vector_index("articles")
await client.delete_index("articles")

commit() is required before newly indexed documents become searchable.

Batch and streaming indexing

indexed, error_count, errors = await client.index_documents(
    "articles",
    [
        {"title": "One", "tags": ["search", "rust"]},
        {"title": "Two", "tags": ["python"]},
    ],
)


async def documents():
    for number in range(10_000):
        yield {"title": f"Document {number}"}


streamed, stream_errors = await client.index_documents_stream("articles", documents())

Repeated list values become repeated field entries. Flat numeric lists are dense vectors; lists of (dimension, weight) pairs are sparse vectors.

Searching

Every search takes one query object whose single key matches a Hermes query variant:

# Exact term
await client.search(
    "articles",
    query={"term": {"field": "title", "term": "hermes"}},
)

# Tokenized full-text match
await client.search(
    "articles",
    query={"match": {"field": "body", "text": "fast retrieval"}},
)

# Recursive boolean query
await client.search(
    "articles",
    query={
        "boolean": {
            "must": [{"match": {"field": "body", "text": "retrieval"}}],
            "must_not": [{"term": {"field": "title", "term": "draft"}}],
        }
    },
)

# Dense vector query and optional reranking
await client.search(
    "articles",
    query={
        "dense_vector": {
            "field": "embedding",
            "vector": [0.1, 0.2, 0.3],
            "nprobe": 16,
        }
    },
    reranker={"field": "embedding", "vector": [0.1, 0.2, 0.3]},
    candidate_limit=20,
    limit=10,
    fields_to_load=["title"],
)

# Hybrid union fusion
await client.search(
    "articles",
    query={
        "fusion": {
            "method": "rrf",
            "rrf_k": 60,
            "queries": [
                {
                    "query": {
                        "sparse_vector": {
                            "field": "sparse_embedding",
                            "indices": [1, 5],
                            "values": [0.8, 0.2],
                        }
                    },
                    "weight": 1.0,
                },
                {
                    "query": {
                        "dense_vector": {
                            "field": "embedding",
                            "vector": [0.1, 0.2, 0.3],
                        }
                    },
                    "weight": 1.0,
                },
            ],
        }
    },
)

Other supported variants are binary_dense_vector, boost, range, prefix, and all. Search results expose the full DocAddress needed by get_document():

hit = results.hits[0]
document = await client.get_document("articles", hit.address)

Deadlines and errors

Every RPC accepts an optional timeout in seconds. A per-call value overrides the client default:

client = HermesClient("localhost:50051", default_timeout=5.0)
results = await client.search(
    "articles",
    query={"all": {}},
    timeout=0.5,
)
await client.force_merge("articles", timeout=3600)

gRPC failures raise grpc.RpcError (normally grpc.aio.AioRpcError). get_document() is the exception: it returns None for NOT_FOUND.

import grpc

try:
    await client.search("missing", query={"all": {}})
except grpc.RpcError as error:
    if error.code() == grpc.StatusCode.NOT_FOUND:
        print("index not found")
    else:
        raise

Development

From hermes-client-python:

uv sync --group dev --group test
uv run ruff check .
uv run ruff format --check .
uv run pytest tests/test_client_unit.py

The remaining tests are integration tests and expect a debug target/debug/hermes-server binary. Regenerate checked-in protobuf stubs after changing hermes-proto/hermes.proto:

uv run --group dev python generate_proto.py

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hermes_client_python-1.8.107.tar.gz (18.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hermes_client_python-1.8.107-py3-none-any.whl (19.8 kB view details)

Uploaded Python 3

File details

Details for the file hermes_client_python-1.8.107.tar.gz.

File metadata

  • Download URL: hermes_client_python-1.8.107.tar.gz
  • Upload date:
  • Size: 18.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for hermes_client_python-1.8.107.tar.gz
Algorithm Hash digest
SHA256 b5400967db0f85802cf13eaead6b26553524b993d4cf92d4ffee82bf17f62cff
MD5 fdc1fab999aa8fd160b5d49f490b325c
BLAKE2b-256 706a637e577f02cf4e408915f134394a04fb91c6a21ced7271b35ea966dcdbeb

See more details on using hashes here.

File details

Details for the file hermes_client_python-1.8.107-py3-none-any.whl.

File metadata

  • Download URL: hermes_client_python-1.8.107-py3-none-any.whl
  • Upload date:
  • Size: 19.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for hermes_client_python-1.8.107-py3-none-any.whl
Algorithm Hash digest
SHA256 65d9a28a2dba6ed726203d05dce901de311fea1c9d9f2eb30dafea4410b20285
MD5 fee1d99be4dcdd478d8378446a2042f5
BLAKE2b-256 9a6ca029a5651b40fc5d842ee2befd4a6caf26a0d6642c035b8a8aa61c5be60d

See more details on using hashes here.

Release history Release notifications | RSS feed

1.8.127

2 files

1.8.124

2 files

1.8.123

2 files

1.8.122

2 files

1.8.121

2 files

1.8.120

2 files

1.8.119

2 files

1.8.118

2 files

1.8.117

2 files

1.8.116

2 files

1.8.115

2 files

1.8.114

2 files

1.8.113

2 files

1.8.112

2 files

1.8.111

2 files

1.8.110

2 files

1.8.109

2 files

1.8.108

2 files

This release

1.8.107 This release

2 files

1.8.105

2 files

1.8.104

2 files

1.8.103

2 files

1.8.102

2 files

1.8.101

2 files

1.8.100

2 files

1.8.99

2 files

1.8.98

2 files

1.8.97

2 files

1.8.96

2 files

1.8.95

2 files

1.8.94

2 files

1.8.93

2 files

1.8.92

2 files

1.8.91

2 files

1.8.90

2 files

1.8.89

2 files

1.8.88

2 files

1.8.87

2 files

1.8.86

2 files

1.8.85

2 files

1.8.84

2 files

1.8.83

2 files

1.8.82

2 files

1.8.81

2 files

1.8.80

2 files

1.8.79

2 files

1.8.78

2 files

1.8.77

2 files

1.8.76

2 files

1.8.75

2 files

1.8.74

2 files

1.8.73

2 files

1.8.72

2 files

1.8.71

2 files

1.8.70

2 files

1.8.69

2 files

1.8.68

2 files

1.8.67

2 files

1.8.66

2 files

1.8.65

2 files

1.8.64

2 files

1.8.63

2 files

1.8.62

2 files

1.8.61

2 files

1.8.60

2 files

1.8.59

2 files

1.8.58

2 files

1.8.57

2 files

1.8.56

2 files

1.8.55

2 files

1.8.54

2 files

1.8.53

2 files

1.8.52

2 files

1.8.51

2 files

1.8.50

2 files

1.8.49

2 files

1.8.48

2 files

1.8.47

2 files

1.8.45

2 files

1.8.44

2 files

1.8.43

2 files

1.8.41

2 files

1.8.40

2 files

1.8.39

2 files

1.8.38

2 files

1.8.37

2 files

1.8.36

2 files

1.8.35

2 files

1.8.34

2 files

1.8.33

2 files

1.8.32

2 files

1.8.31

2 files

1.8.30

2 files

1.8.29

2 files

1.8.28

2 files

1.8.27

2 files

1.8.26

2 files

1.8.25

2 files

1.8.24

2 files

1.8.23

2 files

1.8.22

2 files

1.8.21

2 files

1.8.20

2 files

1.8.19

2 files

1.8.18

2 files

1.8.17

2 files

1.8.16

2 files

1.8.15

2 files

1.8.14

2 files

1.8.13

2 files

1.8.12

2 files

1.8.11

2 files

1.8.10

2 files

1.8.9

2 files

1.8.8

2 files

1.8.7

2 files

1.8.6

2 files

1.8.5

2 files

1.8.4

2 files

1.8.3

2 files

1.8.2

2 files

1.8.1

2 files

1.8.0

2 files

1.7.98

2 files

1.7.97

2 files

1.7.59

2 files

1.7.56

2 files

1.7.55

2 files

1.7.54

2 files

1.7.52

2 files

1.7.51

2 files

1.7.50

2 files

1.7.49

2 files

1.7.48

2 files

1.7.47

2 files

1.7.46

2 files

1.7.45

2 files

1.7.44

2 files

1.7.43

2 files

1.7.42

2 files

1.7.41

2 files

1.7.40

2 files

1.7.39

2 files

1.7.38

2 files

1.7.37

2 files

1.7.36

2 files

1.7.35

2 files

1.7.34

2 files

1.7.33

2 files

1.7.32

2 files

1.7.31

2 files

1.7.30

2 files

1.7.29

2 files

1.7.28

2 files

1.7.27

2 files

1.7.26

2 files

1.7.25

2 files

1.7.24

2 files

1.7.23

2 files

1.7.22

2 files

1.7.21

2 files

1.7.20

2 files

1.7.19

2 files

1.7.18

2 files

1.7.17

2 files

1.7.16

2 files

1.7.15

2 files

1.7.14

2 files

1.7.13

2 files

1.7.12

2 files

1.7.11

2 files

1.7.10

2 files

1.7.9

2 files

1.7.8

2 files

1.7.7

2 files

1.7.6

2 files

1.7.5

2 files

1.7.4

2 files

1.7.3

2 files

1.7.2

2 files

1.7.1

2 files

1.7.0

2 files

1.6.16

2 files

1.6.15

2 files

1.6.14

2 files

1.6.13

2 files

1.6.12

2 files

1.6.11

2 files

1.6.10

2 files

1.6.9

2 files

1.6.8

2 files

1.6.7

2 files

1.6.6

2 files

1.6.5

2 files

1.6.4

2 files

1.6.3

2 files

1.6.2

2 files

1.6.1

2 files

1.5.2

2 files

1.5.1

2 files

1.5.0

2 files

1.4.80

2 files

1.4.79

2 files

1.4.78

2 files

1.4.77

2 files

1.4.76

2 files

1.4.75

2 files

1.4.74

2 files

1.4.73

2 files

1.4.72

2 files

1.4.71

2 files

1.4.70

2 files

1.4.69

2 files

1.4.68

2 files

1.4.67

2 files

1.4.66

2 files

1.4.65

2 files

1.4.64

2 files

1.4.63

2 files

1.4.62

2 files

1.4.61

2 files

1.4.60

2 files

1.4.59

2 files

1.4.57

2 files

1.4.56

2 files

1.4.55

2 files

1.4.54

2 files

1.4.53

2 files

1.4.52

2 files

1.4.51

2 files

1.4.50

2 files

1.4.49

2 files

1.4.48

2 files

1.4.47

2 files

1.4.46

2 files

1.4.45

2 files

1.4.44

2 files

1.4.43

2 files

1.4.42

2 files

1.4.40

2 files

1.4.39

2 files

1.4.38

2 files

1.4.37

2 files

1.4.36

2 files

1.4.35

2 files

1.4.34

2 files

1.4.33

2 files

1.4.32

2 files

1.4.31

2 files

1.4.30

2 files

1.4.29

2 files

1.4.28

2 files

1.4.27

2 files

1.4.26

2 files

1.4.25

2 files

1.4.24

2 files

1.4.23

2 files

1.4.22

2 files

1.4.21

2 files

1.4.20

2 files

1.4.18

2 files

1.4.17

2 files

1.4.16

2 files

1.4.15

2 files

1.4.14

2 files

1.4.13

2 files

1.4.12

2 files

1.4.11

2 files

1.4.10

2 files

1.4.9

2 files

1.4.8

2 files

1.4.7

2 files

1.4.6

2 files

1.4.5

2 files

1.4.4

2 files

1.4.3

2 files

1.4.1

2 files

1.4.0

2 files

1.3.4

2 files

1.3.3

2 files

1.3.2

2 files

1.3.1

2 files

1.2.7

2 files

1.2.6

2 files

1.2.5

2 files

1.2.4

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.0.4

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page