@cobrowser/chatgpt 0.7.40 → 0.7.42-beta.1
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.
|
@@ -17,21 +17,22 @@ export declare class CopilotService extends BaseService {
|
|
|
17
17
|
*
|
|
18
18
|
* this will make it easy to ask chatGpt for quick replies
|
|
19
19
|
* @param conversation
|
|
20
|
+
* @param suggestionLanguage Language we want to get suggestions in
|
|
20
21
|
*/
|
|
21
|
-
suggest(conversation: string): Promise<ChatGPTResponse | undefined>;
|
|
22
|
+
suggest(conversation: string, suggestionLanguage?: string): Promise<ChatGPTResponse | undefined>;
|
|
22
23
|
/**
|
|
23
24
|
* Get suggestions from Chat Completion API.
|
|
24
25
|
*
|
|
25
26
|
* @param message
|
|
26
27
|
*/
|
|
27
|
-
getChatCompletionSuggestions(conversation: string): Promise<ChatGPTResponse | undefined>;
|
|
28
|
+
getChatCompletionSuggestions(conversation: string, suggestionLanguage?: string): Promise<ChatGPTResponse | undefined>;
|
|
28
29
|
/**
|
|
29
30
|
* Get the reply of the assistant if the assistant_id is available
|
|
30
31
|
*
|
|
31
32
|
* @param message
|
|
32
33
|
*/
|
|
33
|
-
getAssistantSuggestions(conversation: string): Promise<ChatGPTResponse | undefined>;
|
|
34
|
+
getAssistantSuggestions(conversation: string, suggestionLanguage?: string): Promise<ChatGPTResponse | undefined>;
|
|
34
35
|
private isAssistantIdFormat;
|
|
35
36
|
private isPromptIdFormat;
|
|
36
|
-
getPromptSuggestions(
|
|
37
|
+
getPromptSuggestions(conversation: string, suggestionLanguage?: string): Promise<ChatGPTResponse | undefined>;
|
|
37
38
|
}
|
|
@@ -59,9 +59,11 @@ class CopilotService extends BaseService_1.default {
|
|
|
59
59
|
*
|
|
60
60
|
* this will make it easy to ask chatGpt for quick replies
|
|
61
61
|
* @param conversation
|
|
62
|
+
* @param suggestionLanguage Language we want to get suggestions in
|
|
62
63
|
*/
|
|
63
|
-
suggest(conversation) {
|
|
64
|
+
suggest(conversation, suggestionLanguage) {
|
|
64
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
logger_1.default.info({ conversation, suggestionLanguage }, ':: CopilotServicee.suggest :: Suggestion Language ::');
|
|
65
67
|
if (!(conversation === null || conversation === void 0 ? void 0 : conversation.length)) {
|
|
66
68
|
logger_1.default.error('Conversation must be provided');
|
|
67
69
|
return Promise.reject(new Error('Conversation must be provided'));
|
|
@@ -78,11 +80,11 @@ class CopilotService extends BaseService_1.default {
|
|
|
78
80
|
}
|
|
79
81
|
// Route based on id shape: asst_* => Assistant API, prompt_* => Responses API
|
|
80
82
|
if (yield this.isAssistantIdFormat(this.assistantId)) {
|
|
81
|
-
return yield this.getAssistantSuggestions(conversation);
|
|
83
|
+
return yield this.getAssistantSuggestions(conversation, suggestionLanguage);
|
|
82
84
|
}
|
|
83
|
-
return yield this.getPromptSuggestions(
|
|
85
|
+
return yield this.getPromptSuggestions(conversation, suggestionLanguage);
|
|
84
86
|
}
|
|
85
|
-
return yield this.getChatCompletionSuggestions(conversation);
|
|
87
|
+
return yield this.getChatCompletionSuggestions(conversation, suggestionLanguage);
|
|
86
88
|
}
|
|
87
89
|
catch (e) {
|
|
88
90
|
this.handleErrors(e);
|
|
@@ -95,14 +97,19 @@ class CopilotService extends BaseService_1.default {
|
|
|
95
97
|
*
|
|
96
98
|
* @param message
|
|
97
99
|
*/
|
|
98
|
-
getChatCompletionSuggestions(conversation) {
|
|
100
|
+
getChatCompletionSuggestions(conversation, suggestionLanguage) {
|
|
99
101
|
return __awaiter(this, void 0, void 0, function* () {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
102
|
+
const mainPrompt = `
|
|
103
|
+
Propose some quick replies for the agent to be used on the following conversation:
|
|
104
|
+
|
|
105
|
+
${conversation}
|
|
106
|
+
|
|
107
|
+
Your response must only contain a valid JSON array of strings. For example:
|
|
108
|
+
|
|
109
|
+
["Reply 1", "Reply 2", "Reply 3"]
|
|
110
|
+
|
|
111
|
+
${suggestionLanguage ? `The replies must be in ${suggestionLanguage}.` : ''}
|
|
112
|
+
`.trim(), mainPromptMessage = {
|
|
106
113
|
role: ChatGPTMessage_1.ChatGPTRole.USER,
|
|
107
114
|
content: mainPrompt,
|
|
108
115
|
},
|
|
@@ -122,11 +129,10 @@ class CopilotService extends BaseService_1.default {
|
|
|
122
129
|
*
|
|
123
130
|
* @param message
|
|
124
131
|
*/
|
|
125
|
-
getAssistantSuggestions(conversation) {
|
|
132
|
+
getAssistantSuggestions(conversation, suggestionLanguage) {
|
|
126
133
|
var _a, _b;
|
|
127
134
|
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
-
const conversationLines = conversation.split('\n').filter(line => line.trim());
|
|
129
|
-
const messages = [];
|
|
135
|
+
const conversationLines = conversation.split('\n').filter(line => line.trim()), messages = [];
|
|
130
136
|
for (const line of conversationLines) {
|
|
131
137
|
if (line.includes('customer:')) {
|
|
132
138
|
messages.push({
|
|
@@ -188,9 +194,10 @@ class CopilotService extends BaseService_1.default {
|
|
|
188
194
|
lastMessageIndex: (messages.length - 1).toString()
|
|
189
195
|
}
|
|
190
196
|
});
|
|
191
|
-
const run = yield openai.beta.threads.runs.create(this.threadId, {
|
|
192
|
-
|
|
193
|
-
|
|
197
|
+
const run = yield openai.beta.threads.runs.create(this.threadId, Object.assign({ assistant_id: (_b = this.assistantId) !== null && _b !== void 0 ? _b : '' }, (suggestionLanguage ? {
|
|
198
|
+
additional_instructions: `IMPORTANT: You must respond in ${suggestionLanguage} language only.
|
|
199
|
+
Regardless of the language used in the conversation, your response must be in ${suggestionLanguage}.`
|
|
200
|
+
} : {})));
|
|
194
201
|
let currentRun = run;
|
|
195
202
|
while (['queued', 'in_progress', 'cancelling'].includes(currentRun.status)) {
|
|
196
203
|
yield new Promise(resolve => setTimeout(resolve, 500));
|
|
@@ -216,55 +223,161 @@ class CopilotService extends BaseService_1.default {
|
|
|
216
223
|
isPromptIdFormat(id) {
|
|
217
224
|
return !!id && /^pmpt_[A-Za-z0-9]+$/.test(id);
|
|
218
225
|
}
|
|
219
|
-
getPromptSuggestions(
|
|
220
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
226
|
+
getPromptSuggestions(conversation, suggestionLanguage) {
|
|
227
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
221
228
|
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
const conversationLines = conversation.split('\n').filter(line => line.trim());
|
|
230
|
+
const messages = [];
|
|
231
|
+
for (const line of conversationLines) {
|
|
232
|
+
if (line.includes('customer:')) {
|
|
233
|
+
messages.push({
|
|
234
|
+
role: 'user',
|
|
235
|
+
content: line.replace(/^customer:\s*/, '').trim()
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
else if (line.includes('agent:')) {
|
|
239
|
+
messages.push({
|
|
240
|
+
role: 'assistant',
|
|
241
|
+
content: line.replace(/^agent:\s*/, '').trim()
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (messages.length === 0) {
|
|
246
|
+
logger_1.default.error('No valid messages found in conversation');
|
|
247
|
+
return Promise.reject(new Error('No valid messages found in conversation'));
|
|
248
|
+
}
|
|
222
249
|
const openai = new openai_1.default({ apiKey: this.openaiApiKey });
|
|
223
250
|
let conversationId = this.conversationId;
|
|
251
|
+
let lastMessageIndex = -1;
|
|
224
252
|
if (!conversationId) {
|
|
225
|
-
const conv = yield openai.conversations.create(
|
|
253
|
+
const conv = yield openai.conversations.create({
|
|
254
|
+
metadata: {
|
|
255
|
+
lastMessageIndex: '-1',
|
|
256
|
+
conversationHistory: JSON.stringify([])
|
|
257
|
+
}
|
|
258
|
+
});
|
|
226
259
|
conversationId = conv.id;
|
|
260
|
+
this.conversationId = conversationId;
|
|
227
261
|
}
|
|
228
|
-
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
262
|
+
else {
|
|
263
|
+
// Retrieve conversation to get metadata
|
|
264
|
+
try {
|
|
265
|
+
const conv = yield openai.conversations.retrieve(conversationId);
|
|
266
|
+
lastMessageIndex = parseInt(((_a = conv.metadata) === null || _a === void 0 ? void 0 : _a.lastMessageIndex) || '-1', 10);
|
|
267
|
+
}
|
|
268
|
+
catch (e) {
|
|
269
|
+
logger_1.default.error('Failed to retrieve conversation metadata', e);
|
|
270
|
+
lastMessageIndex = -1;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Get new messages that haven't been sent yet
|
|
274
|
+
const newMessages = messages.slice(lastMessageIndex + 1);
|
|
275
|
+
if (newMessages.length === 0) {
|
|
276
|
+
// Retrieve the last response from the conversation
|
|
277
|
+
try {
|
|
278
|
+
const convHistory = yield openai.conversations.retrieve(conversationId);
|
|
279
|
+
const lastResponse = convHistory.last_response;
|
|
280
|
+
if (lastResponse) {
|
|
281
|
+
const output = lastResponse.output || [];
|
|
282
|
+
const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
|
|
283
|
+
if (assistantMessages.length) {
|
|
284
|
+
const text = assistantMessages.flatMap((m) => { var _a, _b; return ((_b = (_a = m.content) === null || _a === void 0 ? void 0 : _a.filter((c) => c.type === 'output_text')) === null || _b === void 0 ? void 0 : _b.map((c) => c.text)) || []; });
|
|
285
|
+
return {
|
|
286
|
+
data: [text[text.length - 1]],
|
|
287
|
+
threadId: this.conversationId,
|
|
288
|
+
usageTokens: undefined,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
catch (e) {
|
|
294
|
+
logger_1.default.error('Failed to retrieve last response from conversation', e);
|
|
295
|
+
}
|
|
296
|
+
return Promise.reject(new Error('No new messages to process and no previous response found'));
|
|
297
|
+
}
|
|
298
|
+
const allPreviousMessages = messages.slice(0, lastMessageIndex + 1);
|
|
299
|
+
const contextMessages = [];
|
|
300
|
+
for (const msg of allPreviousMessages) {
|
|
301
|
+
const roleLabel = msg.role === 'user' ? 'customer' : 'agent';
|
|
302
|
+
contextMessages.push(`${roleLabel}: ${msg.content}`);
|
|
303
|
+
}
|
|
304
|
+
const lastUserMessage = newMessages.filter(m => m.role === 'user').pop();
|
|
305
|
+
if (!lastUserMessage) {
|
|
306
|
+
if (conversationId) {
|
|
307
|
+
try {
|
|
308
|
+
yield openai.conversations.update(conversationId, {
|
|
309
|
+
metadata: {
|
|
310
|
+
lastMessageIndex: (messages.length - 1).toString(),
|
|
311
|
+
conversationHistory: JSON.stringify(messages)
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
catch (e) {
|
|
316
|
+
logger_1.default.error('Failed to update conversation metadata', e);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return Promise.reject(new Error('No new user messages to process'));
|
|
320
|
+
}
|
|
321
|
+
let inputWithContext = lastUserMessage.content;
|
|
322
|
+
if (contextMessages.length > 0 || newMessages.length > 1) {
|
|
323
|
+
const allNewMessages = [];
|
|
324
|
+
for (const msg of newMessages) {
|
|
325
|
+
const roleLabel = msg.role === 'user' ? 'customer' : 'agent';
|
|
326
|
+
allNewMessages.push(`${roleLabel}: ${msg.content}`);
|
|
327
|
+
}
|
|
328
|
+
const fullContext = [...contextMessages, ...allNewMessages].join('\n');
|
|
329
|
+
inputWithContext = fullContext;
|
|
330
|
+
}
|
|
331
|
+
const request = Object.assign({ input: inputWithContext, store: true, conversation: { id: conversationId }, include: ['file_search_call.results'] }, (suggestionLanguage ? {
|
|
332
|
+
instructions: `IMPORTANT: You must respond in ${suggestionLanguage} language only.
|
|
333
|
+
Regardless of the language used in the conversation, your response must be in ${suggestionLanguage}.`
|
|
334
|
+
} : {}));
|
|
235
335
|
if (this.assistantId && (yield this.isPromptIdFormat(this.assistantId))) {
|
|
236
336
|
request.prompt = { id: this.assistantId };
|
|
237
337
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
338
|
+
const lastResponse = yield openai.responses.create(request);
|
|
339
|
+
if ((_b = lastResponse.conversation) === null || _b === void 0 ? void 0 : _b.id) {
|
|
340
|
+
this.conversationId = lastResponse.conversation.id;
|
|
341
|
+
conversationId = this.conversationId;
|
|
342
|
+
}
|
|
343
|
+
if (conversationId) {
|
|
344
|
+
try {
|
|
345
|
+
yield openai.conversations.update(conversationId, {
|
|
346
|
+
metadata: {
|
|
347
|
+
lastMessageIndex: (messages.length - 1).toString(),
|
|
348
|
+
conversationHistory: JSON.stringify(messages)
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
catch (e) {
|
|
353
|
+
logger_1.default.error('Failed to update conversation metadata', e);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (!lastResponse) {
|
|
357
|
+
return Promise.reject(new Error('No response generated'));
|
|
243
358
|
}
|
|
244
|
-
|
|
245
|
-
// which includes multiple messages (some of them are not useful for the user, but the last one is)
|
|
246
|
-
const output = response.output || [];
|
|
359
|
+
const output = lastResponse.output || [];
|
|
247
360
|
const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
|
|
248
361
|
if (assistantMessages.length) {
|
|
249
362
|
const text = assistantMessages.flatMap((m) => { var _a, _b; return ((_b = (_a = m.content) === null || _a === void 0 ? void 0 : _a.filter((c) => c.type === 'output_text')) === null || _b === void 0 ? void 0 : _b.map((c) => c.text)) || []; });
|
|
250
363
|
return {
|
|
251
|
-
data: [text.
|
|
364
|
+
data: [text[text.length - 1]],
|
|
252
365
|
threadId: this.conversationId,
|
|
253
366
|
usageTokens: {
|
|
254
|
-
prompt_tokens: Number((
|
|
255
|
-
completion_tokens: Number((
|
|
256
|
-
total_tokens: Number((
|
|
367
|
+
prompt_tokens: Number((_d = ((_c = lastResponse.usage) === null || _c === void 0 ? void 0 : _c.prompt_tokens)) !== null && _d !== void 0 ? _d : 0),
|
|
368
|
+
completion_tokens: Number((_f = ((_e = lastResponse.usage) === null || _e === void 0 ? void 0 : _e.completion_tokens)) !== null && _f !== void 0 ? _f : 0),
|
|
369
|
+
total_tokens: Number((_h = ((_g = lastResponse.usage) === null || _g === void 0 ? void 0 : _g.total_tokens)) !== null && _h !== void 0 ? _h : 0),
|
|
257
370
|
},
|
|
258
371
|
};
|
|
259
372
|
}
|
|
260
|
-
if (
|
|
373
|
+
if (lastResponse.output_text) {
|
|
261
374
|
return {
|
|
262
|
-
data: [
|
|
375
|
+
data: [lastResponse.output_text],
|
|
263
376
|
threadId: this.conversationId,
|
|
264
377
|
usageTokens: {
|
|
265
|
-
prompt_tokens: Number((
|
|
266
|
-
completion_tokens: Number((
|
|
267
|
-
total_tokens: Number((
|
|
378
|
+
prompt_tokens: Number((_k = ((_j = lastResponse.usage) === null || _j === void 0 ? void 0 : _j.prompt_tokens)) !== null && _k !== void 0 ? _k : 0),
|
|
379
|
+
completion_tokens: Number((_m = ((_l = lastResponse.usage) === null || _l === void 0 ? void 0 : _l.completion_tokens)) !== null && _m !== void 0 ? _m : 0),
|
|
380
|
+
total_tokens: Number((_p = ((_o = lastResponse.usage) === null || _o === void 0 ? void 0 : _o.total_tokens)) !== null && _p !== void 0 ? _p : 0),
|
|
268
381
|
},
|
|
269
382
|
};
|
|
270
383
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobrowser/chatgpt",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.42-beta.1",
|
|
4
4
|
"description": "chatgpt services to connect our projects with chatgpt api",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatgpt",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"bugs": {
|
|
41
41
|
"url": "https://bitbucket.org/cobrowser/cb_utils/issues"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "1f4318b0c31d19c651c89e548b58841c060617af"
|
|
44
44
|
}
|