Flowise

Форк
0
301 строка · 12.9 Кб
1
import OpenAI from 'openai'
2
import { StatusCodes } from 'http-status-codes'
3
import { uniqWith, isEqual, cloneDeep } from 'lodash'
4
import { getRunningExpressApp } from '../../utils/getRunningExpressApp'
5
import { Assistant } from '../../database/entities/Assistant'
6
import { Credential } from '../../database/entities/Credential'
7
import { decryptCredentialData, getAppVersion } from '../../utils'
8
import { InternalFlowiseError } from '../../errors/internalFlowiseError'
9
import { getErrorMessage } from '../../errors/utils'
10

11
const createAssistant = async (requestBody: any): Promise<any> => {
12
    try {
13
        const appServer = getRunningExpressApp()
14
        if (!requestBody.details) {
15
            throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Invalid request body`)
16
        }
17
        const assistantDetails = JSON.parse(requestBody.details)
18
        try {
19
            const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
20
                id: requestBody.credential
21
            })
22

23
            if (!credential) {
24
                throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Credential ${requestBody.credential} not found`)
25
            }
26

27
            // Decrpyt credentialData
28
            const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
29
            const openAIApiKey = decryptedCredentialData['openAIApiKey']
30
            if (!openAIApiKey) {
31
                throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `OpenAI ApiKey not found`)
32
            }
33
            const openai = new OpenAI({ apiKey: openAIApiKey })
34

35
            // Prepare tools
36
            let tools = []
37
            if (assistantDetails.tools) {
38
                for (const tool of assistantDetails.tools ?? []) {
39
                    tools.push({
40
                        type: tool
41
                    })
42
                }
43
            }
44

45
            // Save tool_resources to be stored later into database
46
            const savedToolResources = cloneDeep(assistantDetails.tool_resources)
47

48
            // Cleanup tool_resources for creating assistant
49
            if (assistantDetails.tool_resources) {
50
                for (const toolResource in assistantDetails.tool_resources) {
51
                    if (toolResource === 'file_search') {
52
                        assistantDetails.tool_resources['file_search'] = {
53
                            vector_store_ids: assistantDetails.tool_resources['file_search'].vector_store_ids
54
                        }
55
                    } else if (toolResource === 'code_interpreter') {
56
                        assistantDetails.tool_resources['code_interpreter'] = {
57
                            file_ids: assistantDetails.tool_resources['code_interpreter'].file_ids
58
                        }
59
                    }
60
                }
61
            }
62

63
            // If the assistant doesn't exist, create a new one
64
            if (!assistantDetails.id) {
65
                const newAssistant = await openai.beta.assistants.create({
66
                    name: assistantDetails.name,
67
                    description: assistantDetails.description,
68
                    instructions: assistantDetails.instructions,
69
                    model: assistantDetails.model,
70
                    tools,
71
                    tool_resources: assistantDetails.tool_resources,
72
                    temperature: assistantDetails.temperature,
73
                    top_p: assistantDetails.top_p
74
                })
75
                assistantDetails.id = newAssistant.id
76
            } else {
77
                const retrievedAssistant = await openai.beta.assistants.retrieve(assistantDetails.id)
78
                let filteredTools = uniqWith([...retrievedAssistant.tools.filter((tool) => tool.type === 'function'), ...tools], isEqual)
79
                // Remove empty functions
80
                filteredTools = filteredTools.filter((tool) => !(tool.type === 'function' && !(tool as any).function))
81

82
                await openai.beta.assistants.update(assistantDetails.id, {
83
                    name: assistantDetails.name,
84
                    description: assistantDetails.description ?? '',
85
                    instructions: assistantDetails.instructions ?? '',
86
                    model: assistantDetails.model,
87
                    tools: filteredTools,
88
                    tool_resources: assistantDetails.tool_resources,
89
                    temperature: assistantDetails.temperature,
90
                    top_p: assistantDetails.top_p
91
                })
92
            }
93

94
            const newAssistantDetails = {
95
                ...assistantDetails
96
            }
97
            if (savedToolResources) newAssistantDetails.tool_resources = savedToolResources
