@mastra/rag 0.1.8-alpha.10 → 0.1.8-alpha.11
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +6 -0
- package/dist/_tsup-dts-rollup.d.cts +2 -2
- package/dist/_tsup-dts-rollup.d.ts +2 -2
- package/dist/index.cjs +16 -12
- package/dist/index.js +16 -12
- package/package.json +1 -1
- package/src/tools/vector-query.test.ts +239 -0
- package/src/tools/vector-query.ts +22 -15
- package/src/utils/default-settings.ts +4 -4
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/rag@0.1.8-alpha.
|
|
2
|
+
> @mastra/rag@0.1.8-alpha.11 build /home/runner/work/mastra/mastra/packages/rag
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
6
6
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
7
7
|
[34mCLI[39m tsup v8.3.6
|
|
8
8
|
[34mTSC[39m Build start
|
|
9
|
-
[32mTSC[39m ⚡️ Build success in
|
|
9
|
+
[32mTSC[39m ⚡️ Build success in 21457ms
|
|
10
10
|
[34mDTS[39m Build start
|
|
11
11
|
[34mCLI[39m Target: es2022
|
|
12
12
|
Analysis will use the bundled TypeScript version 5.7.3
|
|
13
13
|
[36mWriting package typings: /home/runner/work/mastra/mastra/packages/rag/dist/_tsup-dts-rollup.d.ts[39m
|
|
14
14
|
Analysis will use the bundled TypeScript version 5.7.3
|
|
15
15
|
[36mWriting package typings: /home/runner/work/mastra/mastra/packages/rag/dist/_tsup-dts-rollup.d.cts[39m
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 14197ms
|
|
17
17
|
[34mCLI[39m Cleaning output folder
|
|
18
18
|
[34mESM[39m Build start
|
|
19
19
|
[34mCJS[39m Build start
|
|
20
|
-
[32mCJS[39m [1mdist/index.cjs [22m[32m90.
|
|
21
|
-
[32mCJS[39m ⚡️ Build success in
|
|
22
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
23
|
-
[32mESM[39m ⚡️ Build success in
|
|
20
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m90.75 KB[39m
|
|
21
|
+
[32mCJS[39m ⚡️ Build success in 740ms
|
|
22
|
+
[32mESM[39m [1mdist/index.js [22m[32m90.06 KB[39m
|
|
23
|
+
[32mESM[39m ⚡️ Build success in 741ms
|
package/CHANGELOG.md
CHANGED
|
@@ -143,7 +143,7 @@ declare type ExtractParams = {
|
|
|
143
143
|
export { ExtractParams }
|
|
144
144
|
export { ExtractParams as ExtractParams_alias_1 }
|
|
145
145
|
|
|
146
|
-
declare const filterDescription = "JSON-formatted criteria to refine search results.\n- Uses provided filter if specified\n- Default: {} (no filtering)\n- Example: {\"category\": \"health\"}\n-
|
|
146
|
+
declare const filterDescription = "JSON-formatted criteria to refine search results.\n- Must be valid JSON format\n- Uses provided filter if specified\n- Default: \"{}\" (no filtering)\n- Example: '{\"category\": \"health\"}'\n- Based on query intent\n- Multiple filters can be combined";
|
|
147
147
|
export { filterDescription }
|
|
148
148
|
export { filterDescription as filterDescription_alias_1 }
|
|
149
149
|
export { filterDescription as filterDescription_alias_2 }
|
|
@@ -608,7 +608,7 @@ export declare class TokenTransformer extends TextTransformer {
|
|
|
608
608
|
}): TokenTransformer;
|
|
609
609
|
}
|
|
610
610
|
|
|
611
|
-
declare const topKDescription = "Controls how many matching documents to return.\n- Uses provided value if specified\n- Default: 10 results\n- Higher values provide more context\n- Lower values focus on best matches\n-
|
|
611
|
+
declare const topKDescription = "Controls how many matching documents to return.\n- Must be a valid number\n- Uses provided value if specified\n- Default: 10 results\n- Higher values provide more context\n- Lower values focus on best matches\n- Based on query requirements";
|
|
612
612
|
export { topKDescription }
|
|
613
613
|
export { topKDescription as topKDescription_alias_1 }
|
|
614
614
|
export { topKDescription as topKDescription_alias_2 }
|
|
@@ -143,7 +143,7 @@ declare type ExtractParams = {
|
|
|
143
143
|
export { ExtractParams }
|
|
144
144
|
export { ExtractParams as ExtractParams_alias_1 }
|
|
145
145
|
|
|
146
|
-
declare const filterDescription = "JSON-formatted criteria to refine search results.\n- Uses provided filter if specified\n- Default: {} (no filtering)\n- Example: {\"category\": \"health\"}\n-
|
|
146
|
+
declare const filterDescription = "JSON-formatted criteria to refine search results.\n- Must be valid JSON format\n- Uses provided filter if specified\n- Default: \"{}\" (no filtering)\n- Example: '{\"category\": \"health\"}'\n- Based on query intent\n- Multiple filters can be combined";
|
|
147
147
|
export { filterDescription }
|
|
148
148
|
export { filterDescription as filterDescription_alias_1 }
|
|
149
149
|
export { filterDescription as filterDescription_alias_2 }
|
|
@@ -608,7 +608,7 @@ export declare class TokenTransformer extends TextTransformer {
|
|
|
608
608
|
}): TokenTransformer;
|
|
609
609
|
}
|
|
610
610
|
|
|
611
|
-
declare const topKDescription = "Controls how many matching documents to return.\n- Uses provided value if specified\n- Default: 10 results\n- Higher values provide more context\n- Lower values focus on best matches\n-
|
|
611
|
+
declare const topKDescription = "Controls how many matching documents to return.\n- Must be a valid number\n- Uses provided value if specified\n- Default: 10 results\n- Higher values provide more context\n- Lower values focus on best matches\n- Based on query requirements";
|
|
612
612
|
export { topKDescription }
|
|
613
613
|
export { topKDescription as topKDescription_alias_1 }
|
|
614
614
|
export { topKDescription as topKDescription_alias_2 }
|
package/dist/index.cjs
CHANGED
|
@@ -1814,17 +1814,17 @@ var vectorQuerySearch = async ({
|
|
|
1814
1814
|
var defaultVectorQueryDescription = () => `Access the knowledge base to find information needed to answer user questions.`;
|
|
1815
1815
|
var defaultGraphRagDescription = () => `Access and analyze relationships between information in the knowledge base to answer complex questions about connections and patterns.`;
|
|
1816
1816
|
var topKDescription = `Controls how many matching documents to return.
|
|
1817
|
+
- Must be a valid number
|
|
1817
1818
|
- Uses provided value if specified
|
|
1818
1819
|
- Default: 10 results
|
|
1819
1820
|
- Higher values provide more context
|
|
1820
1821
|
- Lower values focus on best matches
|
|
1821
|
-
- Must be a valid number
|
|
1822
1822
|
- Based on query requirements`;
|
|
1823
1823
|
var filterDescription = `JSON-formatted criteria to refine search results.
|
|
1824
|
-
- Uses provided filter if specified
|
|
1825
|
-
- Default: {} (no filtering)
|
|
1826
|
-
- Example: {"category": "health"}
|
|
1827
1824
|
- Must be valid JSON format
|
|
1825
|
+
- Uses provided filter if specified
|
|
1826
|
+
- Default: "{}" (no filtering)
|
|
1827
|
+
- Example: '{"category": "health"}'
|
|
1828
1828
|
- Based on query intent
|
|
1829
1829
|
- Multiple filters can be combined`;
|
|
1830
1830
|
|
|
@@ -1922,13 +1922,17 @@ var createVectorQueryTool = ({
|
|
|
1922
1922
|
}) => {
|
|
1923
1923
|
const toolId = id || `VectorQuery ${vectorStoreName} ${indexName} Tool`;
|
|
1924
1924
|
const toolDescription = description || defaultVectorQueryDescription();
|
|
1925
|
+
const baseSchema = {
|
|
1926
|
+
queryText: zod.z.string().describe("The text query to search for in the vector database"),
|
|
1927
|
+
topK: zod.z.coerce.number().describe(topKDescription)
|
|
1928
|
+
};
|
|
1929
|
+
const inputSchema = enableFilter ? zod.z.object({
|
|
1930
|
+
...baseSchema,
|
|
1931
|
+
filter: zod.z.coerce.string().describe(filterDescription)
|
|
1932
|
+
}).strict() : zod.z.object(baseSchema).strict();
|
|
1925
1933
|
return tools.createTool({
|
|
1926
1934
|
id: toolId,
|
|
1927
|
-
inputSchema
|
|
1928
|
-
queryText: zod.z.string().describe("The text query to search for in the vector database"),
|
|
1929
|
-
topK: zod.z.number().describe(topKDescription),
|
|
1930
|
-
filter: zod.z.string().describe(filterDescription)
|
|
1931
|
-
}),
|
|
1935
|
+
inputSchema,
|
|
1932
1936
|
outputSchema: zod.z.object({
|
|
1933
1937
|
relevantContext: zod.z.any()
|
|
1934
1938
|
}),
|
|
@@ -1937,14 +1941,14 @@ var createVectorQueryTool = ({
|
|
|
1937
1941
|
const vectorStore = mastra?.vectors?.[vectorStoreName];
|
|
1938
1942
|
if (vectorStore) {
|
|
1939
1943
|
let queryFilter = {};
|
|
1940
|
-
if (enableFilter) {
|
|
1941
|
-
queryFilter =
|
|
1944
|
+
if (enableFilter && filter) {
|
|
1945
|
+
queryFilter = (() => {
|
|
1942
1946
|
try {
|
|
1943
1947
|
return JSON.parse(filter);
|
|
1944
1948
|
} catch {
|
|
1945
1949
|
return filter;
|
|
1946
1950
|
}
|
|
1947
|
-
})()
|
|
1951
|
+
})();
|
|
1948
1952
|
}
|
|
1949
1953
|
if (mastra.logger) {
|
|
1950
1954
|
mastra.logger.debug("Using this filter and topK:", { queryFilter, topK });
|
package/dist/index.js
CHANGED
|
@@ -1812,17 +1812,17 @@ var vectorQuerySearch = async ({
|
|
|
1812
1812
|
var defaultVectorQueryDescription = () => `Access the knowledge base to find information needed to answer user questions.`;
|
|
1813
1813
|
var defaultGraphRagDescription = () => `Access and analyze relationships between information in the knowledge base to answer complex questions about connections and patterns.`;
|
|
1814
1814
|
var topKDescription = `Controls how many matching documents to return.
|
|
1815
|
+
- Must be a valid number
|
|
1815
1816
|
- Uses provided value if specified
|
|
1816
1817
|
- Default: 10 results
|
|
1817
1818
|
- Higher values provide more context
|
|
1818
1819
|
- Lower values focus on best matches
|
|
1819
|
-
- Must be a valid number
|
|
1820
1820
|
- Based on query requirements`;
|
|
1821
1821
|
var filterDescription = `JSON-formatted criteria to refine search results.
|
|
1822
|
-
- Uses provided filter if specified
|
|
1823
|
-
- Default: {} (no filtering)
|
|
1824
|
-
- Example: {"category": "health"}
|
|
1825
1822
|
- Must be valid JSON format
|
|
1823
|
+
- Uses provided filter if specified
|
|
1824
|
+
- Default: "{}" (no filtering)
|
|
1825
|
+
- Example: '{"category": "health"}'
|
|
1826
1826
|
- Based on query intent
|
|
1827
1827
|
- Multiple filters can be combined`;
|
|
1828
1828
|
|
|
@@ -1920,13 +1920,17 @@ var createVectorQueryTool = ({
|
|
|
1920
1920
|
}) => {
|
|
1921
1921
|
const toolId = id || `VectorQuery ${vectorStoreName} ${indexName} Tool`;
|
|
1922
1922
|
const toolDescription = description || defaultVectorQueryDescription();
|
|
1923
|
+
const baseSchema = {
|
|
1924
|
+
queryText: z.string().describe("The text query to search for in the vector database"),
|
|
1925
|
+
topK: z.coerce.number().describe(topKDescription)
|
|
1926
|
+
};
|
|
1927
|
+
const inputSchema = enableFilter ? z.object({
|
|
1928
|
+
...baseSchema,
|
|
1929
|
+
filter: z.coerce.string().describe(filterDescription)
|
|
1930
|
+
}).strict() : z.object(baseSchema).strict();
|
|
1923
1931
|
return createTool({
|
|
1924
1932
|
id: toolId,
|
|
1925
|
-
inputSchema
|
|
1926
|
-
queryText: z.string().describe("The text query to search for in the vector database"),
|
|
1927
|
-
topK: z.number().describe(topKDescription),
|
|
1928
|
-
filter: z.string().describe(filterDescription)
|
|
1929
|
-
}),
|
|
1933
|
+
inputSchema,
|
|
1930
1934
|
outputSchema: z.object({
|
|
1931
1935
|
relevantContext: z.any()
|
|
1932
1936
|
}),
|
|
@@ -1935,14 +1939,14 @@ var createVectorQueryTool = ({
|
|
|
1935
1939
|
const vectorStore = mastra?.vectors?.[vectorStoreName];
|
|
1936
1940
|
if (vectorStore) {
|
|
1937
1941
|
let queryFilter = {};
|
|
1938
|
-
if (enableFilter) {
|
|
1939
|
-
queryFilter =
|
|
1942
|
+
if (enableFilter && filter) {
|
|
1943
|
+
queryFilter = (() => {
|
|
1940
1944
|
try {
|
|
1941
1945
|
return JSON.parse(filter);
|
|
1942
1946
|
} catch {
|
|
1943
1947
|
return filter;
|
|
1944
1948
|
}
|
|
1945
|
-
})()
|
|
1949
|
+
})();
|
|
1946
1950
|
}
|
|
1947
1951
|
if (mastra.logger) {
|
|
1948
1952
|
mastra.logger.debug("Using this filter and topK:", { queryFilter, topK });
|
package/package.json
CHANGED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { vectorQuerySearch } from '../utils';
|
|
3
|
+
import { createVectorQueryTool } from './vector-query';
|
|
4
|
+
|
|
5
|
+
// Mock dependencies
|
|
6
|
+
vi.mock('@mastra/core/tools', () => ({
|
|
7
|
+
createTool: vi.fn(({ inputSchema, execute }) => ({
|
|
8
|
+
inputSchema,
|
|
9
|
+
execute,
|
|
10
|
+
// Return a simplified version of the tool for testing
|
|
11
|
+
__inputSchema: inputSchema,
|
|
12
|
+
})),
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
vi.mock('../utils', () => ({
|
|
16
|
+
vectorQuerySearch: vi.fn().mockResolvedValue({ results: [] }),
|
|
17
|
+
defaultVectorQueryDescription: () => 'Default vector query description',
|
|
18
|
+
filterDescription: 'Filter description',
|
|
19
|
+
topKDescription: 'Top K description',
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
describe('createVectorQueryTool', () => {
|
|
23
|
+
const mockModel = { name: 'test-model' } as any;
|
|
24
|
+
const mockMastra = {
|
|
25
|
+
vectors: {
|
|
26
|
+
testStore: {
|
|
27
|
+
// Mock vector store methods
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
logger: {
|
|
31
|
+
debug: vi.fn(),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
vi.clearAllMocks();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
describe('input schema validation', () => {
|
|
40
|
+
it('should make filter invalid when enableFilter is false', () => {
|
|
41
|
+
// Create tool with enableFilter set to false
|
|
42
|
+
const tool = createVectorQueryTool({
|
|
43
|
+
vectorStoreName: 'testStore',
|
|
44
|
+
indexName: 'testIndex',
|
|
45
|
+
model: mockModel,
|
|
46
|
+
enableFilter: false,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Get the Zod schema
|
|
50
|
+
const schema = tool.__inputSchema;
|
|
51
|
+
|
|
52
|
+
// Test with no filter (should be valid)
|
|
53
|
+
const validInput = {
|
|
54
|
+
queryText: 'test query',
|
|
55
|
+
topK: 5,
|
|
56
|
+
};
|
|
57
|
+
expect(() => schema.parse(validInput)).not.toThrow();
|
|
58
|
+
|
|
59
|
+
// Test with filter (should throw - unexpected property)
|
|
60
|
+
const inputWithFilter = {
|
|
61
|
+
...validInput,
|
|
62
|
+
filter: '{"field": "value"}',
|
|
63
|
+
};
|
|
64
|
+
expect(() => schema.parse(inputWithFilter)).toThrow();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should handle filter permissively when enableFilter is true', () => {
|
|
68
|
+
const tool = createVectorQueryTool({
|
|
69
|
+
vectorStoreName: 'testStore',
|
|
70
|
+
indexName: 'testIndex',
|
|
71
|
+
model: mockModel,
|
|
72
|
+
enableFilter: true,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Get the Zod schema
|
|
76
|
+
const schema = tool.__inputSchema;
|
|
77
|
+
|
|
78
|
+
// Test various filter inputs that should all work
|
|
79
|
+
const testCases = [
|
|
80
|
+
// String inputs
|
|
81
|
+
{ filter: '{"field": "value"}' },
|
|
82
|
+
{ filter: '{}' },
|
|
83
|
+
{ filter: 'simple-string' },
|
|
84
|
+
// Object inputs (should be coerced to strings)
|
|
85
|
+
{ filter: { field: 'value' } },
|
|
86
|
+
{ filter: {} },
|
|
87
|
+
// Numbers (should be coerced)
|
|
88
|
+
{ filter: 123 },
|
|
89
|
+
// Empty/null values (should be coerced)
|
|
90
|
+
{ filter: '' },
|
|
91
|
+
{ filter: null },
|
|
92
|
+
{ filter: undefined },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
testCases.forEach(({ filter }) => {
|
|
96
|
+
expect(() =>
|
|
97
|
+
schema.parse({
|
|
98
|
+
queryText: 'test query',
|
|
99
|
+
topK: 5,
|
|
100
|
+
filter,
|
|
101
|
+
}),
|
|
102
|
+
).not.toThrow();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Verify that all parsed values are strings
|
|
106
|
+
testCases.forEach(({ filter }) => {
|
|
107
|
+
const result = schema.parse({
|
|
108
|
+
queryText: 'test query',
|
|
109
|
+
topK: 5,
|
|
110
|
+
filter,
|
|
111
|
+
});
|
|
112
|
+
expect(typeof result.filter).toBe('string');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should reject unexpected properties in both modes', () => {
|
|
117
|
+
// Test with enableFilter false
|
|
118
|
+
const toolWithoutFilter = createVectorQueryTool({
|
|
119
|
+
vectorStoreName: 'testStore',
|
|
120
|
+
indexName: 'testIndex',
|
|
121
|
+
model: mockModel,
|
|
122
|
+
enableFilter: false,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Should reject unexpected property
|
|
126
|
+
expect(() =>
|
|
127
|
+
toolWithoutFilter.__inputSchema.parse({
|
|
128
|
+
queryText: 'test query',
|
|
129
|
+
topK: 5,
|
|
130
|
+
unexpectedProp: 'value',
|
|
131
|
+
}),
|
|
132
|
+
).toThrow();
|
|
133
|
+
|
|
134
|
+
// Test with enableFilter true
|
|
135
|
+
const toolWithFilter = createVectorQueryTool({
|
|
136
|
+
vectorStoreName: 'testStore',
|
|
137
|
+
indexName: 'testIndex',
|
|
138
|
+
model: mockModel,
|
|
139
|
+
enableFilter: true,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// Should reject unexpected property even with valid filter
|
|
143
|
+
expect(() =>
|
|
144
|
+
toolWithFilter.__inputSchema.parse({
|
|
145
|
+
queryText: 'test query',
|
|
146
|
+
topK: 5,
|
|
147
|
+
filter: '{}',
|
|
148
|
+
unexpectedProp: 'value',
|
|
149
|
+
}),
|
|
150
|
+
).toThrow();
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('execute function', () => {
|
|
155
|
+
it('should not process filter when enableFilter is false', async () => {
|
|
156
|
+
// Create tool with enableFilter set to false
|
|
157
|
+
const tool = createVectorQueryTool({
|
|
158
|
+
vectorStoreName: 'testStore',
|
|
159
|
+
indexName: 'testIndex',
|
|
160
|
+
model: mockModel,
|
|
161
|
+
enableFilter: false,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Execute with no filter
|
|
165
|
+
await tool.execute({
|
|
166
|
+
context: {
|
|
167
|
+
queryText: 'test query',
|
|
168
|
+
topK: 5,
|
|
169
|
+
},
|
|
170
|
+
mastra: mockMastra,
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Check that vectorQuerySearch was called with undefined queryFilter
|
|
174
|
+
expect(vectorQuerySearch).toHaveBeenCalledWith(
|
|
175
|
+
expect.objectContaining({
|
|
176
|
+
queryFilter: undefined,
|
|
177
|
+
}),
|
|
178
|
+
);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should process filter when enableFilter is true and filter is provided', async () => {
|
|
182
|
+
// Create tool with enableFilter set to true
|
|
183
|
+
const tool = createVectorQueryTool({
|
|
184
|
+
vectorStoreName: 'testStore',
|
|
185
|
+
indexName: 'testIndex',
|
|
186
|
+
model: mockModel,
|
|
187
|
+
enableFilter: true,
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const filterJson = '{"field": "value"}';
|
|
191
|
+
|
|
192
|
+
// Execute with filter
|
|
193
|
+
await tool.execute({
|
|
194
|
+
context: {
|
|
195
|
+
queryText: 'test query',
|
|
196
|
+
topK: 5,
|
|
197
|
+
filter: filterJson,
|
|
198
|
+
},
|
|
199
|
+
mastra: mockMastra,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// Check that vectorQuerySearch was called with the parsed filter
|
|
203
|
+
expect(vectorQuerySearch).toHaveBeenCalledWith(
|
|
204
|
+
expect.objectContaining({
|
|
205
|
+
queryFilter: { field: 'value' },
|
|
206
|
+
}),
|
|
207
|
+
);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should handle string filters correctly', async () => {
|
|
211
|
+
// Create tool with enableFilter set to true
|
|
212
|
+
const tool = createVectorQueryTool({
|
|
213
|
+
vectorStoreName: 'testStore',
|
|
214
|
+
indexName: 'testIndex',
|
|
215
|
+
model: mockModel,
|
|
216
|
+
enableFilter: true,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const stringFilter = 'string-filter';
|
|
220
|
+
|
|
221
|
+
// Execute with string filter
|
|
222
|
+
await tool.execute({
|
|
223
|
+
context: {
|
|
224
|
+
queryText: 'test query',
|
|
225
|
+
topK: 5,
|
|
226
|
+
filter: stringFilter,
|
|
227
|
+
},
|
|
228
|
+
mastra: mockMastra,
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
// Check that vectorQuerySearch was called with the string filter
|
|
232
|
+
expect(vectorQuerySearch).toHaveBeenCalledWith(
|
|
233
|
+
expect.objectContaining({
|
|
234
|
+
queryFilter: 'string-filter',
|
|
235
|
+
}),
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
});
|
|
@@ -25,13 +25,22 @@ export const createVectorQueryTool = ({
|
|
|
25
25
|
}): ReturnType<typeof createTool> => {
|
|
26
26
|
const toolId = id || `VectorQuery ${vectorStoreName} ${indexName} Tool`;
|
|
27
27
|
const toolDescription = description || defaultVectorQueryDescription();
|
|
28
|
+
// Create base schema with required fields
|
|
29
|
+
const baseSchema = {
|
|
30
|
+
queryText: z.string().describe('The text query to search for in the vector database'),
|
|
31
|
+
topK: z.coerce.number().describe(topKDescription),
|
|
32
|
+
};
|
|
33
|
+
const inputSchema = enableFilter
|
|
34
|
+
? z
|
|
35
|
+
.object({
|
|
36
|
+
...baseSchema,
|
|
37
|
+
filter: z.coerce.string().describe(filterDescription),
|
|
38
|
+
})
|
|
39
|
+
.strict()
|
|
40
|
+
: z.object(baseSchema).strict();
|
|
28
41
|
return createTool({
|
|
29
42
|
id: toolId,
|
|
30
|
-
inputSchema
|
|
31
|
-
queryText: z.string().describe('The text query to search for in the vector database'),
|
|
32
|
-
topK: z.number().describe(topKDescription),
|
|
33
|
-
filter: z.string().describe(filterDescription),
|
|
34
|
-
}),
|
|
43
|
+
inputSchema,
|
|
35
44
|
outputSchema: z.object({
|
|
36
45
|
relevantContext: z.any(),
|
|
37
46
|
}),
|
|
@@ -42,16 +51,14 @@ export const createVectorQueryTool = ({
|
|
|
42
51
|
// Get relevant chunks from the vector database
|
|
43
52
|
if (vectorStore) {
|
|
44
53
|
let queryFilter = {};
|
|
45
|
-
if (enableFilter) {
|
|
46
|
-
queryFilter =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})()
|
|
54
|
-
: filter;
|
|
54
|
+
if (enableFilter && filter) {
|
|
55
|
+
queryFilter = (() => {
|
|
56
|
+
try {
|
|
57
|
+
return JSON.parse(filter);
|
|
58
|
+
} catch {
|
|
59
|
+
return filter;
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
55
62
|
}
|
|
56
63
|
if (mastra.logger) {
|
|
57
64
|
mastra.logger.debug('Using this filter and topK:', { queryFilter, topK });
|
|
@@ -5,17 +5,17 @@ export const defaultGraphRagDescription = () =>
|
|
|
5
5
|
`Access and analyze relationships between information in the knowledge base to answer complex questions about connections and patterns.`;
|
|
6
6
|
|
|
7
7
|
export const topKDescription = `Controls how many matching documents to return.
|
|
8
|
+
- Must be a valid number
|
|
8
9
|
- Uses provided value if specified
|
|
9
10
|
- Default: 10 results
|
|
10
11
|
- Higher values provide more context
|
|
11
12
|
- Lower values focus on best matches
|
|
12
|
-
- Must be a valid number
|
|
13
13
|
- Based on query requirements`;
|
|
14
14
|
|
|
15
15
|
export const filterDescription = `JSON-formatted criteria to refine search results.
|
|
16
|
-
- Uses provided filter if specified
|
|
17
|
-
- Default: {} (no filtering)
|
|
18
|
-
- Example: {"category": "health"}
|
|
19
16
|
- Must be valid JSON format
|
|
17
|
+
- Uses provided filter if specified
|
|
18
|
+
- Default: "{}" (no filtering)
|
|
19
|
+
- Example: '{"category": "health"}'
|
|
20
20
|
- Based on query intent
|
|
21
21
|
- Multiple filters can be combined`;
|