Skip to main content

Python

This page broadly covers the Weaviate Python client (v4 release). For usage information not specific to the Python client, such as code examples, see the relevant pages in the Weaviate documentation. Some frequently used sections are listed here for convenience.

Inline documentation

For the inline documentation (also known as docstrings) of the Python client, see the Read the Docs page.

Asynchronous usage

The Python client library provides a synchronous API by default through the WeaviateClient class, which is covered on this page. An asynchronous API is also available through the WeaviateAsyncClient class (from weaviate-client v4.7.0 and up). See the async client API page for further details.

Installation

Migrating from v3 to v4

If you are migrating from the v3 client to the v4, see this dedicated guide.

The Python client library is developed and tested using Python 3.8+. It is available on PyPI.org, and can be installed with:

# For beta versions: `pip install --pre -U "weaviate-client==4.*"`
pip install -U weaviate-client

Requirements

gRPC

The v4 client uses remote procedure calls (RPCs) under-the-hood. Accordingly, a port for gRPC must be open to your Weaviate server.

docker-compose.yml example

If you are running Weaviate with Docker, you can map the default port (50051) by adding the following to your docker-compose.yml file:

    ports:
- 8080:8080
- 50051:50051

WCD compatibility

The free (sandbox) tier of WCD is compatible with the v4 client as of 31 January, 2024. Sandboxes created before this date will not be compatible with the v4 client.

Weaviate server version

The v4 client requires Weaviate 1.23.7 or higher. Generally, we encourage you to use the latest version of the Python client and the Weaviate server.

High-level ideas

Helper classes

The client library provides numerous additional Python classes to provide IDE assistance and typing help. You can import them individually, like so:

from weaviate.classes.config import Property, ConfigFactory
from weaviate.classes.data import DataObject
from weaviate.classes.query import Filter

But it may be convenient to import the whole set of classes like this. You will see both usage styles in our documentation.

import weaviate.classes as wvc

For discoverability, the classes are arranged into submodules.

See the list of submodules
ModuleDescription
weaviate.classes.configCollection creation / modification
weaviate.classes.dataCUD operations
weaviate.classes.queryquery/search operations
weaviate.classes.aggregateaggregate operations
weaviate.classes.genericgenerics
weaviate.classes.initinitialization
weaviate.classes.tenantstenants
weaviate.classes.batchbatch operations

Connection termination

You must ensure your client connections are closed. You can use client.close(), or use a context manager to close client connections for you.

client.close() with try / finally

This will close the client connection when the try block is complete (or if an exception is raised).

import weaviate

client = weaviate.connect_to_local() # Connect with default parameters

try:
pass # Do something with the client

finally:
client.close() # Ensure the connection is closed

Context manager

This will close the client connection when you leave the with block.

import weaviate

with weaviate.connect_to_local() as client:
# Do something with the client
pass
# The connection is closed automatically when the context manager exits

Instantiate a client

There are multiple ways to connect to your Weaviate instance. To instantiate a client, use one of these styles:

Connection helper functions

  • weaviate.connect_to_weaviate_cloud()
    • Previously connect_to_wcs()
  • weaviate.connect_to_local()
  • weaviate.connect_to_embedded()
  • weaviate.connect_to_custom()
import weaviate
from weaviate.classes.init import Auth
import os

# Best practice: store your credentials in environment variables
wcd_url = os.environ["WCD_DEMO_URL"]
wcd_api_key = os.environ["WCD_DEMO_RO_KEY"]
openai_api_key = os.environ["OPENAI_APIKEY"]

client = weaviate.connect_to_weaviate_cloud(
cluster_url=wcd_url, # Replace with your Weaviate Cloud URL
auth_credentials=Auth.api_key(wcd_api_key), # Replace with your Weaviate Cloud key
headers={'X-OpenAI-Api-key': openai_api_key} # Replace with your OpenAI API key
)

The v4 client helper functions provide some optional parameters to customize your client.

External API keys

To add API keys for services such as Cohere or OpenAI, use the headers parameter.

import weaviate
import os

client = weaviate.connect_to_local(
headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_APIKEY")
}
)

Timeout values

You can set timeout values, in seconds, for the client. Use the Timeout class to configure the timeout values for initialization checks as well as query and insert operations.

import weaviate
from weaviate.classes.init import AdditionalConfig, Timeout

client = weaviate.connect_to_local(
port=8080,
grpc_port=50051,
additional_config=AdditionalConfig(
timeout=Timeout(init=30, query=60, insert=120) # Values in seconds
)
)
Timeouts on generate queries