98

99
            requestBody.details = JSON.stringify(newAssistantDetails)
100
        } catch (error) {
101
            throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Error creating new assistant - ${getErrorMessage(error)}`)
102
        }
103
        const newAssistant = new Assistant()
104
        Object.assign(newAssistant, requestBody)
105

106
        const assistant = appServer.AppDataSource.getRepository(Assistant).create(newAssistant)
107
        const dbResponse = await appServer.AppDataSource.getRepository(Assistant).save(assistant)
108

109
        await appServer.telemetry.sendTelemetry('assistant_created', {
110
            version: await getAppVersion(),
111
            assistantId: dbResponse.id
112
        })
113
        return dbResponse
114
    } catch (error) {
115
        throw new InternalFlowiseError(
116
            StatusCodes.INTERNAL_SERVER_ERROR,
117
            `Error: assistantsService.createAssistant - ${getErrorMessage(error)}`
118
        )
119
    }
120
}
121

122
const deleteAssistant = async (assistantId: string, isDeleteBoth: any): Promise<any> => {
123
    try {
124
        const appServer = getRunningExpressApp()
125
        const assistant = await appServer.AppDataSource.getRepository(Assistant).findOneBy({
126
            id: assistantId
127
        })
128
        if (!assistant) {
129
            throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Assistant ${assistantId} not found`)
130
        }
131
        try {
132
            const assistantDetails = JSON.parse(assistant.details)
133
            const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
134
                id: assistant.credential
135
            })
136

137
            if (!credential) {
138
                throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Credential ${assistant.credential} not found`)
139
            }
140

141
            // Decrpyt credentialData
142
            const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
143
            const openAIApiKey = decryptedCredentialData['openAIApiKey']
144
            if (!openAIApiKey) {
145
                throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `OpenAI ApiKey not found`)
146
            }
147

148
            const openai = new OpenAI({ apiKey: openAIApiKey })
149
            const dbResponse = await appServer.AppDataSource.getRepository(Assistant).delete({ id: assistantId })
150
            if (isDeleteBoth) await openai.beta.assistants.del(assistantDetails.id)
151
            return dbResponse
152
        } catch (error: any) {
153
            if (error.status === 404 && error.type === 'invalid_request_error') {
154
                return 'OK'
155
            } else {
156
                throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Error deleting assistant - ${getErrorMessage(error)}`)
157
            }
158
        }
159
    } catch (error) {
160
        throw new InternalFlowiseError(
161
            StatusCodes.INTERNAL_SERVER_ERROR,
162
            `Error: assistantsService.deleteAssistant - ${getErrorMessage(error)}`
163
        )
164
    }
165
}
166

167
const getAllAssistants = async (): Promise<any> => {
168
    try {
169
        const appServer = getRunningExpressApp()
170
        const dbResponse = await appServer.AppDataSource.getRepository(Assistant).find()
171
        return dbResponse
172
    } catch (error) {
173
        throw new InternalFlowiseError(
174
            StatusCodes.INTERNAL_SERVER_ERROR,
175
            `Error: assistantsService.getAllAssistants - ${getErrorMessage(error)}`
176
        )
177
    }
178
}
179

