File size: 2,709 Bytes
9705b6c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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;