If you see errors while using the generate submodule, try increasing the query timeout values (Timeout(query=60)).

The generate submodule uses a large language model to generate text. The submodule is dependent on the speed of the language model and any API that serves the language model.

Increase the timeout values to allow the client to wait longer for the language model to respond.

Authentication

Some of the connect helper functions take authentication credentials. For example, connect_to_weaviate_cloud accepts a WCD API key or OIDC authentication credentials.

import weaviate
from weaviate.classes.init import Auth
import os

# Best practice: store your credentials in environment variables
wcd_url = os.environ["WCD_DEMO_URL"]
wcd_api_key = os.environ["WCD_DEMO_RO_KEY"]
openai_api_key = os.environ["OPENAI_APIKEY"]

client = weaviate.connect_to_weaviate_cloud(
cluster_url=wcd_url, # Replace with your Weaviate Cloud URL
auth_credentials=Auth.api_key(wcd_api_key), # Replace with your Weaviate Cloud key
headers={'X-OpenAI-Api-key': openai_api_key} # Replace with your OpenAI API key
)

For OIDC authentication with the Client Credentials flow, use the AuthClientCredentials class.

For OIDC authentication with the Refresh Token flow, use the AuthBearerToken class.

If the helper functions do not provide the customization you need, use the WeaviateClient class to instantiate the client.

Explicit instantiation

If you need to pass custom parameters, use the weaviate.WeaviateClient class to instantiate a client. This is the most flexible way to instantiate the client object.

When you instantiate a connection directly, you have to call the .connect() method to connect to the server.

import weaviate
from weaviate.connect import ConnectionParams
from weaviate.classes.init import AdditionalConfig, Timeout, Auth
import os

client = weaviate.WeaviateClient(
connection_params=ConnectionParams.from_params(
http_host="localhost",
http_port=8099,
http_secure=False,
grpc_host="localhost",
grpc_port=50052,
grpc_secure=False,
),
auth_client_secret=Auth.api_key("secr3tk3y"),
additional_headers={
"X-OpenAI-Api-Key": os.getenv("OPENAI_APIKEY")
},
additional_config=AdditionalConfig(
timeout=Timeout(init=30, query=60, insert=120), # Values in seconds
),
skip_init_checks=False
)

client.connect() # When directly instantiating, you need to connect manually

Async client

Added in weaviate-client v4.7.0

The v4 API client supports asynchronous (asyncio) operations through the WeaviateAsyncClient class.

You can instantiate an WeaviateAsyncClient object directly, or use helper functions with a weaviate.use_async_xxx prefix such as weaviate.use_async_with_weaviate_cloud().

For more details, see the async Python client documentation.

Legacy (v3) API

To create an older, v3 style Client object, use the weaviate.Client class. This method is available for backwards compatibility. Where possible, use a client v4 connection.

To create a v3 style client, refer to the v3 client documentation.

Initial connection checks

When establishing a connection to the Weaviate server, the client performs a series of checks. These includes checks for the server version, and to make sure that the REST and gRPC ports are available.

You can set skip_init_checks to True to skip these checks.

import weaviate

client = weaviate.connect_to_local(
skip_init_checks=True
)

In most cases, you should use the default False setting for skip_init_checks. However, setting skip_init_checks=True may be a useful temporary measure if you have connection issues.

For additional connection configuration, see Timeout values.

Batch imports

The v4 client offers two ways to perform batch imports. From the client object directly, or from the collection object.

We recommend using the collection object to perform batch imports of single collections or tenants. If you are importing objects across many collections, such as in a multi-tenancy configuration, using client.batch may be more convenient.

Batch sizing

There are three methods to configure the batching behavior. They are dynamic, fixed_size and rate_limit.

MethodDescriptionWhen to use
dynamicThe batch size and the number of concurrent requests are dynamically adjusted on-the-fly during import, depending on the server load.Recommended starting point.
fixed_sizeThe batch size and number of concurrent requests are fixed to sizes specified by the user.When you want to specify fixed parameters.
rate_limitThe number of objects sent to Weaviate is rate limited (specified as n_objects per minute).When you want to avoid hitting third-party vectorization API rate limits.

Usage

We recommend using a context manager as shown below.

These methods return a new context manager for each batch. Attributes that are returned from one batch, such as failed_objects or failed_references, are not included in any subsequent calls.

import weaviate

client = weaviate.connect_to_local()

