Skip to content

Commit b14777f

Browse files
committed
feat(tools): rename query builder tools to dataset-based tools
BREAKING CHANGE: Tool keys renamed. generate-query is now get-data-as-dataset. improve-query is now improve-dataset. Descriptions updated to dataset-centric language.
1 parent cd30f8a commit b14777f

14 files changed

Lines changed: 93 additions & 111 deletions

src/__tests__/db-query/unit/db-query.graph.unit.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ describe(`DbQueryGraph Unit`, function () {
3434
stubMap[DbQueryNodes.GenerateChecklist].callsFake(async () => ({
3535
validationChecklist: '1. Test check',
3636
}));
37-
stubMap[DbQueryNodes.GenerateDescription].callsFake(async (state: Record<string, unknown>) =>
38-
state.description ? {} : {description: 'Test description'},
37+
stubMap[DbQueryNodes.GenerateDescription].callsFake(
38+
async (state: Record<string, unknown>) =>
39+
state.description ? {} : {description: 'Test description'},
3940
);
4041
// VerifyChecklist runs in parallel with SqlGeneration — must return partial state
4142
stubMap[DbQueryNodes.VerifyChecklist].callsFake(async () => ({}));
@@ -164,7 +165,9 @@ describe(`DbQueryGraph Unit`, function () {
164165
expect(stubMap[DbQueryNodes.IsImprovement].calledOnce).to.be.true();
165166
expect(stubMap[DbQueryNodes.CheckCache].calledOnce).to.be.true();
166167
expect(stubMap[DbQueryNodes.GetTables].calledOnce).to.be.true();
167-
expect(stubMap[DbQueryNodes.SqlGeneration].getCalls().length).to.be.eql(MAX_ATTEMPTS);
168+
expect(stubMap[DbQueryNodes.SqlGeneration].getCalls().length).to.be.eql(
169+
MAX_ATTEMPTS,
170+
);
168171
expect(
169172
stubMap[DbQueryNodes.SyntacticValidator].getCalls().length,
170173
).to.be.eql(MAX_ATTEMPTS);

src/__tests__/db-query/unit/nodes/semantic-validator.node.unit.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import {expect, sinon} from '@loopback/testlab';
2-
import {
3-
EvaluationResult,
4-
SemanticValidatorNode,
5-
} from '../../../../components';
2+
import {EvaluationResult, SemanticValidatorNode} from '../../../../components';
63
import {LLMProvider} from '../../../../types';
74

85
describe('SemanticValidatorNode Unit', function () {

src/__tests__/db-query/unit/nodes/sql-generation.node.unit.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ describe('SqlGenerationNode Unit', function () {
5555

5656
it('should generate SQL query based on the provided prompt', async () => {
5757
llmStub.resolves({
58-
content:
59-
'<think>thinking about it</think>SELECT * FROM employees;',
58+
content: '<think>thinking about it</think>SELECT * FROM employees;',
6059
});
6160

6261
const state = {
@@ -145,8 +144,7 @@ It should have no other character or symbol or character that is not part of SQL
145144

146145
it('should generate SQL query based on the provided prompt with a single feedback from some validation stage', async () => {
147146
llmStub.resolves({
148-
content:
149-
'<think>thinking about it</think>SELECT * FROM employees;',
147+
content: '<think>thinking about it</think>SELECT * FROM employees;',
150148
});
151149

152150
const state = {
@@ -249,8 +247,7 @@ It should have no other character or symbol or character that is not part of SQL
249247

250248
it('should generate SQL query based on the provided prompt with a multiple feedbacks from from previous loops', async () => {
251249
llmStub.resolves({
252-
content:
253-
'<think>thinking about it</think>SELECT * FROM employees;',
250+
content: '<think>thinking about it</think>SELECT * FROM employees;',
254251
});
255252

256253
const state = {
@@ -361,8 +358,7 @@ It should have no other character or symbol or character that is not part of SQL
361358

362359
it('should generate SQL query with sample queries when no feedbacks but has sample SQL', async () => {
363360
llmStub.resolves({
364-
content:
365-
'<think>thinking about it</think>SELECT * FROM employees;',
361+
content: '<think>thinking about it</think>SELECT * FROM employees;',
366362
});
367363

368364
const state = {
@@ -419,8 +415,7 @@ It should have no other character or symbol or character that is not part of SQL
419415

420416
it('should generate SQL query with baseline sample queries when no feedbacks and not from cache', async () => {
421417
llmStub.resolves({
422-
content:
423-
'<think>thinking about it</think>SELECT * FROM employees;',
418+
content: '<think>thinking about it</think>SELECT * FROM employees;',
424419
});
425420

426421
const state = {
@@ -514,8 +509,7 @@ It should have no other character or symbol or character that is not part of SQL
514509
it('should use cheap LLM when OPTIMIZE_CACHED_QUERIES is true and sampleSql exists', async () => {
515510
process.env.OPTIMIZE_CACHED_QUERIES = 'true';
516511
cheapLLMStub.resolves({
517-
content:
518-
'SELECT * FROM employees WHERE id = 1;',
512+
content: 'SELECT * FROM employees WHERE id = 1;',
519513
});
520514

521515
const state = {
@@ -575,8 +569,7 @@ It should have no other character or symbol or character that is not part of SQL
575569
it('should use smart LLM when OPTIMIZE_CACHED_QUERIES is false and sampleSql exists', async () => {
576570
process.env.OPTIMIZE_CACHED_QUERIES = 'false';
577571
smartLLMStub.resolves({
578-
content:
579-
'SELECT * FROM employees WHERE id = 1;',
572+
content: 'SELECT * FROM employees WHERE id = 1;',
580573
});
581574

582575
const state = {
@@ -636,8 +629,7 @@ It should have no other character or symbol or character that is not part of SQL
636629
it('should use cheap LLM for single table schemas regardless of cache', async () => {
637630
process.env.OPTIMIZE_CACHED_QUERIES = 'false';
638631
cheapLLMStub.resolves({
639-
content:
640-
'SELECT * FROM employees;',
632+
content: 'SELECT * FROM employees;',
641633
});
642634

643635
const state = {
@@ -751,8 +743,7 @@ It should have no other character or symbol or character that is not part of SQL
751743
it('should default to true for OPTIMIZE_CACHED_QUERIES when env var is not set', async () => {
752744
delete process.env.OPTIMIZE_CACHED_QUERIES;
753745
cheapLLMStub.resolves({
754-
content:
755-
'SELECT * FROM employees WHERE id = 1;',
746+
content: 'SELECT * FROM employees WHERE id = 1;',
756747
});
757748

758749
const state = {
@@ -812,8 +803,7 @@ It should have no other character or symbol or character that is not part of SQL
812803
it('should use smart LLM when sampleSql is null despite optimization being enabled', async () => {
813804
process.env.OPTIMIZE_CACHED_QUERIES = 'true';
814805
smartLLMStub.resolves({
815-
content:
816-
'SELECT * FROM employees, departments;',
806+
content: 'SELECT * FROM employees, departments;',
817807
});
818808

819809
const state = {

src/components/db-query/db-query.component.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ import {SchemaStore} from './services/schema.store';
3737
import {TableSearchService} from './services/search/table-search.service';
3838
import {
3939
AskAboutDatasetTool,
40-
GenerateQueryTool,
41-
ImproveQueryTool,
40+
GetDataAsDatasetTool,
41+
ImproveDatasetTool,
4242
} from './tools';
4343
import {PgWithRlsConnector} from './connectors/pg';
4444

@@ -72,8 +72,8 @@ export class DbQueryComponent implements Component {
7272
DbQueryGraph,
7373
// tools
7474
AskAboutDatasetTool,
75-
GenerateQueryTool,
76-
ImproveQueryTool,
75+
GetDataAsDatasetTool,
76+
ImproveDatasetTool,
7777
// nodes
7878
IsImprovementNode,
7979
GetTablesNode,

src/components/db-query/db-query.graph.ts

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -59,56 +59,53 @@ export class DbQueryGraph extends BaseGraph<DbQueryState> {
5959
.addNode(DbQueryNodes.PostCacheAndTables, async () => ({}))
6060
.addNode(DbQueryNodes.PreValidation, async () => ({}))
6161
// PostValidation: merges syntactic + semantic results into status/feedbacks
62-
.addNode(
63-
DbQueryNodes.PostValidation,
64-
async (state: DbQueryState) => {
65-
// Syntactic failures take priority
66-
if (
67-
state.syntacticStatus &&
68-
state.syntacticStatus !== EvaluationResult.Pass
69-
) {
70-
return {
71-
status: state.syntacticStatus,
72-
feedbacks: [
73-
...(state.feedbacks ?? []),
74-
...(state.syntacticFeedback ? [state.syntacticFeedback] : []),
75-
],
76-
syntacticStatus: undefined,
77-
syntacticFeedback: undefined,
78-
semanticStatus: undefined,
79-
semanticFeedback: undefined,
80-
};
81-
}
82-
// Semantic failure
83-
if (
84-
state.semanticStatus &&
85-
state.semanticStatus !== EvaluationResult.Pass
86-
) {
87-
return {
88-
status: state.semanticStatus,
89-
feedbacks: [
90-
...(state.feedbacks ?? []),
91-
...(state.semanticFeedback ? [state.semanticFeedback] : []),
92-
],
93-
syntacticStatus: undefined,
94-
syntacticFeedback: undefined,
95-
semanticStatus: undefined,
96-
semanticFeedback: undefined,
97-
};
98-
}
99-
// Both passed — clear internal validator feedbacks
62+
.addNode(DbQueryNodes.PostValidation, async (state: DbQueryState) => {
63+
// Syntactic failures take priority
64+
if (
65+
state.syntacticStatus &&
66+
state.syntacticStatus !== EvaluationResult.Pass
67+
) {
10068
return {
101-
status: EvaluationResult.Pass,
102-
feedbacks: (state.feedbacks ?? []).filter(
103-
f => !f.startsWith('Query Validation Failed'),
104-
),
69+
status: state.syntacticStatus,
70+
feedbacks: [
71+
...(state.feedbacks ?? []),
72+
...(state.syntacticFeedback ? [state.syntacticFeedback] : []),
73+
],
10574
syntacticStatus: undefined,
10675
syntacticFeedback: undefined,
10776
semanticStatus: undefined,
10877
semanticFeedback: undefined,
10978
};
110-
},
111-
)
79+
}
80+
// Semantic failure
81+
if (
82+
state.semanticStatus &&
83+
state.semanticStatus !== EvaluationResult.Pass
84+
) {
85+
return {
86+
status: state.semanticStatus,
87+
feedbacks: [
88+
...(state.feedbacks ?? []),
89+
...(state.semanticFeedback ? [state.semanticFeedback] : []),
90+
],
91+
syntacticStatus: undefined,
92+
syntacticFeedback: undefined,
93+
semanticStatus: undefined,
94+
semanticFeedback: undefined,
95+
};
96+
}
97+
// Both passed — clear internal validator feedbacks
98+
return {
99+
status: EvaluationResult.Pass,
100+
feedbacks: (state.feedbacks ?? []).filter(
101+
f => !f.startsWith('Query Validation Failed'),
102+
),
103+
syntacticStatus: undefined,
104+
syntacticFeedback: undefined,
105+
semanticStatus: undefined,
106+
semanticFeedback: undefined,
107+
};
108+
})
112109
// === EDGES ===
113110
// Parallel fan-out: cache check and table selection
114111
.addEdge(START, DbQueryNodes.IsImprovement)

src/components/db-query/nodes/get-tables.node.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,7 @@ Use these if they are relevant to the table selection, otherwise ignore them, th
214214
}
215215
return tables.filter(t => {
216216
const name = t.toLowerCase().slice(t.indexOf('.') + 1);
217-
return (
218-
this.permissionHelper!.findMissingPermissions([name]).length === 0
219-
);
217+
return this.permissionHelper!.findMissingPermissions([name]).length === 0;
220218
});
221219
}
222220

src/components/db-query/nodes/semantic-validator.node.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,7 @@ Keep these feedbacks in mind while validating the new query.
101101
semanticStatus: EvaluationResult.Pass,
102102
} as DbQueryState;
103103
} else {
104-
const reason = invalidMatch
105-
? invalidMatch[1].trim()
106-
: response.trim();
104+
const reason = invalidMatch ? invalidMatch[1].trim() : response.trim();
107105
config.writer?.({
108106
type: LLMStreamEventType.Log,
109107
data: `Query Validation Failed by LLM: ${reason}`,

src/components/db-query/nodes/sql-generation.node.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ In the last attempt, you generated this SQL query -
9191
(process.env.OPTIMIZE_CACHED_QUERIES ?? 'true') === 'true';
9292

9393
const isSingleTable =
94-
state.schema.tables &&
95-
Object.keys(state.schema.tables).length === 1;
94+
state.schema.tables && Object.keys(state.schema.tables).length === 1;
9695

9796
// Use cheap LLM for validation fix retries — the query is close, just needs small corrections
9897
const isValidationFixRetry =

src/components/db-query/testing/get-table.node.builder.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function getTableNodeTests(cases: GetTableNodeTestCase[]) {
3737
} as unknown as RunnableConfig,
3838
);
3939
testCase.expectedTables.forEach(table => {
40-
expect(result.schema.tables).to.have.property(table);
40+
expect(result.schema?.tables).to.have.property(table);
4141
});
4242
},
4343
}));

src/components/db-query/tools/ask-about-dataset.tool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ export class AskAboutDatasetTool implements IGraphTool {
8282
{
8383
name: this.key,
8484
description:
85-
'Tool for answering questions about a query, note that it does not run the query and can only answer questions about the query itself, not the data it returns on execution. Call this only if you have a valid dataset ID available.',
85+
'Tool for answering questions about an existing dataset, note that it can only answer questions about the dataset definition, not the data it contains. Call this only if you have a valid dataset ID available.',
8686
schema,
8787
},
8888
);

0 commit comments

Comments
 (0)