@deepagents/text2sql 0.34.0 → 0.36.0
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 +102 -51
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adapters/postgres/index.js +0 -6
- package/dist/lib/adapters/postgres/index.js.map +2 -2
- package/dist/lib/adapters/postgres/postgres.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/index.js +3 -8
- package/dist/lib/adapters/sqlserver/index.js.map +2 -2
- package/dist/lib/adapters/sqlserver/info.sqlserver.grounding.d.ts.map +1 -1
- package/dist/lib/adapters/sqlserver/sqlserver.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/base-contextual-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/extractors/message-extractor.d.ts.map +1 -1
- package/dist/lib/synthesis/index.js +6 -13
- package/dist/lib/synthesis/index.js.map +3 -3
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ AI-powered natural language to SQL. Ask questions in plain English, get executab
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- **Natural Language to SQL** - Convert questions to validated, executable queries
|
|
8
|
-
- **Multi-Database Support** - PostgreSQL, SQLite,
|
|
8
|
+
- **Multi-Database Support** - PostgreSQL, SQLite, SQL Server, MySQL/MariaDB, and BigQuery adapters
|
|
9
9
|
- **Schema-Aware** - Automatic introspection of tables, relationships, indexes, and constraints
|
|
10
10
|
- **Domain Knowledge** - Inject business terms, guardrails, and query patterns via fragments
|
|
11
11
|
- **Conversational** - Multi-turn conversations with context persistence
|
|
@@ -23,16 +23,18 @@ Requires Node.js LTS (20+).
|
|
|
23
23
|
|
|
24
24
|
```typescript
|
|
25
25
|
import { groq } from '@ai-sdk/groq';
|
|
26
|
+
import { InMemoryFs } from 'just-bash';
|
|
26
27
|
import pg from 'pg';
|
|
27
28
|
|
|
28
|
-
import { InMemoryContextStore } from '@deepagents/context';
|
|
29
|
+
import { ContextEngine, InMemoryContextStore } from '@deepagents/context';
|
|
29
30
|
import { Text2Sql } from '@deepagents/text2sql';
|
|
30
31
|
import {
|
|
31
32
|
Postgres,
|
|
33
|
+
columnValues,
|
|
32
34
|
constraints,
|
|
33
35
|
indexes,
|
|
34
36
|
info,
|
|
35
|
-
|
|
37
|
+
rowCount,
|
|
36
38
|
tables,
|
|
37
39
|
views,
|
|
38
40
|
} from '@deepagents/text2sql/postgres';
|
|
@@ -41,24 +43,37 @@ const pool = new pg.Pool({
|
|
|
41
43
|
connectionString: process.env.DATABASE_URL,
|
|
42
44
|
});
|
|
43
45
|
|
|
46
|
+
const store = new InMemoryContextStore();
|
|
47
|
+
const adapter = new Postgres({
|
|
48
|
+
execute: async (sql) => {
|
|
49
|
+
const result = await pool.query(sql);
|
|
50
|
+
return result.rows;
|
|
51
|
+
},
|
|
52
|
+
grounding: [
|
|
53
|
+
tables(),
|
|
54
|
+
views(),
|
|
55
|
+
info(),
|
|
56
|
+
indexes(),
|
|
57
|
+
constraints(),
|
|
58
|
+
rowCount(),
|
|
59
|
+
columnValues(),
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
|
|
44
63
|
const text2sql = new Text2Sql({
|
|
45
64
|
version: 'v1',
|
|
46
|
-
model: groq('gpt-oss-20b'),
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
lowCardinality(),
|
|
59
|
-
],
|
|
60
|
-
}),
|
|
61
|
-
store: new InMemoryContextStore(),
|
|
65
|
+
model: groq('openai/gpt-oss-20b'),
|
|
66
|
+
filesystem: new InMemoryFs(),
|
|
67
|
+
adapter,
|
|
68
|
+
context: (...fragments) => {
|
|
69
|
+
const engine = new ContextEngine({
|
|
70
|
+
store,
|
|
71
|
+
chatId: 'chat-123',
|
|
72
|
+
userId: 'user-456',
|
|
73
|
+
});
|
|
74
|
+
engine.set(...fragments);
|
|
75
|
+
return engine;
|
|
76
|
+
},
|
|
62
77
|
});
|
|
63
78
|
|
|
64
79
|
// Generate SQL
|
|
@@ -72,14 +87,31 @@ Text2SQL works with any model provider supported by the [Vercel AI SDK](https://
|
|
|
72
87
|
|
|
73
88
|
## Fragments
|
|
74
89
|
|
|
75
|
-
Inject domain knowledge using fragments from `@deepagents/context`
|
|
90
|
+
Inject domain knowledge using fragments from `@deepagents/context` inside the
|
|
91
|
+
`context` factory you pass to `Text2Sql`. Those fragments affect `chat()`
|
|
92
|
+
sessions. If you need direct SQL generation with extra fragments, use the
|
|
93
|
+
lower-level `toSql({ fragments })` helper exported from `@deepagents/text2sql`.
|
|
76
94
|
|
|
77
95
|
```typescript
|
|
78
|
-
import {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
import {
|
|
97
|
+
ContextEngine,
|
|
98
|
+
InMemoryContextStore,
|
|
99
|
+
example,
|
|
100
|
+
guardrail,
|
|
101
|
+
hint,
|
|
102
|
+
term,
|
|
103
|
+
} from '@deepagents/context';
|
|
104
|
+
|
|
105
|
+
const store = new InMemoryContextStore();
|
|
106
|
+
|
|
107
|
+
const context = (...fragments) => {
|
|
108
|
+
const engine = new ContextEngine({
|
|
109
|
+
store,
|
|
110
|
+
chatId: 'chat-123',
|
|
111
|
+
userId: 'user-456',
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
engine.set(
|
|
83
115
|
term('MRR', 'monthly recurring revenue'),
|
|
84
116
|
hint('Always exclude test accounts with email ending in @test.com'),
|
|
85
117
|
guardrail({
|
|
@@ -91,8 +123,11 @@ const text2sql = new Text2Sql({
|
|
|
91
123
|
question: 'show me churned customers',
|
|
92
124
|
answer: `SELECT * FROM customers WHERE status = 'churned' ORDER BY churned_at DESC`,
|
|
93
125
|
}),
|
|
94
|
-
|
|
95
|
-
|
|
126
|
+
...fragments,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
return engine;
|
|
130
|
+
};
|
|
96
131
|
```
|
|
97
132
|
|
|
98
133
|
**Domain fragments** (11 types): `term`, `hint`, `guardrail`, `example`, `explain`, `clarification`, `workflow`, `quirk`, `styleGuide`, `analogy`, `glossary`.
|
|
@@ -105,39 +140,53 @@ See [@deepagents/context](../context/README.md) for full fragment documentation.
|
|
|
105
140
|
|
|
106
141
|
Control what schema metadata the AI receives:
|
|
107
142
|
|
|
108
|
-
| Function
|
|
109
|
-
|
|
|
110
|
-
| `tables()`
|
|
111
|
-
| `views()`
|
|
112
|
-
| `info()`
|
|
113
|
-
| `indexes()`
|
|
114
|
-
| `constraints()`
|
|
115
|
-
| `rowCount()`
|
|
116
|
-
| `columnStats()`
|
|
117
|
-
| `
|
|
143
|
+
| Function | Description |
|
|
144
|
+
| ---------------- | --------------------------------------------------------- |
|
|
145
|
+
| `tables()` | Tables, columns, and primary keys |
|
|
146
|
+
| `views()` | Database views |
|
|
147
|
+
| `info()` | Database version and info |
|
|
148
|
+
| `indexes()` | Index information for performance hints |
|
|
149
|
+
| `constraints()` | Foreign keys and other constraints |
|
|
150
|
+
| `rowCount()` | Table sizes (tiny, small, medium, large, huge) |
|
|
151
|
+
| `columnStats()` | Min/max/null distribution for columns |
|
|
152
|
+
| `columnValues()` | Enum-like and low-cardinality columns with sampled values |
|
|
118
153
|
|
|
119
154
|
## Conversations
|
|
120
155
|
|
|
121
|
-
|
|
156
|
+
`chat()` persists history through the `ContextEngine` returned by your `context` factory. Reuse the same store, `chatId`, and `userId` to continue the same thread:
|
|
122
157
|
|
|
123
158
|
```typescript
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
const stream = await text2sql.chat(
|
|
128
|
-
[{ role: 'user', content: 'Show me orders from last month' }],
|
|
129
|
-
{ chatId, userId },
|
|
130
|
-
);
|
|
159
|
+
const stream = await text2sql.chat([
|
|
160
|
+
{ role: 'user', content: 'Show me orders from last month' },
|
|
161
|
+
]);
|
|
131
162
|
|
|
132
163
|
for await (const chunk of stream) {
|
|
133
164
|
// handle streaming response
|
|
134
165
|
}
|
|
135
166
|
|
|
136
|
-
// Continue the
|
|
137
|
-
const followUp = await text2sql.chat(
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
167
|
+
// Continue the same conversation
|
|
168
|
+
const followUp = await text2sql.chat([
|
|
169
|
+
{ role: 'user', content: 'Now filter to only completed ones' },
|
|
170
|
+
]);
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Direct SQL Generation with Extra Fragments
|
|
174
|
+
|
|
175
|
+
```typescript
|
|
176
|
+
import { term } from '@deepagents/context';
|
|
177
|
+
import { toSql } from '@deepagents/text2sql';
|
|
178
|
+
|
|
179
|
+
const result = await toSql({
|
|
180
|
+
input: 'Show ARR by plan',
|
|
181
|
+
adapter,
|
|
182
|
+
model: groq('openai/gpt-oss-20b'),
|
|
183
|
+
fragments: [
|
|
184
|
+
...(await adapter.introspect()),
|
|
185
|
+
term('ARR', 'annual recurring revenue'),
|
|
186
|
+
],
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
console.log(result.sql);
|
|
141
190
|
```
|
|
142
191
|
|
|
143
192
|
## Documentation
|
|
@@ -145,13 +194,15 @@ const followUp = await text2sql.chat(
|
|
|
145
194
|
Full documentation available at [januarylabs.github.io/deepagents](https://januarylabs.github.io/deepagents/docs/text2sql):
|
|
146
195
|
|
|
147
196
|
- [Getting Started](https://januarylabs.github.io/deepagents/docs/text2sql/getting-started)
|
|
148
|
-
- [Generate SQL](https://januarylabs.github.io/deepagents/docs/text2sql/
|
|
197
|
+
- [Generate SQL](https://januarylabs.github.io/deepagents/docs/text2sql/to-sql)
|
|
149
198
|
- [Teach the System](https://januarylabs.github.io/deepagents/docs/text2sql/teach-the-system)
|
|
150
199
|
- [Build Conversations](https://januarylabs.github.io/deepagents/docs/text2sql/build-conversations)
|
|
151
200
|
- [Grounding](https://januarylabs.github.io/deepagents/docs/text2sql/grounding)
|
|
152
201
|
- [PostgreSQL](https://januarylabs.github.io/deepagents/docs/text2sql/postgresql)
|
|
153
202
|
- [SQLite](https://januarylabs.github.io/deepagents/docs/text2sql/sqlite)
|
|
154
203
|
- [SQL Server](https://januarylabs.github.io/deepagents/docs/text2sql/sqlserver)
|
|
204
|
+
- [MySQL / MariaDB](https://januarylabs.github.io/deepagents/docs/text2sql/mysql)
|
|
205
|
+
- [BigQuery](https://januarylabs.github.io/deepagents/docs/text2sql/bigquery)
|
|
155
206
|
|
|
156
207
|
## Repository
|
|
157
208
|
|
package/dist/index.js
CHANGED
|
@@ -5295,7 +5295,7 @@ Action: Ask user: "Top by what metric\u2014total revenue, number of orders, or m
|
|
|
5295
5295
|
// Style preferences
|
|
5296
5296
|
styleGuide({
|
|
5297
5297
|
prefer: "Full table names as aliases (users AS users). Descriptive column aliases (COUNT(*) AS total_count).",
|
|
5298
|
-
never: "Abbreviated aliases (u, oi) or positional aliases (t1, t2, a, b)."
|
|
5298
|
+
never: "Abbreviated aliases (u, oi) or positional aliases (t1, t2, a, b). Schema-qualified column references on aliased tables (e.g. dbo.users.id when table is aliased) \u2014 always use the alias (users.id)."
|
|
5299
5299
|
}),
|
|
5300
5300
|
styleGuide({
|
|
5301
5301
|
prefer: "Concise, business-friendly summaries with key comparisons and helpful follow-ups."
|