try:
with client.batch.dynamic() as batch: # or <collection>.batch.dynamic()
# Batch import objects/references - e.g.:
batch.add_object(properties={"title": "Multitenancy"}, collection="WikiArticle", uuid=src_uuid)
batch.add_object(properties={"title": "Database schema"}, collection="WikiArticle", uuid=tgt_uuid)
batch.add_reference(from_collection="WikiArticle", from_uuid=src_uuid, from_property="linkedArticle", to=tgt_uuid)

finally:
client.close()

If the background thread that is responsible for sending the batches raises an exception during batch processing, the error is raised to the main thread.

Error handling

During a batch import, any failed objects or references will be stored for retrieval. Additionally, a running count of failed objects and references is maintained.

The counter can be accessed through batch.number_errors within the context manager.

A list of failed objects can be obtained through batch.failed_objects and a list of failed references can be obtained through batch.failed_references.

Note that these lists are reset when a batching process is initialized. So make sure to retrieve them before starting a new batch import block.

import weaviate

client = weaviate.connect_to_local()

try:
# ===== First batch import block =====
with client.batch.rate_limit(requests_per_minute=600) as batch: # or <collection>.batch.rate_limit()
# Batch import objects/references
for i in source_iterable: # Some insertion loop
if batch.number_errors > 10: # Monitor errors during insertion
# Break or raise an exception
pass
# Note these are outside the `with` block - they are populated after the context manager exits
failed_objs_a = client.batch.failed_objects # Get failed objects from the first batch import
failed_refs_a = client.batch.failed_references # Get failed references from the first batch import

# ===== Second batch import block =====
# This will clear the failed objects/references
with client.batch.rate_limit(requests_per_minute=600) as batch: # or <collection>.batch.rate_limit()
# Batch import objects/references
for i in source_iterable: # Some insertion loop
if batch.number_errors > 10: # Monitor errors during insertion
# Break or raise an exception
pass
# Note these are outside the `with` block - they are populated after the context manager exits
failed_objs_b = client.batch.failed_objects # Get failed objects from the second batch import
failed_refs_b = client.batch.failed_references # Get failed references from the second batch import

finally:
client.close()

Batch vectorization

Added in v1.25.

Some model providers provide batch vectorization APIs, where each request can include multiple objects.

From Weaviate v1.25.0, a batch import automatically makes use of the model providers' batch vectorization APIs where available. This reduces the number of requests to the model provider, improving throughput.

The client automatically handles vectorization if you set the vectorizer when you create the collection.

collection = client.collections.create(
name="NewCollection",
properties=[
Property(name="url", data_type=DataType.TEXT),
Property(name="title", data_type=DataType.TEXT),
Property(name="raw", data_type=DataType.TEXT),
Property(name="sha", data_type=DataType.TEXT),
],
vectorizer_config=[
Configure.NamedVectors.text2vec_cohere(name="cohereFirst"),
Configure.NamedVectors.text2vec_cohere(name="cohereSecond"),
]
)

To modify the vectorization settings, update the client object. This example adds multiple vectorizers:

  • Cohere. Set the service API key. Set the request rate.

  • OpenAI. Set the service API key. Set the base URL.

  • VoyageAI. Set the service API key.

    from weaviate.classes.config import Integrations

    integrations = [
    # Each model provider may expose different parameters
    Integrations.cohere(
    api_key=cohere_key,
    requests_per_minute_embeddings=rpm_embeddings,
    ),
    Integrations.openai(
    api_key=openai_key,
    requests_per_minute_embeddings=rpm_embeddings,
    tokens_per_minute_embeddings=tpm_embeddings, # e.g. OpenAI also exposes tokens per minute for embeddings
    ),
    ]
    client.integrations.configure(integrations)

Working with collections

Instantiate a collection

You can instantiate a collection object by creating a collection, or by retrieving an existing collection.

import weaviate
import weaviate.classes.config as wvcc

client = weaviate.connect_to_local()

try:
# Note that you can use `client.collections.create_from_dict()` to create a collection from a v3-client-style JSON object
collection = client.collections.create(
name="TestArticle",
vectorizer_config=wvcc.Configure.Vectorizer.text2vec_cohere(),
generative_config=wvcc.Configure.Generative.cohere(),
properties=[
wvcc.Property(
name="title",
data_type=wvcc.DataType.TEXT
)
]
)

finally:
client.close()

Collection submodules

Operations in the v4 client are grouped into submodules. The key submodules for interacting with objects are:

  • data: CUD operations (read operations are in query)
  • batch: Batch import operations
  • query: Search operations
  • generate: Retrieval augmented generation operations
    • Build on top of query operations
  • aggregate: Aggregation operations

