@sqlrooms/ai 0.26.0-rc.2 → 0.26.0-rc.3
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/README.md +60 -149
- package/dist/tools/defaultTools.d.ts +3 -2
- package/dist/tools/defaultTools.d.ts.map +1 -1
- package/dist/tools/defaultTools.js.map +1 -1
- package/dist/tools/query/queryTool.d.ts +18 -11
- package/dist/tools/query/queryTool.d.ts.map +1 -1
- package/dist/tools/query/queryTool.js +5 -4
- package/dist/tools/query/queryTool.js.map +1 -1
- package/package.json +13 -11
package/README.md
CHANGED
|
@@ -19,40 +19,50 @@ npm install @sqlrooms/ai
|
|
|
19
19
|
yarn add @sqlrooms/ai
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Since version 0.8.2, you will need to install the LLM providers you want to use. For example, to use
|
|
22
|
+
Since version 0.8.2, you will need to install the LLM providers you want to use. For example, to use XAI, you can install the `@ai-sdk/xai` package:
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
npm install @ai-sdk/
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Google LLM provider:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npm install @ai-sdk/google
|
|
25
|
+
npm install @ai-sdk/xai
|
|
32
26
|
```
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
npm install @ai-sdk/anthropic
|
|
38
|
-
```
|
|
28
|
+
Since version 0.26.0, you don't need to install the LLM providers anymore. You can use AiSettingsSlice to configure the LLM providers, and sqlrooms/ai will use the configured LLM providers via OpenAI compatible SDK.
|
|
39
29
|
|
|
40
|
-
|
|
30
|
+
```tsx
|
|
31
|
+
import {createAiSettingsSlice} from '@sqlrooms/ai';
|
|
41
32
|
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
// Create a room store with AI capabilities
|
|
34
|
+
const {roomStore, useRoomStore} = createRoomStore({
|
|
35
|
+
...createAiSettingsSlice({
|
|
36
|
+
config: {
|
|
37
|
+
providers: {
|
|
38
|
+
openai: {
|
|
39
|
+
baseUrl: 'https://api.openai.com/v1',
|
|
40
|
+
apiKey: '',
|
|
41
|
+
models: [
|
|
42
|
+
{
|
|
43
|
+
id: 'gpt-4.1',
|
|
44
|
+
modelName: 'gpt-4.1',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
});
|
|
44
50
|
```
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
npm install @ai-sdk/xai
|
|
50
|
-
```
|
|
52
|
+
You can also pass a custom model provider to the AiSlice.
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
```tsx
|
|
55
|
+
import {createAiSlice} from '@sqlrooms/ai';
|
|
53
56
|
|
|
54
|
-
|
|
55
|
-
|
|
57
|
+
// Create a room store with AI capabilities
|
|
58
|
+
const {roomStore, useRoomStore} = createRoomStore({
|
|
59
|
+
...createAiSlice({
|
|
60
|
+
getCustomModel: () => {
|
|
61
|
+
return xai('grok-4');
|
|
62
|
+
},
|
|
63
|
+
...
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
56
66
|
```
|
|
57
67
|
|
|
58
68
|
## Basic Usage
|
|
@@ -71,15 +81,17 @@ const {roomStore, useRoomStore} = createRoomStore({
|
|
|
71
81
|
// Your room configuration
|
|
72
82
|
},
|
|
73
83
|
}),
|
|
84
|
+
// Add AI settings slice
|
|
85
|
+
...createAiSettingsSlice({
|
|
86
|
+
config: {
|
|
87
|
+
// Your AI settings configuration
|
|
88
|
+
},
|
|
89
|
+
}),
|
|
74
90
|
// Add AI slice
|
|
75
91
|
...createAiSlice({
|
|
76
|
-
getApiKey: (modelProvider) => {
|
|
77
|
-
// Return API key for the specified model provider
|
|
78
|
-
return process.env.OPENAI_API_KEY || '';
|
|
79
|
-
},
|
|
80
92
|
initialAnalysisPrompt: 'What insights can you provide from my data?',
|
|
81
93
|
// Optional: Add custom tools
|
|
82
|
-
|
|
94
|
+
tools: {
|
|
83
95
|
// Your custom tools
|
|
84
96
|
},
|
|
85
97
|
// Optional: Custom instructions for the AI
|
|
@@ -124,8 +136,14 @@ export const {roomStore, useRoomStore} = createRoomStore<RoomConfig, RoomState>(
|
|
|
124
136
|
...createDefaultSqlEditorConfig(),
|
|
125
137
|
},
|
|
126
138
|
}),
|
|
127
|
-
// AI slice
|
|
128
|
-
...
|
|
139
|
+
// AI settings slice
|
|
140
|
+
...createAiSettingsSlice({
|
|
141
|
+
config: {
|
|
142
|
+
// Your AI settings configuration
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
// Ai config slice
|
|
146
|
+
...createAiConfigSlice({
|
|
129
147
|
config: {
|
|
130
148
|
// Optional: Pre-configured AI sessions
|
|
131
149
|
sessions: [
|
|
@@ -139,12 +157,17 @@ export const {roomStore, useRoomStore} = createRoomStore<RoomConfig, RoomState>(
|
|
|
139
157
|
},
|
|
140
158
|
],
|
|
141
159
|
currentSessionId: 'default-session',
|
|
142
|
-
}
|
|
143
|
-
getApiKey: (modelProvider) => {
|
|
144
|
-
// Return API key based on provider
|
|
145
|
-
return apiKeys[modelProvider] || '';
|
|
146
160
|
},
|
|
147
|
-
|
|
161
|
+
}),
|
|
162
|
+
// AI slice
|
|
163
|
+
...createAiSlice({
|
|
164
|
+
initialAnalysisPrompt: 'What insights can you provide from my data?',
|
|
165
|
+
tools: {
|
|
166
|
+
// Your custom tools
|
|
167
|
+
},
|
|
168
|
+
getInstructions: (tablesSchema) => {
|
|
169
|
+
return `Analyze the following tables: ${tablesSchema.map((t) => t.name).join(', ')}`;
|
|
170
|
+
},
|
|
148
171
|
}),
|
|
149
172
|
// SQL Editor slice
|
|
150
173
|
...createSqlEditorSlice(),
|
|
@@ -362,119 +385,7 @@ const ChartComponent = useRoomStore((state) =>
|
|
|
362
385
|
|
|
363
386
|
## Data Structure
|
|
364
387
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
```ts
|
|
368
|
-
ai: {
|
|
369
|
-
sessions: [
|
|
370
|
-
{
|
|
371
|
-
id: defaultSessionId,
|
|
372
|
-
name: 'Default Session',
|
|
373
|
-
modelProvider: 'openai',
|
|
374
|
-
model: 'gpt-4o-mini',
|
|
375
|
-
analysisResults: [],
|
|
376
|
-
createdAt: new Date(),
|
|
377
|
-
},
|
|
378
|
-
],
|
|
379
|
-
currentSessionId: defaultSessionId,
|
|
380
|
-
}
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
Each session has a `analysisResults` which is an array of `AnalysisResult`. Each `AnalysisResult` has the following properties:
|
|
384
|
-
|
|
385
|
-
- `id`: The unique identifier for the analysis result
|
|
386
|
-
- `prompt`: The user prompt that was used to generate the analysis result
|
|
387
|
-
- `streamMessage`: The stream message from the LLM
|
|
388
|
-
- `errorMessage`: The error message from the LLM
|
|
389
|
-
- `isCompleted`: Whether the analysis result has been completed
|
|
390
|
-
|
|
391
|
-
For each user prompt, the LLM will run multiple tools (e.g. `query`, `chart`) and return the result as the `streamMessage`. The structure of the `streamMessage` is as follows:
|
|
392
|
-
|
|
393
|
-
- `text`: the final response from the LLM (streamable)
|
|
394
|
-
- `reasoning`: the reasoning of the LLM (only for reason models)
|
|
395
|
-
- `toolCallMessages`: the message array of the tool calls executed by the LLM
|
|
396
|
-
|
|
397
|
-
Each `toolCallMessages` has the following properties:
|
|
398
|
-
|
|
399
|
-
- `toolName`: the name of the tool
|
|
400
|
-
- `toolCallId`: the id of the tool call
|
|
401
|
-
- `args`: the arguments of the tool call
|
|
402
|
-
- `llmResult`: the result from the execution of the tool, which will be sent back to the LLM as response.
|
|
403
|
-
- `additionalData`: the additional data of the tool, which can be used to pass the output of the tool to next tool call or the component for rendering.
|
|
404
|
-
|
|
405
|
-
## Rendering
|
|
406
|
-
|
|
407
|
-
```text
|
|
408
|
-
|--------------------------------|
|
|
409
|
-
| AnalysisResultsContainer |
|
|
410
|
-
|--------------------------------|
|
|
411
|
-
| |--------------------------| |
|
|
412
|
-
| | AnalysisResult | |
|
|
413
|
-
| | | |
|
|
414
|
-
| | streamMessage | |
|
|
415
|
-
| | | |
|
|
416
|
-
| | |---------------------| | |
|
|
417
|
-
| | | Tools | | |
|
|
418
|
-
| | |---------------------| | |
|
|
419
|
-
| | | |---------------| | | |
|
|
420
|
-
| | | |ToolCallMessage| | | |
|
|
421
|
-
| | | |---------------| | | |
|
|
422
|
-
| | | |---------------| | | |
|
|
423
|
-
| | | |ToolCallMessage| | | |
|
|
424
|
-
| | | |---------------| | | |
|
|
425
|
-
| | | ... | | |
|
|
426
|
-
| | |---------------------| | |
|
|
427
|
-
| | | |
|
|
428
|
-
| | text | |
|
|
429
|
-
| |--------------------------| |
|
|
430
|
-
|--------------------------------|
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## Tools
|
|
434
|
-
|
|
435
|
-
In AI package, we provide a tool() to allow creating function tool for LLM to use. It is an extension of the `tool` from `vercel ai sdk`, and it supports not only `execute` function, but also `context` object and `component` object:
|
|
436
|
-
|
|
437
|
-
- `execute` needs to return
|
|
438
|
-
- llmResult: the result send back to LLM (no raw data)
|
|
439
|
-
- additionalData: the data will be used by `component` and next `tool`
|
|
440
|
-
- `context`
|
|
441
|
-
- provide e.g. runtime or async data for `execute`
|
|
442
|
-
- `execute` can access `context` via `options.context`
|
|
443
|
-
- `component`
|
|
444
|
-
- use `additionalData` to render a React component for this `tool`
|
|
445
|
-
|
|
446
|
-
For example, the `query` tool is defined as follows:
|
|
447
|
-
|
|
448
|
-
```ts
|
|
449
|
-
const functions = {
|
|
450
|
-
weather: tool({
|
|
451
|
-
description: 'Get the weather in a city from a weather station',
|
|
452
|
-
parameters: z.object({cityName: z.string()}),
|
|
453
|
-
execute: async ({cityName}, options) => {
|
|
454
|
-
const getStation = options.context?.getStation;
|
|
455
|
-
const station = getStation ? await getStation(cityName) : null;
|
|
456
|
-
return {
|
|
457
|
-
llmResult: `The weather in ${cityName} is sunny from weather station ${station}.`,
|
|
458
|
-
additionalData: {
|
|
459
|
-
weather: 'sunny',
|
|
460
|
-
station,
|
|
461
|
-
},
|
|
462
|
-
};
|
|
463
|
-
},
|
|
464
|
-
context: {
|
|
465
|
-
getStation: async (cityName: string) => {
|
|
466
|
-
const stations = {
|
|
467
|
-
'New York': '123',
|
|
468
|
-
'Los Angeles': '456',
|
|
469
|
-
Chicago: '789',
|
|
470
|
-
};
|
|
471
|
-
return stations[cityName];
|
|
472
|
-
},
|
|
473
|
-
},
|
|
474
|
-
component: WeatherStation,
|
|
475
|
-
}),
|
|
476
|
-
};
|
|
477
|
-
```
|
|
388
|
+
See [ai-core](https://github.com/sqlrooms/sqlrooms/tree/main/packages/ai-core) for the data structure.
|
|
478
389
|
|
|
479
390
|
## Advanced Features
|
|
480
391
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { AiSliceState
|
|
1
|
+
import { AiSliceState } from '@sqlrooms/ai-core';
|
|
2
2
|
import { DuckDbSliceState } from '@sqlrooms/duckdb';
|
|
3
3
|
import { StoreApi } from '@sqlrooms/room-shell';
|
|
4
4
|
import { QueryToolOptions } from './query/queryTool';
|
|
5
|
+
import { OpenAssistantToolSet } from '@openassistant/utils';
|
|
5
6
|
export type DefaultToolsOptions = {
|
|
6
7
|
query?: QueryToolOptions;
|
|
7
8
|
};
|
|
@@ -10,5 +11,5 @@ export type DefaultToolsOptions = {
|
|
|
10
11
|
* Includes:
|
|
11
12
|
* - query: Executes SQL queries against DuckDB
|
|
12
13
|
*/
|
|
13
|
-
export declare function createDefaultAiTools(store: StoreApi<AiSliceState & DuckDbSliceState>, options?: DefaultToolsOptions):
|
|
14
|
+
export declare function createDefaultAiTools(store: StoreApi<AiSliceState & DuckDbSliceState>, options?: DefaultToolsOptions): OpenAssistantToolSet;
|
|
14
15
|
//# sourceMappingURL=defaultTools.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultTools.d.ts","sourceRoot":"","sources":["../../src/tools/defaultTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"defaultTools.d.ts","sourceRoot":"","sources":["../../src/tools/defaultTools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAkB,gBAAgB,EAAC,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAC,oBAAoB,EAAC,MAAM,sBAAsB,CAAC;AAE1D,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,CAAC,EAAE,gBAAgB,CAAC;CAC1B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,QAAQ,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAChD,OAAO,CAAC,EAAE,mBAAmB,GAC5B,oBAAoB,CAKtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultTools.js","sourceRoot":"","sources":["../../src/tools/defaultTools.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,eAAe,EAAmB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"defaultTools.js","sourceRoot":"","sources":["../../src/tools/defaultTools.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,eAAe,EAAmB,MAAM,mBAAmB,CAAC;AAOpE;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,KAAgD,EAChD,OAA6B;IAE7B,MAAM,EAAC,KAAK,EAAC,GAAG,OAAO,IAAI,EAAE,CAAC;IAC9B,OAAO;QACL,KAAK,EAAE,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC;KACrC,CAAC;AACJ,CAAC","sourcesContent":["import {AiSliceState} from '@sqlrooms/ai-core';\nimport {DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {StoreApi} from '@sqlrooms/room-shell';\nimport {createQueryTool, QueryToolOptions} from './query/queryTool';\nimport {OpenAssistantToolSet} from '@openassistant/utils';\n\nexport type DefaultToolsOptions = {\n query?: QueryToolOptions;\n};\n\n/**\n * Default tools available to the AI assistant for data analysis\n * Includes:\n * - query: Executes SQL queries against DuckDB\n */\nexport function createDefaultAiTools(\n store: StoreApi<AiSliceState & DuckDbSliceState>,\n options?: DefaultToolsOptions,\n): OpenAssistantToolSet {\n const {query} = options || {};\n return {\n query: createQueryTool(store, query),\n };\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { AiSliceState
|
|
1
|
+
import { AiSliceState } from '@sqlrooms/ai-core';
|
|
2
|
+
import { OpenAssistantTool } from '@openassistant/utils';
|
|
2
3
|
import { DuckDbSliceState } from '@sqlrooms/duckdb';
|
|
3
4
|
import type { StoreApi } from '@sqlrooms/room-shell';
|
|
4
5
|
import { z } from 'zod';
|
|
@@ -6,20 +7,26 @@ export declare const QueryToolParameters: z.ZodObject<{
|
|
|
6
7
|
type: z.ZodLiteral<"query">;
|
|
7
8
|
sqlQuery: z.ZodString;
|
|
8
9
|
reasoning: z.ZodString;
|
|
9
|
-
},
|
|
10
|
-
sqlQuery: string;
|
|
11
|
-
type: "query";
|
|
12
|
-
reasoning: string;
|
|
13
|
-
}, {
|
|
14
|
-
sqlQuery: string;
|
|
15
|
-
type: "query";
|
|
16
|
-
reasoning: string;
|
|
17
|
-
}>;
|
|
10
|
+
}, z.core.$strip>;
|
|
18
11
|
export type QueryToolParameters = z.infer<typeof QueryToolParameters>;
|
|
12
|
+
export type QueryToolLlmResult = {
|
|
13
|
+
success: boolean;
|
|
14
|
+
data?: {
|
|
15
|
+
type: 'query';
|
|
16
|
+
summary: Record<string, unknown>[] | null;
|
|
17
|
+
firstRows?: Record<string, unknown>[];
|
|
18
|
+
};
|
|
19
|
+
details?: string;
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
};
|
|
22
|
+
export type QueryToolAdditionalData = {
|
|
23
|
+
title: string;
|
|
24
|
+
sqlQuery: string;
|
|
25
|
+
};
|
|
19
26
|
export type QueryToolOptions = {
|
|
20
27
|
readOnly?: boolean;
|
|
21
28
|
autoSummary?: boolean;
|
|
22
29
|
numberOfRowsToShareWithLLM?: number;
|
|
23
30
|
};
|
|
24
|
-
export declare function createQueryTool(store: StoreApi<AiSliceState & DuckDbSliceState>, options?: QueryToolOptions):
|
|
31
|
+
export declare function createQueryTool(store: StoreApi<AiSliceState & DuckDbSliceState>, options?: QueryToolOptions): OpenAssistantTool<typeof QueryToolParameters, QueryToolLlmResult, QueryToolAdditionalData, unknown>;
|
|
25
32
|
//# sourceMappingURL=queryTool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryTool.d.ts","sourceRoot":"","sources":["../../../src/tools/query/queryTool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"queryTool.d.ts","sourceRoot":"","sources":["../../../src/tools/query/queryTool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAGL,gBAAgB,EAEjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAGtB,eAAO,MAAM,mBAAmB;;;;iBAI9B,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEtE,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE;QACL,IAAI,EAAE,OAAO,CAAC;QACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;QAC1C,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;KACvC,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC,CAAC;AAEF,wBAAgB,eAAe,CAC7B,KAAK,EAAE,QAAQ,CAAC,YAAY,GAAG,gBAAgB,CAAC,EAChD,OAAO,CAAC,EAAE,gBAAgB,GACzB,iBAAiB,CAClB,OAAO,mBAAmB,EAC1B,kBAAkB,EAClB,uBAAuB,EACvB,OAAO,CACR,CA+FA"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { extendedTool } from '@openassistant/utils';
|
|
2
1
|
import { arrowTableToJson, splitSqlStatements, } from '@sqlrooms/duckdb';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
import { QueryToolResult } from './QueryToolResult';
|
|
@@ -9,12 +8,14 @@ export const QueryToolParameters = z.object({
|
|
|
9
8
|
});
|
|
10
9
|
export function createQueryTool(store, options) {
|
|
11
10
|
const { readOnly = true, autoSummary = false, numberOfRowsToShareWithLLM = 0, } = options || {};
|
|
12
|
-
return
|
|
11
|
+
return {
|
|
12
|
+
name: 'query',
|
|
13
13
|
description: `A tool for running SQL queries on the tables in the database.
|
|
14
14
|
Please only run one query at a time.
|
|
15
15
|
If a query fails, please don't try to run it again with the same syntax.`,
|
|
16
16
|
parameters: QueryToolParameters,
|
|
17
|
-
execute: async (
|
|
17
|
+
execute: async (params) => {
|
|
18
|
+
const { type, sqlQuery } = params;
|
|
18
19
|
try {
|
|
19
20
|
const connector = await store.getState().db.getConnector();
|
|
20
21
|
// TODO use options.abortSignal: maybe call db.cancelPendingQuery
|
|
@@ -82,7 +83,7 @@ If a query fails, please don't try to run it again with the same syntax.`,
|
|
|
82
83
|
}
|
|
83
84
|
},
|
|
84
85
|
component: QueryToolResult,
|
|
85
|
-
}
|
|
86
|
+
};
|
|
86
87
|
}
|
|
87
88
|
/**
|
|
88
89
|
* Generates summary statistics for a SQL query result
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queryTool.js","sourceRoot":"","sources":["../../../src/tools/query/queryTool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"queryTool.js","sourceRoot":"","sources":["../../../src/tools/query/queryTool.ts"],"names":[],"mappings":"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","sourcesContent":["import {AiSliceState} from '@sqlrooms/ai-core';\nimport {OpenAssistantTool} from '@openassistant/utils';\nimport {\n arrowTableToJson,\n DuckDbConnector,\n DuckDbSliceState,\n splitSqlStatements,\n} from '@sqlrooms/duckdb';\nimport type {StoreApi} from '@sqlrooms/room-shell';\nimport {z} from 'zod';\nimport {QueryToolResult} from './QueryToolResult';\n\nexport const QueryToolParameters = z.object({\n type: z.literal('query'),\n sqlQuery: z.string(),\n reasoning: z.string(),\n});\nexport type QueryToolParameters = z.infer<typeof QueryToolParameters>;\n\nexport type QueryToolLlmResult = {\n success: boolean;\n data?: {\n type: 'query';\n summary: Record<string, unknown>[] | null;\n firstRows?: Record<string, unknown>[];\n };\n details?: string;\n errorMessage?: string;\n};\n\nexport type QueryToolAdditionalData = {\n title: string;\n sqlQuery: string;\n};\n\nexport type QueryToolOptions = {\n readOnly?: boolean;\n autoSummary?: boolean;\n numberOfRowsToShareWithLLM?: number;\n};\n\nexport function createQueryTool(\n store: StoreApi<AiSliceState & DuckDbSliceState>,\n options?: QueryToolOptions,\n): OpenAssistantTool<\n typeof QueryToolParameters,\n QueryToolLlmResult,\n QueryToolAdditionalData,\n unknown\n> {\n const {\n readOnly = true,\n autoSummary = false,\n numberOfRowsToShareWithLLM = 0,\n } = options || {};\n return {\n name: 'query',\n description: `A tool for running SQL queries on the tables in the database.\nPlease only run one query at a time.\nIf a query fails, please don't try to run it again with the same syntax.`,\n parameters: QueryToolParameters,\n execute: async (params: QueryToolParameters) => {\n const {type, sqlQuery} = params;\n try {\n const connector = await store.getState().db.getConnector();\n // TODO use options.abortSignal: maybe call db.cancelPendingQuery\n const result = await connector.query(sqlQuery);\n\n const parsedQuery = await store.getState().db.sqlSelectToJson(sqlQuery);\n\n if (\n parsedQuery.error &&\n // Only SELECT statements can be serialized to json, so we ignore not implemented errors\n parsedQuery.error_type !== 'not implemented'\n ) {\n throw new Error(parsedQuery.error_message);\n }\n\n if (readOnly) {\n if (parsedQuery.error) {\n throw new Error(\n `Query is not a valid SELECT statement: ${parsedQuery.error_message}`,\n );\n }\n if (\n parsedQuery.statements.length !== 1 || // only one statement allowed\n parsedQuery.statements[0]?.node.type !== 'SELECT_NODE' // only SELECT statements allowed\n ) {\n throw new Error('Query is not a valid SELECT statement');\n }\n }\n\n const summaryData = await (async () => {\n if (!autoSummary) return null;\n if (parsedQuery.error) return null;\n const lastNode =\n parsedQuery.statements[parsedQuery.statements.length - 1]?.node;\n\n // Only get summary if the last statement isn't already a SUMMARIZE query\n if (\n lastNode?.type === 'SELECT_NODE' &&\n lastNode?.from_table?.show_type === 'SUMMARY'\n ) {\n return arrowTableToJson(result);\n }\n const statements = splitSqlStatements(sqlQuery);\n const lastStatement = statements[statements.length - 1];\n if (!lastStatement) return null;\n return await getQuerySummary(connector, lastStatement);\n })();\n\n // Conditionally get rows of the result as a json object based on numberOfRowsToShareWithLLM\n const firstRows =\n numberOfRowsToShareWithLLM > 0\n ? arrowTableToJson(result.slice(0, numberOfRowsToShareWithLLM))\n : [];\n\n return {\n llmResult: {\n success: true,\n data: {\n type,\n summary: summaryData,\n ...(numberOfRowsToShareWithLLM > 0 ? {firstRows} : {}),\n },\n },\n additionalData: {\n title: 'Query Result',\n sqlQuery,\n },\n };\n } catch (error) {\n return {\n llmResult: {\n success: false,\n details: 'Query execution failed.',\n errorMessage:\n error instanceof Error ? error.message : 'Unknown error',\n },\n };\n }\n },\n component: QueryToolResult,\n };\n}\n\n/**\n * Generates summary statistics for a SQL query result\n * @param connector - DuckDB connection instance\n * @param sqlQuery - SQL SELECT query to analyze\n * @returns Summary statistics as JSON object, or null if the query is not a SELECT statement or if summary generation fails\n */\nasync function getQuerySummary(connector: DuckDbConnector, sqlQuery: string) {\n if (!sqlQuery.toLowerCase().trim().startsWith('select')) {\n return null;\n }\n\n try {\n const summaryResult = await connector.query(`SUMMARIZE (\n ${sqlQuery}\n )`);\n return arrowTableToJson(summaryResult);\n } catch (error) {\n console.warn('Failed to get summary for query. Error:', error);\n return null;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlrooms/ai",
|
|
3
|
-
"version": "0.26.0-rc.
|
|
3
|
+
"version": "0.26.0-rc.3",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -18,21 +18,23 @@
|
|
|
18
18
|
"access": "public"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@
|
|
22
|
-
"@sqlrooms/ai-
|
|
23
|
-
"@sqlrooms/ai-
|
|
24
|
-
"@sqlrooms/
|
|
25
|
-
"@sqlrooms/
|
|
26
|
-
"@sqlrooms/
|
|
27
|
-
"@sqlrooms/
|
|
28
|
-
"
|
|
21
|
+
"@openassistant/utils": "1.0.0-alpha.0",
|
|
22
|
+
"@sqlrooms/ai-config": "0.26.0-rc.3",
|
|
23
|
+
"@sqlrooms/ai-core": "0.26.0-rc.3",
|
|
24
|
+
"@sqlrooms/ai-settings": "0.26.0-rc.3",
|
|
25
|
+
"@sqlrooms/data-table": "0.26.0-rc.3",
|
|
26
|
+
"@sqlrooms/duckdb": "0.26.0-rc.3",
|
|
27
|
+
"@sqlrooms/room-shell": "0.26.0-rc.3",
|
|
28
|
+
"@sqlrooms/ui": "0.26.0-rc.3",
|
|
29
|
+
"@sqlrooms/utils": "0.26.0-rc.3",
|
|
30
|
+
"ai": "^5.0.44",
|
|
29
31
|
"immer": "^10.1.3",
|
|
30
32
|
"lucide-react": "^0.544.0",
|
|
31
33
|
"react-markdown": "^10.1.0",
|
|
32
34
|
"recharts": "^2.12.7",
|
|
33
35
|
"rehype-raw": "^7.0.0",
|
|
34
36
|
"remark-gfm": "^4.0.0",
|
|
35
|
-
"zod": "^
|
|
37
|
+
"zod": "^4.1.8"
|
|
36
38
|
},
|
|
37
39
|
"peerDependencies": {
|
|
38
40
|
"apache-arrow": "17.0.0",
|
|
@@ -46,5 +48,5 @@
|
|
|
46
48
|
"typecheck": "tsc --noEmit",
|
|
47
49
|
"typedoc": "typedoc"
|
|
48
50
|
},
|
|
49
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "536764b2aa924e5bb6650fe0bc674113179ff444"
|
|
50
52
|
}
|