-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdatabase_query.ts
More file actions
99 lines (84 loc) · 2.96 KB
/
database_query.ts
File metadata and controls
99 lines (84 loc) · 2.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { Configuration, OpenAIApi } from "openai";
import { Action, ctx, io } from "@interval/sdk";
import { prisma } from "../../database";
export default new Action({
name: "🗂️ AI database query",
description: `Answer questions about ViewTube data with help from OpenAI`,
handler: async () => {
if (!process.env.OPENAI_API_KEY) {
throw new Error(
`This action requires the OPENAI_API_KEY environment variable to be set.`
);
}
const result = await prisma.$queryRawUnsafe<
{
table_name: string;
column_name: string;
}[]
>(`
SELECT
table_name,
column_name
FROM information_schema.columns
WHERE table_schema = 'public'
`);
const tablesWithProps: Record<string, string[]> = {};
for (const row of result) {
if (!tablesWithProps[row.table_name]) {
tablesWithProps[row.table_name] = [];
}
tablesWithProps[row.table_name].push(row.column_name);
}
const promptLines = [
`Given the following Postgres SQL tables each with the "public" table_schema, with their properties:`,
"#",
];
for (const [table, props] of Object.entries(tablesWithProps)) {
promptLines.push(`# ${table}(${props.join(", ")})`);
}
promptLines.push(`#`);
const userQuery = await io.input.text("What do you want to know?", {
multiline: true,
placeholder:
"List departments which employed more than 10 employees in the last 3 months",
});
promptLines.push(`Can you write a query to ${userQuery}`);
promptLines.push(
'Please make sure to enclose column names that contain uppercase characters in double quotes like this: SELECT "someColumn" from table;'
);
promptLines.push(`SELECT`);
const configuration = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);
const prompt = promptLines.join(`\n`);
// Uncomment these lines to debug prompt ⬇️
// await io.display.code(`Generating query using the following prompt:`, {
// code: prompt,
// language: "plaintext",
// });
await ctx.loading.start("Generating query...");
const response = await openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [{ content: prompt, role: "user" }],
temperature: 0,
max_tokens: 150,
top_p: 1.0,
frequency_penalty: 0.0,
presence_penalty: 0.0,
stop: ["#", ";"],
});
const aiQuery =
`SELECT ${response.data.choices[0].message?.content}`.trim();
const { choice } = await io.display
.markdown(["**Query to execute:**", "`" + aiQuery + "`"].join("\n"))
.withChoices(["Execute query", "Cancel"]);
if (choice !== "Execute query") {
return;
}
const aiQueryResult = await prisma.$queryRawUnsafe<any[]>(aiQuery);
await io.display.table(`${aiQueryResult.length} rows`, {
data: aiQueryResult,
});
},
});