data

The data submodule contains all object-level CUD operations, including:

  • insert for creating objects.
    • This function takes the object properties as a dictionary.
  • insert_many for adding multiple objects with one request.
    • This function takes the object properties as a dictionary or as a DataObject instance.
    • Note: For larger numbers of objects, consider using batch imports.
  • update for updating objects (for PATCH operations).
  • replace for replacing objects (for PUT operations).
  • delete_by_id for deleting objects by ID.
  • delete_many for batch deletion.
  • reference_xxx for reference operations, including reference_add, reference_add_many, reference_update and reference_delete.

See some examples below. Note that each function will return varying types of objects.

questions = client.collections.get("JeopardyQuestion")

new_uuid = questions.data.insert(
properties={
"question": "This is the capital of Australia."
},
references={ # For adding cross-references
"hasCategory": target_uuid
}
)
insert_many sends one request

insert_many sends one request for the entire function call. For requests with a large number of objects, consider using batch imports.

insert_many with DataObjects

The insert_many function takes a list of DataObject instances or a list of dictionaries. This is useful if you want to specify additional information to the properties, such as cross-references, object uuid, or a custom vector.

from weaviate.util import generate_uuid5

questions = client.collections.get("JeopardyQuestion")

data_objects = list()
for i in range(5):
properties = {"question": f"Test Question {i+1}"}
data_object = wvc.data.DataObject(
properties=properties,
uuid=generate_uuid5(properties)
)
data_objects.append(data_object)

response = questions.data.insert_many(data_objects)

Cross-reference creation

Cross-references should be added under a references parameter in the relevant function/method, with a structure like:

{
"<REFERENCE_PROPERTY_NAME>": "<TARGET_UUID>"
}

For example:

from weaviate.util import generate_uuid5

questions = client.collections.get("JeopardyQuestion")

data_objects = list()
for i in range(5):
properties = {"question": f"Test Question {i+1}"}
data_object = wvc.data.DataObject(
properties=properties,
references={
"hasCategory": target_uuid
},
uuid=generate_uuid5(properties)
)
data_objects.append(data_object)

response = questions.data.insert_many(data_objects)

Using the properties parameter to add references is deprecated and will be removed in the future.

query

The query submodule contains all object-level query operations, including fetch_objects for retrieving objects without additional search parameters, bm25 for keyword search, near_<xxx> for vector search operators, hybrid for hybrid search and so on.

These queries return a _QueryReturn object, which contains a list of _Object objects.

questions = client.collections.get("JeopardyQuestion")
response = questions.query.bm25(
query="animal",
limit=2
)

for o in response.objects:
print(o.properties) # Object properties

Queries with custom returns

You can further specify:

  • Whether to include the object vector (via include_vector)
    • Default is False
  • Which properties to include (via return_properties)
    • All properties are returned by default
  • Which references to include (via return_references)
  • Which metadata to include
    • No metadata is returned by default

Each object includes its UUID as well as all properties by default.

For example:

questions = client.collections.get("JeopardyQuestion")
response = questions.query.bm25(
query="animal",
limit=2
)

for o in response.objects:
print(o.properties) # All properties by default
print(o.references) # References not returned by default
print(o.uuid) # UUID included by default
print(o.vector) # No vector
print(o.metadata) # No metadata

query + group by

Results of a query can be grouped by a property as shown here.

The results are organized by both their individual objects as well as the group.

  • The objects attribute is a list of objects, each containing a belongs_to_group property to indicate which group it belongs to.
  • The group attribute is a dictionary with each key indicating the value of the group, and the value being a list of objects belonging to that group.
questions = client.collections.get("JeopardyQuestion")
response = questions.query.near_text(
query="animal",
distance=0.2,
group_by=wvc.query.GroupBy(
prop="points",
number_of_groups=3,
objects_per_group=5
)
)

for k, v in response.groups.items(): # View by group
print(k, v)

for o in response.objects: # View by object
print(o)

generate

The generate methods perform retrieval augmented generation (RAG). This is a two-step process involving a search followed by prompting a large language model. Therefore, function names are shared across the query and generate submodules, with additional parameters available in the generate submodule.

questions = client.collections.get("JeopardyQuestion")
response = questions.generate.bm25(
query="animal",
limit=2,
grouped_task="What do these animals have in common?",
single_prompt="Translate the following into French: {answer}"
)

