@memberjunction/query-gen 0.0.1 → 2.126.1

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.
Files changed (138) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +34 -0
  3. package/COORDINATOR.md +768 -0
  4. package/IMPLEMENTATION_PLAN.md +1753 -0
  5. package/LLM_ENTITY_GROUPING_PLAN.md +977 -0
  6. package/README.md +675 -29
  7. package/dist/cli/commands/export.d.ts +15 -0
  8. package/dist/cli/commands/export.d.ts.map +1 -0
  9. package/dist/cli/commands/export.js +178 -0
  10. package/dist/cli/commands/export.js.map +1 -0
  11. package/dist/cli/commands/generate.d.ts +19 -0
  12. package/dist/cli/commands/generate.d.ts.map +1 -0
  13. package/dist/cli/commands/generate.js +282 -0
  14. package/dist/cli/commands/generate.js.map +1 -0
  15. package/dist/cli/commands/validate.d.ts +17 -0
  16. package/dist/cli/commands/validate.d.ts.map +1 -0
  17. package/dist/cli/commands/validate.js +193 -0
  18. package/dist/cli/commands/validate.js.map +1 -0
  19. package/dist/cli/config.d.ts +51 -0
  20. package/dist/cli/config.d.ts.map +1 -0
  21. package/dist/cli/config.js +142 -0
  22. package/dist/cli/config.js.map +1 -0
  23. package/dist/cli/index.d.ts +13 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +57 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/core/EntityGrouper.d.ts +74 -0
  28. package/dist/core/EntityGrouper.d.ts.map +1 -0
  29. package/dist/core/EntityGrouper.js +246 -0
  30. package/dist/core/EntityGrouper.js.map +1 -0
  31. package/dist/core/MetadataExporter.d.ts +59 -0
  32. package/dist/core/MetadataExporter.d.ts.map +1 -0
  33. package/dist/core/MetadataExporter.js +151 -0
  34. package/dist/core/MetadataExporter.js.map +1 -0
  35. package/dist/core/QueryDatabaseWriter.d.ts +50 -0
  36. package/dist/core/QueryDatabaseWriter.d.ts.map +1 -0
  37. package/dist/core/QueryDatabaseWriter.js +152 -0
  38. package/dist/core/QueryDatabaseWriter.js.map +1 -0
  39. package/dist/core/QueryFixer.d.ts +48 -0
  40. package/dist/core/QueryFixer.d.ts.map +1 -0
  41. package/dist/core/QueryFixer.js +115 -0
  42. package/dist/core/QueryFixer.js.map +1 -0
  43. package/dist/core/QueryRefiner.d.ts +94 -0
  44. package/dist/core/QueryRefiner.d.ts.map +1 -0
  45. package/dist/core/QueryRefiner.js +267 -0
  46. package/dist/core/QueryRefiner.js.map +1 -0
  47. package/dist/core/QueryTester.d.ts +70 -0
  48. package/dist/core/QueryTester.d.ts.map +1 -0
  49. package/dist/core/QueryTester.js +243 -0
  50. package/dist/core/QueryTester.js.map +1 -0
  51. package/dist/core/QueryWriter.d.ts +57 -0
  52. package/dist/core/QueryWriter.d.ts.map +1 -0
  53. package/dist/core/QueryWriter.js +184 -0
  54. package/dist/core/QueryWriter.js.map +1 -0
  55. package/dist/core/QuestionGenerator.d.ts +58 -0
  56. package/dist/core/QuestionGenerator.d.ts.map +1 -0
  57. package/dist/core/QuestionGenerator.js +145 -0
  58. package/dist/core/QuestionGenerator.js.map +1 -0
  59. package/dist/data/schema.d.ts +230 -0
  60. package/dist/data/schema.d.ts.map +1 -0
  61. package/dist/data/schema.js +6 -0
  62. package/dist/data/schema.js.map +1 -0
  63. package/dist/index.d.ts +28 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +77 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/prompts/PromptNames.d.ts +32 -0
  68. package/dist/prompts/PromptNames.d.ts.map +1 -0
  69. package/dist/prompts/PromptNames.js +35 -0
  70. package/dist/prompts/PromptNames.js.map +1 -0
  71. package/dist/utils/category-builder.d.ts +28 -0
  72. package/dist/utils/category-builder.d.ts.map +1 -0
  73. package/dist/utils/category-builder.js +90 -0
  74. package/dist/utils/category-builder.js.map +1 -0
  75. package/dist/utils/entity-helpers.d.ts +49 -0
  76. package/dist/utils/entity-helpers.d.ts.map +1 -0
  77. package/dist/utils/entity-helpers.js +189 -0
  78. package/dist/utils/entity-helpers.js.map +1 -0
  79. package/dist/utils/error-handlers.d.ts +19 -0
  80. package/dist/utils/error-handlers.d.ts.map +1 -0
  81. package/dist/utils/error-handlers.js +41 -0
  82. package/dist/utils/error-handlers.js.map +1 -0
  83. package/dist/utils/graph-helpers.d.ts +51 -0
  84. package/dist/utils/graph-helpers.d.ts.map +1 -0
  85. package/dist/utils/graph-helpers.js +82 -0
  86. package/dist/utils/graph-helpers.js.map +1 -0
  87. package/dist/utils/prompt-helpers.d.ts +25 -0
  88. package/dist/utils/prompt-helpers.d.ts.map +1 -0
  89. package/dist/utils/prompt-helpers.js +66 -0
  90. package/dist/utils/prompt-helpers.js.map +1 -0
  91. package/dist/utils/query-helpers.d.ts +23 -0
  92. package/dist/utils/query-helpers.d.ts.map +1 -0
  93. package/dist/utils/query-helpers.js +34 -0
  94. package/dist/utils/query-helpers.js.map +1 -0
  95. package/dist/utils/user-helpers.d.ts +15 -0
  96. package/dist/utils/user-helpers.d.ts.map +1 -0
  97. package/dist/utils/user-helpers.js +32 -0
  98. package/dist/utils/user-helpers.js.map +1 -0
  99. package/dist/vectors/EmbeddingService.d.ts +58 -0
  100. package/dist/vectors/EmbeddingService.d.ts.map +1 -0
  101. package/dist/vectors/EmbeddingService.js +90 -0
  102. package/dist/vectors/EmbeddingService.js.map +1 -0
  103. package/dist/vectors/SimilaritySearch.d.ts +51 -0
  104. package/dist/vectors/SimilaritySearch.d.ts.map +1 -0
  105. package/dist/vectors/SimilaritySearch.js +85 -0
  106. package/dist/vectors/SimilaritySearch.js.map +1 -0
  107. package/docs/API.md +1040 -0
  108. package/docs/ARCHITECTURE.md +1120 -0
  109. package/examples/advanced-usage.ts +401 -0
  110. package/examples/basic-usage.ts +285 -0
  111. package/package.json +48 -6
  112. package/src/cli/commands/export.ts +173 -0
  113. package/src/cli/commands/generate.ts +330 -0
  114. package/src/cli/commands/validate.ts +185 -0
  115. package/src/cli/config.ts +203 -0
  116. package/src/cli/index.ts +63 -0
  117. package/src/core/EntityGrouper.ts +318 -0
  118. package/src/core/MetadataExporter.ts +148 -0
  119. package/src/core/QueryDatabaseWriter.ts +187 -0
  120. package/src/core/QueryFixer.ts +153 -0
  121. package/src/core/QueryRefiner.ts +382 -0
  122. package/src/core/QueryTester.ts +264 -0
  123. package/src/core/QueryWriter.ts +239 -0
  124. package/src/core/QuestionGenerator.ts +199 -0
  125. package/src/data/golden-queries.json +1371 -0
  126. package/src/data/schema.ts +252 -0
  127. package/src/index.ts +49 -0
  128. package/src/prompts/PromptNames.ts +36 -0
  129. package/src/utils/category-builder.ts +97 -0
  130. package/src/utils/entity-helpers.ts +203 -0
  131. package/src/utils/error-handlers.ts +41 -0
  132. package/src/utils/graph-helpers.ts +99 -0
  133. package/src/utils/prompt-helpers.ts +79 -0
  134. package/src/utils/query-helpers.ts +32 -0
  135. package/src/utils/user-helpers.ts +39 -0
  136. package/src/vectors/EmbeddingService.ts +109 -0
  137. package/src/vectors/SimilaritySearch.ts +108 -0
  138. package/tsconfig.json +39 -0
