@mastra/qdrant 1.0.0-beta.3 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/docs/README.md +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/SOURCE_MAP.json +1 -1
- package/dist/docs/rag/01-vector-databases.md +10 -5
- package/dist/docs/rag/02-retrieval.md +5 -6
- package/dist/docs/vectors/01-reference.md +23 -0
- package/dist/index.cjs +155 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +155 -0
- package/dist/index.js.map +1 -1
- package/dist/vector/index.d.ts +83 -0
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @mastra/qdrant
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.4
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Added support for creating payload (metadata) indexes in Qdrant ([#11839](https://github.com/mastra-ai/mastra/pull/11839))
|
|
8
|
+
|
|
9
|
+
Qdrant Cloud and deployments with `strict_mode_config = true` require explicit payload indexes for metadata filtering. This release adds two new methods to `QdrantVector`:
|
|
10
|
+
|
|
11
|
+
**New exports:**
|
|
12
|
+
- `PayloadSchemaType` - Union type for Qdrant payload schema types ('keyword', 'integer', 'float', 'geo', 'text', 'bool', 'datetime', 'uuid')
|
|
13
|
+
- `CreatePayloadIndexParams` - Parameters interface for creating payload indexes
|
|
14
|
+
- `DeletePayloadIndexParams` - Parameters interface for deleting payload indexes
|
|
15
|
+
|
|
16
|
+
**New methods:**
|
|
17
|
+
- `createPayloadIndex()` - Creates a payload index on a collection field for efficient filtering
|
|
18
|
+
- `deletePayloadIndex()` - Removes a payload index from a collection field
|
|
19
|
+
|
|
20
|
+
**Example usage:**
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { QdrantVector } from '@mastra/qdrant';
|
|
24
|
+
|
|
25
|
+
const qdrant = new QdrantVector({ url: `http://localhost:6333`, id: 'my-store' });
|
|
26
|
+
|
|
27
|
+
// Create a keyword index for filtering by source
|
|
28
|
+
await qdrant.createPayloadIndex({
|
|
29
|
+
indexName: 'my-collection',
|
|
30
|
+
fieldName: 'source',
|
|
31
|
+
fieldSchema: 'keyword',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// Now filtering works in strict mode environments
|
|
35
|
+
const results = await qdrant.query({
|
|
36
|
+
indexName: 'my-collection',
|
|
37
|
+
queryVector: embeddings,
|
|
38
|
+
filter: { source: 'document-a' },
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Closes #8923
|
|
43
|
+
|
|
44
|
+
### Patch Changes
|
|
45
|
+
|
|
46
|
+
- Updated dependencies [[`ebae12a`](https://github.com/mastra-ai/mastra/commit/ebae12a2dd0212e75478981053b148a2c246962d), [`c61a0a5`](https://github.com/mastra-ai/mastra/commit/c61a0a5de4904c88fd8b3718bc26d1be1c2ec6e7), [`69136e7`](https://github.com/mastra-ai/mastra/commit/69136e748e32f57297728a4e0f9a75988462f1a7), [`449aed2`](https://github.com/mastra-ai/mastra/commit/449aed2ba9d507b75bf93d427646ea94f734dfd1), [`eb648a2`](https://github.com/mastra-ai/mastra/commit/eb648a2cc1728f7678768dd70cd77619b448dab9), [`0131105`](https://github.com/mastra-ai/mastra/commit/0131105532e83bdcbb73352fc7d0879eebf140dc), [`9d5059e`](https://github.com/mastra-ai/mastra/commit/9d5059eae810829935fb08e81a9bb7ecd5b144a7), [`ef756c6`](https://github.com/mastra-ai/mastra/commit/ef756c65f82d16531c43f49a27290a416611e526), [`b00ccd3`](https://github.com/mastra-ai/mastra/commit/b00ccd325ebd5d9e37e34dd0a105caae67eb568f), [`3bdfa75`](https://github.com/mastra-ai/mastra/commit/3bdfa7507a91db66f176ba8221aa28dd546e464a), [`e770de9`](https://github.com/mastra-ai/mastra/commit/e770de941a287a49b1964d44db5a5763d19890a6), [`52e2716`](https://github.com/mastra-ai/mastra/commit/52e2716b42df6eff443de72360ae83e86ec23993), [`27b4040`](https://github.com/mastra-ai/mastra/commit/27b4040bfa1a95d92546f420a02a626b1419a1d6), [`610a70b`](https://github.com/mastra-ai/mastra/commit/610a70bdad282079f0c630e0d7bb284578f20151), [`8dc7f55`](https://github.com/mastra-ai/mastra/commit/8dc7f55900395771da851dc7d78d53ae84fe34ec), [`8379099`](https://github.com/mastra-ai/mastra/commit/8379099fc467af6bef54dd7f80c9bd75bf8bbddf), [`8c0ec25`](https://github.com/mastra-ai/mastra/commit/8c0ec25646c8a7df253ed1e5ff4863a0d3f1316c), [`ff4d9a6`](https://github.com/mastra-ai/mastra/commit/ff4d9a6704fc87b31a380a76ed22736fdedbba5a), [`69821ef`](https://github.com/mastra-ai/mastra/commit/69821ef806482e2c44e2197ac0b050c3fe3a5285), [`1ed5716`](https://github.com/mastra-ai/mastra/commit/1ed5716830867b3774c4a1b43cc0d82935f32b96), [`4186bdd`](https://github.com/mastra-ai/mastra/commit/4186bdd00731305726fa06adba0b076a1d50b49f), [`7aaf973`](https://github.com/mastra-ai/mastra/commit/7aaf973f83fbbe9521f1f9e7a4fd99b8de464617)]:
|
|
47
|
+
- @mastra/core@1.0.0-beta.22
|
|
48
|
+
|
|
3
49
|
## 1.0.0-beta.3
|
|
4
50
|
|
|
5
51
|
### Patch Changes
|
package/dist/docs/README.md
CHANGED
package/dist/docs/SKILL.md
CHANGED
|
@@ -12,6 +12,7 @@ After generating embeddings, you need to store them in a database that supports
|
|
|
12
12
|
import { MongoDBVector } from "@mastra/mongodb";
|
|
13
13
|
|
|
14
14
|
const store = new MongoDBVector({
|
|
15
|
+
id: 'mongodb-vector',
|
|
15
16
|
uri: process.env.MONGODB_URI,
|
|
16
17
|
dbName: process.env.MONGODB_DATABASE,
|
|
17
18
|
});
|
|
@@ -144,6 +145,7 @@ await store.upsert({
|
|
|
144
145
|
import { AstraVector } from "@mastra/astra";
|
|
145
146
|
|
|
146
147
|
const store = new AstraVector({
|
|
148
|
+
id: 'astra-vector',
|
|
147
149
|
token: process.env.ASTRA_DB_TOKEN,
|
|
148
150
|
endpoint: process.env.ASTRA_DB_ENDPOINT,
|
|
149
151
|
keyspace: process.env.ASTRA_DB_KEYSPACE,
|
|
@@ -170,7 +172,7 @@ import { LibSQLVector } from "@mastra/core/vector/libsql";
|
|
|
170
172
|
|
|
171
173
|
const store = new LibSQLVector({
|
|
172
174
|
id: 'libsql-vector',
|
|
173
|
-
|
|
175
|
+
url: process.env.DATABASE_URL,
|
|
174
176
|
authToken: process.env.DATABASE_AUTH_TOKEN, // Optional: for Turso cloud databases
|
|
175
177
|
});
|
|
176
178
|
|
|
@@ -217,6 +219,7 @@ await store.upsert({
|
|
|
217
219
|
import { CloudflareVector } from "@mastra/vectorize";
|
|
218
220
|
|
|
219
221
|
const store = new CloudflareVector({
|
|
222
|
+
id: 'cloudflare-vector',
|
|
220
223
|
accountId: process.env.CF_ACCOUNT_ID,
|
|
221
224
|
apiToken: process.env.CF_API_TOKEN,
|
|
222
225
|
});
|
|
@@ -238,7 +241,7 @@ await store.upsert({
|
|
|
238
241
|
```ts title="vector-store.ts"
|
|
239
242
|
import { OpenSearchVector } from "@mastra/opensearch";
|
|
240
243
|
|
|
241
|
-
const store = new OpenSearchVector({
|
|
244
|
+
const store = new OpenSearchVector({ id: "opensearch", node: process.env.OPENSEARCH_URL });
|
|
242
245
|
|
|
243
246
|
await store.createIndex({
|
|
244
247
|
indexName: "my-collection",
|
|
@@ -259,7 +262,7 @@ await store.upsert({
|
|
|
259
262
|
```ts title="vector-store.ts"
|
|
260
263
|
import { ElasticSearchVector } from "@mastra/elasticsearch";
|
|
261
264
|
|
|
262
|
-
const store = new ElasticSearchVector({ url: process.env.ELASTICSEARCH_URL });
|
|
265
|
+
const store = new ElasticSearchVector({ id: 'elasticsearch-vector', url: process.env.ELASTICSEARCH_URL });
|
|
263
266
|
|
|
264
267
|
await store.createIndex({
|
|
265
268
|
indexName: "my-collection",
|
|
@@ -280,6 +283,7 @@ await store.upsert({
|
|
|
280
283
|
import { CouchbaseVector } from "@mastra/couchbase";
|
|
281
284
|
|
|
282
285
|
const store = new CouchbaseVector({
|
|
286
|
+
id: 'couchbase-vector',
|
|
283
287
|
connectionString: process.env.COUCHBASE_CONNECTION_STRING,
|
|
284
288
|
username: process.env.COUCHBASE_USERNAME,
|
|
285
289
|
password: process.env.COUCHBASE_PASSWORD,
|
|
@@ -331,6 +335,7 @@ For detailed setup instructions and best practices, see the [official LanceDB do
|
|
|
331
335
|
import { S3Vectors } from "@mastra/s3vectors";
|
|
332
336
|
|
|
333
337
|
const store = new S3Vectors({
|
|
338
|
+
id: 's3-vectors',
|
|
334
339
|
vectorBucketName: "my-vector-bucket",
|
|
335
340
|
clientConfig: {
|
|
336
341
|
region: "us-east-1",
|
|
@@ -373,7 +378,7 @@ The dimension size must match the output dimension of your chosen embedding mode
|
|
|
373
378
|
- Cohere embed-multilingual-v3: 1024 dimensions
|
|
374
379
|
- Google text-embedding-004: 768 dimensions (or custom)
|
|
375
380
|
|
|
376
|
-
|
|
381
|
+
> **Note:**
|
|
377
382
|
Index dimensions cannot be changed after creation. To use a different model, delete and recreate the index with the new dimension size.
|
|
378
383
|
|
|
379
384
|
### Naming Rules for Databases
|
|
@@ -537,7 +542,7 @@ The upsert operation:
|
|
|
537
542
|
|
|
538
543
|
Vector stores support rich metadata (any JSON-serializable fields) for filtering and organization. Since metadata is stored with no fixed schema, use consistent field naming to avoid unexpected query results.
|
|
539
544
|
|
|
540
|
-
|
|
545
|
+
> **Note:**
|
|
541
546
|
Metadata is crucial for vector storage - without it, you'd only have numerical embeddings with no way to return the original text or filter results. Always store at least the source text as metadata.
|
|
542
547
|
|
|
543
548
|
```ts
|
|
@@ -171,7 +171,7 @@ The Vector Query Tool supports database-specific configurations that enable you
|
|
|
171
171
|
> **Note:**
|
|
172
172
|
These configurations are for **query-time options** like namespaces, performance tuning, and filtering—not for database connection setup.
|
|
173
173
|
|
|
174
|
-
Connection credentials (URLs, auth tokens) are configured when you instantiate the vector store class (e.g., `new LibSQLVector({
|
|
174
|
+
Connection credentials (URLs, auth tokens) are configured when you instantiate the vector store class (e.g., `new LibSQLVector({ url: '...' })`).
|
|
175
175
|
|
|
176
176
|
```ts
|
|
177
177
|
import { createVectorQueryTool } from "@mastra/rag";
|
|
@@ -258,11 +258,10 @@ requestContext.set("databaseConfig", {
|
|
|
258
258
|
},
|
|
259
259
|
});
|
|
260
260
|
|
|
261
|
-
await pineconeQueryTool.execute(
|
|
262
|
-
|
|
263
|
-
mastra,
|
|
264
|
-
|
|
265
|
-
});
|
|
261
|
+
await pineconeQueryTool.execute(
|
|
262
|
+
{ queryText: "search query" },
|
|
263
|
+
{ mastra, requestContext }
|
|
264
|
+
);
|
|
266
265
|
```
|
|
267
266
|
|
|
268
267
|
For detailed configuration options and advanced usage, see the [Vector Query Tool Reference](https://mastra.ai/reference/v1/tools/vector-query-tool).
|
|
@@ -54,6 +54,29 @@ Deletes a vector from the specified index by its ID.
|
|
|
54
54
|
|
|
55
55
|
Delete multiple vectors by IDs or by metadata filter. Either `ids` or `filter` must be provided, but not both.
|
|
56
56
|
|
|
57
|
+
### createPayloadIndex()
|
|
58
|
+
|
|
59
|
+
Creates a payload (metadata) index on a collection field to enable efficient filtering. This is **required** for Qdrant Cloud and any Qdrant instance with `strict_mode_config = true`.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// Create a keyword index for filtering by source
|
|
63
|
+
await store.createPayloadIndex({
|
|
64
|
+
indexName: "my_index",
|
|
65
|
+
fieldName: "source",
|
|
66
|
+
fieldSchema: "keyword",
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const results = await store.query({
|
|
70
|
+
indexName: "my_index",
|
|
71
|
+
queryVector: queryVector,
|
|
72
|
+
filter: { source: "document-a" },
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### deletePayloadIndex()
|
|
77
|
+
|
|
78
|
+
Removes a payload index from a collection field.
|
|
79
|
+
|
|
57
80
|
## Response Types
|
|
58
81
|
|
|
59
82
|
Query results are returned in this format:
|
package/dist/index.cjs
CHANGED
|
@@ -725,6 +725,161 @@ var QdrantVector = class extends vector.MastraVector {
|
|
|
725
725
|
);
|
|
726
726
|
}
|
|
727
727
|
}
|
|
728
|
+
/**
|
|
729
|
+
* Creates a payload index on a Qdrant collection to enable efficient filtering on metadata fields.
|
|
730
|
+
*
|
|
731
|
+
* This is required for Qdrant Cloud and any Qdrant instance with `strict_mode_config = true`,
|
|
732
|
+
* where metadata (payload) fields must be explicitly indexed before they can be used for filtering.
|
|
733
|
+
*
|
|
734
|
+
* @param params - The parameters for creating the payload index.
|
|
735
|
+
* @param params.indexName - The name of the collection (index) to create the payload index on.
|
|
736
|
+
* @param params.fieldName - The name of the payload field to index.
|
|
737
|
+
* @param params.fieldSchema - The schema type for the field (e.g., 'keyword', 'integer', 'text').
|
|
738
|
+
* @param params.wait - Whether to wait for the operation to complete. Defaults to true.
|
|
739
|
+
* @returns A promise that resolves when the index is created (idempotent if index already exists).
|
|
740
|
+
* @throws Will throw a MastraError if arguments are invalid or if the operation fails.
|
|
741
|
+
*
|
|
742
|
+
* @example
|
|
743
|
+
* ```ts
|
|
744
|
+
* // Create a keyword index for filtering by source
|
|
745
|
+
* await qdrant.createPayloadIndex({
|
|
746
|
+
* indexName: 'my-collection',
|
|
747
|
+
* fieldName: 'source',
|
|
748
|
+
* fieldSchema: 'keyword',
|
|
749
|
+
* });
|
|
750
|
+
*
|
|
751
|
+
* // Create an integer index for numeric filtering
|
|
752
|
+
* await qdrant.createPayloadIndex({
|
|
753
|
+
* indexName: 'my-collection',
|
|
754
|
+
* fieldName: 'price',
|
|
755
|
+
* fieldSchema: 'integer',
|
|
756
|
+
* });
|
|
757
|
+
* ```
|
|
758
|
+
*
|
|
759
|
+
* @see https://qdrant.tech/documentation/concepts/indexing/#payload-index
|
|
760
|
+
*/
|
|
761
|
+
async createPayloadIndex({
|
|
762
|
+
indexName,
|
|
763
|
+
fieldName,
|
|
764
|
+
fieldSchema,
|
|
765
|
+
wait = true
|
|
766
|
+
}) {
|
|
767
|
+
const validSchemas = [
|
|
768
|
+
"keyword",
|
|
769
|
+
"integer",
|
|
770
|
+
"float",
|
|
771
|
+
"geo",
|
|
772
|
+
"text",
|
|
773
|
+
"bool",
|
|
774
|
+
"datetime",
|
|
775
|
+
"uuid"
|
|
776
|
+
];
|
|
777
|
+
if (!indexName || typeof indexName !== "string" || indexName.trim() === "") {
|
|
778
|
+
throw new error.MastraError({
|
|
779
|
+
id: storage.createVectorErrorId("QDRANT", "CREATE_PAYLOAD_INDEX", "INVALID_ARGS"),
|
|
780
|
+
text: "indexName must be a non-empty string",
|
|
781
|
+
domain: error.ErrorDomain.STORAGE,
|
|
782
|
+
category: error.ErrorCategory.USER,
|
|
783
|
+
details: { indexName, fieldName, fieldSchema }
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
if (!fieldName || typeof fieldName !== "string" || fieldName.trim() === "") {
|
|
787
|
+
throw new error.MastraError({
|
|
788
|
+
id: storage.createVectorErrorId("QDRANT", "CREATE_PAYLOAD_INDEX", "INVALID_ARGS"),
|
|
789
|
+
text: "fieldName must be a non-empty string",
|
|
790
|
+
domain: error.ErrorDomain.STORAGE,
|
|
791
|
+
category: error.ErrorCategory.USER,
|
|
792
|
+
details: { indexName, fieldName, fieldSchema }
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
if (!validSchemas.includes(fieldSchema)) {
|
|
796
|
+
throw new error.MastraError({
|
|
797
|
+
id: storage.createVectorErrorId("QDRANT", "CREATE_PAYLOAD_INDEX", "INVALID_ARGS"),
|
|
798
|
+
text: `fieldSchema must be one of: ${validSchemas.join(", ")}`,
|
|
799
|
+
domain: error.ErrorDomain.STORAGE,
|
|
800
|
+
category: error.ErrorCategory.USER,
|
|
801
|
+
details: { indexName, fieldName, fieldSchema }
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
try {
|
|
805
|
+
await this.client.createPayloadIndex(indexName, {
|
|
806
|
+
field_name: fieldName,
|
|
807
|
+
field_schema: fieldSchema,
|
|
808
|
+
wait
|
|
809
|
+
});
|
|
810
|
+
} catch (error$1) {
|
|
811
|
+
const message = error$1?.message || error$1?.toString() || "";
|
|
812
|
+
if (error$1?.status === 409 || message.toLowerCase().includes("exists")) {
|
|
813
|
+
this.logger.info(`Payload index for field "${fieldName}" already exists on collection "${indexName}"`);
|
|
814
|
+
return;
|
|
815
|
+
}
|
|
816
|
+
throw new error.MastraError(
|
|
817
|
+
{
|
|
818
|
+
id: storage.createVectorErrorId("QDRANT", "CREATE_PAYLOAD_INDEX", "FAILED"),
|
|
819
|
+
domain: error.ErrorDomain.STORAGE,
|
|
820
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
821
|
+
details: { indexName, fieldName, fieldSchema }
|
|
822
|
+
},
|
|
823
|
+
error$1
|
|
824
|
+
);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* Deletes a payload index from a Qdrant collection.
|
|
829
|
+
*
|
|
830
|
+
* @param params - The parameters for deleting the payload index.
|
|
831
|
+
* @param params.indexName - The name of the collection (index) to delete the payload index from.
|
|
832
|
+
* @param params.fieldName - The name of the payload field index to delete.
|
|
833
|
+
* @param params.wait - Whether to wait for the operation to complete. Defaults to true.
|
|
834
|
+
* @returns A promise that resolves when the index is deleted (idempotent if index doesn't exist).
|
|
835
|
+
* @throws Will throw a MastraError if the operation fails.
|
|
836
|
+
*
|
|
837
|
+
* @example
|
|
838
|
+
* ```ts
|
|
839
|
+
* await qdrant.deletePayloadIndex({
|
|
840
|
+
* indexName: 'my-collection',
|
|
841
|
+
* fieldName: 'source',
|
|
842
|
+
* });
|
|
843
|
+
* ```
|
|
844
|
+
*/
|
|
845
|
+
async deletePayloadIndex({ indexName, fieldName, wait = true }) {
|
|
846
|
+
if (!indexName || typeof indexName !== "string" || indexName.trim() === "") {
|
|
847
|
+
throw new error.MastraError({
|
|
848
|
+
id: storage.createVectorErrorId("QDRANT", "DELETE_PAYLOAD_INDEX", "INVALID_ARGS"),
|
|
849
|
+
text: "indexName must be a non-empty string",
|
|
850
|
+
domain: error.ErrorDomain.STORAGE,
|
|
851
|
+
category: error.ErrorCategory.USER,
|
|
852
|
+
details: { indexName, fieldName }
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
if (!fieldName || typeof fieldName !== "string" || fieldName.trim() === "") {
|
|
856
|
+
throw new error.MastraError({
|
|
857
|
+
id: storage.createVectorErrorId("QDRANT", "DELETE_PAYLOAD_INDEX", "INVALID_ARGS"),
|
|
858
|
+
text: "fieldName must be a non-empty string",
|
|
859
|
+
domain: error.ErrorDomain.STORAGE,
|
|
860
|
+
category: error.ErrorCategory.USER,
|
|
861
|
+
details: { indexName, fieldName }
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
try {
|
|
865
|
+
await this.client.deletePayloadIndex(indexName, fieldName, { wait });
|
|
866
|
+
} catch (error$1) {
|
|
867
|
+
const message = error$1?.message || error$1?.toString() || "";
|
|
868
|
+
if (error$1?.status === 404 || message.toLowerCase().includes("not found") || message.toLowerCase().includes("not exist")) {
|
|
869
|
+
this.logger.info(`Payload index for field "${fieldName}" does not exist on collection "${indexName}"`);
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
throw new error.MastraError(
|
|
873
|
+
{
|
|
874
|
+
id: storage.createVectorErrorId("QDRANT", "DELETE_PAYLOAD_INDEX", "FAILED"),
|
|
875
|
+
domain: error.ErrorDomain.STORAGE,
|
|
876
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
877
|
+
details: { indexName, fieldName }
|
|
878
|
+
},
|
|
879
|
+
error$1
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
728
883
|
};
|
|
729
884
|
|
|
730
885
|
// src/vector/prompt.ts
|