print(response.generated) # Generated text from grouped task
for o in response.objects:
print(o.generated) # Generated text from single prompt
print(o.properties) # Object properties

Outputs of the generate submodule queries include generate attributes at the top level for the grouped_task tasks, while generate attributes attached with each object contain results from single_prompt tasks.

aggregate

To use the aggregate submodule, supply one or more ways to aggregate the data. For example, they could be by a count of objects matching the criteria, or by a metric aggregating the objects' properties.

from weaviate.classes.query import Filter

questions = client.collections.get("JeopardyQuestion")
response = questions.aggregate.over_all(
filters=Filter.by_property(name="question").like("*animal*"),
total_count=True
)

print(response.total_count)

aggregate + group by

Results of a query can be grouped and aggregated as shown here.

The results are organized the group, returning a list of groups.

from weaviate.classes.aggregate import GroupByAggregate

questions = client.collections.get("JeopardyQuestion")
response = questions.aggregate.near_text(
query="animal",
distance=0.2,
group_by=GroupByAggregate(prop="points"),
return_metrics=wvc.query.Metrics("points").integer(mean=True)
)

for o in response.groups:
print(o)

Model Provider Integrations

Model provider integrations are configured using the weaviate.classes.config.Configure class. More specifically, they are configured through the Generate, Reranker, Vectorizer or NamedVector namespaces as shown in the examples below:

from weaviate.classes.config import Configure

client.collections.create(
"DemoCollection",
generative_config=Configure.Generative.anthropic()
# Additional parameters not shown
)

Manually specify provider integrations

In the rare cases where Weaviate supports a model provider that is not yet integrated into the client library, you can manually specify the model provider configuration through the .custom() methods in each namespace.

Note that the module_config keys should follow the naming convention of Weaviate database, which uses camelCase for keys. For example, api_endpoint in .anthropic() becomes apiEndpoint in .custom().

from weaviate.classes.config import Configure

client.collections.create(
"DemoCollection",
generative_config=Configure.Generative.custom(
module_name="generative-anthropic",
module_config={"model": "claude-3-5-sonnet-20240620"}
)
# Additional parameters not shown
)

Collection iterator (cursor API)

The v4 client adds a Pythonic iterator method for each collection. This wraps the cursor API and allows you to iterate over all objects in a collection.

This example fetches all the objects, and their properties, from the questions collection.

all_objects = [question for question in questions.iterator()]

You can specify which properties to retrieve. This example fetches the answer property.

all_object_answers = [question for question in questions.iterator(return_properties=["answer"])]

You can also specify which metadata to retrieve. This example fetches the creation_time metadata.

all_object_ids = [question for question in questions.iterator(return_metadata=wvc.query.MetadataQuery(creation_time=True))]  # Get selected metadata

Since the cursor API requires the object UUID for indexing, the uuid metadata is always retrieved.

You can also get the size of the collection by using the built-in len function.

articles = client.collections.get("Article")
print(len(articles))

Data model and generics

You can choose to provide a generic type to a query or data operation. This can be beneficial as the generic class is used to extract the return properties and statically type the response.

from typing import TypedDict

questions = client.collections.get("JeopardyQuestion")

class Question(TypedDict):
question: str
answer: str
points: int

response = questions.query.fetch_objects(
limit=2,
return_properties=Question, # Your generic class is used to extract the return properties and statically type the response
return_metadata=wvc.query.MetadataQuery(creation_time=True) # MetaDataQuery object is used to specify the metadata to be returned in the response
)

Migration guides

Migrating from v3 to v4

If you are migrating from the v3 client to the v4, see this dedicated guide.

Beta releases

Migration guides - beta releases

Changes in v4.4b9

weaviate.connect_to_x methods

The timeout argument in now a part of the additional_config argument. It takes the class weaviate.config.AdditionalConfig as input.

Queries

All optional arguments to methods in the query namespace now are enforced as keyword arguments.

There is now runtime logic for parsing query arguments enforcing the correct type.

Batch processing

Introduction of three distinct algorithms using different batching styles under-the-hood:

  • client.batch.dynamic()
  • client.batch.fixed_size()
  • client.batch.rate_limit()

client.batch.dynamic() as batch is a drop-in replacement for the previous client.batch as batch, which is now deprecated and will be removed on release.

with client.batch.dynamic() as batch:
...

is equivalent to:

with client.batch as batch:
...

client.batch.fixed_size() as batch is a way to configure your batching algorithm to only use a fixed size.

with client.batch.dynamic() as batch:
...

is equivalent to:

client.batch.configure_fixed_size()
with client.batch as batch:
...