@@ -0,0 +1,401 @@
1
+ /**
2
+ * Advanced Usage Example for QueryGen
3
+ *
4
+ * This example demonstrates advanced features:
5
+ * 1. Vector similarity search with golden queries
6
+ * 2. Query refinement with evaluation
7
+ * 3. Batch processing multiple entities
8
+ * 4. Custom configuration
9
+ * 5. Database export
10
+ */
11
+
12
+ import {
13
+ EntityGrouper,
14
+ QuestionGenerator,
15
+ QueryWriter,
16
+ QueryTester,
17
+ QueryRefiner,
18
+ MetadataExporter,
19
+ QueryDatabaseWriter,
20
+ EmbeddingService,
21
+ SimilaritySearch,
22
+ formatEntityMetadataForPrompt,
23
+ extractErrorMessage,
24
+ ValidatedQuery,
25
+ GoldenQuery,
26
+ QueryGenConfig
27
+ } from '@memberjunction/query-gen';
28
+ import { Metadata, UserInfo, DatabaseProviderBase } from '@memberjunction/core';
29
+
30
+ /**
31
+ * Example golden queries for few-shot learning
32
+ * In production, these would be loaded from database or metadata files
33
+ */
34
+ const GOLDEN_QUERIES: GoldenQuery[] = [
35
+ {
36
+ name: 'Top Customers By Revenue',
37
+ userQuestion: 'What are the top 10 customers by total revenue?',
38
+ description: 'Identify highest-value customers based on order revenue',
39
+ technicalDescription: 'Sum order totals per customer, sort descending, limit 10',
40
+ sql: `
41
+ SELECT TOP 10
42
+ c.Name as CustomerName,
43
+ c.Email as CustomerEmail,
44
+ COUNT(o.ID) as OrderCount,
45
+ COALESCE(SUM(o.Total), 0) as TotalRevenue
46
+ FROM [dbo].[vwCustomers] c
47
+ LEFT JOIN [sales].[vwOrders] o ON o.CustomerID = c.ID
48
+ GROUP BY c.Name, c.Email
49
+ ORDER BY TotalRevenue DESC
50
+ `,
51
+ parameters: [],
52
+ selectClause: [
53
+ { name: 'CustomerName', description: 'Customer name', type: 'string', optional: false },
54
+ { name: 'CustomerEmail', description: 'Customer email', type: 'string', optional: false },
55
+ { name: 'OrderCount', description: 'Number of orders', type: 'number', optional: false },
56
+ { name: 'TotalRevenue', description: 'Sum of order totals', type: 'number', optional: false }
57
+ ]
58
+ },
59
+ {
60
+ name: 'Recent Orders By Status',
61
+ userQuestion: 'Show me recent orders grouped by status',
62
+ description: 'Count orders in each status for the last 30 days',
63
+ technicalDescription: 'Count orders grouped by status, filtered by date range',
64
+ sql: `
65
+ SELECT
66
+ o.Status,
67
+ COUNT(o.ID) as OrderCount,
68
+ COALESCE(SUM(o.Total), 0) as TotalRevenue
69
+ FROM [sales].[vwOrders] o
70
+ WHERE o.OrderDate >= DATEADD(DAY, -30, GETDATE())
71
+ GROUP BY o.Status
72
+ ORDER BY OrderCount DESC
73
+ `,
74
+ parameters: [],
75
+ selectClause: [
76
+ { name: 'Status', description: 'Order status', type: 'string', optional: false },
77
+ { name: 'OrderCount', description: 'Number of orders', type: 'number', optional: false },
78
+ { name: 'TotalRevenue', description: 'Total revenue', type: 'number', optional: false }
79
+ ]
80
+ }
81
+ ];
82
+
83
+ /**
84
+ * Custom configuration for this example
85
+ */
86
+ const CUSTOM_CONFIG: Partial<QueryGenConfig> = {
87
+ maxEntitiesPerGroup: 2,
88
+ minEntitiesPerGroup: 1,
89
+ questionsPerGroup: 2,
90
+ maxRefinementIterations: 3,
91
+ maxFixingIterations: 5,
92
+ topSimilarQueries: 3, // Use top 3 golden queries
93
+ embeddingModel: 'text-embedding-3-small',
94
+ verbose: true
95
+ };
96
+
97
+ /**
98
+ * Generate queries for a single entity with full workflow
99
+ */
100
+ async function generateQueriesForEntity(
101
+ entityName: string,
102
+ contextUser: UserInfo,
103
+ goldenQueries: GoldenQuery[]
104
+ ): Promise<ValidatedQuery[]> {
105
+ console.log(`\n${'='.repeat(80)}`);
106
+ console.log(`Processing Entity: ${entityName}`);
107
+ console.log('='.repeat(80));
108
+
109
+ const validatedQueries: ValidatedQuery[] = [];
110
+
111
+ // Load entity
112
+ const md = new Metadata();
113
+ const entity = md.Entities.find(e => e.Name === entityName);
114
+ if (!entity) {
115
+ console.error(`✗ Entity '${entityName}' not found`);
116
+ return [];
117
+ }
118
+
119
+ console.log(`✓ Entity loaded: ${entity.Name}`);
120
+
121
+ // Create entity groups
122
+ const grouper = new EntityGrouper();
123
+ const groups = await grouper.generateEntityGroups(
124
+ [entity],
125
+ CUSTOM_CONFIG.minEntitiesPerGroup!,
126
+ CUSTOM_CONFIG.maxEntitiesPerGroup!
127
+ );
128
+
129
+ console.log(`✓ Created ${groups.length} entity group(s)`);
130
+
131
+ // Process first group for this example
132
+ const entityGroup = groups[0];
133
+
134
+ // Generate business questions
135
+ const questionGen = new QuestionGenerator(contextUser);
136
+ const questions = await questionGen.generateQuestions(entityGroup);
137
+
138
+ console.log(`✓ Generated ${questions.length} business question(s)`);
139
+
140
+ // Initialize services
141
+ const embeddingService = new EmbeddingService(CUSTOM_CONFIG.embeddingModel!);
142
+ const similaritySearch = new SimilaritySearch();
143
+ const dataProvider = Metadata.Provider.DatabaseConnection as DatabaseProviderBase;
144
+
145
+ // Embed golden queries once
146
+ console.log('⟳ Embedding golden queries...');
147
+ const embeddedGolden = await embeddingService.embedGoldenQueries(goldenQueries);
148
+ console.log(`✓ Embedded ${embeddedGolden.length} golden queries`);
149
+
150
+ // Process each question
151
+ for (let i = 0; i < questions.length; i++) {
152
+ const question = questions[i];
153
+ console.log(`\n${'─'.repeat(80)}`);
154
+ console.log(`Question ${i + 1}/${questions.length}: ${question.userQuestion}`);
155
+ console.log('─'.repeat(80));
156
+
157
+ try {
158
+ // 1. Embed question for similarity search
159
+ console.log('⟳ Embedding question...');
160
+ const questionEmbeddings = await embeddingService.embedQuery({
161
+ name: '',
162
+ userQuestion: question.userQuestion,
163
+ description: question.description,
164
+ technicalDescription: question.technicalDescription
165
+ });
166
+
167
+ // 2. Find similar golden queries
168
+ console.log('⟳ Finding similar golden queries...');
169
+ const fewShotResults = await similaritySearch.findSimilarQueries(
170
+ questionEmbeddings,
171
+ embeddedGolden,
172
+ CUSTOM_CONFIG.topSimilarQueries!
173
+ );
174
+
175
+ console.log(`✓ Found ${fewShotResults.length} similar queries:`);
176
+ fewShotResults.forEach((result, idx) => {
177
+ console.log(` ${idx + 1}. ${result.query.name} (similarity: ${result.similarity.toFixed(3)})`);
178
+ });
179
+
180
+ const fewShotExamples = fewShotResults.map(r => r.query);
181
+
182
+ // 3. Generate SQL query
183
+ console.log('⟳ Generating SQL query...');
184
+ const entityMetadata = entityGroup.entities.map(e =>
185
+ formatEntityMetadataForPrompt(e, entityGroup.entities)
186
+ );
187
+
188
+ const queryWriter = new QueryWriter(contextUser);
189
+ const generatedQuery = await queryWriter.generateQuery(
190
+ question,
191
+ entityMetadata,
192
+ fewShotExamples
193
+ );
194
+
195
+ console.log('✓ Query generated');
196
+ console.log(` Parameters: ${generatedQuery.parameters.length}`);
197
+ console.log(` Output fields: ${generatedQuery.selectClause.length}`);
198
+
199
+ // 4. Test and fix query
200
+ console.log('⟳ Testing query...');
201
+ const tester = new QueryTester(
202
+ dataProvider,
203
+ entityMetadata,
204
+ question,
205
+ contextUser
206
+ );
207
+
208
+ const testResult = await tester.testQuery(
209
+ generatedQuery,
210
+ CUSTOM_CONFIG.maxFixingIterations!
211
+ );
212
+
213
+ if (!testResult.success) {
214
+ console.error(`✗ Query test failed: ${testResult.error}`);
215
+ continue;
216
+ }
217
+
218
+ console.log(`✓ Query test passed (${testResult.attempts} attempt(s))`);
219
+ console.log(` Rows returned: ${testResult.rowCount}`);
220
+
221
+ // 5. Refine query with evaluation
222
+ console.log('⟳ Refining query...');
223
+ const refiner = new QueryRefiner(tester, contextUser);
224
+
225
+ const refined = await refiner.refineQuery(
226
+ generatedQuery,
227
+ question,
228
+ entityMetadata,
229
+ CUSTOM_CONFIG.maxRefinementIterations!
230
+ );
231
+
232
+ console.log(`✓ Query refined (${refined.refinementCount} iteration(s))`);
233
+ console.log(' Evaluation:');
234
+ console.log(` Answers question: ${refined.evaluation.answersQuestion}`);
235
+ console.log(` Confidence: ${refined.evaluation.confidence}`);
236
+ console.log(` Needs refinement: ${refined.evaluation.needsRefinement}`);
237
+
238
+ if (refined.evaluation.suggestions.length > 0) {
239
+ console.log(' Suggestions:');
240
+ refined.evaluation.suggestions.forEach(s => {
241
+ console.log(` - ${s}`);
242
+ });
243
+ }
244
+
245
+ // Add to validated queries
246
+ validatedQueries.push({
247
+ businessQuestion: question,
248
+ query: refined.query,
249
+ testResult: refined.testResult,
250
+ evaluation: refined.evaluation,
251
+ entityGroup
252
+ });
253
+
254
+ console.log(`✓ Query validated and added to export list`);
255
+
256
+ } catch (error: unknown) {
257
+ console.error(`✗ Error processing question: ${extractErrorMessage(error, 'Question Processing')}`);
258
+ }
259
+ }
260
+
261
+ return validatedQueries;
262
+ }
263
+
264
+ /**
265
+ * Main function demonstrating advanced QueryGen usage
266
+ */
267
+ async function main() {
268
+ console.log('QueryGen Advanced Usage Example\n');
269
+
270
+ // ========================================
271
+ // Setup
272
+ // ========================================
273
+
274
+ const contextUser = new UserInfo();
275
+ contextUser.Email = 'system@example.com';
276
+ contextUser.Name = 'System User';
277
+ contextUser.FirstName = 'System';
278
+ contextUser.LastName = 'User';
279
+
280
+ if (!Metadata.Provider) {
281
+ console.error('ERROR: Metadata provider not configured');
282
+ process.exit(1);
283
+ }
284
+
285
+ // ========================================
286
+ // Batch Processing Multiple Entities
287
+ // ========================================
288
+
289
+ const targetEntities = ['Customers', 'Orders']; // Customize as needed
290
+ const allValidatedQueries: ValidatedQuery[] = [];
291
+
292
+ console.log('Configuration:');
293
+ console.log(JSON.stringify(CUSTOM_CONFIG, null, 2));
294
+
295
+ for (const entityName of targetEntities) {
296
+ try {
297
+ const queries = await generateQueriesForEntity(
298
+ entityName,
299
+ contextUser,
300
+ GOLDEN_QUERIES
301
+ );
302
+
303
+ allValidatedQueries.push(...queries);
304
+ console.log(`\n✓ ${entityName}: Generated ${queries.length} validated query/queries`);
305
+
306
+ } catch (error: unknown) {
307
+ console.error(`✗ ${entityName}: ${extractErrorMessage(error, 'Entity Processing')}`);
308
+ }
309
+ }
310
+
311
+ // ========================================
312
+ // Export Results
313
+ // ========================================
314
+
315
+ console.log(`\n${'='.repeat(80)}`);
316
+ console.log('Exporting Results');
317
+ console.log('='.repeat(80));
318
+
319
+ if (allValidatedQueries.length === 0) {
320
+ console.log('⚠ No queries to export');
321
+ return;
322
+ }
323
+
324
+ // 1. Export to metadata files
325
+ console.log('\n1. Exporting to metadata files...');
326
+ const exporter = new MetadataExporter();
327
+
328
+ try {
329
+ const exportResult = await exporter.exportQueries(
330
+ allValidatedQueries,
331
+ './examples/output'
332
+ );
333
+
334
+ console.log(`✓ Metadata export complete`);
335
+ console.log(` Output path: ${exportResult.outputPath}`);
336
+ console.log(` Query count: ${exportResult.queryCount}`);
337
+ } catch (error: unknown) {
338
+ console.error(`✗ Metadata export failed: ${extractErrorMessage(error, 'Metadata Export')}`);
339
+ }
340
+
341
+ // 2. Export to database
342
+ console.log('\n2. Exporting to database...');
343
+ const dbWriter = new QueryDatabaseWriter();
344
+
345
+ try {
346
+ await dbWriter.writeQueriesToDatabase(allValidatedQueries, contextUser);
347
+ console.log(`✓ Database export complete`);
348
+ console.log(` Query count: ${allValidatedQueries.length}`);
349
+ } catch (error: unknown) {
350
+ console.error(`✗ Database export failed: ${extractErrorMessage(error, 'Database Export')}`);
351
+ }
352
+
353
+ // ========================================
354
+ // Summary
355
+ // ========================================
356
+
357
+ console.log(`\n${'='.repeat(80)}`);
358
+ console.log('Advanced QueryGen Workflow Complete!');
359
+ console.log('='.repeat(80));
360
+ console.log();
361
+ console.log('Summary:');
362
+ console.log(` Entities Processed: ${targetEntities.length}`);
363
+ console.log(` Total Queries Generated: ${allValidatedQueries.length}`);
364
+ console.log(` Golden Queries Used: ${GOLDEN_QUERIES.length}`);
365
+ console.log(` Max Entities Per Group: ${CUSTOM_CONFIG.maxEntitiesPerGroup}`);
366
+ console.log(` Max Refinement Iterations: ${CUSTOM_CONFIG.maxRefinementIterations}`);
367
+ console.log();
368
+
369
+ // Show query breakdown
370
+ if (allValidatedQueries.length > 0) {
371
+ console.log('Query Breakdown:');
372
+ allValidatedQueries.forEach((vq, i) => {
373
+ console.log(` ${i + 1}. ${vq.businessQuestion.userQuestion}`);
374
+ console.log(` Entities: ${vq.entityGroup.entities.map(e => e.Name).join(', ')}`);
375
+ console.log(` Test: ${vq.testResult.success ? 'Passed' : 'Failed'}`);
376
+ console.log(` Evaluation: ${vq.evaluation.answersQuestion ? 'Passed' : 'Failed'} (confidence: ${vq.evaluation.confidence})`);
377
+ });
378
+ console.log();
379
+ }
380
+
381
+ console.log('Features Demonstrated:');
382
+ console.log(' ✓ Vector similarity search with golden queries');
383
+ console.log(' ✓ Few-shot learning with similar examples');
384
+ console.log(' ✓ Automatic query testing and error fixing');
385
+ console.log(' ✓ AI-powered query evaluation and refinement');
386
+ console.log(' ✓ Batch processing of multiple entities');
387
+ console.log(' ✓ Export to both metadata files and database');
388
+ console.log(' ✓ Custom configuration');
389
+ console.log();
390
+ }
391
+
392
+ // Run main function
393
+ main()
394
+ .then(() => {
395
+ console.log('✓ Example completed successfully');
396
+ process.exit(0);
397
+ })
398
+ .catch((error: unknown) => {
399
+ console.error('✗ Example failed:', extractErrorMessage(error, 'Advanced Usage Example'));
400
+ process.exit(1);
401
+ });
@@ -0,0 +1,285 @@
1
+ /**
2
+ * Basic Usage Example for QueryGen
3
+ *
4
+ * This example demonstrates the fundamental workflow:
5
+ * 1. Load entities
6
+ * 2. Create entity groups
7
+ * 3. Generate business questions
8
+ * 4. Generate SQL queries
9
+ * 5. Test queries
10
+ * 6. Export results
11
+ */
12
+
13
+ import {
14
+ EntityGrouper,
15
+ QuestionGenerator,
16
+ QueryWriter,
17
+ QueryTester,
18
+ MetadataExporter,
19
+ formatEntityMetadataForPrompt,
20
+ extractErrorMessage,
21
+ ValidatedQuery
22
+ } from '@memberjunction/query-gen';
23
+ import { Metadata, UserInfo, DatabaseProviderBase } from '@memberjunction/core';
24
+
25
+ /**
26
+ * Main function demonstrating basic QueryGen usage
27
+ */
28
+ async function main() {
29
+ console.log('QueryGen Basic Usage Example\n');
30
+
31
+ // ========================================
32
+ // Step 1: Setup
33
+ // ========================================
34
+
35
+ // Create context user for server-side operations
36
+ const contextUser = new UserInfo();
37
+ contextUser.Email = 'system@example.com';
38
+ contextUser.Name = 'System User';
39
+ contextUser.FirstName = 'System';
40
+ contextUser.LastName = 'User';
41
+
42
+ // Ensure metadata provider is configured
43
+ if (!Metadata.Provider) {
44
+ console.error('ERROR: Metadata provider not configured');
45
+ console.error('Please configure database connection before running this example');
46
+ process.exit(1);
47
+ }
48
+
49
+ // ========================================
50
+ // Step 2: Load Entities
51
+ // ========================================
52
+
53
+ console.log('Step 1: Loading entities...');
54
+ const md = new Metadata();
55
+
56
+ // Filter to specific entity for this example
57
+ const targetEntityName = 'Customers'; // Change this to test with different entities
58
+ const entity = md.Entities.find(e => e.Name === targetEntityName);
59
+
60
+ if (!entity) {
61
+ console.error(`ERROR: Entity '${targetEntityName}' not found`);
62
+ process.exit(1);
63
+ }
64
+
65
+ console.log(`✓ Found entity: ${entity.Name}\n`);
66
+
67
+ // ========================================
68
+ // Step 3: Create Entity Groups
69
+ // ========================================
70
+
71
+ console.log('Step 2: Creating entity groups...');
72
+ const grouper = new EntityGrouper();
73
+
74
+ // Create groups of 1-2 entities
75
+ const groups = await grouper.generateEntityGroups([entity], 1, 2);
76
+
77
+ console.log(`✓ Created ${groups.length} entity group(s)\n`);
78
+
79
+ // Show first group
80
+ const entityGroup = groups[0];
81
+ console.log('Entity group:', {
82
+ entities: entityGroup.entities.map(e => e.Name),
83
+ relationshipType: entityGroup.relationshipType,
84
+ primaryEntity: entityGroup.primaryEntity.Name
85
+ });
86
+ console.log();
87
+
88
+ // ========================================
89
+ // Step 4: Generate Business Questions
90
+ // ========================================
91
+
92
+ console.log('Step 3: Generating business questions...');
93
+ const questionGen = new QuestionGenerator(contextUser);
94
+
95
+ let questions;
96
+ try {
97
+ questions = await questionGen.generateQuestions(entityGroup);
98
+ console.log(`✓ Generated ${questions.length} business question(s)\n`);
99
+
100
+ // Show questions
101
+ questions.forEach((q, i) => {
102
+ console.log(`Question ${i + 1}:`);
103
+ console.log(` User Question: ${q.userQuestion}`);
104
+ console.log(` Description: ${q.description}`);
105
+ console.log(` Complexity: ${q.complexity}`);
106
+ console.log(` Requires Aggregation: ${q.requiresAggregation}`);
107
+ console.log(` Requires Joins: ${q.requiresJoins}`);
108
+ console.log();
109
+ });
110
+ } catch (error: unknown) {
111
+ console.error('ERROR generating questions:', extractErrorMessage(error, 'Question Generation'));
112
+ process.exit(1);
113
+ }
114
+
115
+ // ========================================
116
+ // Step 5: Generate SQL Query
117
+ // ========================================
118
+
119
+ console.log('Step 4: Generating SQL query...');
120
+
121
+ // Format entity metadata for prompt
122
+ const entityMetadata = entityGroup.entities.map(e =>
123
+ formatEntityMetadataForPrompt(e, entityGroup.entities)
124
+ );
125
+
126
+ // Use first question for this example
127
+ const businessQuestion = questions[0];
128
+
129
+ // For this basic example, we'll skip few-shot learning (no golden queries)
130
+ const fewShotExamples: any[] = [];
131
+
132
+ const queryWriter = new QueryWriter(contextUser);
133
+
134
+ let generatedQuery;
135
+ try {
136
+ generatedQuery = await queryWriter.generateQuery(
137
+ businessQuestion,
138
+ entityMetadata,
139
+ fewShotExamples
140
+ );
141
+
142
+ console.log('✓ Generated SQL query\n');
143
+ console.log('SQL Template:');
144
+ console.log('─'.repeat(80));
145
+ console.log(generatedQuery.sql);
146
+ console.log('─'.repeat(80));
147
+ console.log();
148
+
149
+ console.log('Parameters:', generatedQuery.parameters.length);
150
+ generatedQuery.parameters.forEach(param => {
151
+ console.log(` - ${param.name} (${param.type}): ${param.description}`);
152
+ });
153
+ console.log();
154
+
155
+ console.log('Output Fields:', generatedQuery.selectClause.length);
156
+ generatedQuery.selectClause.forEach(field => {
157
+ console.log(` - ${field.name} (${field.type}): ${field.description}`);
158
+ });
159
+ console.log();
160
+ } catch (error: unknown) {
161
+ console.error('ERROR generating query:', extractErrorMessage(error, 'Query Generation'));
162
+ process.exit(1);
163
+ }
164
+
165
+ // ========================================
166
+ // Step 6: Test Query
167
+ // ========================================
168
+
169
+ console.log('Step 5: Testing query...');
170
+
171
+ const dataProvider = Metadata.Provider.DatabaseConnection as DatabaseProviderBase;
172
+ const tester = new QueryTester(
173
+ dataProvider,
174
+ entityMetadata,
175
+ businessQuestion,
176
+ contextUser
177
+ );
178
+
179
+ let testResult;
180
+ try {
181
+ // Test with up to 5 error-fixing attempts
182
+ testResult = await tester.testQuery(generatedQuery, 5);
183
+
184
+ if (testResult.success) {
185
+ console.log(`✓ Query test passed in ${testResult.attempts} attempt(s)`);
186
+ console.log(` Rows returned: ${testResult.rowCount}`);
187
+ console.log();
188
+
189
+ // Show sample results (first 3 rows)
190
+ if (testResult.sampleRows && testResult.sampleRows.length > 0) {
191
+ console.log('Sample Results (first 3 rows):');
192
+ console.log('─'.repeat(80));
193
+ testResult.sampleRows.slice(0, 3).forEach((row, i) => {
194
+ console.log(`Row ${i + 1}:`, JSON.stringify(row, null, 2));
195
+ });
196
+ console.log('─'.repeat(80));
197
+ console.log();
198
+ }
199
+ } else {
200
+ console.error(`✗ Query test failed after ${testResult.attempts} attempt(s)`);
201
+ console.error(' Error:', testResult.error);
202
+ console.log();
203
+ console.log('Note: This example will continue with export despite test failure');
204
+ console.log();
205
+ }
206
+ } catch (error: unknown) {
207
+ console.error('ERROR testing query:', extractErrorMessage(error, 'Query Testing'));
208
+ console.log('Note: This example will continue with export despite test error');
209
+ console.log();
210
+ }
211
+
212
+ // ========================================
213
+ // Step 7: Export Results
214
+ // ========================================
215
+
216
+ console.log('Step 6: Exporting query...');
217
+
218
+ // Create ValidatedQuery object
219
+ const validatedQuery: ValidatedQuery = {
220
+ businessQuestion,
221
+ query: generatedQuery,
222
+ testResult: testResult || {
223
+ success: false,
224
+ error: 'Test was skipped or failed',
225
+ attempts: 0
226
+ },
227
+ evaluation: {
228
+ answersQuestion: true,
229
+ confidence: 0.8,
230
+ reasoning: 'Basic example - no formal evaluation performed',
231
+ suggestions: [],
232
+ needsRefinement: false
233
+ },
234
+ entityGroup
235
+ };
236
+
237
+ const exporter = new MetadataExporter();
238
+
239
+ try {
240
+ const exportResult = await exporter.exportQueries(
241
+ [validatedQuery],
242
+ './examples/output'
243
+ );
244
+
245
+ console.log(`✓ Query exported successfully`);
246
+ console.log(` Output path: ${exportResult.outputPath}`);
247
+ console.log(` Query count: ${exportResult.queryCount}`);
248
+ console.log();
249
+ } catch (error: unknown) {
250
+ console.error('ERROR exporting query:', extractErrorMessage(error, 'Query Export'));
251
+ process.exit(1);
252
+ }
253
+
254
+ // ========================================
255
+ // Summary
256
+ // ========================================
257
+
258
+ console.log('═'.repeat(80));
259
+ console.log('Basic QueryGen Workflow Complete!');
260
+ console.log('═'.repeat(80));
261
+ console.log();
262
+ console.log('Summary:');
263
+ console.log(` Entity: ${entity.Name}`);
264
+ console.log(` Questions Generated: ${questions.length}`);
265
+ console.log(` Query Generated: Yes`);
266
+ console.log(` Query Tested: ${testResult?.success ? 'Passed' : 'Failed/Skipped'}`);
267
+ console.log(` Query Exported: Yes`);
268
+ console.log();
269
+ console.log('Next Steps:');
270
+ console.log(' 1. Review the exported query metadata file');
271
+ console.log(' 2. Test the query with different parameter values');
272
+ console.log(' 3. Run the advanced-usage.ts example for refinement workflow');
273
+ console.log();
274
+ }
275
+
276
+ // Run main function
277
+ main()
278
+ .then(() => {
279
+ console.log('✓ Example completed successfully');
280
+ process.exit(0);
281
+ })
282
+ .catch((error: unknown) => {
283
+ console.error('✗ Example failed:', extractErrorMessage(error, 'Basic Usage Example'));
284
+ process.exit(1);
285
+ });