flowquery 1.0.25 → 1.0.26
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/.github/workflows/release.yml +1 -0
- package/.husky/pre-commit +3 -2
- package/dist/flowquery.min.js +1 -1
- package/dist/parsing/parser.d.ts.map +1 -1
- package/dist/parsing/parser.js +1 -0
- package/dist/parsing/parser.js.map +1 -1
- package/docs/flowquery.min.js +1 -1
- package/flowquery-py/pyproject.toml +1 -1
- package/flowquery-py/src/parsing/parser.py +1 -0
- package/flowquery-py/tests/compute/test_runner.py +26 -0
- package/flowquery-py/tests/parsing/test_parser.py +18 -0
- package/flowquery-vscode/flowQueryEngine/flowquery.min.js +1 -1
- package/jest.config.js +6 -9
- package/misc/apps/RAG/data/chats.json +302 -0
- package/misc/apps/RAG/data/emails.json +182 -0
- package/misc/apps/RAG/data/events.json +226 -0
- package/misc/apps/RAG/data/files.json +172 -0
- package/misc/apps/RAG/data/users.json +158 -0
- package/misc/apps/RAG/jest.config.js +21 -0
- package/misc/apps/RAG/package.json +9 -2
- package/misc/apps/RAG/src/App.tsx +5 -5
- package/misc/apps/RAG/src/components/ChatContainer.tsx +53 -124
- package/misc/apps/RAG/src/components/FlowQueryAgent.ts +151 -157
- package/misc/apps/RAG/src/components/index.ts +1 -1
- package/misc/apps/RAG/src/graph/index.ts +19 -0
- package/misc/apps/RAG/src/graph/initializeGraph.ts +254 -0
- package/misc/apps/RAG/src/index.tsx +25 -13
- package/misc/apps/RAG/src/prompts/FlowQuerySystemPrompt.ts +146 -231
- package/misc/apps/RAG/src/prompts/index.ts +4 -4
- package/misc/apps/RAG/src/tests/graph.test.ts +35 -0
- package/misc/apps/RAG/src/utils/FlowQueryExecutor.ts +20 -21
- package/misc/apps/RAG/src/utils/FlowQueryExtractor.ts +35 -30
- package/misc/apps/RAG/src/utils/Llm.ts +248 -0
- package/misc/apps/RAG/src/utils/index.ts +7 -4
- package/misc/apps/RAG/tsconfig.json +4 -3
- package/misc/apps/RAG/webpack.config.js +40 -40
- package/package.json +1 -1
- package/src/parsing/parser.ts +1 -0
- package/tests/compute/runner.test.ts +1 -1
- package/tests/parsing/parser.test.ts +16 -0
- package/misc/apps/RAG/src/plugins/README.md +0 -139
- package/misc/apps/RAG/src/plugins/index.ts +0 -72
- package/misc/apps/RAG/src/plugins/loaders/CatFacts.ts +0 -70
- package/misc/apps/RAG/src/plugins/loaders/FetchJson.ts +0 -65
- package/misc/apps/RAG/src/plugins/loaders/Form.ts +0 -594
- package/misc/apps/RAG/src/plugins/loaders/Llm.ts +0 -450
- package/misc/apps/RAG/src/plugins/loaders/MockData.ts +0 -101
- package/misc/apps/RAG/src/plugins/loaders/Table.ts +0 -274
- package/misc/apps/RAG/src/plugins/loaders/Weather.ts +0 -138
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* FlowQuery Agent
|
|
3
|
-
*
|
|
3
|
+
*
|
|
4
4
|
* Orchestrates the multi-step flow:
|
|
5
5
|
* 1. Send user query to LLM to generate a FlowQuery statement
|
|
6
6
|
* 2. Execute the FlowQuery statement
|
|
7
7
|
* 3. Send results back to LLM for interpretation
|
|
8
8
|
* 4. Return final response to user
|
|
9
9
|
*/
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { isAdaptiveCard } from
|
|
15
|
-
import { generateInterpretationPrompt } from '../prompts';
|
|
10
|
+
import { generateInterpretationPrompt } from "../prompts";
|
|
11
|
+
import { FlowQueryExecutionResult, FlowQueryExecutor } from "../utils/FlowQueryExecutor";
|
|
12
|
+
import { FlowQueryExtraction, extractFlowQuery } from "../utils/FlowQueryExtractor";
|
|
13
|
+
import { LlmOptions, llm, llmStream } from "../utils/Llm";
|
|
14
|
+
import { isAdaptiveCard } from "./AdaptiveCardRenderer";
|
|
16
15
|
|
|
17
16
|
/**
|
|
18
17
|
* Represents a step in the agent's execution process.
|
|
19
18
|
*/
|
|
20
19
|
export interface AgentStep {
|
|
21
|
-
type:
|
|
20
|
+
type: "query_generation" | "query_execution" | "interpretation" | "direct_response" | "retry";
|
|
22
21
|
content: string;
|
|
23
22
|
timestamp: Date;
|
|
24
23
|
metadata?: {
|
|
@@ -45,7 +44,7 @@ export interface AgentResult {
|
|
|
45
44
|
/**
|
|
46
45
|
* Callback for streaming agent responses.
|
|
47
46
|
*/
|
|
48
|
-
export type AgentStreamCallback = (chunk: string, step: AgentStep[
|
|
47
|
+
export type AgentStreamCallback = (chunk: string, step: AgentStep["type"]) => void;
|
|
49
48
|
|
|
50
49
|
/**
|
|
51
50
|
* Options for the FlowQuery agent.
|
|
@@ -56,7 +55,7 @@ export interface FlowQueryAgentOptions {
|
|
|
56
55
|
/** LLM options to use */
|
|
57
56
|
llmOptions?: LlmOptions;
|
|
58
57
|
/** Conversation history */
|
|
59
|
-
conversationHistory?: Array<{ role:
|
|
58
|
+
conversationHistory?: Array<{ role: "user" | "assistant"; content: string }>;
|
|
60
59
|
/** Callback for streaming responses */
|
|
61
60
|
onStream?: AgentStreamCallback;
|
|
62
61
|
/** Whether to show intermediate steps to the user */
|
|
@@ -67,7 +66,7 @@ export interface FlowQueryAgentOptions {
|
|
|
67
66
|
|
|
68
67
|
/**
|
|
69
68
|
* FlowQuery Agent class that orchestrates the multi-step query processing flow.
|
|
70
|
-
*
|
|
69
|
+
*
|
|
71
70
|
* @example
|
|
72
71
|
* ```typescript
|
|
73
72
|
* const agent = new FlowQueryAgent();
|
|
@@ -89,17 +88,20 @@ export class FlowQueryAgent {
|
|
|
89
88
|
|
|
90
89
|
/**
|
|
91
90
|
* Process a user query through the FlowQuery agent.
|
|
92
|
-
*
|
|
91
|
+
*
|
|
93
92
|
* @param userQuery - The natural language query from the user
|
|
94
93
|
* @param options - Agent configuration options
|
|
95
94
|
* @returns The agent result including final response and steps taken
|
|
96
95
|
*/
|
|
97
|
-
async processQuery(
|
|
98
|
-
userQuery: string,
|
|
99
|
-
options: FlowQueryAgentOptions
|
|
100
|
-
): Promise<AgentResult> {
|
|
96
|
+
async processQuery(userQuery: string, options: FlowQueryAgentOptions): Promise<AgentResult> {
|
|
101
97
|
const steps: AgentStep[] = [];
|
|
102
|
-
const {
|
|
98
|
+
const {
|
|
99
|
+
systemPrompt,
|
|
100
|
+
llmOptions = {},
|
|
101
|
+
conversationHistory = [],
|
|
102
|
+
onStream,
|
|
103
|
+
showIntermediateSteps = true,
|
|
104
|
+
} = options;
|
|
103
105
|
|
|
104
106
|
try {
|
|
105
107
|
// Step 1: Generate FlowQuery from natural language
|
|
@@ -109,10 +111,10 @@ export class FlowQueryAgent {
|
|
|
109
111
|
messages: conversationHistory,
|
|
110
112
|
});
|
|
111
113
|
|
|
112
|
-
const generationContent = generationResponse.choices[0]?.message?.content ||
|
|
113
|
-
|
|
114
|
+
const generationContent = generationResponse.choices[0]?.message?.content || "";
|
|
115
|
+
|
|
114
116
|
steps.push({
|
|
115
|
-
type:
|
|
117
|
+
type: "query_generation",
|
|
116
118
|
content: generationContent,
|
|
117
119
|
timestamp: new Date(),
|
|
118
120
|
});
|
|
@@ -123,12 +125,12 @@ export class FlowQueryAgent {
|
|
|
123
125
|
// If no query needed (direct response from LLM)
|
|
124
126
|
if (extraction.noQueryNeeded || !extraction.found) {
|
|
125
127
|
const directResponse = extraction.directResponse || generationContent;
|
|
126
|
-
|
|
128
|
+
|
|
127
129
|
steps.push({
|
|
128
|
-
type:
|
|
130
|
+
type: "direct_response",
|
|
129
131
|
content: directResponse,
|
|
130
132
|
timestamp: new Date(),
|
|
131
|
-
metadata: { extraction }
|
|
133
|
+
metadata: { extraction },
|
|
132
134
|
});
|
|
133
135
|
|
|
134
136
|
return {
|
|
@@ -140,16 +142,16 @@ export class FlowQueryAgent {
|
|
|
140
142
|
|
|
141
143
|
// Step 3: Execute the FlowQuery
|
|
142
144
|
let executionResult = await this.flowQueryExecutor.execute(extraction.query!);
|
|
143
|
-
|
|
145
|
+
|
|
144
146
|
steps.push({
|
|
145
|
-
type:
|
|
147
|
+
type: "query_execution",
|
|
146
148
|
content: this.flowQueryExecutor.formatResult(executionResult),
|
|
147
149
|
timestamp: new Date(),
|
|
148
150
|
metadata: {
|
|
149
151
|
query: extraction.query!,
|
|
150
152
|
executionResult,
|
|
151
|
-
extraction
|
|
152
|
-
}
|
|
153
|
+
extraction,
|
|
154
|
+
},
|
|
153
155
|
});
|
|
154
156
|
|
|
155
157
|
// If execution failed, attempt retry with error context
|
|
@@ -164,20 +166,20 @@ export class FlowQueryAgent {
|
|
|
164
166
|
retryCount++;
|
|
165
167
|
|
|
166
168
|
steps.push({
|
|
167
|
-
type:
|
|
169
|
+
type: "retry",
|
|
168
170
|
content: `Retry ${retryCount}: Error was "${currentError}"`,
|
|
169
171
|
timestamp: new Date(),
|
|
170
172
|
metadata: {
|
|
171
173
|
query: currentQuery,
|
|
172
|
-
executionResult: currentResult
|
|
173
|
-
}
|
|
174
|
+
executionResult: currentResult,
|
|
175
|
+
},
|
|
174
176
|
});
|
|
175
177
|
|
|
176
178
|
// Ask LLM to generate a corrected query
|
|
177
179
|
const correctedQuery = await this.generateCorrectedQuery(
|
|
178
180
|
userQuery,
|
|
179
181
|
currentQuery,
|
|
180
|
-
currentError ||
|
|
182
|
+
currentError || "Unknown error",
|
|
181
183
|
steps,
|
|
182
184
|
options
|
|
183
185
|
);
|
|
@@ -190,12 +192,12 @@ export class FlowQueryAgent {
|
|
|
190
192
|
currentResult,
|
|
191
193
|
options
|
|
192
194
|
);
|
|
193
|
-
|
|
195
|
+
|
|
194
196
|
return {
|
|
195
197
|
finalResponse: errorInterpretation,
|
|
196
198
|
steps,
|
|
197
199
|
success: false,
|
|
198
|
-
error: currentResult.error
|
|
200
|
+
error: currentResult.error,
|
|
199
201
|
};
|
|
200
202
|
}
|
|
201
203
|
|
|
@@ -205,13 +207,13 @@ export class FlowQueryAgent {
|
|
|
205
207
|
currentError = currentResult.error;
|
|
206
208
|
|
|
207
209
|
steps.push({
|
|
208
|
-
type:
|
|
210
|
+
type: "query_execution",
|
|
209
211
|
content: this.flowQueryExecutor.formatResult(currentResult),
|
|
210
212
|
timestamp: new Date(),
|
|
211
213
|
metadata: {
|
|
212
214
|
query: correctedQuery,
|
|
213
|
-
executionResult: currentResult
|
|
214
|
-
}
|
|
215
|
+
executionResult: currentResult,
|
|
216
|
+
},
|
|
215
217
|
});
|
|
216
218
|
}
|
|
217
219
|
|
|
@@ -223,12 +225,12 @@ export class FlowQueryAgent {
|
|
|
223
225
|
currentResult,
|
|
224
226
|
options
|
|
225
227
|
);
|
|
226
|
-
|
|
228
|
+
|
|
227
229
|
return {
|
|
228
230
|
finalResponse: errorInterpretation,
|
|
229
231
|
steps,
|
|
230
232
|
success: false,
|
|
231
|
-
error: currentResult.error
|
|
233
|
+
error: currentResult.error,
|
|
232
234
|
};
|
|
233
235
|
}
|
|
234
236
|
|
|
@@ -244,8 +246,8 @@ export class FlowQueryAgent {
|
|
|
244
246
|
executionResult
|
|
245
247
|
);
|
|
246
248
|
|
|
247
|
-
let finalResponse =
|
|
248
|
-
|
|
249
|
+
let finalResponse = "";
|
|
250
|
+
|
|
249
251
|
if (onStream) {
|
|
250
252
|
// Stream the interpretation response
|
|
251
253
|
for await (const chunk of llmStream(interpretationPrompt, {
|
|
@@ -253,10 +255,10 @@ export class FlowQueryAgent {
|
|
|
253
255
|
systemPrompt: generateInterpretationPrompt(),
|
|
254
256
|
messages: conversationHistory,
|
|
255
257
|
})) {
|
|
256
|
-
const deltaContent = chunk.choices?.[0]?.delta?.content ||
|
|
258
|
+
const deltaContent = chunk.choices?.[0]?.delta?.content || "";
|
|
257
259
|
if (deltaContent) {
|
|
258
260
|
finalResponse += deltaContent;
|
|
259
|
-
onStream(deltaContent,
|
|
261
|
+
onStream(deltaContent, "interpretation");
|
|
260
262
|
}
|
|
261
263
|
}
|
|
262
264
|
} else {
|
|
@@ -265,26 +267,26 @@ export class FlowQueryAgent {
|
|
|
265
267
|
systemPrompt: generateInterpretationPrompt(),
|
|
266
268
|
messages: conversationHistory,
|
|
267
269
|
});
|
|
268
|
-
finalResponse = interpretationResponse.choices[0]?.message?.content ||
|
|
270
|
+
finalResponse = interpretationResponse.choices[0]?.message?.content || "";
|
|
269
271
|
}
|
|
270
272
|
|
|
271
273
|
steps.push({
|
|
272
|
-
type:
|
|
274
|
+
type: "interpretation",
|
|
273
275
|
content: finalResponse,
|
|
274
276
|
timestamp: new Date(),
|
|
275
277
|
});
|
|
276
278
|
|
|
277
279
|
// Build the complete response with optional intermediate steps
|
|
278
|
-
let completeResponse =
|
|
279
|
-
|
|
280
|
+
let completeResponse = "";
|
|
281
|
+
|
|
280
282
|
if (showIntermediateSteps && extraction.explanation) {
|
|
281
|
-
completeResponse += extraction.explanation +
|
|
283
|
+
completeResponse += extraction.explanation + "\n\n";
|
|
282
284
|
}
|
|
283
|
-
|
|
285
|
+
|
|
284
286
|
if (showIntermediateSteps) {
|
|
285
287
|
completeResponse += `**Query executed:**\n\`\`\`flowquery\n${extraction.query}\n\`\`\`\n\n`;
|
|
286
288
|
}
|
|
287
|
-
|
|
289
|
+
|
|
288
290
|
completeResponse += finalResponse;
|
|
289
291
|
|
|
290
292
|
return {
|
|
@@ -294,7 +296,7 @@ export class FlowQueryAgent {
|
|
|
294
296
|
};
|
|
295
297
|
} catch (error) {
|
|
296
298
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
297
|
-
|
|
299
|
+
|
|
298
300
|
return {
|
|
299
301
|
finalResponse: `⚠️ An error occurred: ${errorMessage}`,
|
|
300
302
|
steps,
|
|
@@ -310,9 +312,25 @@ export class FlowQueryAgent {
|
|
|
310
312
|
async *processQueryStream(
|
|
311
313
|
userQuery: string,
|
|
312
314
|
options: FlowQueryAgentOptions
|
|
313
|
-
): AsyncGenerator<
|
|
315
|
+
): AsyncGenerator<
|
|
316
|
+
{
|
|
317
|
+
chunk: string;
|
|
318
|
+
step: AgentStep["type"];
|
|
319
|
+
done: boolean;
|
|
320
|
+
steps?: AgentStep[];
|
|
321
|
+
adaptiveCard?: Record<string, unknown>;
|
|
322
|
+
newMessage?: boolean;
|
|
323
|
+
},
|
|
324
|
+
void,
|
|
325
|
+
unknown
|
|
326
|
+
> {
|
|
314
327
|
const steps: AgentStep[] = [];
|
|
315
|
-
const {
|
|
328
|
+
const {
|
|
329
|
+
systemPrompt,
|
|
330
|
+
llmOptions = {},
|
|
331
|
+
conversationHistory = [],
|
|
332
|
+
showIntermediateSteps = true,
|
|
333
|
+
} = options;
|
|
316
334
|
|
|
317
335
|
try {
|
|
318
336
|
// Step 1: Generate FlowQuery from natural language (non-streaming for speed)
|
|
@@ -322,10 +340,10 @@ export class FlowQueryAgent {
|
|
|
322
340
|
messages: conversationHistory,
|
|
323
341
|
});
|
|
324
342
|
|
|
325
|
-
const generationContent = generationResponse.choices[0]?.message?.content ||
|
|
326
|
-
|
|
343
|
+
const generationContent = generationResponse.choices[0]?.message?.content || "";
|
|
344
|
+
|
|
327
345
|
steps.push({
|
|
328
|
-
type:
|
|
346
|
+
type: "query_generation",
|
|
329
347
|
content: generationContent,
|
|
330
348
|
timestamp: new Date(),
|
|
331
349
|
});
|
|
@@ -336,39 +354,39 @@ export class FlowQueryAgent {
|
|
|
336
354
|
// If no query needed
|
|
337
355
|
if (extraction.noQueryNeeded || !extraction.found) {
|
|
338
356
|
const directResponse = extraction.directResponse || generationContent;
|
|
339
|
-
|
|
357
|
+
|
|
340
358
|
steps.push({
|
|
341
|
-
type:
|
|
359
|
+
type: "direct_response",
|
|
342
360
|
content: directResponse,
|
|
343
361
|
timestamp: new Date(),
|
|
344
|
-
metadata: { extraction }
|
|
362
|
+
metadata: { extraction },
|
|
345
363
|
});
|
|
346
364
|
|
|
347
|
-
yield { chunk: directResponse, step:
|
|
365
|
+
yield { chunk: directResponse, step: "direct_response", done: true, steps };
|
|
348
366
|
return;
|
|
349
367
|
}
|
|
350
368
|
|
|
351
369
|
// Emit intermediate step: show the query being executed
|
|
352
370
|
if (showIntermediateSteps) {
|
|
353
|
-
yield {
|
|
354
|
-
chunk: `\`\`\`flowquery\n${extraction.query}\n\`\`\`\n\n`,
|
|
355
|
-
step:
|
|
356
|
-
done: false
|
|
371
|
+
yield {
|
|
372
|
+
chunk: `\`\`\`flowquery\n${extraction.query}\n\`\`\`\n\n`,
|
|
373
|
+
step: "query_generation",
|
|
374
|
+
done: false,
|
|
357
375
|
};
|
|
358
376
|
}
|
|
359
377
|
|
|
360
378
|
// Step 3: Execute the FlowQuery
|
|
361
379
|
let executionResult = await this.flowQueryExecutor.execute(extraction.query!);
|
|
362
|
-
|
|
380
|
+
|
|
363
381
|
steps.push({
|
|
364
|
-
type:
|
|
382
|
+
type: "query_execution",
|
|
365
383
|
content: this.flowQueryExecutor.formatResult(executionResult),
|
|
366
384
|
timestamp: new Date(),
|
|
367
385
|
metadata: {
|
|
368
386
|
query: extraction.query!,
|
|
369
387
|
executionResult,
|
|
370
|
-
extraction
|
|
371
|
-
}
|
|
388
|
+
extraction,
|
|
389
|
+
},
|
|
372
390
|
});
|
|
373
391
|
|
|
374
392
|
// Handle execution errors with retry logic
|
|
@@ -381,65 +399,65 @@ export class FlowQueryAgent {
|
|
|
381
399
|
|
|
382
400
|
while (!currentResult.success && retryCount < maxRetries) {
|
|
383
401
|
retryCount++;
|
|
384
|
-
|
|
402
|
+
|
|
385
403
|
// Show the failure in the current message before marking it complete
|
|
386
|
-
yield {
|
|
387
|
-
chunk: `\n⚠️ **Query execution failed:** ${currentError}\n`,
|
|
388
|
-
step:
|
|
389
|
-
done: false
|
|
404
|
+
yield {
|
|
405
|
+
chunk: `\n⚠️ **Query execution failed:** ${currentError}\n`,
|
|
406
|
+
step: "query_execution",
|
|
407
|
+
done: false,
|
|
390
408
|
};
|
|
391
|
-
|
|
409
|
+
|
|
392
410
|
// Complete the previous message before starting a new one
|
|
393
|
-
yield {
|
|
394
|
-
chunk:
|
|
395
|
-
step:
|
|
396
|
-
done: true
|
|
411
|
+
yield {
|
|
412
|
+
chunk: "",
|
|
413
|
+
step: "query_execution",
|
|
414
|
+
done: true,
|
|
397
415
|
};
|
|
398
|
-
|
|
416
|
+
|
|
399
417
|
// Notify user of retry attempt - start a new message for the retry
|
|
400
|
-
yield {
|
|
401
|
-
chunk: `🔄 Attempting to fix (retry ${retryCount}/${maxRetries})...\n\n`,
|
|
402
|
-
step:
|
|
418
|
+
yield {
|
|
419
|
+
chunk: `🔄 Attempting to fix (retry ${retryCount}/${maxRetries})...\n\n`,
|
|
420
|
+
step: "retry",
|
|
403
421
|
done: false,
|
|
404
|
-
newMessage: true
|
|
422
|
+
newMessage: true,
|
|
405
423
|
};
|
|
406
424
|
|
|
407
425
|
steps.push({
|
|
408
|
-
type:
|
|
426
|
+
type: "retry",
|
|
409
427
|
content: `Retry ${retryCount}: Error was "${currentError}"`,
|
|
410
428
|
timestamp: new Date(),
|
|
411
429
|
metadata: {
|
|
412
430
|
query: currentQuery,
|
|
413
|
-
executionResult: currentResult
|
|
414
|
-
}
|
|
431
|
+
executionResult: currentResult,
|
|
432
|
+
},
|
|
415
433
|
});
|
|
416
434
|
|
|
417
435
|
// Ask LLM to generate a corrected query
|
|
418
436
|
const correctedQuery = await this.generateCorrectedQuery(
|
|
419
437
|
userQuery,
|
|
420
438
|
currentQuery,
|
|
421
|
-
currentError ||
|
|
439
|
+
currentError || "Unknown error",
|
|
422
440
|
steps,
|
|
423
441
|
options
|
|
424
442
|
);
|
|
425
443
|
|
|
426
444
|
if (!correctedQuery) {
|
|
427
445
|
// LLM couldn't generate a correction
|
|
428
|
-
yield {
|
|
429
|
-
chunk: `Unable to generate a corrected query. Please try rephrasing your request.\n`,
|
|
430
|
-
step:
|
|
431
|
-
done: true,
|
|
432
|
-
steps
|
|
446
|
+
yield {
|
|
447
|
+
chunk: `Unable to generate a corrected query. Please try rephrasing your request.\n`,
|
|
448
|
+
step: "retry",
|
|
449
|
+
done: true,
|
|
450
|
+
steps,
|
|
433
451
|
};
|
|
434
452
|
return;
|
|
435
453
|
}
|
|
436
454
|
|
|
437
455
|
// Show the corrected query
|
|
438
456
|
if (showIntermediateSteps) {
|
|
439
|
-
yield {
|
|
440
|
-
chunk: `**Corrected query:**\n\`\`\`flowquery\n${correctedQuery}\n\`\`\`\n\n`,
|
|
441
|
-
step:
|
|
442
|
-
done: false
|
|
457
|
+
yield {
|
|
458
|
+
chunk: `**Corrected query:**\n\`\`\`flowquery\n${correctedQuery}\n\`\`\`\n\n`,
|
|
459
|
+
step: "retry",
|
|
460
|
+
done: false,
|
|
443
461
|
};
|
|
444
462
|
}
|
|
445
463
|
|
|
@@ -449,28 +467,28 @@ export class FlowQueryAgent {
|
|
|
449
467
|
currentError = currentResult.error;
|
|
450
468
|
|
|
451
469
|
steps.push({
|
|
452
|
-
type:
|
|
470
|
+
type: "query_execution",
|
|
453
471
|
content: this.flowQueryExecutor.formatResult(currentResult),
|
|
454
472
|
timestamp: new Date(),
|
|
455
473
|
metadata: {
|
|
456
474
|
query: correctedQuery,
|
|
457
|
-
executionResult: currentResult
|
|
458
|
-
}
|
|
475
|
+
executionResult: currentResult,
|
|
476
|
+
},
|
|
459
477
|
});
|
|
460
478
|
}
|
|
461
479
|
|
|
462
480
|
// If still failing after retries, give up
|
|
463
481
|
if (!currentResult.success) {
|
|
464
482
|
const errorMessage = `⚠️ Query execution failed after ${maxRetries} retries: ${currentError}\n\nLast query attempted:\n\`\`\`flowquery\n${currentQuery}\n\`\`\``;
|
|
465
|
-
yield { chunk: errorMessage, step:
|
|
483
|
+
yield { chunk: errorMessage, step: "query_execution", done: true, steps };
|
|
466
484
|
return;
|
|
467
485
|
}
|
|
468
486
|
|
|
469
487
|
// Mark the retry message as complete before proceeding to interpretation
|
|
470
|
-
yield {
|
|
471
|
-
chunk:
|
|
472
|
-
step:
|
|
473
|
-
done: true
|
|
488
|
+
yield {
|
|
489
|
+
chunk: "",
|
|
490
|
+
step: "retry",
|
|
491
|
+
done: true,
|
|
474
492
|
};
|
|
475
493
|
|
|
476
494
|
// Update executionResult for interpretation phase
|
|
@@ -489,34 +507,34 @@ export class FlowQueryAgent {
|
|
|
489
507
|
!!adaptiveCard
|
|
490
508
|
);
|
|
491
509
|
|
|
492
|
-
let interpretationContent =
|
|
510
|
+
let interpretationContent = "";
|
|
493
511
|
|
|
494
512
|
for await (const chunk of llmStream(interpretationPrompt, {
|
|
495
513
|
...llmOptions,
|
|
496
514
|
systemPrompt: generateInterpretationPrompt(),
|
|
497
515
|
messages: conversationHistory,
|
|
498
516
|
})) {
|
|
499
|
-
const deltaContent = chunk.choices?.[0]?.delta?.content ||
|
|
517
|
+
const deltaContent = chunk.choices?.[0]?.delta?.content || "";
|
|
500
518
|
if (deltaContent) {
|
|
501
519
|
interpretationContent += deltaContent;
|
|
502
|
-
yield { chunk: deltaContent, step:
|
|
520
|
+
yield { chunk: deltaContent, step: "interpretation", done: false };
|
|
503
521
|
}
|
|
504
522
|
}
|
|
505
523
|
|
|
506
524
|
steps.push({
|
|
507
|
-
type:
|
|
525
|
+
type: "interpretation",
|
|
508
526
|
content: interpretationContent,
|
|
509
527
|
timestamp: new Date(),
|
|
510
528
|
});
|
|
511
529
|
|
|
512
|
-
yield { chunk:
|
|
530
|
+
yield { chunk: "", step: "interpretation", done: true, steps, adaptiveCard };
|
|
513
531
|
} catch (error) {
|
|
514
532
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
515
|
-
yield {
|
|
516
|
-
chunk: `⚠️ An error occurred: ${errorMessage}`,
|
|
517
|
-
step:
|
|
518
|
-
done: true,
|
|
519
|
-
steps
|
|
533
|
+
yield {
|
|
534
|
+
chunk: `⚠️ An error occurred: ${errorMessage}`,
|
|
535
|
+
step: "interpretation",
|
|
536
|
+
done: true,
|
|
537
|
+
steps,
|
|
520
538
|
};
|
|
521
539
|
}
|
|
522
540
|
}
|
|
@@ -526,7 +544,9 @@ export class FlowQueryAgent {
|
|
|
526
544
|
* Checks if any result is an Adaptive Card (type: "AdaptiveCard") and returns it.
|
|
527
545
|
* Searches for Adaptive Cards at the top level or within any property of result objects.
|
|
528
546
|
*/
|
|
529
|
-
private extractAdaptiveCardFromResults(
|
|
547
|
+
private extractAdaptiveCardFromResults(
|
|
548
|
+
results: unknown[] | undefined
|
|
549
|
+
): Record<string, unknown> | undefined {
|
|
530
550
|
if (!results || !Array.isArray(results)) {
|
|
531
551
|
return undefined;
|
|
532
552
|
}
|
|
@@ -536,9 +556,9 @@ export class FlowQueryAgent {
|
|
|
536
556
|
if (isAdaptiveCard(result)) {
|
|
537
557
|
return result;
|
|
538
558
|
}
|
|
539
|
-
|
|
559
|
+
|
|
540
560
|
// Check if any property of the result object is an Adaptive Card
|
|
541
|
-
if (typeof result ===
|
|
561
|
+
if (typeof result === "object" && result !== null) {
|
|
542
562
|
const obj = result as Record<string, unknown>;
|
|
543
563
|
for (const value of Object.values(obj)) {
|
|
544
564
|
if (isAdaptiveCard(value)) {
|
|
@@ -562,7 +582,7 @@ export class FlowQueryAgent {
|
|
|
562
582
|
): string {
|
|
563
583
|
const resultsJson = JSON.stringify(executionResult.results, null, 2);
|
|
564
584
|
const resultCount = executionResult.results?.length || 0;
|
|
565
|
-
|
|
585
|
+
|
|
566
586
|
let prompt = `The user asked: "${originalQuery}"
|
|
567
587
|
|
|
568
588
|
This was translated to the following FlowQuery:
|
|
@@ -602,14 +622,14 @@ ${resultsJson}
|
|
|
602
622
|
|
|
603
623
|
// Build context from previous steps
|
|
604
624
|
const stepsContext = previousSteps
|
|
605
|
-
.filter(step => step.type ===
|
|
606
|
-
.map(step => {
|
|
607
|
-
if (step.type ===
|
|
625
|
+
.filter((step) => step.type === "query_execution" || step.type === "retry")
|
|
626
|
+
.map((step) => {
|
|
627
|
+
if (step.type === "retry") {
|
|
608
628
|
return `- Retry attempt: ${step.content}`;
|
|
609
629
|
}
|
|
610
|
-
return `- Query: \`${step.metadata?.query}\` → Error: ${step.metadata?.executionResult?.error ||
|
|
630
|
+
return `- Query: \`${step.metadata?.query}\` → Error: ${step.metadata?.executionResult?.error || "unknown"}`;
|
|
611
631
|
})
|
|
612
|
-
.join(
|
|
632
|
+
.join("\n");
|
|
613
633
|
|
|
614
634
|
const retryPrompt = `The user asked: "${originalQuery}"
|
|
615
635
|
|
|
@@ -621,7 +641,7 @@ ${failedQuery}
|
|
|
621
641
|
However, the query failed with this error:
|
|
622
642
|
${errorMessage}
|
|
623
643
|
|
|
624
|
-
${stepsContext ? `Previous attempts:\n${stepsContext}\n\n` :
|
|
644
|
+
${stepsContext ? `Previous attempts:\n${stepsContext}\n\n` : ""}Please analyze the error and generate a CORRECTED FlowQuery that will work. Pay close attention to:
|
|
625
645
|
- Syntax errors in the query
|
|
626
646
|
- Incorrect loader names or function names
|
|
627
647
|
- Missing or incorrect parameters
|
|
@@ -636,7 +656,7 @@ Generate the corrected query using the same format as before (with explanation i
|
|
|
636
656
|
messages: conversationHistory,
|
|
637
657
|
});
|
|
638
658
|
|
|
639
|
-
const responseContent = response.choices[0]?.message?.content ||
|
|
659
|
+
const responseContent = response.choices[0]?.message?.content || "";
|
|
640
660
|
const extraction = extractFlowQuery(responseContent);
|
|
641
661
|
|
|
642
662
|
if (extraction.found && extraction.query) {
|
|
@@ -645,7 +665,7 @@ Generate the corrected query using the same format as before (with explanation i
|
|
|
645
665
|
|
|
646
666
|
return null;
|
|
647
667
|
} catch (error) {
|
|
648
|
-
console.error(
|
|
668
|
+
console.error("Error generating corrected query:", error);
|
|
649
669
|
return null;
|
|
650
670
|
}
|
|
651
671
|
}
|
|
@@ -673,42 +693,16 @@ Please explain what went wrong in user-friendly terms and, if possible, suggest
|
|
|
673
693
|
|
|
674
694
|
const response = await llm(errorPrompt, {
|
|
675
695
|
...options.llmOptions,
|
|
676
|
-
systemPrompt:
|
|
696
|
+
systemPrompt:
|
|
697
|
+
"You are a helpful assistant explaining query errors. Be concise and helpful.",
|
|
677
698
|
messages: options.conversationHistory,
|
|
678
699
|
});
|
|
679
700
|
|
|
680
|
-
return
|
|
681
|
-
|
|
701
|
+
return (
|
|
702
|
+
response.choices[0]?.message?.content ||
|
|
703
|
+
`The query failed with error: ${executionResult.error}`
|
|
704
|
+
);
|
|
682
705
|
}
|
|
683
706
|
}
|
|
684
707
|
|
|
685
|
-
// Create a default instance for convenience
|
|
686
|
-
const defaultAgent = new FlowQueryAgent();
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* Process a user query through the FlowQuery agent.
|
|
690
|
-
*
|
|
691
|
-
* @param userQuery - The natural language query from the user
|
|
692
|
-
* @param options - Agent configuration options
|
|
693
|
-
* @returns The agent result including final response and steps taken
|
|
694
|
-
* @deprecated Use `new FlowQueryAgent().processQuery()` instead
|
|
695
|
-
*/
|
|
696
|
-
export async function processQuery(
|
|
697
|
-
userQuery: string,
|
|
698
|
-
options: FlowQueryAgentOptions
|
|
699
|
-
): Promise<AgentResult> {
|
|
700
|
-
return defaultAgent.processQuery(userQuery, options);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
/**
|
|
704
|
-
* Process a query with streaming support for the final interpretation.
|
|
705
|
-
* @deprecated Use `new FlowQueryAgent().processQueryStream()` instead
|
|
706
|
-
*/
|
|
707
|
-
export function processQueryStream(
|
|
708
|
-
userQuery: string,
|
|
709
|
-
options: FlowQueryAgentOptions
|
|
710
|
-
): AsyncGenerator<{ chunk: string; step: AgentStep['type']; done: boolean; steps?: AgentStep[]; adaptiveCard?: Record<string, unknown>; newMessage?: boolean }, void, unknown> {
|
|
711
|
-
return defaultAgent.processQueryStream(userQuery, options);
|
|
712
|
-
}
|
|
713
|
-
|
|
714
708
|
export default FlowQueryAgent;
|