client.batch.rate_limit() as batch is a new way to help avoid hitting third-party vectorization API rate limits. By specifying request_per_minute in the rate_limit() method, you can force the batching algorithm to send objects to Weaviate at the speed your third-party API is capable of processing objects.

These methods now return completely localized context managers. This means that failed_objects and failed_references of one batch won't be included in any subsequent calls.

Finally, if the background thread responsible for sending the batches raises an exception this is now re-raised in the main thread rather than silently erroring.

Filters

The argument prop in Filter.by_property has been renamed to name

Ref counting is now achievable using Filter.by_ref_count(ref) rather than Filter([ref])

Changes in v4.4b8

Reference filters

Reference filters have a simplified syntax. The new syntax looks like this:

Filter.by_ref("ref").by_property("target_property")

Changes in v4.4b7

Library imports

Importing directly from weaviate is deprecated. Use import weaviate.classes as wvc instead.

Close client connections

Starting in v4.4b7, you have to explicitly close your client connections. There are two ways to close client connections.

Use client.close() to explicitly close your client connections.

import weaviate
client = weaviate.connect_to_local()

print(client.is_ready())

client.close()

Use a context manager to close client connections for you.

import weaviate

with weaviate.connect_to_local() as client:
print(client.is_ready())

# Python closes the client when you leave the 'with' block
Batch processing

The v4.4b7 client introduces changes to client.batch.

  • client.batch requires a context manager.
  • Manual mode is removed, you cannot send batches with .create_objects.
  • Batch size and the number of concurrent requests are dynamically assigned. Use batch.configure_fixed_size to specify values.
  • The add_reference method is updated.
  • The to_object_collection method is removed.

Updated client.batch parameters

Old valueValue in v4.4b7
from_object_uuid: UUIDfrom_uuid: UUID
from_object_collection: strfrom_collection: str
from_property_name: strfrom_property: str
to_object_uuid: UUIDto: Union[WeaviateReference, List[UUID]]
to_object_collection: Optional[str] = None
tenant: Optional[str] = Nonetenant: Optional[str] = None
Filter syntax

Filter syntax is updated in v4.4b7.

NOTE: The filter reference syntax is simplified in 4.4b8.

Old syntaxNew syntax in v4.4b7
Filter(path=property)Filter.by_property(property)
Filter(path=["ref", "target_class", "target_property"])Filter.by_ref().link_on("ref").by_property("target_property")
FilterMetadata.ByXXFilter.by_id()
Filter.by_creation_time()
Filter.by_update_time()

The pre-4.4b7 filter syntax is deprecated. The new, v4.4b7 syntax looks like this.

import weaviate
import datetime
import weaviate.classes as wvc

client = weaviate.connect_to_local()

jeopardy = client.collections.get("JeopardyQuestion")
response = jeopardy.query.fetch_objects(
filters=wvc.query.Filter.by_property("round").equal("Double Jeopardy!") &
wvc.query.Filter.by_creation_time().greater_or_equal(datetime.datetime(2005, 1, 1)) |
wvc.query.Filter.by_creation_time().greater_or_equal(datetime.datetime(2000, 12, 31)),
limit=3
)


client.close()
reference_add_many updated

The reference_add_many syntax is updated; DataReferenceOneToMany is now DataReference.

collection.data.reference_add_many(
[
DataReference(
from_property="ref",
from_uuid=uuid_from,
to_uuid=*one or a list of UUIDs*,
)
]
)
References

Multi-target references updated. These are the new functions:

  • ReferenceProperty.MultiTarget
  • DataReference.MultiTarget
  • QueryReference.MultiTarget

Use ReferenceToMulti for multi-target references.

Older client changes

References
Reorganization of classes/parameters
  • weaviate.classes submodule further split into:
    • weaviate.classes.config
    • weaviate.classes.data
    • weaviate.classes.query
    • weaviate.classes.generic
  • vector_index_config parameter factory functions for wvc.config.Configure and wvc.config.Reconfigure have changed to, e.g.:
    client.collections.create(
    name="MyCollection",
    vector_index_config=wvc.config.Configure.VectorIndex.hnsw(
    distance_metric=wvc.config.VectorDistances.COSINE,
    vector_cache_max_objects=1000000,
    quantizer=wvc.config.Configure.VectorIndex.Quantizer.pq()
    ),
    )
    • vector_index_type parameter has been removed.
  • vectorize_class_name parameter in the Property constructor method is vectorize_collection_name.
  • [collection].data.update() / .replace() *args order changed, aiming to accommodate not providing properties when updating.
  • [collection].data.reference_add / .reference_delete / .reference_replace the ref keyword was renamed to to.
  • collections.create() / get(): data_model kwarg to keyword to provide generics was renamed to data_model_properties .
  • [object].metadata.uuid is now [object].uuid.
  • [object].metadata.creation_time_unix is now [object].metadata.creation_time.
  • [object].metadata.last_update_time_unix is now [object].metadata.last_update.
  • quantitizer is renamed to quantizer
  • To request the vector in the returned data, use the include_vector parameter (example).
