| const { createStartHandler } = require('../callbacks'); | |
| const spendTokens = require('../../../models/spendTokens'); | |
| class RunManager { | |
| constructor(fields) { | |
| const { req, res, abortController, debug } = fields; | |
| this.abortController = abortController; | |
| this.user = req.user.id; | |
| this.req = req; | |
| this.res = res; | |
| this.debug = debug; | |
| this.runs = new Map(); | |
| this.convos = new Map(); | |
| } | |
| addRun(runId, runData) { | |
| if (!this.runs.has(runId)) { | |
| this.runs.set(runId, runData); | |
| if (runData.conversationId) { | |
| this.convos.set(runData.conversationId, runId); | |
| } | |
| return runData; | |
| } else { | |
| const existingData = this.runs.get(runId); | |
| const update = { ...existingData, ...runData }; | |
| this.runs.set(runId, update); | |
| if (update.conversationId) { | |
| this.convos.set(update.conversationId, runId); | |
| } | |
| return update; | |
| } | |
| } | |
| removeRun(runId) { | |
| if (this.runs.has(runId)) { | |
| this.runs.delete(runId); | |
| } else { | |
| console.error(`Run with ID ${runId} does not exist.`); | |
| } | |
| } | |
| getAllRuns() { | |
| return Array.from(this.runs.values()); | |
| } | |
| getRunById(runId) { | |
| return this.runs.get(runId); | |
| } | |
| getRunByConversationId(conversationId) { | |
| const runId = this.convos.get(conversationId); | |
| return { run: this.runs.get(runId), runId }; | |
| } | |
| createCallbacks(metadata) { | |
| return [ | |
| { | |
| handleChatModelStart: createStartHandler({ ...metadata, manager: this }), | |
| handleLLMEnd: async (output, runId, _parentRunId) => { | |
| if (this.debug) { | |
| console.log(`handleLLMEnd: ${JSON.stringify(metadata)}`); | |
| console.dir({ output, runId, _parentRunId }, { depth: null }); | |
| } | |
| const { tokenUsage } = output.llmOutput; | |
| const run = this.getRunById(runId); | |
| this.removeRun(runId); | |
| const txData = { | |
| user: this.user, | |
| model: run?.model ?? 'gpt-3.5-turbo', | |
| ...metadata, | |
| }; | |
| await spendTokens(txData, tokenUsage); | |
| }, | |
| handleLLMError: async (err) => { | |
| this.debug && console.log(`handleLLMError: ${JSON.stringify(metadata)}`); | |
| this.debug && console.error(err); | |
| if (metadata.context === 'title') { | |
| return; | |
| } else if (metadata.context === 'plugins') { | |
| throw new Error(err); | |
| } | |
| const { conversationId } = metadata; | |
| const { run } = this.getRunByConversationId(conversationId); | |
| if (run && run.error) { | |
| const { error } = run; | |
| throw new Error(error); | |
| } | |
| }, | |
| }, | |
| ]; | |
| } | |
| } | |
| module.exports = RunManager; | |