-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathchat-gpt.ts
110 lines (102 loc) · 2.93 KB
/
chat-gpt.ts
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
100
101
102
103
104
105
106
107
108
109
110
import {
ChatCompletionRequestMessage,
CreateCompletionResponseUsage,
OpenAIApi
} from 'openai'
import { HistoryMode } from './options'
import { Result } from './result'
import { DatabaseConnection } from './connectors/utils'
import { Instrospection } from './types'
export type GptSqlResponse = {
query: string
sqlQuery?: string
result?: Result
error?: string
usage?: CreateCompletionResponseUsage
}
type MessageOptions = {
query: string
history?: GptSqlResponse[]
historyMode: HistoryMode
dbConnection: DatabaseConnection
introspection?: Instrospection
}
const createMessages = async ({
query,
history,
historyMode,
introspection,
dbConnection
}: MessageOptions): Promise<ChatCompletionRequestMessage[]> => {
// * Get the SQL introspection
const schema = JSON.stringify(
introspection ? introspection : await dbConnection.getIntrospection(),
null,
0
)
const messages: ChatCompletionRequestMessage[] = [
{
role: 'system',
content: `You are a database developer that only responds in ${dbConnection.dialectName} without formatting`
},
{
role: 'system',
content: 'uuids should be generated with gen_random_uuid()'
},
{
role: 'system',
content: 'queries on strings should be case insensitive'
},
{
role: 'system',
content: `database: ${schema}`
}
]
// * Add all previous queries
history
?.filter(entry => !!entry.sqlQuery)
.forEach(entry => {
messages.push({ role: 'user', content: entry.query })
messages.push({ role: 'assistant', content: entry.sqlQuery! })
if (historyMode === 'all' && entry.result) {
messages.push({
role: 'system',
content: `the result of the query is: ${JSON.stringify(
entry.result
)}`
})
}
if (entry.error) {
messages.push({
role: 'system',
content: `the query failed with error: ${entry.error}`
})
}
})
// * Add the query
messages.push({
role: 'user',
content: query
})
return messages
}
export const getSqlQuery = async ({
openai,
model,
...options
}: MessageOptions & {
openai: OpenAIApi
model: string
}): Promise<{ sqlQuery: string; usage?: CreateCompletionResponseUsage }> => {
// * Query OpenAI
const completion = await openai.createChatCompletion({
model,
messages: await createMessages(options),
temperature: 0
})
const sqlQuery = completion.data.choices[0].message?.content
if (!sqlQuery) {
throw new Error('empty response')
}
return { sqlQuery, usage: completion.data.usage }
}