#1639·deepface

[FEATURE]: migrate the weaviate backend to weaviate-client v4 (gRPC, no GraphQL)

Author: dudanogueiraCreated Sep 30, 2026Updated Sep 30, 2026

Description

The weaviate backend (deepface/modules/database/weaviate.py) is built on the v3 weaviate-client (weaviate.Client, client.query.get(...).do()). The v3 client is no longer maintained, and every search, dedup check and full scan goes through Weaviate's GraphQL API, which is being phased out in favor of gRPC. I'd like to port the backend to weaviate-client v4. I have it working and am happy to send the PR.

While testing the current backend (master, weaviate-client==3.26.7, Weaviate 1.39) I ran into these:

  1. register, search and identify with connection_details raise AttributeError: 'Client' object has no attribute 'close'. WeaviateClient.close() calls client.close(), which the v3 client doesn't have. The work itself is done, but the call fails. Today it only works when the user passes their own client via connection=.
  2. search(search_method="exact") only compares the first 100 registered faces. fetch_all_embeddings runs a GraphQL Get without a limit, and Weaviate returns QUERY_DEFAULTS_LIMIT (100 by default) objects. With 250 faces registered, 150 are never compared.
  3. DEEPFACE_WEAVIATE_URI, the env var listed in inventory.py and in the register/search docstrings, is never read. The code reads DEEPFACE_WEAVIATE_URL.
  4. WEAVIATE_HNSW_M has no effect. It is sent as M, but Weaviate's setting is maxConnections, so the default of 32 always applies.
  5. insert_embeddings has several problems:
    • It runs one GraphQL query per face to check for duplicates.
    • It ignores batch errors.
    • It reports skipped faces in inserted.

Proposed change

Two PRs, the second building on the first:

  1. Migrate to weaviate-client v4, with REST and gRPC and no GraphQL.
    • The collection names and schema stay the same, so existing data keeps working without a migration.
    • It fixes the issues above.
    • connection_details accepts a url, a dict, or a JSON string (for DEEPFACE_CONNECTION_DETAILS). The dict exposes the v4 connection options: self-hosted, Weaviate Cloud, separate gRPC host/port, API key, bearer token and OIDC auth, timeouts, proxies and skip_init_checks.
    • Requests carry the X-Weaviate-Client-Integration: deepface/<version> header, so the Weaviate team can see deepface usage and keep the integration working.
    • Requirements: weaviate-client>=4.16.0 and Weaviate 1.27+.
  2. Optional tenant and quantization settings (off by default).
    • tenant keeps each gallery of faces isolated using Weaviate multi-tenancy, e.g. one gallery per customer or site on the same cluster.
    • quantization (rq, bq, sq, pq) reduces memory use. Weaviate rescores results with the original vectors, so distances and thresholds are unchanged.

Additional Info

It is tested against Weaviate 1.27 to 1.39. On the same register → search → identify flow, requests to /v1/graphql drop from 152 to 0, and search results are identical to master's. Unit tests (mocked) and integration tests (docker-compose) are included.

Branches: https://github.com/dudanogueira/deepface/tree/feat/weaviate-client-v4 and https://github.com/dudanogueira/deepface/tree/feat/weaviate-quantization-tenancy

A notebook that runs the whole flow is at https://github.com/weaviate/recipes/tree/feat/deepface-recipe/integrations/data-platforms/deepface

Disclosure: I work at Weaviate.