@mastra/memory 1.5.1 → 1.5.2
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 +28 -0
- package/dist/{chunk-6PKWQ3GH.js → chunk-HNPAIFCZ.js} +59 -16
- package/dist/chunk-HNPAIFCZ.js.map +1 -0
- package/dist/{chunk-6XVTMLW4.cjs → chunk-PVFLHAZX.cjs} +59 -16
- package/dist/chunk-PVFLHAZX.cjs.map +1 -0
- package/dist/docs/SKILL.md +55 -0
- package/dist/docs/assets/SOURCE_MAP.json +103 -0
- package/dist/docs/references/docs-agents-agent-approval.md +558 -0
- package/dist/docs/references/docs-agents-agent-memory.md +209 -0
- package/dist/docs/references/docs-agents-network-approval.md +275 -0
- package/dist/docs/references/docs-agents-networks.md +299 -0
- package/dist/docs/references/docs-agents-supervisor-agents.md +304 -0
- package/dist/docs/references/docs-memory-memory-processors.md +314 -0
- package/dist/docs/references/docs-memory-message-history.md +260 -0
- package/dist/docs/references/docs-memory-observational-memory.md +248 -0
- package/dist/docs/references/docs-memory-overview.md +45 -0
- package/dist/docs/references/docs-memory-semantic-recall.md +272 -0
- package/dist/docs/references/docs-memory-storage.md +261 -0
- package/dist/docs/references/docs-memory-working-memory.md +400 -0
- package/dist/docs/references/reference-core-getMemory.md +50 -0
- package/dist/docs/references/reference-core-listMemory.md +56 -0
- package/dist/docs/references/reference-memory-clone-utilities.md +199 -0
- package/dist/docs/references/reference-memory-cloneThread.md +130 -0
- package/dist/docs/references/reference-memory-createThread.md +68 -0
- package/dist/docs/references/reference-memory-getThreadById.md +24 -0
- package/dist/docs/references/reference-memory-listThreads.md +145 -0
- package/dist/docs/references/reference-memory-memory-class.md +147 -0
- package/dist/docs/references/reference-memory-observational-memory.md +565 -0
- package/dist/docs/references/reference-processors-token-limiter-processor.md +115 -0
- package/dist/docs/references/reference-storage-dynamodb.md +282 -0
- package/dist/docs/references/reference-storage-libsql.md +135 -0
- package/dist/docs/references/reference-storage-mongodb.md +262 -0
- package/dist/docs/references/reference-storage-postgresql.md +526 -0
- package/dist/docs/references/reference-storage-upstash.md +160 -0
- package/dist/docs/references/reference-vectors-libsql.md +305 -0
- package/dist/docs/references/reference-vectors-mongodb.md +295 -0
- package/dist/docs/references/reference-vectors-pg.md +408 -0
- package/dist/docs/references/reference-vectors-upstash.md +294 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{observational-memory-AJWSMZVP.js → observational-memory-KAFD4QZK.js} +3 -3
- package/dist/{observational-memory-AJWSMZVP.js.map → observational-memory-KAFD4QZK.js.map} +1 -1
- package/dist/{observational-memory-Q5TO525O.cjs → observational-memory-Q47HN5YL.cjs} +17 -17
- package/dist/{observational-memory-Q5TO525O.cjs.map → observational-memory-Q47HN5YL.cjs.map} +1 -1
- package/dist/processors/index.cjs +15 -15
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/observational-memory.d.ts +2 -2
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/chunk-6PKWQ3GH.js.map +0 -1
- package/dist/chunk-6XVTMLW4.cjs.map +0 -1
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# PG Vector Store
|
|
2
|
+
|
|
3
|
+
The PgVector class provides vector search using [PostgreSQL](https://www.postgresql.org/) with [pgvector](https://github.com/pgvector/pgvector) extension. It provides robust vector similarity search capabilities within your existing PostgreSQL database.
|
|
4
|
+
|
|
5
|
+
## Constructor Options
|
|
6
|
+
|
|
7
|
+
**connectionString?:** (`string`): PostgreSQL connection URL
|
|
8
|
+
|
|
9
|
+
**host?:** (`string`): PostgreSQL server host
|
|
10
|
+
|
|
11
|
+
**port?:** (`number`): PostgreSQL server port
|
|
12
|
+
|
|
13
|
+
**database?:** (`string`): PostgreSQL database name
|
|
14
|
+
|
|
15
|
+
**user?:** (`string`): PostgreSQL user
|
|
16
|
+
|
|
17
|
+
**password?:** (`string`): PostgreSQL password
|
|
18
|
+
|
|
19
|
+
**ssl?:** (`boolean | ConnectionOptions`): Enable SSL or provide custom SSL configuration
|
|
20
|
+
|
|
21
|
+
**schemaName?:** (`string`): The name of the schema you want the vector store to use. Will use the default schema if not provided.
|
|
22
|
+
|
|
23
|
+
**max?:** (`number`): Maximum number of pool connections (default: 20)
|
|
24
|
+
|
|
25
|
+
**idleTimeoutMillis?:** (`number`): Idle connection timeout in milliseconds (default: 30000)
|
|
26
|
+
|
|
27
|
+
**pgPoolOptions?:** (`PoolConfig`): Additional pg pool configuration options
|
|
28
|
+
|
|
29
|
+
## Constructor Examples
|
|
30
|
+
|
|
31
|
+
### Connection String
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { PgVector } from '@mastra/pg'
|
|
35
|
+
|
|
36
|
+
const vectorStore = new PgVector({
|
|
37
|
+
id: 'pg-vector',
|
|
38
|
+
connectionString: 'postgresql://user:password@localhost:5432/mydb',
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Host/Port/Database Configuration
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
const vectorStore = new PgVector({
|
|
46
|
+
id: 'pg-vector',
|
|
47
|
+
host: 'localhost',
|
|
48
|
+
port: 5432,
|
|
49
|
+
database: 'mydb',
|
|
50
|
+
user: 'postgres',
|
|
51
|
+
password: 'password',
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Advanced Configuration
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
const vectorStore = new PgVector({
|
|
59
|
+
id: 'pg-vector',
|
|
60
|
+
connectionString: 'postgresql://user:password@localhost:5432/mydb',
|
|
61
|
+
schemaName: 'custom_schema',
|
|
62
|
+
max: 30,
|
|
63
|
+
idleTimeoutMillis: 60000,
|
|
64
|
+
pgPoolOptions: {
|
|
65
|
+
connectionTimeoutMillis: 5000,
|
|
66
|
+
allowExitOnIdle: true,
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Methods
|
|
72
|
+
|
|
73
|
+
### createIndex()
|
|
74
|
+
|
|
75
|
+
**indexName:** (`string`): Name of the index to create
|
|
76
|
+
|
|
77
|
+
**dimension:** (`number`): Vector dimension (must match your embedding model)
|
|
78
|
+
|
|
79
|
+
**metric?:** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`)
|
|
80
|
+
|
|
81
|
+
**indexConfig?:** (`IndexConfig`): Index configuration (Default: `{ type: 'ivfflat' }`)
|
|
82
|
+
|
|
83
|
+
**buildIndex?:** (`boolean`): Whether to build the index (Default: `true`)
|
|
84
|
+
|
|
85
|
+
#### IndexConfig
|
|
86
|
+
|
|
87
|
+
**type:** (`'flat' | 'hnsw' | 'ivfflat'`): stringflat:flatSequential scan (no index) that performs exhaustive search.ivfflat:ivfflatClusters vectors into lists for approximate search.hnsw:hnswGraph-based index offering fast search times and high recall. (Default: `ivfflat`)
|
|
88
|
+
|
|
89
|
+
**ivf?:** (`IVFConfig`): objectlists?:numberNumber of lists. If not specified, automatically calculated based on dataset size. (Minimum 100, Maximum 4000)
|
|
90
|
+
|
|
91
|
+
**hnsw?:** (`HNSWConfig`): objectm?:numberMaximum number of connections per node (default: 8)efConstruction?:numberBuild-time complexity (default: 32)
|
|
92
|
+
|
|
93
|
+
#### Memory Requirements
|
|
94
|
+
|
|
95
|
+
HNSW indexes require significant shared memory during construction. For 100K vectors:
|
|
96
|
+
|
|
97
|
+
- Small dimensions (64d): \~60MB with default settings
|
|
98
|
+
- Medium dimensions (256d): \~180MB with default settings
|
|
99
|
+
- Large dimensions (384d+): \~250MB+ with default settings
|
|
100
|
+
|
|
101
|
+
Higher M values or efConstruction values will increase memory requirements significantly. Adjust your system's shared memory limits if needed.
|
|
102
|
+
|
|
103
|
+
### upsert()
|
|
104
|
+
|
|
105
|
+
**indexName:** (`string`): Name of the index to upsert vectors into
|
|
106
|
+
|
|
107
|
+
**vectors:** (`number[][]`): Array of embedding vectors
|
|
108
|
+
|
|
109
|
+
**metadata?:** (`Record<string, any>[]`): Metadata for each vector
|
|
110
|
+
|
|
111
|
+
**ids?:** (`string[]`): Optional vector IDs (auto-generated if not provided)
|
|
112
|
+
|
|
113
|
+
### query()
|
|
114
|
+
|
|
115
|
+
**indexName:** (`string`): Name of the index to query
|
|
116
|
+
|
|
117
|
+
**queryVector:** (`number[]`): Query vector
|
|
118
|
+
|
|
119
|
+
**topK?:** (`number`): Number of results to return (Default: `10`)
|
|
120
|
+
|
|
121
|
+
**filter?:** (`Record<string, any>`): Metadata filters
|
|
122
|
+
|
|
123
|
+
**includeVector?:** (`boolean`): Whether to include the vector in the result (Default: `false`)
|
|
124
|
+
|
|
125
|
+
**minScore?:** (`number`): Minimum similarity score threshold (Default: `0`)
|
|
126
|
+
|
|
127
|
+
**options?:** (`{ ef?: number; probes?: number }`): objectef?:numberHNSW search parameterprobes?:numberIVF search parameter
|
|
128
|
+
|
|
129
|
+
### listIndexes()
|
|
130
|
+
|
|
131
|
+
Returns an array of index names as strings.
|
|
132
|
+
|
|
133
|
+
### describeIndex()
|
|
134
|
+
|
|
135
|
+
**indexName:** (`string`): Name of the index to describe
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
interface PGIndexStats {
|
|
141
|
+
dimension: number
|
|
142
|
+
count: number
|
|
143
|
+
metric: 'cosine' | 'euclidean' | 'dotproduct'
|
|
144
|
+
type: 'flat' | 'hnsw' | 'ivfflat'
|
|
145
|
+
config: {
|
|
146
|
+
m?: number
|
|
147
|
+
efConstruction?: number
|
|
148
|
+
lists?: number
|
|
149
|
+
probes?: number
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### deleteIndex()
|
|
155
|
+
|
|
156
|
+
**indexName:** (`string`): Name of the index to delete
|
|
157
|
+
|
|
158
|
+
### updateVector()
|
|
159
|
+
|
|
160
|
+
Update a single vector by ID or by metadata filter. Either `id` or `filter` must be provided, but not both.
|
|
161
|
+
|
|
162
|
+
**indexName:** (`string`): Name of the index containing the vector
|
|
163
|
+
|
|
164
|
+
**id?:** (`string`): ID of the vector to update (mutually exclusive with filter)
|
|
165
|
+
|
|
166
|
+
**filter?:** (`Record<string, any>`): Metadata filter to identify vector(s) to update (mutually exclusive with id)
|
|
167
|
+
|
|
168
|
+
**update:** (`{ vector?: number[]; metadata?: Record<string, any>; }`): Object containing the vector and/or metadata to update
|
|
169
|
+
|
|
170
|
+
Updates an existing vector by ID or filter. At least one of vector or metadata must be provided in the update object.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Update by ID
|
|
174
|
+
await pgVector.updateVector({
|
|
175
|
+
indexName: 'my_vectors',
|
|
176
|
+
id: 'vector123',
|
|
177
|
+
update: {
|
|
178
|
+
vector: [0.1, 0.2, 0.3],
|
|
179
|
+
metadata: { label: 'updated' },
|
|
180
|
+
},
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
// Update by filter
|
|
184
|
+
await pgVector.updateVector({
|
|
185
|
+
indexName: 'my_vectors',
|
|
186
|
+
filter: { category: 'product' },
|
|
187
|
+
update: {
|
|
188
|
+
metadata: { status: 'reviewed' },
|
|
189
|
+
},
|
|
190
|
+
})
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### deleteVector()
|
|
194
|
+
|
|
195
|
+
**indexName:** (`string`): Name of the index containing the vector
|
|
196
|
+
|
|
197
|
+
**id:** (`string`): ID of the vector to delete
|
|
198
|
+
|
|
199
|
+
Deletes a single vector by ID from the specified index.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
await pgVector.deleteVector({ indexName: 'my_vectors', id: 'vector123' })
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### deleteVectors()
|
|
206
|
+
|
|
207
|
+
Delete multiple vectors by IDs or by metadata filter. Either `ids` or `filter` must be provided, but not both.
|
|
208
|
+
|
|
209
|
+
**indexName:** (`string`): Name of the index containing the vectors to delete
|
|
210
|
+
|
|
211
|
+
**ids?:** (`string[]`): Array of vector IDs to delete (mutually exclusive with filter)
|
|
212
|
+
|
|
213
|
+
**filter?:** (`Record<string, any>`): Metadata filter to identify vectors to delete (mutually exclusive with ids)
|
|
214
|
+
|
|
215
|
+
### disconnect()
|
|
216
|
+
|
|
217
|
+
Closes the database connection pool. Should be called when done using the store.
|
|
218
|
+
|
|
219
|
+
### buildIndex()
|
|
220
|
+
|
|
221
|
+
**indexName:** (`string`): Name of the index to define
|
|
222
|
+
|
|
223
|
+
**metric?:** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`)
|
|
224
|
+
|
|
225
|
+
**indexConfig:** (`IndexConfig`): Configuration for the index type and parameters
|
|
226
|
+
|
|
227
|
+
Builds or rebuilds an index with specified metric and configuration. Will drop any existing index before creating the new one.
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
// Define HNSW index
|
|
231
|
+
await pgVector.buildIndex('my_vectors', 'cosine', {
|
|
232
|
+
type: 'hnsw',
|
|
233
|
+
hnsw: {
|
|
234
|
+
m: 8,
|
|
235
|
+
efConstruction: 32,
|
|
236
|
+
},
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
// Define IVF index
|
|
240
|
+
await pgVector.buildIndex('my_vectors', 'cosine', {
|
|
241
|
+
type: 'ivfflat',
|
|
242
|
+
ivf: {
|
|
243
|
+
lists: 100,
|
|
244
|
+
},
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
// Define flat index
|
|
248
|
+
await pgVector.buildIndex('my_vectors', 'cosine', {
|
|
249
|
+
type: 'flat',
|
|
250
|
+
})
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Response Types
|
|
254
|
+
|
|
255
|
+
Query results are returned in this format:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
interface QueryResult {
|
|
259
|
+
id: string
|
|
260
|
+
score: number
|
|
261
|
+
metadata: Record<string, any>
|
|
262
|
+
vector?: number[] // Only included if includeVector is true
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Error Handling
|
|
267
|
+
|
|
268
|
+
The store throws typed errors that can be caught:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
try {
|
|
272
|
+
await store.query({
|
|
273
|
+
indexName: 'index_name',
|
|
274
|
+
queryVector: queryVector,
|
|
275
|
+
})
|
|
276
|
+
} catch (error) {
|
|
277
|
+
if (error instanceof VectorStoreError) {
|
|
278
|
+
console.log(error.code) // 'connection_failed' | 'invalid_dimension' | etc
|
|
279
|
+
console.log(error.details) // Additional error context
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
## Index Configuration Guide
|
|
285
|
+
|
|
286
|
+
### Performance Optimization
|
|
287
|
+
|
|
288
|
+
#### IVFFlat Tuning
|
|
289
|
+
|
|
290
|
+
- **lists parameter**: Set to `sqrt(n) * 2` where n is the number of vectors
|
|
291
|
+
- More lists = better accuracy but slower build time
|
|
292
|
+
- Fewer lists = faster build but potentially lower accuracy
|
|
293
|
+
|
|
294
|
+
#### HNSW Tuning
|
|
295
|
+
|
|
296
|
+
- **m parameter**:
|
|
297
|
+
|
|
298
|
+
- 8-16: Moderate accuracy, lower memory
|
|
299
|
+
- 16-32: High accuracy, moderate memory
|
|
300
|
+
- 32-64: Very high accuracy, high memory
|
|
301
|
+
|
|
302
|
+
- **efConstruction**:
|
|
303
|
+
|
|
304
|
+
- 32-64: Fast build, good quality
|
|
305
|
+
- 64-128: Slower build, better quality
|
|
306
|
+
- 128-256: Slowest build, best quality
|
|
307
|
+
|
|
308
|
+
### Index Recreation Behavior
|
|
309
|
+
|
|
310
|
+
The system automatically detects configuration changes and only rebuilds indexes when necessary:
|
|
311
|
+
|
|
312
|
+
- Same configuration: Index is kept (no recreation)
|
|
313
|
+
- Changed configuration: Index is dropped and rebuilt
|
|
314
|
+
- This prevents the performance issues from unnecessary index recreations
|
|
315
|
+
|
|
316
|
+
## Best Practices
|
|
317
|
+
|
|
318
|
+
- Regularly evaluate your index configuration to ensure optimal performance.
|
|
319
|
+
- Adjust parameters like `lists` and `m` based on dataset size and query requirements.
|
|
320
|
+
- **Monitor index performance** using `describeIndex()` to track usage
|
|
321
|
+
- Rebuild indexes periodically to maintain efficiency, especially after significant data changes
|
|
322
|
+
|
|
323
|
+
## Direct Pool Access
|
|
324
|
+
|
|
325
|
+
The `PgVector` class exposes its underlying PostgreSQL connection pool as a public field:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
pgVector.pool // instance of pg.Pool
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
This enables advanced usage such as running direct SQL queries, managing transactions, or monitoring pool state. When using the pool directly:
|
|
332
|
+
|
|
333
|
+
- You are responsible for releasing clients (`client.release()`) after use.
|
|
334
|
+
- The pool remains accessible after calling `disconnect()`, but new queries will fail.
|
|
335
|
+
- Direct access bypasses any validation or transaction logic provided by PgVector methods.
|
|
336
|
+
|
|
337
|
+
This design supports advanced use cases but requires careful resource management by the user.
|
|
338
|
+
|
|
339
|
+
## Usage Example
|
|
340
|
+
|
|
341
|
+
### Local embeddings with fastembed
|
|
342
|
+
|
|
343
|
+
Embeddings are numeric vectors used by memory's `semanticRecall` to retrieve related messages by meaning (not keywords). This setup uses `@mastra/fastembed` to generate vector embeddings.
|
|
344
|
+
|
|
345
|
+
Install `fastembed` to get started:
|
|
346
|
+
|
|
347
|
+
**npm**:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npm install @mastra/fastembed@latest
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**pnpm**:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
pnpm add @mastra/fastembed@latest
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
**Yarn**:
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
yarn add @mastra/fastembed@latest
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Bun**:
|
|
366
|
+
|
|
367
|
+
```bash
|
|
368
|
+
bun add @mastra/fastembed@latest
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
Add the following to your agent:
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
import { Memory } from '@mastra/memory'
|
|
375
|
+
import { Agent } from '@mastra/core/agent'
|
|
376
|
+
import { PostgresStore, PgVector } from '@mastra/pg'
|
|
377
|
+
import { fastembed } from '@mastra/fastembed'
|
|
378
|
+
|
|
379
|
+
export const pgAgent = new Agent({
|
|
380
|
+
id: 'pg-agent',
|
|
381
|
+
name: 'PG Agent',
|
|
382
|
+
instructions:
|
|
383
|
+
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
384
|
+
model: 'openai/gpt-5.1',
|
|
385
|
+
memory: new Memory({
|
|
386
|
+
storage: new PostgresStore({
|
|
387
|
+
id: 'pg-agent-storage',
|
|
388
|
+
connectionString: process.env.DATABASE_URL!,
|
|
389
|
+
}),
|
|
390
|
+
vector: new PgVector({
|
|
391
|
+
id: 'pg-agent-vector',
|
|
392
|
+
connectionString: process.env.DATABASE_URL!,
|
|
393
|
+
}),
|
|
394
|
+
embedder: fastembed,
|
|
395
|
+
options: {
|
|
396
|
+
lastMessages: 10,
|
|
397
|
+
semanticRecall: {
|
|
398
|
+
topK: 3,
|
|
399
|
+
messageRange: 2,
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
}),
|
|
403
|
+
})
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
## Related
|
|
407
|
+
|
|
408
|
+
- [Metadata Filters](https://mastra.ai/reference/rag/metadata-filters)
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
# Upstash Vector Store
|
|
2
|
+
|
|
3
|
+
The UpstashVector class provides vector search using [Upstash Vector](https://upstash.com/vector), a serverless vector database service that provides vector similarity search with metadata filtering capabilities and hybrid search support.
|
|
4
|
+
|
|
5
|
+
## Constructor Options
|
|
6
|
+
|
|
7
|
+
**url:** (`string`): Upstash Vector database URL
|
|
8
|
+
|
|
9
|
+
**token:** (`string`): Upstash Vector API token
|
|
10
|
+
|
|
11
|
+
## Methods
|
|
12
|
+
|
|
13
|
+
### createIndex()
|
|
14
|
+
|
|
15
|
+
Note: This method is a no-op for Upstash as indexes are created automatically.
|
|
16
|
+
|
|
17
|
+
**indexName:** (`string`): Name of the index to create
|
|
18
|
+
|
|
19
|
+
**dimension:** (`number`): Vector dimension (must match your embedding model)
|
|
20
|
+
|
|
21
|
+
**metric?:** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`)
|
|
22
|
+
|
|
23
|
+
### upsert()
|
|
24
|
+
|
|
25
|
+
**indexName:** (`string`): Name of the index to upsert into
|
|
26
|
+
|
|
27
|
+
**vectors:** (`number[][]`): Array of embedding vectors
|
|
28
|
+
|
|
29
|
+
**sparseVectors?:** (`{ indices: number[], values: number[] }[]`): Array of sparse vectors for hybrid search. Each sparse vector must have matching indices and values arrays.
|
|
30
|
+
|
|
31
|
+
**metadata?:** (`Record<string, any>[]`): Metadata for each vector
|
|
32
|
+
|
|
33
|
+
**ids?:** (`string[]`): Optional vector IDs (auto-generated if not provided)
|
|
34
|
+
|
|
35
|
+
### query()
|
|
36
|
+
|
|
37
|
+
**indexName:** (`string`): Name of the index to query
|
|
38
|
+
|
|
39
|
+
**queryVector:** (`number[]`): Query vector to find similar vectors
|
|
40
|
+
|
|
41
|
+
**sparseVector?:** (`{ indices: number[], values: number[] }`): Optional sparse vector for hybrid search. Must have matching indices and values arrays.
|
|
42
|
+
|
|
43
|
+
**topK?:** (`number`): Number of results to return (Default: `10`)
|
|
44
|
+
|
|
45
|
+
**filter?:** (`Record<string, any>`): Metadata filters for the query
|
|
46
|
+
|
|
47
|
+
**includeVector?:** (`boolean`): Whether to include vectors in the results (Default: `false`)
|
|
48
|
+
|
|
49
|
+
**fusionAlgorithm?:** (`FusionAlgorithm`): Algorithm used to combine dense and sparse search results in hybrid search (e.g., RRF - Reciprocal Rank Fusion)
|
|
50
|
+
|
|
51
|
+
**queryMode?:** (`QueryMode`): Search mode: 'DENSE' for dense-only, 'SPARSE' for sparse-only, or 'HYBRID' for combined search
|
|
52
|
+
|
|
53
|
+
### listIndexes()
|
|
54
|
+
|
|
55
|
+
Returns an array of index names (namespaces) as strings.
|
|
56
|
+
|
|
57
|
+
### describeIndex()
|
|
58
|
+
|
|
59
|
+
**indexName:** (`string`): Name of the index to describe
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
interface IndexStats {
|
|
65
|
+
dimension: number
|
|
66
|
+
count: number
|
|
67
|
+
metric: 'cosine' | 'euclidean' | 'dotproduct'
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### deleteIndex()
|
|
72
|
+
|
|
73
|
+
**indexName:** (`string`): Name of the index (namespace) to delete
|
|
74
|
+
|
|
75
|
+
### updateVector()
|
|
76
|
+
|
|
77
|
+
**indexName:** (`string`): Name of the index to update
|
|
78
|
+
|
|
79
|
+
**id:** (`string`): ID of the item to update
|
|
80
|
+
|
|
81
|
+
**update:** (`object`): Update object containing vector, sparse vector, and/or metadata
|
|
82
|
+
|
|
83
|
+
The `update` object can have the following properties:
|
|
84
|
+
|
|
85
|
+
- `vector` (optional): An array of numbers representing the new dense vector.
|
|
86
|
+
- `sparseVector` (optional): A sparse vector object with `indices` and `values` arrays for hybrid indexes.
|
|
87
|
+
- `metadata` (optional): A record of key-value pairs for metadata.
|
|
88
|
+
|
|
89
|
+
### deleteVector()
|
|
90
|
+
|
|
91
|
+
**indexName:** (`string`): Name of the index from which to delete the item
|
|
92
|
+
|
|
93
|
+
**id:** (`string`): ID of the item to delete
|
|
94
|
+
|
|
95
|
+
Attempts to delete an item by its ID from the specified index. Logs an error message if the deletion fails.
|
|
96
|
+
|
|
97
|
+
## Hybrid Vector Search
|
|
98
|
+
|
|
99
|
+
Upstash Vector supports hybrid search that combines semantic search (dense vectors) with keyword-based search (sparse vectors) for improved relevance and accuracy.
|
|
100
|
+
|
|
101
|
+
### Basic Hybrid Usage
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { UpstashVector } from '@mastra/upstash'
|
|
105
|
+
|
|
106
|
+
const vectorStore = new UpstashVector({
|
|
107
|
+
id: 'upstash-vector',
|
|
108
|
+
url: process.env.UPSTASH_VECTOR_URL,
|
|
109
|
+
token: process.env.UPSTASH_VECTOR_TOKEN,
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// Upsert vectors with both dense and sparse components
|
|
113
|
+
const denseVectors = [
|
|
114
|
+
[0.1, 0.2, 0.3],
|
|
115
|
+
[0.4, 0.5, 0.6],
|
|
116
|
+
]
|
|
117
|
+
const sparseVectors = [
|
|
118
|
+
{ indices: [1, 5, 10], values: [0.8, 0.6, 0.4] },
|
|
119
|
+
{ indices: [2, 6, 11], values: [0.7, 0.5, 0.3] },
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
await vectorStore.upsert({
|
|
123
|
+
indexName: 'hybrid-index',
|
|
124
|
+
vectors: denseVectors,
|
|
125
|
+
sparseVectors: sparseVectors,
|
|
126
|
+
metadata: [{ title: 'Document 1' }, { title: 'Document 2' }],
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// Query with hybrid search
|
|
130
|
+
const results = await vectorStore.query({
|
|
131
|
+
indexName: 'hybrid-index',
|
|
132
|
+
queryVector: [0.1, 0.2, 0.3],
|
|
133
|
+
sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
|
|
134
|
+
topK: 10,
|
|
135
|
+
})
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Advanced Hybrid Search Options
|
|
139
|
+
|
|
140
|
+
```typescript
|
|
141
|
+
import { FusionAlgorithm, QueryMode } from '@upstash/vector'
|
|
142
|
+
|
|
143
|
+
// Query with specific fusion algorithm
|
|
144
|
+
const fusionResults = await vectorStore.query({
|
|
145
|
+
indexName: 'hybrid-index',
|
|
146
|
+
queryVector: [0.1, 0.2, 0.3],
|
|
147
|
+
sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
|
|
148
|
+
fusionAlgorithm: FusionAlgorithm.RRF,
|
|
149
|
+
topK: 10,
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
// Dense-only search
|
|
153
|
+
const denseResults = await vectorStore.query({
|
|
154
|
+
indexName: 'hybrid-index',
|
|
155
|
+
queryVector: [0.1, 0.2, 0.3],
|
|
156
|
+
queryMode: QueryMode.DENSE,
|
|
157
|
+
topK: 10,
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
// Sparse-only search
|
|
161
|
+
const sparseResults = await vectorStore.query({
|
|
162
|
+
indexName: 'hybrid-index',
|
|
163
|
+
queryVector: [0.1, 0.2, 0.3], // Still required for index structure
|
|
164
|
+
sparseVector: { indices: [1, 5], values: [0.9, 0.7] },
|
|
165
|
+
queryMode: QueryMode.SPARSE,
|
|
166
|
+
topK: 10,
|
|
167
|
+
})
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Updating Hybrid Vectors
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
// Update both dense and sparse components
|
|
174
|
+
await vectorStore.updateVector({
|
|
175
|
+
indexName: 'hybrid-index',
|
|
176
|
+
id: 'vector-id',
|
|
177
|
+
update: {
|
|
178
|
+
vector: [0.2, 0.3, 0.4],
|
|
179
|
+
sparseVector: { indices: [2, 7, 12], values: [0.9, 0.8, 0.6] },
|
|
180
|
+
metadata: { title: 'Updated Document' },
|
|
181
|
+
},
|
|
182
|
+
})
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Response Types
|
|
186
|
+
|
|
187
|
+
Query results are returned in this format:
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
interface QueryResult {
|
|
191
|
+
id: string
|
|
192
|
+
score: number
|
|
193
|
+
metadata: Record<string, any>
|
|
194
|
+
vector?: number[] // Only included if includeVector is true
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Error Handling
|
|
199
|
+
|
|
200
|
+
The store throws typed errors that can be caught:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
try {
|
|
204
|
+
await store.query({
|
|
205
|
+
indexName: 'index_name',
|
|
206
|
+
queryVector: queryVector,
|
|
207
|
+
})
|
|
208
|
+
} catch (error) {
|
|
209
|
+
if (error instanceof VectorStoreError) {
|
|
210
|
+
console.log(error.code) // 'connection_failed' | 'invalid_dimension' | etc
|
|
211
|
+
console.log(error.details) // Additional error context
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Environment Variables
|
|
217
|
+
|
|
218
|
+
Required environment variables:
|
|
219
|
+
|
|
220
|
+
- `UPSTASH_VECTOR_URL`: Your Upstash Vector database URL
|
|
221
|
+
- `UPSTASH_VECTOR_TOKEN`: Your Upstash Vector API token
|
|
222
|
+
|
|
223
|
+
## Usage Example
|
|
224
|
+
|
|
225
|
+
### Local embeddings with fastembed
|
|
226
|
+
|
|
227
|
+
Embeddings are numeric vectors used by memory's `semanticRecall` to retrieve related messages by meaning (not keywords). This setup uses `@mastra/fastembed` to generate vector embeddings.
|
|
228
|
+
|
|
229
|
+
Install `fastembed` to get started:
|
|
230
|
+
|
|
231
|
+
**npm**:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
npm install @mastra/fastembed@latest
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**pnpm**:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
pnpm add @mastra/fastembed@latest
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Yarn**:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
yarn add @mastra/fastembed@latest
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**Bun**:
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
bun add @mastra/fastembed@latest
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
Add the following to your agent:
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
import { Memory } from '@mastra/memory'
|
|
259
|
+
import { Agent } from '@mastra/core/agent'
|
|
260
|
+
import { UpstashStore, UpstashVector } from '@mastra/upstash'
|
|
261
|
+
import { fastembed } from '@mastra/fastembed'
|
|
262
|
+
|
|
263
|
+
export const upstashAgent = new Agent({
|
|
264
|
+
id: 'upstash-agent',
|
|
265
|
+
name: 'Upstash Agent',
|
|
266
|
+
instructions:
|
|
267
|
+
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
|
|
268
|
+
model: 'openai/gpt-5.1',
|
|
269
|
+
memory: new Memory({
|
|
270
|
+
storage: new UpstashStore({
|
|
271
|
+
id: 'upstash-agent-storage',
|
|
272
|
+
url: process.env.UPSTASH_REDIS_REST_URL!,
|
|
273
|
+
token: process.env.UPSTASH_REDIS_REST_TOKEN!,
|
|
274
|
+
}),
|
|
275
|
+
vector: new UpstashVector({
|
|
276
|
+
id: 'upstash-agent-vector',
|
|
277
|
+
url: process.env.UPSTASH_VECTOR_REST_URL!,
|
|
278
|
+
token: process.env.UPSTASH_VECTOR_REST_TOKEN!,
|
|
279
|
+
}),
|
|
280
|
+
embedder: fastembed,
|
|
281
|
+
options: {
|
|
282
|
+
lastMessages: 10,
|
|
283
|
+
semanticRecall: {
|
|
284
|
+
topK: 3,
|
|
285
|
+
messageRange: 2,
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
}),
|
|
289
|
+
})
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Related
|
|
293
|
+
|
|
294
|
+
- [Metadata Filters](https://mastra.ai/reference/rag/metadata-filters)
|
package/dist/index.cjs
CHANGED
|
@@ -16377,7 +16377,7 @@ Notes:
|
|
|
16377
16377
|
"Observational memory async buffering is enabled by default but the installed version of @mastra/core does not support it. Either upgrade @mastra/core, @mastra/memory, and your storage adapter (@mastra/libsql, @mastra/pg, or @mastra/mongodb) to the latest version, or explicitly disable async buffering by setting `observation: { bufferTokens: false }` in your observationalMemory config."
|
|
16378
16378
|
);
|
|
16379
16379
|
}
|
|
16380
|
-
const { ObservationalMemory } = await import('./observational-memory-
|
|
16380
|
+
const { ObservationalMemory } = await import('./observational-memory-Q47HN5YL.cjs');
|
|
16381
16381
|
return new ObservationalMemory({
|
|
16382
16382
|
storage: memoryStore,
|
|
16383
16383
|
scope: omConfig.scope,
|