mirror of
https://github.com/qdrant/landing_page.git
synced 2026-09-28 23:48:31 +02:00
Merge remote-tracking branch 'origin/tutorial/async-api' into tutorial/async-api
This commit is contained in:
@@ -5,23 +5,21 @@ weight: 18
|
||||
|
||||
# Using Qdrant asynchronously
|
||||
|
||||
Asynchronous programming is being broadly adopted in the Python ecosystem. Tools such as FastAPI [have embraced that new
|
||||
paradigm](https://fastapi.tiangolo.com/async/), but it's also becoming a standard for ML models served as SaaS. For example, the Cohere SDK
|
||||
Asynchronous programming is being broadly adopted in the Python ecosystem. Tools such as FastAPI [have embraced this new
|
||||
paradigm](https://fastapi.tiangolo.com/async/), but it is also becoming a standard for ML models served as SaaS. For example, the Cohere SDK
|
||||
[provides an async client](https://cohere-sdk.readthedocs.io/en/latest/cohere.html#asyncclient) next to its synchronous counterpart.
|
||||
|
||||
Databases are often launched as separate services and are accessed via a network. All the interactions with them are IO-bound and can
|
||||
be performed asynchronously so as not to waste time actively waiting for a server response. If you use Python, that is achieved by
|
||||
be performed asynchronously so as not to waste time actively waiting for a server response. In Python, this is achieved by
|
||||
using [`async/await`](https://docs.python.org/3/library/asyncio-task.html) syntax. That lets the interpreter switch to another task
|
||||
while waiting for a response from the server.
|
||||
|
||||
Qdrant exposes two interfaces: HTTP and gRPC. The official SDKs for different languages are based on the autogenerated clients, and
|
||||
in Python [qdrant-client](https://github.com/qdrant/qdrant-client), you can call all the methods asynchronously. This tutorial presents
|
||||
how to do it.
|
||||
in Python [qdrant-client](https://github.com/qdrant/qdrant-client), you can call all the methods asynchronously. This tutorial will teach you how to do just that.
|
||||
|
||||
## When the usage of async API is justified?
|
||||
## When to use async API
|
||||
|
||||
If the application you are writing will never support multiple users at once, for example, it is a script run once daily, then there
|
||||
is no need to use async API. But if you are writing a web service that multiple users will use simultaneously, you shouldn't be
|
||||
There is no need to use async API if the application you are writing will never support multiple users at once (e.g it is a script that runs once per day). However, if you are writing a web service that multiple users will use simultaneously, you shouldn't be
|
||||
blocking the threads of the web server as it limits the number of concurrent requests it can handle. In this case, you should use
|
||||
the async API.
|
||||
|
||||
@@ -31,9 +29,9 @@ cannot be used in synchronous functions. On the other hand, calling an IO-bound
|
||||
an antipattern. Therefore, if you build an async web service, exposed through an [ASGI](https://asgi.readthedocs.io/en/latest/) server,
|
||||
you should use the async API for all the interactions with Qdrant.
|
||||
|
||||
## How to use async API?
|
||||
## How to use async API
|
||||
|
||||
Calling any method of Qdrant requires establishing a connection to the server. We need to create an instance of `QdrantClient`
|
||||
Calling any method of Qdrant requires establishing a connection to the server. You need to create an instance of `QdrantClient`
|
||||
that will act as a gateway. If you want to do it locally, please make sure Qdrant server is running. If it's not, then you can launch it
|
||||
in a Docker container:
|
||||
|
||||
@@ -55,16 +53,16 @@ client = QdrantClient("localhost")
|
||||
# client = QdrantClient("https://your-cluster-url.cloud.com", api_key="your-api-key")
|
||||
```
|
||||
|
||||
The default client only exposes the synchronous methods for interacting with the server. To access the async client and it's underlying methods, we need to use autogenerated async clients.
|
||||
It is possible to use asynchronous HTTP API by using `qdrant_client.http.api_client.AsyncApis`. The asynchronous gRPC API if more efficient than the HTTP API, which is why we recommend you use it and we will be using it here.
|
||||
The default client only exposes the synchronous methods for interacting with the server. To access the async client and it's underlying methods, you need to use autogenerated async clients.
|
||||
It is possible to use asynchronous HTTP API by using `qdrant_client.http.api_client.AsyncApis`. We recommend you use the asynchronous gRPC API, as it is more efficient than the HTTP API.
|
||||
|
||||
### gRPC API
|
||||
## Using the gRPC API
|
||||
|
||||
Every instance of `QdrantClient` has two properties we are going to use: `async_grpc_collections` and `async_grpc_points`. They expose
|
||||
Every instance of `QdrantClient` has two properties: `async_grpc_collections` and `async_grpc_points`. They expose
|
||||
the autogenerated clients for [collections](/documentation/concepts/collections/) and [points](/documentation/concepts/points/) respectively.
|
||||
|
||||
The gRPC client uses type definitions for all the interactions with the server. They are autogenerated from the source code of Qdrant
|
||||
server, and we have to import them if we want to call any of the available methods.
|
||||
The gRPC client uses type definitions for all interactions with the server. They are autogenerated from the source code of Qdrant
|
||||
server, and you have to import them if you want to call any of the available methods.
|
||||
|
||||
```python
|
||||
from qdrant_client import grpc
|
||||
@@ -73,7 +71,7 @@ from qdrant_client import grpc
|
||||
If your IDE does not support autocompletion for the autogenerated clients, you can refer to the documentation and [see the available
|
||||
fields for each of them](https://github.com/qdrant/qdrant/blob/master/docs/grpc/docs.md).
|
||||
|
||||
#### Creating a collection
|
||||
## Step 1: Create a collection
|
||||
|
||||
Let's create a collection and add some points to it.
|
||||
|
||||
@@ -101,9 +99,9 @@ response = await client.async_grpc_collections.Create(
|
||||
Our collection was set up for 100-dimensional vectors, cosine distance and 8-bit quantization. The timeout is set to 10 seconds, so
|
||||
if the server does not respond within 10 seconds, the request will be aborted.
|
||||
|
||||
#### Checking collection info
|
||||
### Verify collection info
|
||||
|
||||
We can check the collection info to see if it was created successfully, and configured as we expected:
|
||||
You can check the collection info to see if it was created and properly configured:
|
||||
|
||||
```python
|
||||
response = await client.async_grpc_collections.Get(
|
||||
@@ -113,7 +111,7 @@ response = await client.async_grpc_collections.Get(
|
||||
)
|
||||
```
|
||||
|
||||
The `response` object is going to be an instance of `grpc.GetCollectionInfoResponse` and we can access the fields we need or simply
|
||||
The `response` object is going to be an instance of `grpc.GetCollectionInfoResponse` and you can access the fields you need or simply
|
||||
display its content.
|
||||
|
||||
```python
|
||||
@@ -175,7 +173,7 @@ As you can see, the collection was created properly and is ready to be used. To
|
||||
[API specification](https://qdrant.github.io/qdrant/redoc/index.html#tag/collections/operation/get_collection) that describes the
|
||||
meaning of each parameter.
|
||||
|
||||
##### Handling exceptions
|
||||
### Handling exceptions
|
||||
|
||||
If the collection does not exist, the server will return an error. We can handle it by catching the exception. We may expect
|
||||
some specific exceptions, or simply catch all the errors that subclass `RpcError` from `grpc` package:
|
||||
@@ -206,7 +204,7 @@ Our exception contain the details about the error, including the status code and
|
||||
We can use those details to properly handle some specific cases. For example, if we want to create a collection only if it does not
|
||||
exist, we can check the status code and create it if it is `StatusCode.NOT_FOUND`:
|
||||
|
||||
#### Updating collection configuration
|
||||
## Step 2: Update collection configuration
|
||||
|
||||
It's quite likely that we will want to update the collection configuration. For example, we may want to change the HNSW parameters to improve
|
||||
the search precision. Let's change the `ef_construct` parameter to 200:
|
||||
@@ -222,13 +220,12 @@ await client.async_grpc_collections.Update(
|
||||
)
|
||||
```
|
||||
|
||||
#### Deleting a collection
|
||||
### Delete a collection
|
||||
|
||||
There is plenty of other methods available for collections, like creating aliases or checking the status of the cluster. We are not going
|
||||
to call all of them in this tutorial, but you can always [check the list of available methods and their parameters in the
|
||||
There are plenty of methods available for collections, such as creating aliases or checking the status of the cluster. This tutorial won't use all of them, but you can always [check the list of available methods and their parameters in the
|
||||
documentation](https://github.com/qdrant/qdrant/blob/master/docs/grpc/docs.md#collections_serviceproto).
|
||||
|
||||
Right now, we are just going to delete the collection we created:
|
||||
Right now, you can just delete the collection you created:
|
||||
|
||||
```python
|
||||
await client.async_grpc_collections.Delete(
|
||||
@@ -237,12 +234,11 @@ await client.async_grpc_collections.Delete(
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
That's it when it comes to collection management. Let's move on to points (individual vectors) allowing us to load data into our collection
|
||||
|
||||
#### Adding points to the collection
|
||||
## Step 3: Add points to the collection
|
||||
|
||||
Assuming your collection created successfuly, we can now add some
|
||||
Assuming your collection was created successfuly, you can now add some
|
||||
points to it. Let's add our first two points into the collection:
|
||||
|
||||
```python
|
||||
@@ -279,15 +275,13 @@ response = await client.async_grpc_points.Upsert(
|
||||
)
|
||||
```
|
||||
|
||||
Those points are automatically indexed and available for search. In the future, we can add more points, or update the existing ones. All the point related
|
||||
operations are [documented in the Qdrant server repository](https://github.com/qdrant/qdrant/blob/master/docs/grpc/docs.md#points_serviceproto).
|
||||
Those points are automatically indexed and available for search. In the future, you can add more points, or update the existing ones. All point related operations are [documented in the Qdrant server repository](https://github.com/qdrant/qdrant/blob/master/docs/grpc/docs.md#points_serviceproto).
|
||||
|
||||
The main operation we need from the vector database is semantic search. Let's see how to perform it.
|
||||
The main operation you need from the vector database is semantic search. Let's see how to perform it.
|
||||
|
||||
#### Asynchronous semantic search
|
||||
## Step 4: Run a query
|
||||
|
||||
Search operation requires a query vector and a collection name. We can also specify the number of results we want to retrieve and some other
|
||||
parameters, but let's take one step at a time. The minimal example may look like this:
|
||||
The search operation requires a query vector and a collection name. You can also specify the number of results you want to retrieve and some other parameters. A minimal example might look like this:
|
||||
|
||||
```python
|
||||
response = await client.async_grpc_points.Search(
|
||||
@@ -314,7 +308,7 @@ result {
|
||||
time: 0.000456134
|
||||
```
|
||||
|
||||
##### Returning vectors and payloads
|
||||
### Return vectors and payloads
|
||||
|
||||
If you need the vectors and payloads of the points, you can specify it in the request:
|
||||
|
||||
@@ -332,10 +326,9 @@ response = await client.async_grpc_points.Search(
|
||||
|
||||
That's all the code you need to bring back the vector and payload.
|
||||
|
||||
##### Applying filters
|
||||
## Step 5: Add a filter
|
||||
|
||||
If you ever used SQL, you are probably familiar with the `WHERE` clause. It allows you to filter the results of the query. Qdrant has similar
|
||||
functionality. Let's say we want to find all the points similar to given vector, but with `int_param` equal to 32. We can do it like this:
|
||||
If you ever used SQL, you are probably familiar with the `WHERE` clause. It lets you filter the results of the query. Qdrant has a similar functionality. Imagine you want to find all the points similar to given vector, but with `int_param` equal to 32. You can do it like this:
|
||||
|
||||
```python
|
||||
response = await client.async_grpc_points.Search(
|
||||
@@ -358,15 +351,12 @@ response = await client.async_grpc_points.Search(
|
||||
)
|
||||
```
|
||||
|
||||
We can build even more sophisticated filters with the `must`, `should` and `must_not` clauses. You can find more details in the [filtering
|
||||
documentation](https://qdrant.tech/documentation/concepts/filtering/#filtering).
|
||||
You can build even more sophisticated filters with the `must`, `should` and `must_not` clauses. You can find more details in the [filtering documentation](https://qdrant.tech/documentation/concepts/filtering/#filtering).
|
||||
|
||||
Analogous to search, we can also [scroll our collection](https://qdrant.tech/documentation/concepts/points/#scroll-points) to retrieve all the
|
||||
points or use the [recommendation API](https://qdrant.tech/documentation/concepts/search/#recommendation-api) to find points similar to positive
|
||||
and dissimilar to negative examples.
|
||||
Analogous to search, you can also [scroll our collection](https://qdrant.tech/documentation/concepts/points/#scroll-points) to retrieve all the points or use the [recommendation API](https://qdrant.tech/documentation/concepts/search/#recommendation-api) to find points similar to positive and dissimilar to negative examples.
|
||||
|
||||
## Support of Qdrant async API in Python libraries
|
||||
## Supported Python libraries
|
||||
|
||||
There is plenty of Python libraries that Qdrant integrates with. Until recently, only [Langchain]() provided async Python API support.
|
||||
Qdrant is the only vector database with full coverage of async API in Langchain. The documentation [describes how to use
|
||||
Qdrant integrates with numerous Python libraries. Until recently, only [Langchain]() provided async Python API support.
|
||||
Qdrant is the only vector database with full coverage of async API in Langchain. Their documentation [describes how to use
|
||||
it](https://python.langchain.com/docs/modules/data_connection/vectorstores/#asynchronous-operations).
|
||||
|
||||
Reference in New Issue
Block a user