Data types
  • Time metadata (for creation and last updated time) now returns a datetime object, and the parameters are renamed to creation_time and last_update_time under MetadataQuery.
    • metadata.creation_time.timestamp() * 1000 will return the same value as before.
  • query.fetch_object_by_id() now uses gRPC under the hood (rather than REST), and returns objects in the same format as other queries.
  • UUID and DATE properties are returned as typed objects.

Best practices and notes

Exception handling

The client library raises exceptions for various error conditions. These include, for example:

  • weaviate.exceptions.WeaviateConnectionError for failed connections.
  • weaviate.exceptions.WeaviateQueryError for failed queries.
  • weaviate.exceptions.WeaviateBatchError for failed batch operations.
  • weaviate.exceptions.WeaviateClosedClientError for operations on a closed client.

Each of these exceptions inherit from weaviate.exceptions.WeaviateBaseError, and can be caught using this base class, as shown below.

try:
collection = client.collections.get("NonExistentCollection")
collection.query.fetch_objects(limit=2)
except weaviate.exceptions.WeaviateBaseError as e:
print(f"Caught a Weaviate error: {e.message}")

You can review this module which defines the exceptions that can be raised by the client library.

The client library doc strings also provide information on the exceptions that can be raised by each method. You can view these by using the help function in Python, by using the ? operator in Jupyter notebooks, or by using an IDE, such as hover-over tooltips in VSCode.

Thread-safety

While the Python client is fundamentally designed to be thread-safe, it's important to note that due to its dependency on the requests library, complete thread safety isn't guaranteed.

This is an area that we are looking to improve in the future.

Thread safety

The batching algorithm in our client is not thread-safe. Keep this in mind to help ensure smoother, more predictable operations when using our Python client in multi-threaded environments.

If you are performing batching in a multi-threaded scenario, ensure that only one of the threads is performing the batching workflow at any given time. No two threads can use the same client.batch object at one time.

Response object structure

Each query response object typically include multiple attributes. Consider this query.

questions = client.collections.get("JeopardyQuestion")
response = questions.generate.near_text(
query="history",
limit=2,
single_prompt="Translate this into French {question}",
grouped_task="Summarize this into a sentence",
return_metadata=wvc.query.MetadataQuery(
distance=True,
creation_time=True
)
)

print("Grouped Task generated outputs:")
print(response.generated)
for o in response.objects:
print(f"Outputs for object {o.uuid}")
print(f"Generated text:")
print(o.generated)
print(f"Properties:")
print(o.properties)
print(f"Metadata")
print(o.metadata)

Each response includes attributes such as objects and generated. Then, each object in objects include multiple attributes such as uuid, vector, properties, references, metadata and generated.

