mirror of
https://github.com/qdrant/landing_page.git
synced 2026-09-28 23:48:31 +02:00
add blog
This commit is contained in:
@@ -0,0 +1,591 @@
|
|||||||
|
---
|
||||||
|
title: "Qdrant 1.13"
|
||||||
|
draft: false
|
||||||
|
short_description: ""
|
||||||
|
description: ""
|
||||||
|
preview_image: /blog/qdrant-1.13.x/social_preview.png
|
||||||
|
social_preview_image: /blog/qdrant-1.13.x/social_preview.png
|
||||||
|
date: 2025-01-15T00:00:00-08:00
|
||||||
|
author: David Myriel
|
||||||
|
featured: true
|
||||||
|
tags:
|
||||||
|
---
|
||||||
|
|
||||||
|
[**Qdrant 1.13.0 is out!**](https://github.com/qdrant/qdrant/releases/tag/v1.13.0) Let's look at major new features and a few minor additions:
|
||||||
|
|
||||||
|
**GPU Indexing:** Add GPU support for HNSW super fast indexing.</br>
|
||||||
|
**Streaming Snapshots:** Create snapshots on the fly without putting them on disk first.</br>
|
||||||
|
**Strict Mode:** Restrict certain type of operations on collections</br>
|
||||||
|
|
||||||
|
**HNSW Graph Optimization:** Compress HNSW graph links.</br>
|
||||||
|
**Named Vector Filtering:** Add Has Vector filtering condition, check if a named vector is present on a point.</br>
|
||||||
|
**Memory Map for Payload Storage:** Use mmap storage for payloads by default to make it more efficient, eliminating unexpected latency spikes. </br>
|
||||||
|
|
||||||
|
|
||||||
|
## GPU Indexing
|
||||||
|
Qdrant introduces GPU-accelerated HNSW indexing to dramatically reduce index construction times.
|
||||||
|
This feature is optimized for large datasets where indexing speed is critical.
|
||||||
|
The new feature delivers speeds up to 10x faster than CPU-based methods.
|
||||||
|
It is built with Vulkan API for broad GPU compatibility, including Nvidia, AMD, and integrated GPUs.
|
||||||
|
As of right now this solution supports only on-premises deployments, but we will introduce cloud shortly.
|
||||||
|
|
||||||
|
Technical Highlights
|
||||||
|
• Multi-GPU Support: Index segments concurrently to handle large-scale workloads.
|
||||||
|
• Hybrid Compatibility: Seamlessly integrate GPU-enabled and CPU-only nodes in the same cluster.
|
||||||
|
• Hardware Flexibility: Supports mid-range GPUs like Nvidia T4 for optimal cost-performance balance.
|
||||||
|
• Full Feature Support: Maintains compatibility with filtering, quantization, and payloads.
|
||||||
|
|
||||||
|
### Using Qdrant on GPU Instances
|
||||||
|
Setup is simple with pre-configured Docker images for GPU environments.
|
||||||
|
Users can enable GPU indexing with minimal configuration changes.
|
||||||
|
Logs clearly indicate GPU detection and usage for transparency.
|
||||||
|
|
||||||
|
Read more in documentation
|
||||||
|
|
||||||
|
## Streaming Snapshots
|
||||||
|
|
||||||
|
|
||||||
|
## Strict Mode
|
||||||
|
|
||||||
|
Qdrant’s Strict Mode introduces operational controls to safeguard resource usage and maintain consistent performance in shared, serverless environments.
|
||||||
|
By capping the computational cost of operations like unindexed filtering, batch sizes, and search parameters (e.g., hnsw_ef and oversampling), it prevents inefficient usage patterns that could overload collections.
|
||||||
|
Additional limits on payload sizes, filter conditions, and timeouts ensure that even high-demand applications remain predictable and responsive.
|
||||||
|
|
||||||
|
Strict Mode is configured at the collection level via `strict_mode_config`, this feature allows users to define thresholds while preserving backward compatibility.
|
||||||
|
Newly created collections default to strict mode, enforcing compliance by design and balancing workloads across tenants.
|
||||||
|
|
||||||
|
Strict Mode also enhances usability by providing detailed error messages when requests exceed defined limits, offering clear guidance on resolution steps.
|
||||||
|
The robust verification system guarantees that all operations adhere to the configured constraints, making Qdrant an excellent choice for multi-tenant and serverless deployments.
|
||||||
|
Strict Mode mitigates the noisy neighbor problem and ensures efficient resource allocation.
|
||||||
|
|
||||||
|
### Using Strict Mode
|
||||||
|
See [schema definitions](https://api.qdrant.tech/api-reference/collections/create-collection#request.body.strict_mode_config) for all the `strict_mode_config` parameters.
|
||||||
|
|
||||||
|
Upon crossing a limit, the server will return a client side error with the information about the limit that was crossed.
|
||||||
|
|
||||||
|
As part of the config, the `enabled` field act as a toggle to enable or disable the strict mode dynamically.
|
||||||
|
|
||||||
|
The `strict_mode_config` can be enabled when creating a collection, for instance below to active the `unindexed_filtering_retrieve` limit.
|
||||||
|
|
||||||
|
```http
|
||||||
|
PUT /collections/{collection_name}
|
||||||
|
{
|
||||||
|
"strict_mode_config": {
|
||||||
|
"enabled": true,
|
||||||
|
"unindexed_filtering_retrieve": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X PUT http://localhost:6333/collections/{collection_name} \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data-raw '{
|
||||||
|
"strict_mode_config": {
|
||||||
|
"enabled":" true,
|
||||||
|
"unindexed_filtering_retrieve": true
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from qdrant_client import QdrantClient, models
|
||||||
|
|
||||||
|
client = QdrantClient(url="http://localhost:6333")
|
||||||
|
|
||||||
|
client.create_collection(
|
||||||
|
collection_name="{collection_name}",
|
||||||
|
strict_mode_config=models.SparseVectorParams{ enabled=True, unindexed_filtering_retrieve=True },
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { QdrantClient } from "@qdrant/js-client-rest";
|
||||||
|
|
||||||
|
const client = new QdrantClient({ host: "localhost", port: 6333 });
|
||||||
|
|
||||||
|
client.createCollection("{collection_name}", {
|
||||||
|
strict_mode_config: {
|
||||||
|
enabled: true,
|
||||||
|
unindexed_filtering_retrieve: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use qdrant_client::Qdrant;
|
||||||
|
use qdrant_client::qdrant::{CreateCollectionBuilder, StrictModeConfigBuilder};
|
||||||
|
|
||||||
|
let client = Qdrant::from_url("http://localhost:6334").build()?;
|
||||||
|
|
||||||
|
client
|
||||||
|
.create_collection(
|
||||||
|
CreateCollectionBuilder::new("{collection_name}")
|
||||||
|
.strict_config_mode(StrictModeConfigBuilder::default().enabled(true).unindexed_filtering_retrieve(true)),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
```
|
||||||
|
```java
|
||||||
|
import io.qdrant.client.QdrantClient;
|
||||||
|
import io.qdrant.client.QdrantGrpcClient;
|
||||||
|
import io.qdrant.client.grpc.Collections.CreateCollection;
|
||||||
|
import io.qdrant.client.grpc.Collections.StrictModeCOnfig;
|
||||||
|
|
||||||
|
QdrantClient client =
|
||||||
|
new QdrantClient(QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
|
||||||
|
|
||||||
|
client
|
||||||
|
.createCollectionAsync(
|
||||||
|
CreateCollection.newBuilder()
|
||||||
|
.setCollectionName("{collection_name}")
|
||||||
|
.setStrictModeConfig(
|
||||||
|
StrictModeConfig.newBuilder().setEnabled(true).setUnindexedFilteringRetrieve(true).build())
|
||||||
|
.build())
|
||||||
|
.get();
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Qdrant.Client;
|
||||||
|
using Qdrant.Client.Grpc;
|
||||||
|
|
||||||
|
var client = new QdrantClient("localhost", 6334);
|
||||||
|
|
||||||
|
await client.CreateCollectionAsync(
|
||||||
|
collectionName: "{collection_name}",
|
||||||
|
strictModeConfig: new StrictModeConfig { enabled = true, unindexed_filtering_retrieve = true }
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/qdrant/go-client/qdrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
client, err := qdrant.NewClient(&qdrant.Config{
|
||||||
|
Host: "localhost",
|
||||||
|
Port: 6334,
|
||||||
|
})
|
||||||
|
|
||||||
|
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
|
||||||
|
CollectionName: "{collection_name}",
|
||||||
|
StrictModeConfig: &qdrant.StrictModeConfig{
|
||||||
|
Enabled: qdrant.PtrOf(true),
|
||||||
|
IndexingThreshold: qdrant.PtrOf(true),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
or enabled later on an existing collection.
|
||||||
|
|
||||||
|
```http
|
||||||
|
PATCH /collections/{collection_name}
|
||||||
|
{
|
||||||
|
"strict_mode_config": {
|
||||||
|
"enabled": true,
|
||||||
|
"unindexed_filtering_retrieve": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X PATCH http://localhost:6333/collections/{collection_name} \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data-raw '{
|
||||||
|
"strict_mode_config": {
|
||||||
|
"enabled": true,
|
||||||
|
"unindexed_filtering_retrieve": true
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from qdrant_client import QdrantClient, models
|
||||||
|
|
||||||
|
client = QdrantClient(url="http://localhost:6333")
|
||||||
|
|
||||||
|
client.update_collection(
|
||||||
|
collection_name="{collection_name}",
|
||||||
|
strict_mode_config=models.StrictModeConfig(enabled=True, unindexed_filtering_retrieve=True),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
```typescript
|
||||||
|
import { QdrantClient } from "@qdrant/js-client-rest";
|
||||||
|
|
||||||
|
const client = new QdrantClient({ host: "localhost", port: 6333 });
|
||||||
|
|
||||||
|
client.updateCollection("{collection_name}", {
|
||||||
|
strict_mode_config: {
|
||||||
|
enabled: true,
|
||||||
|
unindexed_filtering_retrieve: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use qdrant_client::qdrant::{StrictModeConfigBuilder, UpdateCollectionBuilder};
|
||||||
|
|
||||||
|
client
|
||||||
|
.update_collection(
|
||||||
|
UpdateCollectionBuilder::new("{collection_name}").strict_mode_config(
|
||||||
|
StrictModeConfigBuilder::default().enabled(true).unindexed_filtering_retrieve(true),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
import io.qdrant.client.grpc.Collections.StrictModeConfigBuilder;
|
||||||
|
import io.qdrant.client.grpc.Collections.UpdateCollection;
|
||||||
|
|
||||||
|
client.updateCollectionAsync(
|
||||||
|
UpdateCollection.newBuilder()
|
||||||
|
.setCollectionName("{collection_name}")
|
||||||
|
.setStrictModeConfig(
|
||||||
|
StrictModeConfig.newBuilder().setEnabled(true).setUnindexedFilteringRetrieve(true).build())
|
||||||
|
.build());
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Qdrant.Client;
|
||||||
|
using Qdrant.Client.Grpc;
|
||||||
|
|
||||||
|
var client = new QdrantClient("localhost", 6334);
|
||||||
|
|
||||||
|
await client.UpdateCollectionAsync(
|
||||||
|
collectionName: "{collection_name}",
|
||||||
|
strictModeConfig: new StrictModeConfig { Enabled = true, UnindexedFilteringRetrieve = true }
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/qdrant/go-client/qdrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
client, err := qdrant.NewClient(&qdrant.Config{
|
||||||
|
Host: "localhost",
|
||||||
|
Port: 6334,
|
||||||
|
})
|
||||||
|
|
||||||
|
client.UpdateCollection(context.Background(), &qdrant.UpdateCollection{
|
||||||
|
CollectionName: "{collection_name}",
|
||||||
|
StrictModeConfig: &qdrant.StrictModeConfig{
|
||||||
|
Enabled: qdrant.PtrOf(true),
|
||||||
|
UnindexedFilteringRetrieve: qdrant.PtrOf(true),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
It can be disabled on an existing collection.
|
||||||
|
|
||||||
|
```http
|
||||||
|
PATCH /collections/{collection_name}
|
||||||
|
{
|
||||||
|
"strict_mode_config": {
|
||||||
|
"enabled": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -X PATCH http://localhost:6333/collections/{collection_name} \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
--data-raw '{
|
||||||
|
"strict_mode_config": {
|
||||||
|
"enabled": false,
|
||||||
|
}
|
||||||
|
}'
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from qdrant_client import QdrantClient, models
|
||||||
|
|
||||||
|
client = QdrantClient(url="http://localhost:6333")
|
||||||
|
|
||||||
|
client.update_collection(
|
||||||
|
collection_name="{collection_name}",
|
||||||
|
strict_mode_config=models.StrictModeConfig(enabled=False),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { QdrantClient } from "@qdrant/js-client-rest";
|
||||||
|
|
||||||
|
const client = new QdrantClient({ host: "localhost", port: 6333 });
|
||||||
|
|
||||||
|
client.updateCollection("{collection_name}", {
|
||||||
|
strict_mode_config: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use qdrant_client::qdrant::{StrictModeConfigBuilder, UpdateCollectionBuilder};
|
||||||
|
|
||||||
|
client
|
||||||
|
.update_collection(
|
||||||
|
UpdateCollectionBuilder::new("{collection_name}").strict_mode_config(
|
||||||
|
StrictModeConfigBuilder::default().enabled(false),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
import io.qdrant.client.grpc.Collections.StrictModeConfigBuilder;
|
||||||
|
import io.qdrant.client.grpc.Collections.UpdateCollection;
|
||||||
|
|
||||||
|
client.updateCollectionAsync(
|
||||||
|
UpdateCollection.newBuilder()
|
||||||
|
.setCollectionName("{collection_name}")
|
||||||
|
.setStrictModeConfig(
|
||||||
|
StrictModeConfig.newBuilder().setEnabled(false).build())
|
||||||
|
.build());
|
||||||
|
```
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Qdrant.Client;
|
||||||
|
using Qdrant.Client.Grpc;
|
||||||
|
|
||||||
|
var client = new QdrantClient("localhost", 6334);
|
||||||
|
|
||||||
|
await client.UpdateCollectionAsync(
|
||||||
|
collectionName: "{collection_name}",
|
||||||
|
strictModeConfig: new StrictModeConfig { Enabled = false }
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/qdrant/go-client/qdrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
client, err := qdrant.NewClient(&qdrant.Config{
|
||||||
|
Host: "localhost",
|
||||||
|
Port: 6334,
|
||||||
|
})
|
||||||
|
|
||||||
|
client.UpdateCollection(context.Background(), &qdrant.UpdateCollection{
|
||||||
|
CollectionName: "{collection_name}",
|
||||||
|
StrictModeConfig: &qdrant.StrictModeConfig{
|
||||||
|
Enabled: qdrant.PtrOf(false),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## HNSW Graph Optimization
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Named Vector Filtering
|
||||||
|
|
||||||
|
This condition enables filtering by the presence of a given named vector on a point.
|
||||||
|
|
||||||
|
For example, if we have two named vector in our collection.
|
||||||
|
|
||||||
|
```http
|
||||||
|
PUT /collections/{collection_name}
|
||||||
|
{
|
||||||
|
"vectors": {
|
||||||
|
"image": {
|
||||||
|
"size": 4,
|
||||||
|
"distance": "Dot"
|
||||||
|
},
|
||||||
|
"text": {
|
||||||
|
"size": 8,
|
||||||
|
"distance": "Cosine"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sparse_vectors": {
|
||||||
|
"sparse-image": {},
|
||||||
|
"sparse-text": {},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Some points in the collection might have all vectors, some might have only a subset of them.
|
||||||
|
|
||||||
|
<aside role="status">If your collection does not have named vectors, use an empty (<code>""</code>) name.</aside>
|
||||||
|
|
||||||
|
This is how you can search for points which have the dense `image` vector defined:
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /collections/{collection_name}/points/scroll
|
||||||
|
{
|
||||||
|
"filter": {
|
||||||
|
"must": [
|
||||||
|
{ "has_vector": "image" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```python
|
||||||
|
from qdrant_client import QdrantClient, models
|
||||||
|
|
||||||
|
client = QdrantClient(url="http://localhost:6333")
|
||||||
|
|
||||||
|
client.scroll(
|
||||||
|
collection_name="{collection_name}",
|
||||||
|
scroll_filter=models.Filter(
|
||||||
|
must=[
|
||||||
|
models.HasVectorCondition(has_vector="image"),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
client.scroll("{collection_name}", {
|
||||||
|
filter: {
|
||||||
|
must: [
|
||||||
|
{
|
||||||
|
has_vector: "image",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
```rust
|
||||||
|
use qdrant_client::qdrant::{Condition, Filter, ScrollPointsBuilder};
|
||||||
|
use qdrant_client::Qdrant;
|
||||||
|
|
||||||
|
let client = Qdrant::from_url("http://localhost:6334").build()?;
|
||||||
|
|
||||||
|
client
|
||||||
|
.scroll(
|
||||||
|
ScrollPointsBuilder::new("{collection_name}")
|
||||||
|
.filter(Filter::must([Condition::has_vector("image")])),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
```
|
||||||
|
```java
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static io.qdrant.client.ConditionFactory.hasVector;
|
||||||
|
import static io.qdrant.client.PointIdFactory.id;
|
||||||
|
|
||||||
|
import io.qdrant.client.grpc.Points.Filter;
|
||||||
|
import io.qdrant.client.grpc.Points.ScrollPoints;
|
||||||
|
|
||||||
|
client
|
||||||
|
.scrollAsync(
|
||||||
|
ScrollPoints.newBuilder()
|
||||||
|
.setCollectionName("{collection_name}")
|
||||||
|
.setFilter(
|
||||||
|
Filter.newBuilder()
|
||||||
|
.addMust(hasVector("image"))
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.get();
|
||||||
|
```
|
||||||
|
```csharp
|
||||||
|
using Qdrant.Client;
|
||||||
|
using static Qdrant.Client.Grpc.Conditions;
|
||||||
|
|
||||||
|
var client = new QdrantClient("localhost", 6334);
|
||||||
|
|
||||||
|
await client.ScrollAsync(collectionName: "{collection_name}", filter: HasVector("image"));
|
||||||
|
```
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/qdrant/go-client/qdrant"
|
||||||
|
)
|
||||||
|
|
||||||
|
client, err := qdrant.NewClient(&qdrant.Config{
|
||||||
|
Host: "localhost",
|
||||||
|
Port: 6334,
|
||||||
|
})
|
||||||
|
|
||||||
|
client.Scroll(context.Background(), &qdrant.ScrollPoints{
|
||||||
|
CollectionName: "{collection_name}",
|
||||||
|
Filter: &qdrant.Filter{
|
||||||
|
Must: []*qdrant.Condition{
|
||||||
|
qdrant.NewHasVector(
|
||||||
|
"image",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Memory Map for Payload Storage
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
Reference in New Issue
Block a user