180
const getAssistantById = async (assistantId: string): Promise<any> => {
181
    try {
182
        const appServer = getRunningExpressApp()
183
        const dbResponse = await appServer.AppDataSource.getRepository(Assistant).findOneBy({
184
            id: assistantId
185
        })
186
        if (!dbResponse) {
187
            throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Assistant ${assistantId} not found`)
188
        }
189
        return dbResponse
190
    } catch (error) {
191
        throw new InternalFlowiseError(
192
            StatusCodes.INTERNAL_SERVER_ERROR,
193
            `Error: assistantsService.getAssistantById - ${getErrorMessage(error)}`
194
        )
195
    }
196
}
197

198
const updateAssistant = async (assistantId: string, requestBody: any): Promise<any> => {
199
    try {
200
        const appServer = getRunningExpressApp()
201
        const assistant = await appServer.AppDataSource.getRepository(Assistant).findOneBy({
202
            id: assistantId
203
        })
204

205
        if (!assistant) {
206
            throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Assistant ${assistantId} not found`)
207
        }
208
        try {
209
            const openAIAssistantId = JSON.parse(assistant.details)?.id
210
            const body = requestBody
211
            const assistantDetails = JSON.parse(body.details)
212
            const credential = await appServer.AppDataSource.getRepository(Credential).findOneBy({
213
                id: body.credential
214
            })
215

216
            if (!credential) {
217
                throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `Credential ${body.credential} not found`)
218
            }
219

220
            // Decrpyt credentialData
221
            const decryptedCredentialData = await decryptCredentialData(credential.encryptedData)
222
            const openAIApiKey = decryptedCredentialData['openAIApiKey']
223
            if (!openAIApiKey) {
224
                throw new InternalFlowiseError(StatusCodes.NOT_FOUND, `OpenAI ApiKey not found`)
225
            }
226

227
            const openai = new OpenAI({ apiKey: openAIApiKey })
228

229
            let tools = []
230
            if (assistantDetails.tools) {
231
                for (const tool of assistantDetails.tools ?? []) {
232
                    tools.push({
233
                        type: tool
234
                    })
235
                }
236
            }
237

238
            // Save tool_resources to be stored later into database
239
            const savedToolResources = cloneDeep(assistantDetails.tool_resources)
240

241
            // Cleanup tool_resources before updating
242
            if (assistantDetails.tool_resources) {
243
                for (const toolResource in assistantDetails.tool_resources) {
244
                    if (toolResource === 'file_search') {
245
                        assistantDetails.tool_resources['file_search'] = {
246
                            vector_store_ids: assistantDetails.tool_resources['file_search'].vector_store_ids
247
                        }
248
                    } else if (toolResource === 'code_interpreter') {
249
                        assistantDetails.tool_resources['code_interpreter'] = {
250
                            file_ids: assistantDetails.tool_resources['code_interpreter'].file_ids
251
                        }
252
                    }
253
                }
254
            }
255

256
            const retrievedAssistant = await openai.beta.assistants.retrieve(openAIAssistantId)
257
            let filteredTools = uniqWith([...retrievedAssistant.tools.filter((tool) => tool.type === 'function'), ...tools], isEqual)
258
            filteredTools = filteredTools.filter((tool) => !(tool.type === 'function' && !(tool as any).function))
259

260
            await openai.beta.assistants.update(openAIAssistantId, {
261
                name: assistantDetails.name,
262
                description: assistantDetails.description,
263
                instructions: assistantDetails.instructions,
264
                model: assistantDetails.model,
265
                tools: filteredTools,
266
                tool_resources: assistantDetails.tool_resources,
267
                temperature: assistantDetails.temperature,
268
                top_p: assistantDetails.top_p
269
            })
270

271
            const newAssistantDetails = {
272
                ...assistantDetails,
273
                id: openAIAssistantId
274
            }
275
            if (savedToolResources) newAssistantDetails.tool_resources = savedToolResources
276

277
            const updateAssistant = new Assistant()
278
            body.details = JSON.stringify(newAssistantDetails)
279
            Object.assign(updateAssistant, body)
280

281
            appServer.AppDataSource.getRepository(Assistant).merge(assistant, updateAssistant)
282
            const dbResponse = await appServer.AppDataSource.getRepository(Assistant).save(assistant)
283
            return dbResponse
284
        } catch (error) {
285
            throw new InternalFlowiseError(StatusCodes.INTERNAL_SERVER_ERROR, `Error updating assistant - ${getErrorMessage(error)}`)
286
        }
287
    } catch (error) {
288
        throw new InternalFlowiseError(
289
            StatusCodes.INTERNAL_SERVER_ERROR,
290
            `Error: assistantsService.updateAssistant - ${getErrorMessage(error)}`
291
        )
292
    }
293
}
294

295
export default {
296
    createAssistant,
297
    deleteAssistant,
298
    getAllAssistants,
299
    getAssistantById,
300
    updateAssistant
301
}
302

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.