_GenerativeReturn(objects=[_GenerativeObject(uuid=UUID('61e29275-8f53-5e28-a355-347d45a847b3'), metadata=_MetadataReturn(creation_time=datetime.datetime(2024, 1, 2, 18, 3, 7, 475000, tzinfo=datetime.timezone.utc), last_update_time=None, distance=0.19253945350646973, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={'points': 1000.0, 'answer': 'Daniel Boorstein', 'air_date': datetime.datetime(1990, 3, 26, 0, 0, tzinfo=datetime.timezone.utc), 'round': 'Double Jeopardy!', 'question': 'This historian & former Librarian of Congress was teaching history at Harvard while studying law at Yale'}, references=None, vector=None, generated="Cet historien et ancien bibliothécaire du Congrès enseignait l'histoire à Harvard tout en étudiant le droit à Yale."), _GenerativeObject(uuid=UUID('e987d1a1-2599-5dd8-bd22-4f3b0338539a'), metadata=_MetadataReturn(creation_time=datetime.datetime(2024, 1, 2, 18, 3, 8, 185000, tzinfo=datetime.timezone.utc), last_update_time=None, distance=0.193121075630188, certainty=None, score=None, explain_score=None, is_consistent=None, rerank_score=None), properties={'points': 400.0, 'air_date': datetime.datetime(2007, 5, 11, 0, 0, tzinfo=datetime.timezone.utc), 'answer': 'an opinion', 'round': 'Jeopardy!', 'question': 'This, a personal view or belief, comes from the Old French for "to think"'}, references=None, vector=None, generated='Ceci, une opinion personnelle ou une croyance, provient du vieux français signifiant "penser".')], generated='Daniel Boorstein, a historian and former Librarian of Congress, taught history at Harvard while studying law at Yale, and an opinion is a personal view or belief derived from the Old French word for "to think".')

To limit the response payload, you can specify which properties and metadata to return.

Input argument validation

The client library performs input argument validation by default to make sure that the input types match the expected types.

You can disable this validation to improve performance. You can do this by setting the skip_argument_validation parameter to True when you instantiate a collection object, with collections.get, or with collections.create for example.

# Configure the `performant_articles` to skip argument validation on its methods
performant_articles = client.collections.get("Article", skip_argument_validation=True)

This may be useful in cases where you are using the client library in a production environment, where you can be confident that the input arguments are typed correctly.

Tab completion in Jupyter notebooks

If you use a browser to run the Python client with a Jupyter notebook, press Tab for code completion while you edit. If you use VSCode to run your Jupyter notebook, press control + space for code completion.

Raw GraphQL queries

To provide raw GraphQL queries, you can use the client.graphql_raw_query method (previously client.query.raw in the v3 client). This method takes a string as input.

Code examples & resources

Usage information for various operations and features can be found throughout the Weaviate documentation.

Some frequently used sections are the how-to guides for Managing data and Queries. The how-to guides include concise examples for common operations.

In particular, check out the pages for:

The Weaviate API reference pages for search and REST may also be useful starting points.

Releases

Go to the GitHub releases page to see the history of the Python client library releases.

Click here for a table of Weaviate and corresponding client versions

This table lists the Weaviate core versions and corresponding client library versions.

Weaviate
(GitHub)
First
release date
Python
(GitHub)
TypeScript/
JavaScript
(GitHub)
Go
(GitHub)
Java
(GitHub)
1.28.x2024-12-114.10.xTBCTBCTBC
1.27.x2024-10-164.9.x3.2.x4.16.x5.0.x
4.9.x
1.26.x2024-07-224.7.x3.1.x4.15.x4.8.x
1.25.x2024-05-104.6.x2.1.x4.13.x4.6.x
1.24.x2024-02-274.5.x2.0.x4.10.x4.4.x
1.23.x2023-12-183.26.x1.5.x4.10.x4.4.x
1.22.x2023-10-273.25.x1.5.x4.10.x4.3.x
1.21.x2023-08-173.22.x1.4.x4.9.x4.2.x
1.20.x2023-07-063.22.x1.1.x4.7.x4.2.x
1.19.x2023-05-043.17.x1.1.x14.7.x4.0.x
1.18.x2023-03-073.13.x2.14.x4.6.x3.6.x
1.17.x2022-12-203.9.x2.14.x4.5.x3.5.x
1.16.x2022-10-313.8.x2.13.x4.4.x3.4.x
1.15.x2022-09-073.6.x2.12.x4.3.x3.3.x
1.14.x2022-07-073.6.x2.11.x4.2.x3.2.x
1.13.x2022-05-033.4.x2.9.x4.0.x2.4.x
1.12.x2022-04-053.4.x2.8.x3.0.x2.3.x
1.11.x2022-03-143.2.x2.7.x2.6.x2.3.x
1.10.x2022-01-273.1.x2.5.x2.4.x2.1.x
1.9.x2021-12-103.1.x2.4.x2.4.x2.1.x
1.8.x2021-11-303.1.x2.4.x2.3.x1.1.x
1.7.x2021-09-013.1.x2.4.x2.3.x1.1.x
1.6.x2021-08-112.4.x2.3.x2.2.x1.0.x
1.5.x2021-07-132.2.x2.1.x2.1.x1.0.x
1.4.x2021-06-092.2.x2.1.x2.1.x1.0.x
1.3.x2021-04-232.2.x2.1.x2.1.x1.0.x
1.2.x2021-03-152.2.x2.0.x1.1.x-
1.1.x2021-02-102.1.x---
1.0.x2021-01-142.0.x---

TypeScript client change

The TypeScript client replaced the JavaScript client on 2023-03-17.

Questions and feedback

If you have any questions or feedback, let us know in the user forum.