mirror of https://github.com/buster-so/buster.git
fix prompts of dashboard and metric tools
This commit is contained in:
parent
5d2631b848
commit
0f0a5ed7d1
|
@ -2,7 +2,7 @@ Creates dashboard configuration files with YAML content following the dashboard
|
||||||
|
|
||||||
## COMPLETE DASHBOARD YAML SCHEMA
|
## COMPLETE DASHBOARD YAML SCHEMA
|
||||||
|
|
||||||
# DASHBOARD CONFIGURATION - YML STRUCTURE
|
`# DASHBOARD CONFIGURATION - YML STRUCTURE
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
# Required fields:
|
# Required fields:
|
||||||
#
|
#
|
||||||
|
@ -32,5 +32,96 @@ Creates dashboard configuration files with YAML content following the dashboard
|
||||||
# 8. String values generally should NOT use quotes unless they contain special characters (like :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `) or start/end with whitespace.
|
# 8. String values generally should NOT use quotes unless they contain special characters (like :, {, }, [, ], ,, &, *, #, ?, |, -, <, >, =, !, %, @, `) or start/end with whitespace.
|
||||||
# 9. If a string contains special characters or needs to preserve leading/trailing whitespace, enclose it in double quotes (`"`). Example: `name: "Sales & Marketing Dashboard"`
|
# 9. If a string contains special characters or needs to preserve leading/trailing whitespace, enclose it in double quotes (`"`). Example: `name: "Sales & Marketing Dashboard"`
|
||||||
# 10. Avoid special characters in names and descriptions where possible, but if needed, use quotes as described in rule 9. UUIDs should NEVER be quoted.
|
# 10. Avoid special characters in names and descriptions where possible, but if needed, use quotes as described in rule 9. UUIDs should NEVER be quoted.
|
||||||
|
# ----------------------------------------
|
||||||
|
|
||||||
|
type: object
|
||||||
|
name: Dashboard Configuration Schema
|
||||||
|
description: Specifies the structure and constraints of a dashboard config file.
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: The title of the dashboard (e.g. Sales & Marketing Dashboard) - do NOT use quotes
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
description: A description of the dashboard, its metrics, and its purpose
|
||||||
|
rows:
|
||||||
|
type: array
|
||||||
|
description: Array of row objects, each containing metric items
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: integer
|
||||||
|
description: This is just an integer representing the row number 1 -> n
|
||||||
|
items:
|
||||||
|
type: array
|
||||||
|
description: Array of metrics to display in this row (max 4 items)
|
||||||
|
maxItems: 4
|
||||||
|
items:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
description: UUIDv4 identifier of an existing metric
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
column_sizes:
|
||||||
|
type: array
|
||||||
|
description: Required array of column sizes (must sum to exactly 12)
|
||||||
|
items:
|
||||||
|
type: integer
|
||||||
|
minimum: 3
|
||||||
|
maximum: 12
|
||||||
|
required:
|
||||||
|
- id
|
||||||
|
- items
|
||||||
|
- column_sizes
|
||||||
|
required:
|
||||||
|
- name
|
||||||
|
- description
|
||||||
|
- rows`
|
||||||
|
|
||||||
|
**Key Requirements:**
|
||||||
|
- `name`: Dashboard title (no underscores, descriptive name)
|
||||||
|
- `description`: Natural language explanation of the dashboard's purpose and contents
|
||||||
|
- `rows`: Array of row objects, each with unique ID, items (metric UUIDs), and column_sizes
|
||||||
|
- Each row must have 1-4 items maximum
|
||||||
|
- `column_sizes` must sum to exactly 12 and each size must be >= 3
|
||||||
|
- All metric IDs must be valid UUIDs of existing metrics
|
||||||
|
- Row IDs must be unique integers (typically 1, 2, 3, etc.)
|
||||||
|
|
||||||
|
**Dashboard Layout Rules:**
|
||||||
|
- Grid system: Each row spans 12 columns total
|
||||||
|
- Column sizes: [12] = full width, [6,6] = two halves, [4,4,4] = three thirds, [3,3,3,3] = four quarters
|
||||||
|
- Common layouts: [12], [6,6], [4,8], [3,9], [4,4,4], [3,3,6], [3,3,3,3]
|
||||||
|
- Each metric item gets the corresponding column size in the same position
|
||||||
|
|
||||||
|
**Example Structure:**
|
||||||
|
```yaml
|
||||||
|
name: Sales Performance Dashboard
|
||||||
|
description: Comprehensive overview of sales metrics including revenue, conversions, and geographic performance
|
||||||
|
rows:
|
||||||
|
- id: 1
|
||||||
|
items:
|
||||||
|
- id: 550e8400-e29b-41d4-a716-446655440001
|
||||||
|
column_sizes:
|
||||||
|
- 12
|
||||||
|
- id: 2
|
||||||
|
items:
|
||||||
|
- id: 550e8400-e29b-41d4-a716-446655440002
|
||||||
|
- id: 550e8400-e29b-41d4-a716-446655440003
|
||||||
|
column_sizes:
|
||||||
|
- 6
|
||||||
|
- 6
|
||||||
|
- id: 3
|
||||||
|
items:
|
||||||
|
- id: 550e8400-e29b-41d4-a716-446655440004
|
||||||
|
- id: 550e8400-e29b-41d4-a716-446655440005
|
||||||
|
- id: 550e8400-e29b-41d4-a716-446655440006
|
||||||
|
column_sizes:
|
||||||
|
- 4
|
||||||
|
- 4
|
||||||
|
- 4
|
||||||
|
```
|
||||||
|
|
||||||
**CRITICAL:** Follow the schema exactly - all metric IDs must reference existing metrics, column sizes must sum to 12, and row IDs must be unique. The tool will validate all metric references against the database.
|
**CRITICAL:** Follow the schema exactly - all metric IDs must reference existing metrics, column sizes must sum to 12, and row IDs must be unique. The tool will validate all metric references against the database.
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import dashboardToolDescription from './dashboard-tool-description.txt';
|
||||||
|
import { getDashboardToolDescription } from './get-dashboard-tool-description';
|
||||||
|
|
||||||
|
describe('getDashboardToolDescription', () => {
|
||||||
|
it('should return the dashboard tool description from the .txt file', () => {
|
||||||
|
const description = getDashboardToolDescription();
|
||||||
|
|
||||||
|
// Verify it returns a non-empty string
|
||||||
|
expect(typeof description).toBe('string');
|
||||||
|
expect(description.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Verify it contains the expected content from the actual .txt file
|
||||||
|
expect(description).toContain('Creates dashboard configuration files');
|
||||||
|
expect(description).toContain('COMPLETE DASHBOARD YAML SCHEMA');
|
||||||
|
expect(description).toContain('DASHBOARD CONFIGURATION - YML STRUCTURE');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have no template variables in the .txt file', () => {
|
||||||
|
const content = dashboardToolDescription;
|
||||||
|
|
||||||
|
// Find any template variables in the file
|
||||||
|
const templateVariablePattern = /\{\{([^}]+)\}\}/g;
|
||||||
|
const foundVariables = new Set<string>();
|
||||||
|
|
||||||
|
const matches = Array.from(content.matchAll(templateVariablePattern));
|
||||||
|
for (const match of matches) {
|
||||||
|
if (match[1]) {
|
||||||
|
foundVariables.add(match[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should have no template variables since this tool just returns the raw content
|
||||||
|
expect(foundVariables.size).toBe(0);
|
||||||
|
|
||||||
|
// If any variables are found, list them for debugging
|
||||||
|
if (foundVariables.size > 0) {
|
||||||
|
console.error('Found unexpected template variables:', Array.from(foundVariables));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,13 +1,5 @@
|
||||||
import dashboardToolDescription from './dashboard-tool-description.txt';
|
import dashboardToolDescription from './dashboard-tool-description.txt';
|
||||||
|
|
||||||
/**
|
|
||||||
* Template parameters for the dashboard tool prompt
|
|
||||||
*/
|
|
||||||
export interface DashboardToolTemplateParams {
|
|
||||||
dataSourceSyntax: string;
|
|
||||||
date: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export the template function for use in dashboard tool
|
* Export the template function for use in dashboard tool
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
import { describe, expect, it } from 'vitest';
|
|
||||||
import dashboardToolDescription from './dashboard-tool-description.txt';
|
|
||||||
import { getDashboardToolDescription } from './get-dashboard-tool-description';
|
|
||||||
|
|
||||||
describe('Dashboard Tool Prompt Instructions', () => {
|
|
||||||
it('should validate template file has no template variables', () => {
|
|
||||||
const content = dashboardToolDescription;
|
|
||||||
|
|
||||||
// Find any template variables in the file
|
|
||||||
const templateVariablePattern = /\{\{([^}]+)\}\}/g;
|
|
||||||
const foundVariables = new Set<string>();
|
|
||||||
|
|
||||||
const matches = Array.from(content.matchAll(templateVariablePattern));
|
|
||||||
for (const match of matches) {
|
|
||||||
if (match[1] && match[1] !== 'variable') {
|
|
||||||
foundVariables.add(match[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should have no template variables since this tool just fetches the raw content
|
|
||||||
expect(foundVariables.size).toBe(0);
|
|
||||||
expect(content.length).toBeGreaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load the dashboard tool description correctly', () => {
|
|
||||||
const result = getDashboardToolDescription();
|
|
||||||
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(typeof result).toBe('string');
|
|
||||||
expect(result.length).toBeGreaterThan(0);
|
|
||||||
|
|
||||||
// Should return the raw content from the text file
|
|
||||||
expect(result).toBe(dashboardToolDescription);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain expected sections from the dashboard description', () => {
|
|
||||||
const result = getDashboardToolDescription();
|
|
||||||
|
|
||||||
// Check for key sections that should be in the dashboard description
|
|
||||||
expect(result).toContain('Creates dashboard configuration files');
|
|
||||||
expect(result).toContain('COMPLETE DASHBOARD YAML SCHEMA');
|
|
||||||
expect(result).toContain('DASHBOARD CONFIGURATION - YML STRUCTURE');
|
|
||||||
expect(result).toContain('Required fields:');
|
|
||||||
expect(result).toContain('Rules:');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,78 +1,46 @@
|
||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { getMetricToolDescriptionPrompt } from './get-metric-tool-description';
|
import { getMetricToolDescription } from './get-metric-tool-description';
|
||||||
import metricToolDescription from './metric-tool-description.txt';
|
import metricToolDescription from './metric-tool-description.txt';
|
||||||
|
|
||||||
describe('Metric Tool Description Instructions', () => {
|
describe('getMetricToolDescription', () => {
|
||||||
it('should validate template file contains expected variables', () => {
|
it('should return the metric tool description from the .txt file', () => {
|
||||||
|
const description = getMetricToolDescription();
|
||||||
|
|
||||||
|
// Verify it returns a non-empty string
|
||||||
|
expect(typeof description).toBe('string');
|
||||||
|
expect(description.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Verify it contains the expected content from the actual .txt file
|
||||||
|
expect(description).toContain('Creates metric configuration files with YAML content');
|
||||||
|
expect(description).toContain('COMPLETE METRIC YAML SCHEMA SPECIFICATION');
|
||||||
|
expect(description).toContain('selectedChartType');
|
||||||
|
expect(description).toContain('columnLabelFormats');
|
||||||
|
|
||||||
|
// Verify it has the full schema documentation
|
||||||
|
expect(description).toContain('# METRIC CONFIGURATION - YML STRUCTURE');
|
||||||
|
expect(description).toContain('bar, line, scatter, pie, combo, metric, table');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have no template variables in the .txt file', () => {
|
||||||
const content = metricToolDescription;
|
const content = metricToolDescription;
|
||||||
|
|
||||||
// Expected template variables
|
// Find any template variables in the file
|
||||||
const expectedVariables = ['sql_dialect_guidance', 'date'];
|
|
||||||
|
|
||||||
// Find all template variables in the file
|
|
||||||
const templateVariablePattern = /\{\{([^}]+)\}\}/g;
|
const templateVariablePattern = /\{\{([^}]+)\}\}/g;
|
||||||
const foundVariables = new Set<string>();
|
const foundVariables = new Set<string>();
|
||||||
|
|
||||||
const matches = Array.from(content.matchAll(templateVariablePattern));
|
const matches = Array.from(content.matchAll(templateVariablePattern));
|
||||||
for (const match of matches) {
|
for (const match of matches) {
|
||||||
if (match[1] && match[1] !== 'variable') {
|
if (match[1]) {
|
||||||
foundVariables.add(match[1]);
|
foundVariables.add(match[1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to arrays for easier comparison
|
// Should have no template variables since this tool just returns the raw content
|
||||||
const foundVariablesArray = Array.from(foundVariables).sort();
|
expect(foundVariables.size).toBe(0);
|
||||||
const expectedVariablesArray = expectedVariables.sort();
|
|
||||||
|
|
||||||
// Check that we have exactly the expected variables
|
// If any variables are found, list them for debugging
|
||||||
expect(foundVariablesArray).toEqual(expectedVariablesArray);
|
if (foundVariables.size > 0) {
|
||||||
|
console.error('Found unexpected template variables:', Array.from(foundVariables));
|
||||||
// Also verify each expected variable exists
|
|
||||||
for (const variable of expectedVariables) {
|
|
||||||
expect(content).toMatch(new RegExp(`\\{\\{${variable}\\}\\}`));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure no unexpected variables exist
|
|
||||||
expect(foundVariables.size).toBe(expectedVariables.length);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load and process the prompt template correctly', () => {
|
|
||||||
const sqlDialectGuidance = 'Test SQL guidance for PostgreSQL';
|
|
||||||
const result = getMetricToolDescriptionPrompt(sqlDialectGuidance);
|
|
||||||
|
|
||||||
expect(result).toBeDefined();
|
|
||||||
expect(typeof result).toBe('string');
|
|
||||||
expect(result.length).toBeGreaterThan(0);
|
|
||||||
|
|
||||||
// Should contain the SQL guidance we provided
|
|
||||||
expect(result).toContain(sqlDialectGuidance);
|
|
||||||
|
|
||||||
// Should not contain any unreplaced template variables
|
|
||||||
expect(result).not.toMatch(/\{\{sql_dialect_guidance\}\}/);
|
|
||||||
expect(result).not.toMatch(/\{\{date\}\}/);
|
|
||||||
|
|
||||||
// Should contain the current date in YYYY-MM-DD format
|
|
||||||
const currentDate = new Date().toISOString().split('T')[0];
|
|
||||||
expect(result).toContain(currentDate);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should contain expected sections from the prompt template', () => {
|
|
||||||
const result = getMetricToolDescriptionPrompt('Test guidance');
|
|
||||||
|
|
||||||
// Check for key sections that should be in the prompt
|
|
||||||
// Note: These expectations may need to be adjusted based on the actual content
|
|
||||||
// of the metric-tool-description.txt file
|
|
||||||
expect(result.length).toBeGreaterThan(0);
|
|
||||||
// Additional specific content checks can be added based on the prompt template structure
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should throw an error for empty SQL dialect guidance', () => {
|
|
||||||
expect(() => {
|
|
||||||
getMetricToolDescriptionPrompt('');
|
|
||||||
}).toThrow('SQL dialect guidance is required');
|
|
||||||
|
|
||||||
expect(() => {
|
|
||||||
getMetricToolDescriptionPrompt(' '); // whitespace only
|
|
||||||
}).toThrow('SQL dialect guidance is required');
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,40 +1,8 @@
|
||||||
import metricToolDescription from './metric-tool-description.txt';
|
import metricToolDescription from './metric-tool-description.txt';
|
||||||
|
|
||||||
/**
|
|
||||||
* Template parameters for the metric tool description prompt
|
|
||||||
*/
|
|
||||||
export interface MetricToolTemplateParams {
|
|
||||||
dataSourceSyntax: string;
|
|
||||||
date: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads the metric tool description prompt template and replaces variables
|
|
||||||
*/
|
|
||||||
function loadAndProcessPrompt(sqlDialectGuidance: string): string {
|
|
||||||
if (!sqlDialectGuidance.trim()) {
|
|
||||||
throw new Error('SQL dialect guidance is required');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace template variables
|
|
||||||
const currentDate = new Date().toISOString().split('T')[0] ?? '';
|
|
||||||
const processedContent = metricToolDescription
|
|
||||||
.replace(/\{\{sql_dialect_guidance\}\}/g, sqlDialectGuidance)
|
|
||||||
.replace(/\{\{date\}\}/g, currentDate);
|
|
||||||
|
|
||||||
return processedContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Export the template function for use in metric tool
|
* Export the template function for use in metric tool
|
||||||
*/
|
*/
|
||||||
export const getMetricToolDescription = (): string => {
|
export const getMetricToolDescription = (): string => {
|
||||||
return metricToolDescription;
|
return metricToolDescription;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Export the template function with parameters for use in metric tool
|
|
||||||
*/
|
|
||||||
export const getMetricToolDescriptionPrompt = (sqlDialectGuidance: string): string => {
|
|
||||||
return loadAndProcessPrompt(sqlDialectGuidance);
|
|
||||||
};
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue