backend-manager 3.2.13 → 3.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -14,9 +14,7 @@ module.exports = function (payload, config) {
|
|
|
14
14
|
subject: `Free ${config.brand.name} download link for ${payload.name || 'you'}!`,
|
|
15
15
|
template: 'd-1d730ac8cc544b7cbccc8fa4a4b3f9ce',
|
|
16
16
|
group: 24077,
|
|
17
|
-
|
|
18
|
-
copy: false,
|
|
19
|
-
},
|
|
17
|
+
copy: false,
|
|
20
18
|
data: {},
|
|
21
19
|
}
|
|
22
20
|
}
|
|
@@ -330,6 +330,12 @@ BackendAssistant.prototype._log = function () {
|
|
|
330
330
|
}
|
|
331
331
|
}
|
|
332
332
|
|
|
333
|
+
BackendAssistant.prototype.getUser = function () {
|
|
334
|
+
const self = this;
|
|
335
|
+
|
|
336
|
+
return self?.usage?.user || self.request.user;
|
|
337
|
+
}
|
|
338
|
+
|
|
333
339
|
BackendAssistant.prototype.errorify = function (e, options) {
|
|
334
340
|
const self = this;
|
|
335
341
|
const res = self.ref.res;
|
|
@@ -27,6 +27,7 @@ Middleware.prototype.run = function (library, options) {
|
|
|
27
27
|
const data = assistant.request.data;
|
|
28
28
|
const geolocation = assistant.request.geolocation;
|
|
29
29
|
const client = assistant.request.client;
|
|
30
|
+
const isProduction = assistant.meta.environment === 'production';
|
|
30
31
|
|
|
31
32
|
// Set options
|
|
32
33
|
options = options || {};
|
|
@@ -56,11 +57,11 @@ Middleware.prototype.run = function (library, options) {
|
|
|
56
57
|
|
|
57
58
|
// Setup usage
|
|
58
59
|
if (options.setupUsage) {
|
|
59
|
-
assistant.usage = await Manager.Usage().init(assistant);
|
|
60
|
+
assistant.usage = await Manager.Usage().init(assistant, {log: isProduction});
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
// Log working user
|
|
63
|
-
const workingUser = assistant
|
|
64
|
+
const workingUser = assistant.getUser();
|
|
64
65
|
assistant.log(`Middleware.process(): User (${workingUser.auth.uid}, ${workingUser.auth.email}, ${workingUser.plan.id}=${workingUser.plan.status}):`, JSON.stringify(workingUser));
|
|
65
66
|
|
|
66
67
|
// Setup analytics
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
const fetch = require('wonderful-fetch');
|
|
2
|
+
const jetpack = require('fs-jetpack');
|
|
2
3
|
const powertools = require('node-powertools');
|
|
4
|
+
const _ = require('lodash');
|
|
5
|
+
|
|
6
|
+
const TOKEN_COST_TABLE = {
|
|
7
|
+
// Nov 6th, 2023
|
|
8
|
+
'gpt-4-1106-preview': {
|
|
9
|
+
input: 0.0100,
|
|
10
|
+
output: 0.0300,
|
|
11
|
+
},
|
|
12
|
+
'gpt-4': {
|
|
13
|
+
input: 0.0300,
|
|
14
|
+
output: 0.0600,
|
|
15
|
+
},
|
|
16
|
+
'gpt-3.5-turbo': {
|
|
17
|
+
input: 0.0010,
|
|
18
|
+
output: 0.0020,
|
|
19
|
+
},
|
|
20
|
+
}
|
|
3
21
|
|
|
4
22
|
function OpenAI(assistant, key) {
|
|
5
23
|
const self = this;
|
|
@@ -9,37 +27,71 @@ function OpenAI(assistant, key) {
|
|
|
9
27
|
self.user = assistant.user;
|
|
10
28
|
self.key = key;
|
|
11
29
|
|
|
30
|
+
self.tokens = {
|
|
31
|
+
total: {
|
|
32
|
+
count: 0,
|
|
33
|
+
price: 0,
|
|
34
|
+
},
|
|
35
|
+
input: {
|
|
36
|
+
count: 0,
|
|
37
|
+
price: 0,
|
|
38
|
+
},
|
|
39
|
+
output: {
|
|
40
|
+
count: 0,
|
|
41
|
+
price: 0,
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
|
|
12
45
|
return self;
|
|
13
46
|
}
|
|
14
47
|
|
|
15
|
-
OpenAI.prototype.request = function (options
|
|
48
|
+
OpenAI.prototype.request = function (options) {
|
|
16
49
|
const self = this;
|
|
17
50
|
const Manager = self.Manager;
|
|
18
51
|
const assistant = self.assistant;
|
|
19
52
|
|
|
20
|
-
assistant.log('callOpenAI(): Starting', self.key);
|
|
21
|
-
assistant.log('callOpenAI(): Starting', options, messages, template);
|
|
22
|
-
|
|
23
53
|
return new Promise(async function(resolve, reject) {
|
|
24
|
-
options =
|
|
25
|
-
options.prompt = options.prompt || '';
|
|
26
|
-
options.timeout = options.timeout || 120000;
|
|
27
|
-
options.model = options.model || (
|
|
28
|
-
self.user.plan.id === 'basic'
|
|
29
|
-
? BASIC_MODEL
|
|
30
|
-
: PREMIUM_MODEL
|
|
31
|
-
);
|
|
32
|
-
options.user = options.user || assistant.request.geolocation.ip;
|
|
54
|
+
options = _.merge({}, options);
|
|
33
55
|
|
|
34
|
-
|
|
35
|
-
options.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
options.model = typeof options.model === 'undefined' ? 'gpt-3.5-turbo' : options.model;
|
|
57
|
+
options.timeout = typeof options.timeout === 'undefined' ? 120000 : options.timeout;
|
|
58
|
+
options.moderate = typeof options.moderate === 'undefined' ? true : options.moderate;
|
|
59
|
+
options.user = options.user || assistant.getUser();
|
|
60
|
+
|
|
61
|
+
options.prompt = options.prompt || {};
|
|
62
|
+
options.prompt.path = options.prompt.path || '';
|
|
63
|
+
options.prompt.settings = options.prompt.settings || {};
|
|
64
|
+
|
|
65
|
+
options.message = options.message || {};
|
|
66
|
+
options.message.path = options.message.path || '';
|
|
67
|
+
options.message.settings = options.message.settings || {};
|
|
39
68
|
|
|
40
|
-
|
|
69
|
+
options.history = options.history || {};
|
|
70
|
+
options.history.messages = options.history.messages || [];
|
|
71
|
+
options.history.limit = typeof options.history.limit === 'undefined' ? 5 : options.history.limit;
|
|
72
|
+
|
|
73
|
+
options.response = typeof options.response === 'undefined' ? undefined : options.response;
|
|
74
|
+
options.temperature = typeof options.temperature === 'undefined' ? 0.7 : options.temperature;
|
|
75
|
+
options.maxTokens = typeof options.maxTokens === 'undefined' ? 512 : options.maxTokens;
|
|
76
|
+
|
|
77
|
+
assistant.log('callOpenAI(): Starting', self.key);
|
|
41
78
|
assistant.log('callOpenAI(): Starting', options);
|
|
42
79
|
|
|
80
|
+
// Load prompt
|
|
81
|
+
const prompt = powertools.template(
|
|
82
|
+
jetpack.read(options.prompt.path),
|
|
83
|
+
options.prompt.settings,
|
|
84
|
+
).trim();
|
|
85
|
+
const message = powertools.template(
|
|
86
|
+
jetpack.read(options.message.path),
|
|
87
|
+
options.message.settings,
|
|
88
|
+
).trim();
|
|
89
|
+
const user = options.user?.auth?.uid || assistant.request.geolocation.ip;
|
|
90
|
+
|
|
91
|
+
assistant.log('callOpenAI(): Prompt', prompt);
|
|
92
|
+
assistant.log('callOpenAI(): Message', message);
|
|
93
|
+
assistant.log('callOpenAI(): User', user);
|
|
94
|
+
|
|
43
95
|
function _request(mode, options) {
|
|
44
96
|
return new Promise(async function(resolve, reject) {
|
|
45
97
|
let resultPath = '';
|
|
@@ -58,25 +110,33 @@ OpenAI.prototype.request = function (options, messages, template) {
|
|
|
58
110
|
|
|
59
111
|
if (mode === 'chatgpt') {
|
|
60
112
|
request.url = 'https://api.openai.com/v1/chat/completions';
|
|
61
|
-
messages = messages.slice(-
|
|
62
|
-
messages.unshift({
|
|
113
|
+
options.history.messages = options.history.messages.slice(-options.history.limit);
|
|
114
|
+
options.history.messages.unshift({
|
|
63
115
|
role: 'system',
|
|
64
|
-
content:
|
|
116
|
+
content: prompt,
|
|
117
|
+
});
|
|
118
|
+
options.history.messages.push({
|
|
119
|
+
role: 'user',
|
|
120
|
+
content: message,
|
|
65
121
|
});
|
|
122
|
+
|
|
123
|
+
// Log message
|
|
124
|
+
assistant.log('callOpenAI(): Messages', options.history.messages);
|
|
125
|
+
|
|
66
126
|
request.body = {
|
|
67
127
|
model: options.model,
|
|
68
|
-
response_format: { type: 'json_object' },
|
|
69
|
-
messages: messages,
|
|
70
|
-
temperature:
|
|
71
|
-
max_tokens:
|
|
72
|
-
user:
|
|
128
|
+
response_format: options.response === 'json' ? { type: 'json_object' } : undefined,
|
|
129
|
+
messages: options.history.messages,
|
|
130
|
+
temperature: options.temperature,
|
|
131
|
+
max_tokens: options.maxTokens,
|
|
132
|
+
user: user,
|
|
73
133
|
}
|
|
74
134
|
resultPath = 'choices[0].message.content';
|
|
75
135
|
} else if (mode === 'moderation') {
|
|
76
136
|
request.url = 'https://api.openai.com/v1/moderations';
|
|
77
137
|
request.body = {
|
|
78
|
-
input:
|
|
79
|
-
user:
|
|
138
|
+
input: message,
|
|
139
|
+
user: user,
|
|
80
140
|
}
|
|
81
141
|
resultPath = 'results[0]';
|
|
82
142
|
}
|
|
@@ -102,25 +162,39 @@ OpenAI.prototype.request = function (options, messages, template) {
|
|
|
102
162
|
});
|
|
103
163
|
}
|
|
104
164
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
165
|
+
// Moderate if needed
|
|
166
|
+
let moderation = null;
|
|
167
|
+
if (options.moderate) {
|
|
168
|
+
moderation = await _request('moderation', options)
|
|
169
|
+
.then(async (r) => {
|
|
170
|
+
assistant.log('callOpenAI(): Moderated', r);
|
|
109
171
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
return reject(new Error('Moderation not approved'));
|
|
113
|
-
}
|
|
172
|
+
// Save moderation
|
|
173
|
+
self.moderation = r;
|
|
114
174
|
|
|
115
|
-
|
|
116
|
-
.then((r) => {
|
|
117
|
-
try {
|
|
118
|
-
return resolve(JSON.parse(r));
|
|
119
|
-
} catch (e) {
|
|
120
|
-
return reject(e);
|
|
121
|
-
}
|
|
175
|
+
return r;
|
|
122
176
|
})
|
|
123
|
-
.catch((e) =>
|
|
177
|
+
.catch((e) => e);
|
|
178
|
+
|
|
179
|
+
if (moderation.flagged) {
|
|
180
|
+
return reject(assistant.errorify(`This request is inappropriate`, {code: 400, sentry: false, send: false, log: false}));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Request
|
|
185
|
+
await _request('chatgpt', options)
|
|
186
|
+
.then((r) => {
|
|
187
|
+
try {
|
|
188
|
+
const content = options.response === 'json' ? JSON.parse(r) : r;
|
|
189
|
+
|
|
190
|
+
return resolve({
|
|
191
|
+
content: content,
|
|
192
|
+
tokens: self.tokens,
|
|
193
|
+
moderation: moderation,
|
|
194
|
+
})
|
|
195
|
+
} catch (e) {
|
|
196
|
+
return reject(e);
|
|
197
|
+
}
|
|
124
198
|
})
|
|
125
199
|
.catch((e) => reject(e));
|
|
126
200
|
});
|