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 phrase, 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:

async with HermesClient("localhost:50051", default_timeout=5.0) as client:
    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.124.tar.gz (19.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.124-py3-none-any.whl (20.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: hermes_client_python-1.8.124.tar.gz
  • Upload date:
  • Size: 19.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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.124.tar.gz
Algorithm Hash digest
SHA256 96efe8f3bc173da76fb0c481c71e8ca9d37ab3cc6bd8e9b2e6dabb1a5499dc6e
MD5 a68e8805c7b86b78ed5e4320d0a6c6d0
BLAKE2b-256 fe9b403efb122eb77d60a1beb3733619e9365bced424e29249aad4257442b7a6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: hermes_client_python-1.8.124-py3-none-any.whl
  • Upload date:
  • Size: 20.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.10 {"installer":{"name":"uv","version":"0.12.10","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.124-py3-none-any.whl
Algorithm Hash digest
SHA256 5048e7d0600beb8b0be0cb726ef46d54a85ddc9b6f645f0d094a7a71c12d339c
MD5 729eefea873f49e49ebcc9158f8efa67
BLAKE2b-256 7361388f227ff2e7c67d5c504e36739380a382fc661cd80a419446c626a84fde

See more details on using hashes here.

Release history Release notifications | RSS feed

1.8.127

2 files

This release

1.8.124 This release

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

1.8.107

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