@cobrowser/chatgpt 0.7.31-beta.4 → 0.7.32-dev.0
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/dist/constants.d.ts +2 -2
- package/dist/constants.js +19 -23
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/services/AssistantService/AssistantService.d.ts +3 -3
- package/dist/services/AssistantService/AssistantService.js +6 -3
- package/dist/services/BaseService/BaseService.d.ts +5 -16
- package/dist/services/BaseService/BaseService.js +7 -84
- package/dist/services/CopilotService/CopilotService.d.ts +10 -13
- package/dist/services/CopilotService/CopilotService.js +118 -51
- package/dist/services/ResponseService/ResponseService.d.ts +37 -0
- package/dist/services/ResponseService/ResponseService.js +213 -0
- package/dist/services/TranslationService/TranslationService.d.ts +4 -4
- package/dist/services/TranslationService/TranslationService.js +3 -7
- package/package.json +4 -5
- package/dist/models/ChatGPTResponse.d.ts +0 -8
- package/dist/models/ChatGPTResponse.js +0 -2
- package/dist/models/ChatGPTUsageTokens.d.ts +0 -6
- package/dist/models/ChatGPTUsageTokens.js +0 -2
package/dist/constants.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ export declare const MESSAGE_TYPES: {
|
|
|
6
6
|
text: string;
|
|
7
7
|
button: string;
|
|
8
8
|
};
|
|
9
|
-
export declare const DEFAULT_PROMPT = "
|
|
9
|
+
export declare const DEFAULT_PROMPT = "You are a helpful assistant. Your role is to address visitor \nqueries related to the ongoing conversation and the last message received. Please ensure \nthat responses remain within the ongoing conversation. Politely decline any user queries \nthat is not present in the ongoing conversation. \n\nYou will always respond with a JSON. It will be in the format: \n\n{ answer: '', suggestions: [], connectWithAgent: true or false }\n\nFields in the JSON:\n\nAnswer: It will consist of the user's query answer based on the ongoing conversation. \nRestrict this field to 100 characters.\n\nSuggestions: Request 2 suggestions from user's perspective that he can ask. \nIt should be an array of strings. Restrict each suggestion to 50 characters.\n \nConnectWithAgent: It is a boolean. It should be set to true if the user's query is \nnot found in the ongoing conversation. Politely tell the user to talk to a real agent. \nAlso when it is true, do not provide any suggestions.\n";
|
|
10
10
|
export declare const DESTINATION_LANGUAGE = "English";
|
|
11
11
|
export declare const LANGUAGE_DETECTION_SYSTEM_ROLE = "\n You are a language detection assistant. Your task is to analyze short text input and determine \n its language using ISO language code. Respond only in JSON format with two key-value pairs: \n - 'languageCode': the detected language's ISO code (or undefined if detection fails).\n - 'isError': a boolean value (true if detection fails, false otherwise).\n";
|
|
12
12
|
export declare const WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = "\n You are a language detection assistant. Your task is to analyze the most frequently occurring words in the given text \n and determine the language based on those words. Respond only in JSON format with two key-value pairs: \n - 'languageCode': the detected language's ISO code (or undefined if detection fails).\n - 'isError': a boolean value (true if detection fails, false otherwise).\n";
|
|
13
|
-
export declare const TRANSLATION_SYSTEM_ROLE = "\n You are a translator that responds exclusively in JSON format. Your response must be a JSON object containing:\n - '
|
|
13
|
+
export declare const TRANSLATION_SYSTEM_ROLE = "\n You are a translator that responds exclusively in JSON format. Your response must be a JSON object containing:\n - 'data': it is an array of objects. Each object in the array must contain:\n - 'translated_message': The original input message before translation.\n - 'translation: The translated version of 'translated_message', ensuring it is natural, culturally appropriate, and commonly used by native speakers.\n - 'isError': a boolean value (true if translation fails, false otherwise).\n\n Ensure that 'translation' accurately represents the meaning of 'translated_message' while considering cultural nuances, usual expressions, and natural phrasing in the target language. \n Your response must follow this structure strictly.\n";
|
package/dist/constants.js
CHANGED
|
@@ -12,27 +12,26 @@ exports.MESSAGE_TYPES = {
|
|
|
12
12
|
button: 'button'
|
|
13
13
|
};
|
|
14
14
|
// Default prompt for ChatGPT
|
|
15
|
-
exports.DEFAULT_PROMPT = `
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
that is not present in the ongoing conversation.
|
|
15
|
+
exports.DEFAULT_PROMPT = `You are a helpful assistant. Your role is to address visitor
|
|
16
|
+
queries related to the ongoing conversation and the last message received. Please ensure
|
|
17
|
+
that responses remain within the ongoing conversation. Politely decline any user queries
|
|
18
|
+
that is not present in the ongoing conversation.
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
You will always respond with a JSON. It will be in the format:
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
{ answer: '', suggestions: [], connectWithAgent: true or false }
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
Fields in the JSON:
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
Answer: It will consist of the user's query answer based on the ongoing conversation.
|
|
27
|
+
Restrict this field to 100 characters.
|
|
29
28
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
Suggestions: Request 2 suggestions from user's perspective that he can ask.
|
|
30
|
+
It should be an array of strings. Restrict each suggestion to 50 characters.
|
|
31
|
+
|
|
32
|
+
ConnectWithAgent: It is a boolean. It should be set to true if the user's query is
|
|
33
|
+
not found in the ongoing conversation. Politely tell the user to talk to a real agent.
|
|
34
|
+
Also when it is true, do not provide any suggestions.
|
|
36
35
|
`;
|
|
37
36
|
// Default destination language
|
|
38
37
|
exports.DESTINATION_LANGUAGE = 'English';
|
|
@@ -53,14 +52,11 @@ exports.WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = `
|
|
|
53
52
|
// Message translation system role
|
|
54
53
|
exports.TRANSLATION_SYSTEM_ROLE = `
|
|
55
54
|
You are a translator that responds exclusively in JSON format. Your response must be a JSON object containing:
|
|
56
|
-
- '
|
|
57
|
-
- '
|
|
58
|
-
- 'translation: The translated version of '
|
|
55
|
+
- 'data': it is an array of objects. Each object in the array must contain:
|
|
56
|
+
- 'translated_message': The original input message before translation.
|
|
57
|
+
- 'translation: The translated version of 'translated_message', ensuring it is natural, culturally appropriate, and commonly used by native speakers.
|
|
59
58
|
- 'isError': a boolean value (true if translation fails, false otherwise).
|
|
60
59
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
Ensure that 'translation' accurately represents the meaning of 'original' while considering cultural nuances, usual expressions, and natural phrasing in the target language.
|
|
64
|
-
|
|
60
|
+
Ensure that 'translation' accurately represents the meaning of 'translated_message' while considering cultural nuances, usual expressions, and natural phrasing in the target language.
|
|
65
61
|
Your response must follow this structure strictly.
|
|
66
62
|
`;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export * from './services/TranslationService/TranslationService';
|
|
|
2
2
|
export * from './services/CopilotService/CopilotService';
|
|
3
3
|
export * from './services/ChatService/ChatService';
|
|
4
4
|
export * from './services/AssistantService/AssistantService';
|
|
5
|
+
export * from './services/ResponseService/ResponseService';
|
package/dist/index.js
CHANGED
|
@@ -18,3 +18,4 @@ __exportStar(require("./services/TranslationService/TranslationService"), export
|
|
|
18
18
|
__exportStar(require("./services/CopilotService/CopilotService"), exports);
|
|
19
19
|
__exportStar(require("./services/ChatService/ChatService"), exports);
|
|
20
20
|
__exportStar(require("./services/AssistantService/AssistantService"), exports);
|
|
21
|
+
__exportStar(require("./services/ResponseService/ResponseService"), exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
2
|
-
import ChatGPTResponse from '../../models/ChatGPTResponse';
|
|
1
|
+
import ChatGptResponse from '../../models/ChatGptResponse';
|
|
3
2
|
import BaseService from '../BaseService/BaseService';
|
|
3
|
+
import { AssistantResponseFormatOption } from 'openai/resources/beta/threads/threads';
|
|
4
4
|
export declare class AssistantService extends BaseService {
|
|
5
5
|
assistantId: string | undefined;
|
|
6
6
|
threadId: string | undefined;
|
|
@@ -22,5 +22,5 @@ export declare class AssistantService extends BaseService {
|
|
|
22
22
|
tools?: any[];
|
|
23
23
|
functionOutputs?: string;
|
|
24
24
|
definedSchema?: AssistantResponseFormatOption;
|
|
25
|
-
}): Promise<
|
|
25
|
+
}): Promise<ChatGptResponse | undefined>;
|
|
26
26
|
}
|
|
@@ -68,7 +68,10 @@ class AssistantService extends BaseService_1.default {
|
|
|
68
68
|
const openai = new openai_1.default({ apiKey: this.openaiApiKey });
|
|
69
69
|
let run;
|
|
70
70
|
if (runOptions.functionOutputs && this.runId) {
|
|
71
|
-
run = yield openai.beta.threads.runs.submitToolOutputsAndPoll(this.
|
|
71
|
+
run = yield openai.beta.threads.runs.submitToolOutputsAndPoll(this.runId, {
|
|
72
|
+
thread_id: this.threadId,
|
|
73
|
+
tool_outputs: JSON.parse(runOptions.functionOutputs)
|
|
74
|
+
});
|
|
72
75
|
}
|
|
73
76
|
else {
|
|
74
77
|
const lastThreadMessasges = yield openai.beta.threads.messages.list(this.threadId, { order: "desc", limit: 2 });
|
|
@@ -92,7 +95,7 @@ class AssistantService extends BaseService_1.default {
|
|
|
92
95
|
}
|
|
93
96
|
while (['queued', 'in_progress', 'cancelling'].includes(run.status)) {
|
|
94
97
|
yield new Promise(resolve => setTimeout(resolve, 500));
|
|
95
|
-
run = yield openai.beta.threads.runs.retrieve(run.
|
|
98
|
+
run = yield openai.beta.threads.runs.retrieve(run.id, { thread_id: run.thread_id });
|
|
96
99
|
}
|
|
97
100
|
if (run.status === 'completed') {
|
|
98
101
|
const { data } = yield openai.beta.threads.messages.list(run.thread_id, { order: 'desc', limit: 1 });
|
|
@@ -101,7 +104,7 @@ class AssistantService extends BaseService_1.default {
|
|
|
101
104
|
if (assistantMessages.length) {
|
|
102
105
|
let answer = assistantMessages.map(message => message.value).join('\n');
|
|
103
106
|
return {
|
|
104
|
-
|
|
107
|
+
firstChoice: answer.replace(/【.*?】/g, ''),
|
|
105
108
|
threadId: run.thread_id,
|
|
106
109
|
usageTokens: run.usage,
|
|
107
110
|
};
|
|
@@ -1,30 +1,20 @@
|
|
|
1
1
|
import { AxiosError, AxiosInstance, AxiosResponse } from 'axios';
|
|
2
|
-
import
|
|
3
|
-
interface Response<Data = any> {
|
|
4
|
-
result: Data;
|
|
5
|
-
}
|
|
2
|
+
import ChatGptUsageTokens from '../../models/ChatGptUsageTokens';
|
|
6
3
|
declare class BaseService {
|
|
7
|
-
readonly BASE_CHAT_COMPLETION_URL = "https://api.openai.com/v1/chat/completions";
|
|
8
4
|
request: AxiosInstance;
|
|
5
|
+
readonly BASE_CHAT_COMPLETION_URL = "https://api.openai.com/v1/chat/completions";
|
|
9
6
|
openaiApiKey: string | undefined;
|
|
10
7
|
chatGptModel: string;
|
|
11
8
|
maxNumberOfChatCompletionResult: number;
|
|
12
9
|
/**
|
|
10
|
+
*
|
|
13
11
|
* @param apiKey
|
|
14
12
|
* @param model the main chatGPT model to use
|
|
15
13
|
* @param apiUrl Api url to be used to make API calls to openAI services
|
|
16
14
|
* @param maxNumberOfChoices How many chat completion choices to generate for each request.
|
|
15
|
+
*
|
|
17
16
|
*/
|
|
18
17
|
constructor(apiKey?: string | undefined, model?: string, apiUrl?: string, maxNumberOfChoices?: number);
|
|
19
|
-
/**
|
|
20
|
-
* Automatically wraps all async methods to sanitize their return values
|
|
21
|
-
* This ensures ALL service methods are automatically sanitized without any developer intervention
|
|
22
|
-
*/
|
|
23
|
-
private processAsyncMethods;
|
|
24
|
-
/**
|
|
25
|
-
* Recursively sanitizes any value
|
|
26
|
-
*/
|
|
27
|
-
private clean;
|
|
28
18
|
/**
|
|
29
19
|
* Filter the response from chatGpt API and only get the first choice
|
|
30
20
|
* @param response
|
|
@@ -34,12 +24,11 @@ declare class BaseService {
|
|
|
34
24
|
* Filter the response from chatGpt API and get the usage tokens
|
|
35
25
|
* @param response
|
|
36
26
|
*/
|
|
37
|
-
getResponseUsageTokens(response: AxiosResponse):
|
|
27
|
+
getResponseUsageTokens(response: AxiosResponse): ChatGptUsageTokens | undefined;
|
|
38
28
|
/**
|
|
39
29
|
* function to handle requests errors
|
|
40
30
|
* @param error
|
|
41
31
|
*/
|
|
42
32
|
handleErrors(error: AxiosError): void;
|
|
43
|
-
protected response<Data>(data: Data): Response<Data>;
|
|
44
33
|
}
|
|
45
34
|
export default BaseService;
|
|
@@ -1,39 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
4
|
};
|
|
14
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
6
|
const axios_1 = __importDefault(require("axios"));
|
|
16
|
-
const xss_validation_1 = require("@cobrowser/xss-validation");
|
|
17
7
|
const logger_1 = __importDefault(require("../logger"));
|
|
18
8
|
class BaseService {
|
|
19
9
|
/**
|
|
10
|
+
*
|
|
20
11
|
* @param apiKey
|
|
21
12
|
* @param model the main chatGPT model to use
|
|
22
13
|
* @param apiUrl Api url to be used to make API calls to openAI services
|
|
23
14
|
* @param maxNumberOfChoices How many chat completion choices to generate for each request.
|
|
15
|
+
*
|
|
24
16
|
*/
|
|
25
17
|
constructor(apiKey = process.env.OPEN_AI_API_KEY, model = 'gpt-4o', apiUrl, maxNumberOfChoices = 1) {
|
|
26
|
-
Object.defineProperty(this, "
|
|
18
|
+
Object.defineProperty(this, "request", {
|
|
27
19
|
enumerable: true,
|
|
28
20
|
configurable: true,
|
|
29
21
|
writable: true,
|
|
30
|
-
value:
|
|
22
|
+
value: void 0
|
|
31
23
|
});
|
|
32
|
-
Object.defineProperty(this, "
|
|
24
|
+
Object.defineProperty(this, "BASE_CHAT_COMPLETION_URL", {
|
|
33
25
|
enumerable: true,
|
|
34
26
|
configurable: true,
|
|
35
27
|
writable: true,
|
|
36
|
-
value:
|
|
28
|
+
value: 'https://api.openai.com/v1/chat/completions'
|
|
37
29
|
});
|
|
38
30
|
Object.defineProperty(this, "openaiApiKey", {
|
|
39
31
|
enumerable: true,
|
|
@@ -63,70 +55,6 @@ class BaseService {
|
|
|
63
55
|
this.openaiApiKey = apiKey;
|
|
64
56
|
this.chatGptModel = model;
|
|
65
57
|
this.maxNumberOfChatCompletionResult = maxNumberOfChoices;
|
|
66
|
-
// Automatically wrap all async methods that return ChatGpt responses
|
|
67
|
-
this.processAsyncMethods();
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Automatically wraps all async methods to sanitize their return values
|
|
71
|
-
* This ensures ALL service methods are automatically sanitized without any developer intervention
|
|
72
|
-
*/
|
|
73
|
-
processAsyncMethods() {
|
|
74
|
-
const proto = Object.getPrototypeOf(this), methodNames = Object.getOwnPropertyNames(proto);
|
|
75
|
-
console.log('BASE SERVICE processAsyncMethods methodNames: ', methodNames);
|
|
76
|
-
for (const methodName of methodNames) {
|
|
77
|
-
const method = proto[methodName];
|
|
78
|
-
console.log('BASE SERVICE processAsyncMethods method: ', method);
|
|
79
|
-
// Skip constructor, non-functions, and utility methods
|
|
80
|
-
// But include service methods like getReply, getAssistant, etc.
|
|
81
|
-
if (methodName === 'constructor' ||
|
|
82
|
-
methodName === 'suggest' ||
|
|
83
|
-
typeof method !== 'function' ||
|
|
84
|
-
(methodName.startsWith('get') &&
|
|
85
|
-
!methodName.startsWith('getReply') &&
|
|
86
|
-
!methodName.startsWith('getAssist') &&
|
|
87
|
-
!methodName.startsWith('getChatGPT')) ||
|
|
88
|
-
methodName.startsWith('handle') ||
|
|
89
|
-
methodName.includes('Sanitize') ||
|
|
90
|
-
methodName.includes('sanitize')) {
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
const originalMethod = method.bind(this);
|
|
94
|
-
console.log('ORIGINAL METHOD: ', originalMethod);
|
|
95
|
-
// Replace the method with a sanitizing wrapper
|
|
96
|
-
this[methodName] = (...args) => __awaiter(this, void 0, void 0, function* () {
|
|
97
|
-
console.log('WRAPPER args: ', args);
|
|
98
|
-
try {
|
|
99
|
-
const result = this.response(yield originalMethod(...args)), sanitizedResult = this.clean(result);
|
|
100
|
-
console.log('BASE SERVICE processAsyncMethods sanitizedResult: ', sanitizedResult);
|
|
101
|
-
return sanitizedResult;
|
|
102
|
-
}
|
|
103
|
-
catch (error) {
|
|
104
|
-
throw error;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Recursively sanitizes any value
|
|
111
|
-
*/
|
|
112
|
-
clean(value) {
|
|
113
|
-
console.log('BASE SERVICE clean value: ', value);
|
|
114
|
-
if (!value) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
// Data could be plain string or JSON string.
|
|
118
|
-
if (typeof value === 'string') {
|
|
119
|
-
try {
|
|
120
|
-
value = JSON.parse(value);
|
|
121
|
-
}
|
|
122
|
-
catch (error) { }
|
|
123
|
-
}
|
|
124
|
-
const sanitized = xss_validation_1.XSSProtector.sanitize(value), encoded = xss_validation_1.XSSProtector.encode(sanitized);
|
|
125
|
-
console.log('BASE SERVICE clean sanitized aaaaa: ', sanitized);
|
|
126
|
-
console.log('BASE SERVICE clean encoded: ', encoded);
|
|
127
|
-
console.log('BASE SERVICE clean encoded data: ', encoded.result.data);
|
|
128
|
-
logger_1.default.info({ value, sanitized, encoded }, ':: Sanitized Response ::');
|
|
129
|
-
return encoded;
|
|
130
58
|
}
|
|
131
59
|
/**
|
|
132
60
|
* Filter the response from chatGpt API and only get the first choice
|
|
@@ -137,7 +65,7 @@ class BaseService {
|
|
|
137
65
|
if ((_a = response.data.choices) === null || _a === void 0 ? void 0 : _a.length) {
|
|
138
66
|
const firstChatGptResponseMessage = response.data.choices[0].message;
|
|
139
67
|
logger_1.default.info(`First ChatGpt Message: ${firstChatGptResponseMessage.content}`);
|
|
140
|
-
return
|
|
68
|
+
return firstChatGptResponseMessage.content;
|
|
141
69
|
}
|
|
142
70
|
return undefined;
|
|
143
71
|
}
|
|
@@ -171,10 +99,5 @@ class BaseService {
|
|
|
171
99
|
}
|
|
172
100
|
logger_1.default.error(`error message ${error.message}`);
|
|
173
101
|
}
|
|
174
|
-
response(data) {
|
|
175
|
-
return {
|
|
176
|
-
result: data,
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
102
|
}
|
|
180
103
|
exports.default = BaseService;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import ChatGptResponse from '../../models/ChatGptResponse';
|
|
2
|
+
import BaseService from '../BaseService/BaseService';
|
|
1
3
|
import ChatGptMessage from '../../models/ChatGptMessage';
|
|
2
4
|
import Item from '../../models/Item';
|
|
3
|
-
import BaseService from '../BaseService/BaseService';
|
|
4
|
-
import ChatGPTResponse from '../../models/ChatGPTResponse';
|
|
5
|
-
import ChatGPTUsageTokens from 'src/models/ChatGPTUsageTokens';
|
|
6
5
|
export declare class CopilotService extends BaseService {
|
|
7
6
|
assistantId: string | undefined;
|
|
8
7
|
threadId: string | undefined;
|
|
8
|
+
conversationId: string | undefined;
|
|
9
9
|
constructor(apiKey?: string, model?: string, assistantId?: string, threadId?: string, apiUrl?: string, maxNumberOfChoices?: number);
|
|
10
10
|
/**
|
|
11
11
|
* a method to be used to suggest some quick replies for the agent based on the conversation
|
|
@@ -19,24 +19,21 @@ export declare class CopilotService extends BaseService {
|
|
|
19
19
|
* this will make it easy to ask chatGpt for quick replies
|
|
20
20
|
* @param conversation
|
|
21
21
|
*/
|
|
22
|
-
suggest(conversation: string): Promise<
|
|
22
|
+
suggest(conversation: string): Promise<ChatGptResponse | undefined>;
|
|
23
23
|
/**
|
|
24
24
|
* this will request chatGPT to recommend product or item based on the whole conversation
|
|
25
25
|
* @param conversation the whole chat conversation
|
|
26
26
|
* @param items the items to recommend from
|
|
27
27
|
*/
|
|
28
|
-
recommend(conversation: ChatGptMessage[], items: Item[]): Promise<
|
|
29
|
-
data: string | undefined;
|
|
30
|
-
usageTokens: ChatGPTUsageTokens | undefined;
|
|
31
|
-
}>;
|
|
32
|
-
getChatGPTQuickReplies(conversation: string): Promise<{
|
|
33
|
-
data: string | undefined;
|
|
34
|
-
usageTokens: ChatGPTUsageTokens | undefined;
|
|
35
|
-
}>;
|
|
28
|
+
recommend(conversation: ChatGptMessage[], items: Item[]): Promise<string | undefined>;
|
|
36
29
|
/**
|
|
37
30
|
* Get the reply of the assistant if the assistant_id is available
|
|
38
31
|
*
|
|
39
32
|
* @param message
|
|
40
33
|
*/
|
|
41
|
-
getAssistantReply(
|
|
34
|
+
getAssistantReply(message: string): Promise<ChatGptResponse | undefined>;
|
|
35
|
+
private isAssistantIdFormat;
|
|
36
|
+
private isPromptIdFormat;
|
|
37
|
+
private ensureConversation;
|
|
38
|
+
getPromptReply(message: string): Promise<ChatGptResponse | undefined>;
|
|
42
39
|
}
|
|
@@ -13,10 +13,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.CopilotService = void 0;
|
|
16
|
-
const
|
|
16
|
+
const BaseService_1 = __importDefault(require("../BaseService/BaseService"));
|
|
17
17
|
const logger_1 = __importDefault(require("../logger"));
|
|
18
|
+
const ChatGptMessage_1 = require("../../models/ChatGptMessage");
|
|
18
19
|
const openai_1 = __importDefault(require("openai"));
|
|
19
|
-
const BaseService_1 = __importDefault(require("../BaseService/BaseService"));
|
|
20
20
|
class CopilotService extends BaseService_1.default {
|
|
21
21
|
constructor(apiKey, model, assistantId, threadId, apiUrl, maxNumberOfChoices) {
|
|
22
22
|
super(apiKey, model, apiUrl, maxNumberOfChoices);
|
|
@@ -32,9 +32,14 @@ class CopilotService extends BaseService_1.default {
|
|
|
32
32
|
writable: true,
|
|
33
33
|
value: void 0
|
|
34
34
|
});
|
|
35
|
+
Object.defineProperty(this, "conversationId", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
writable: true,
|
|
39
|
+
value: void 0
|
|
40
|
+
});
|
|
35
41
|
this.assistantId = assistantId;
|
|
36
42
|
this.threadId = threadId;
|
|
37
|
-
console.log('API URL: ', apiUrl);
|
|
38
43
|
}
|
|
39
44
|
/**
|
|
40
45
|
* a method to be used to suggest some quick replies for the agent based on the conversation
|
|
@@ -50,17 +55,44 @@ class CopilotService extends BaseService_1.default {
|
|
|
50
55
|
*/
|
|
51
56
|
suggest(conversation) {
|
|
52
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
-
console.log('SUGGEST conversation: ', conversation);
|
|
54
58
|
if (!(conversation === null || conversation === void 0 ? void 0 : conversation.length)) {
|
|
55
|
-
logger_1.default.error('
|
|
56
|
-
return Promise.reject(new Error('
|
|
59
|
+
logger_1.default.error('conversation must be provided');
|
|
60
|
+
return Promise.reject(new Error('conversation must be provided'));
|
|
57
61
|
}
|
|
58
62
|
try {
|
|
59
63
|
if (this.assistantId) {
|
|
60
|
-
|
|
64
|
+
// Here we get the last customer message as we dont need the whole conversation
|
|
65
|
+
// as we are doing with the other approach
|
|
66
|
+
const conversationArray = conversation.split('\n');
|
|
67
|
+
const lastCustomerMessage = conversationArray.reverse().find(e => e.includes('customer:'));
|
|
68
|
+
if (!lastCustomerMessage) {
|
|
69
|
+
logger_1.default.error('last customer message not found');
|
|
70
|
+
return Promise.reject(new Error('last customer message not found'));
|
|
71
|
+
}
|
|
72
|
+
// Route based on id shape: asst_* => Assistant API, prompt_* => Responses API
|
|
73
|
+
if (this.isAssistantIdFormat(this.assistantId)) {
|
|
74
|
+
return yield this.getAssistantReply(lastCustomerMessage);
|
|
75
|
+
}
|
|
76
|
+
return yield this.getPromptReply(lastCustomerMessage);
|
|
61
77
|
}
|
|
62
|
-
|
|
63
|
-
|
|
78
|
+
// main prompt used to instruct chatGPT to suggest some quick replies
|
|
79
|
+
const mainPrompt = `Propose some quick replies for the agent to be used on the following conversation
|
|
80
|
+
Your response must only contains a valid JSON array of strings like this:
|
|
81
|
+
["Reply 1", "Reply 2", "Reply 3"]. the conversation is:-\n${conversation}`,
|
|
82
|
+
// main prompt will be the whole conversation as string
|
|
83
|
+
mainPromptMessage = {
|
|
84
|
+
role: ChatGptMessage_1.ChatGptRole.USER,
|
|
85
|
+
content: mainPrompt,
|
|
86
|
+
},
|
|
87
|
+
// the body we need to send to the request
|
|
88
|
+
requestBody = {
|
|
89
|
+
model: this.chatGptModel,
|
|
90
|
+
messages: [mainPromptMessage],
|
|
91
|
+
}, response = yield this.request.post('', requestBody);
|
|
92
|
+
return {
|
|
93
|
+
firstChoice: this.getResponseFirstChoice(response),
|
|
94
|
+
usageTokens: this.getResponseUsageTokens(response),
|
|
95
|
+
};
|
|
64
96
|
}
|
|
65
97
|
catch (e) {
|
|
66
98
|
this.handleErrors(e);
|
|
@@ -92,10 +124,7 @@ class CopilotService extends BaseService_1.default {
|
|
|
92
124
|
model: this.chatGptModel,
|
|
93
125
|
messages: [firstMessage, ...conversation],
|
|
94
126
|
}, response = yield this.request.post('', requestBody);
|
|
95
|
-
return
|
|
96
|
-
data: this.getResponseFirstChoice(response),
|
|
97
|
-
usageTokens: this.getResponseUsageTokens(response),
|
|
98
|
-
};
|
|
127
|
+
return this.getResponseFirstChoice(response);
|
|
99
128
|
}
|
|
100
129
|
catch (e) {
|
|
101
130
|
this.handleErrors(e);
|
|
@@ -103,72 +132,43 @@ class CopilotService extends BaseService_1.default {
|
|
|
103
132
|
}
|
|
104
133
|
});
|
|
105
134
|
}
|
|
106
|
-
getChatGPTQuickReplies(conversation) {
|
|
107
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
// main prompt used to instruct chatGPT to suggest some quick replies
|
|
109
|
-
const mainPrompt = `Propose some quick replies for the agent to be used on the following conversation
|
|
110
|
-
Your response must only contains a valid JSON array of strings like this:
|
|
111
|
-
["Reply 1", "Reply 2", "Reply 3"]. the conversation is:-\n${conversation}`,
|
|
112
|
-
// main prompt will be the whole conversation as string
|
|
113
|
-
mainPromptMessage = {
|
|
114
|
-
role: ChatGptMessage_1.ChatGptRole.USER,
|
|
115
|
-
content: mainPrompt,
|
|
116
|
-
},
|
|
117
|
-
// the body we need to send to the request
|
|
118
|
-
requestBody = {
|
|
119
|
-
model: this.chatGptModel,
|
|
120
|
-
messages: [mainPromptMessage],
|
|
121
|
-
}, response = yield this.request.post('', requestBody);
|
|
122
|
-
return {
|
|
123
|
-
data: this.getResponseFirstChoice(response),
|
|
124
|
-
usageTokens: this.getResponseUsageTokens(response),
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
135
|
/**
|
|
129
136
|
* Get the reply of the assistant if the assistant_id is available
|
|
130
137
|
*
|
|
131
138
|
* @param message
|
|
132
139
|
*/
|
|
133
|
-
getAssistantReply(
|
|
140
|
+
getAssistantReply(message) {
|
|
134
141
|
var _a;
|
|
135
142
|
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
-
console.log('getAssistantReply conversation: ', conversation);
|
|
137
|
-
// Here we get the last customer message as we dont need the whole conversation
|
|
138
|
-
// as we are doing with the other approach
|
|
139
|
-
const conversationArray = conversation.split('\n'), lastCustomerMessage = conversationArray.reverse().find(e => e.includes('customer:'));
|
|
140
|
-
if (!lastCustomerMessage) {
|
|
141
|
-
logger_1.default.error('last customer message not found');
|
|
142
|
-
return Promise.reject(new Error('last customer message not found'));
|
|
143
|
-
}
|
|
144
143
|
const openai = new openai_1.default({ apiKey: this.openaiApiKey });
|
|
145
144
|
let run;
|
|
146
145
|
if (!this.threadId) {
|
|
147
146
|
const thread = yield openai.beta.threads.create();
|
|
148
147
|
this.threadId = thread.id;
|
|
149
148
|
}
|
|
150
|
-
const lastThreadMessasges = yield openai.beta.threads.messages.list(this.threadId, { order: "desc", limit: 2 })
|
|
149
|
+
const lastThreadMessasges = yield openai.beta.threads.messages.list(this.threadId, { order: "desc", limit: 2 });
|
|
150
|
+
const isRepeatedMessage = lastThreadMessasges.data.find(msg => msg.content[0].type === 'text' && msg.content[0].text.value === message);
|
|
151
151
|
// making sure that we're not saving repeated messages
|
|
152
152
|
if (isRepeatedMessage) {
|
|
153
153
|
const runs = yield openai.beta.threads.runs.list(this.threadId, { order: "desc", limit: 1 });
|
|
154
154
|
run = runs.data[0];
|
|
155
155
|
}
|
|
156
156
|
else {
|
|
157
|
-
yield openai.beta.threads.messages.create(this.threadId, { role: "user", content:
|
|
157
|
+
yield openai.beta.threads.messages.create(this.threadId, { role: "user", content: message });
|
|
158
158
|
run = yield openai.beta.threads.runs.create(this.threadId, { assistant_id: (_a = this.assistantId) !== null && _a !== void 0 ? _a : '' });
|
|
159
159
|
}
|
|
160
160
|
while (['queued', 'in_progress', 'cancelling'].includes(run.status)) {
|
|
161
161
|
yield new Promise(resolve => setTimeout(resolve, 500));
|
|
162
|
-
run = yield openai.beta.threads.runs.retrieve(run.
|
|
162
|
+
run = yield openai.beta.threads.runs.retrieve(run.id, { thread_id: run.thread_id });
|
|
163
163
|
}
|
|
164
164
|
if (run.status === 'completed') {
|
|
165
|
-
const { data } = yield openai.beta.threads.messages.list(run.thread_id, { order: 'desc', limit: 1 })
|
|
166
|
-
|
|
165
|
+
const { data } = yield openai.beta.threads.messages.list(run.thread_id, { order: 'desc', limit: 1 });
|
|
166
|
+
const messages = data.flatMap((message) => message === null || message === void 0 ? void 0 : message.content.map((content) => ((content.type === 'text' && message.role === 'assistant') ? content.text : '')));
|
|
167
|
+
const assistantMessages = messages.filter(message => typeof message === 'object' && 'value' in message && typeof message.value === 'string');
|
|
167
168
|
if (assistantMessages.length) {
|
|
168
169
|
let answers = assistantMessages.map(message => message.value);
|
|
169
|
-
console.log('GET ASSISTANT REPLY answers: ', answers);
|
|
170
170
|
return {
|
|
171
|
-
|
|
171
|
+
firstChoice: JSON.stringify(answers),
|
|
172
172
|
threadId: run.thread_id,
|
|
173
173
|
usageTokens: run.usage,
|
|
174
174
|
};
|
|
@@ -177,5 +177,72 @@ class CopilotService extends BaseService_1.default {
|
|
|
177
177
|
return undefined;
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
|
+
isAssistantIdFormat(id) {
|
|
181
|
+
return !!id && /^asst_[A-Za-z0-9]+$/.test(id);
|
|
182
|
+
}
|
|
183
|
+
isPromptIdFormat(id) {
|
|
184
|
+
return !!id && /^pmpt_[A-Za-z0-9]+$/.test(id);
|
|
185
|
+
}
|
|
186
|
+
ensureConversation(openai) {
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
if (this.conversationId) {
|
|
189
|
+
return this.conversationId;
|
|
190
|
+
}
|
|
191
|
+
const conv = yield openai.conversations.create();
|
|
192
|
+
this.conversationId = conv.id;
|
|
193
|
+
return conv.id;
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
getPromptReply(message) {
|
|
197
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
|
|
198
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
199
|
+
const openai = new openai_1.default({ apiKey: this.openaiApiKey });
|
|
200
|
+
const conversationId = yield this.ensureConversation(openai);
|
|
201
|
+
const request = {
|
|
202
|
+
//model: this.chatGptModel || 'gpt-4o-mini',
|
|
203
|
+
input: message,
|
|
204
|
+
store: true,
|
|
205
|
+
conversation: conversationId,
|
|
206
|
+
include: ['file_search_call.results'],
|
|
207
|
+
};
|
|
208
|
+
if (this.assistantId && this.isPromptIdFormat(this.assistantId)) {
|
|
209
|
+
request.prompt = { id: this.assistantId };
|
|
210
|
+
}
|
|
211
|
+
const response = yield openai.responses.create(request);
|
|
212
|
+
response.output.forEach((item, index) => {
|
|
213
|
+
});
|
|
214
|
+
if ((_a = response.conversation) === null || _a === void 0 ? void 0 : _a.id) {
|
|
215
|
+
this.conversationId = response.conversation.id;
|
|
216
|
+
}
|
|
217
|
+
// Sometimes if the prompt needs a file search, the output will be an array of messages
|
|
218
|
+
// which includes multiple messages (some of them are not useful for the user, but the last one is)
|
|
219
|
+
const output = response.output || [];
|
|
220
|
+
const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
|
|
221
|
+
if (assistantMessages.length) {
|
|
222
|
+
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)) || []; });
|
|
223
|
+
return {
|
|
224
|
+
firstChoice: text.pop(),
|
|
225
|
+
threadId: this.conversationId,
|
|
226
|
+
usageTokens: {
|
|
227
|
+
prompt_tokens: Number((_c = ((_b = response.usage) === null || _b === void 0 ? void 0 : _b.prompt_tokens)) !== null && _c !== void 0 ? _c : 0),
|
|
228
|
+
completion_tokens: Number((_e = ((_d = response.usage) === null || _d === void 0 ? void 0 : _d.completion_tokens)) !== null && _e !== void 0 ? _e : 0),
|
|
229
|
+
total_tokens: Number((_g = ((_f = response.usage) === null || _f === void 0 ? void 0 : _f.total_tokens)) !== null && _g !== void 0 ? _g : 0),
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (response.output_text) {
|
|
234
|
+
return {
|
|
235
|
+
firstChoice: response.output_text,
|
|
236
|
+
threadId: this.conversationId,
|
|
237
|
+
usageTokens: {
|
|
238
|
+
prompt_tokens: Number((_j = ((_h = response.usage) === null || _h === void 0 ? void 0 : _h.prompt_tokens)) !== null && _j !== void 0 ? _j : 0),
|
|
239
|
+
completion_tokens: Number((_l = ((_k = response.usage) === null || _k === void 0 ? void 0 : _k.completion_tokens)) !== null && _l !== void 0 ? _l : 0),
|
|
240
|
+
total_tokens: Number((_o = ((_m = response.usage) === null || _m === void 0 ? void 0 : _m.total_tokens)) !== null && _o !== void 0 ? _o : 0),
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return undefined;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
180
247
|
}
|
|
181
248
|
exports.CopilotService = CopilotService;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import ChatGptResponse from '../../models/ChatGptResponse';
|
|
2
|
+
import OpenAI from "openai";
|
|
3
|
+
import BaseService from '../BaseService/BaseService';
|
|
4
|
+
interface ResponseServiceOptions {
|
|
5
|
+
instructions?: string;
|
|
6
|
+
tools?: any[];
|
|
7
|
+
functionOutputs?: string;
|
|
8
|
+
definedSchema?: any;
|
|
9
|
+
conversationId?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class ResponseService extends BaseService {
|
|
12
|
+
promptId: string | undefined;
|
|
13
|
+
conversationId: string | undefined;
|
|
14
|
+
lastResponseId: string | undefined;
|
|
15
|
+
constructor(apiKey?: string, promptId?: string, conversationId?: string);
|
|
16
|
+
/**
|
|
17
|
+
* Create a new conversation/response chain
|
|
18
|
+
*/
|
|
19
|
+
createConversation(): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Get the reply using the Response API
|
|
22
|
+
*
|
|
23
|
+
* @param message
|
|
24
|
+
* @param runOptions
|
|
25
|
+
*/
|
|
26
|
+
getReply(message: string, runOptions?: ResponseServiceOptions): Promise<ChatGptResponse | undefined>;
|
|
27
|
+
handleFunctionOutputs(openai: OpenAI, functionOutputs: string, runOptions?: ResponseServiceOptions): Promise<ChatGptResponse>;
|
|
28
|
+
processResponseOutput(response: any): ChatGptResponse;
|
|
29
|
+
reset(): void;
|
|
30
|
+
getConversationId(): string | undefined;
|
|
31
|
+
getLastResponseId(): string | undefined;
|
|
32
|
+
getPromptId(): string | undefined;
|
|
33
|
+
setPromptId(promptId: string): void;
|
|
34
|
+
setConversationId(conversationId: string): void;
|
|
35
|
+
setLastResponseId(lastResponseId: string): void;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ResponseService = void 0;
|
|
16
|
+
const logger_1 = __importDefault(require("../logger"));
|
|
17
|
+
const openai_1 = __importDefault(require("openai"));
|
|
18
|
+
const BaseService_1 = __importDefault(require("../BaseService/BaseService"));
|
|
19
|
+
class ResponseService extends BaseService_1.default {
|
|
20
|
+
constructor(apiKey, promptId, conversationId) {
|
|
21
|
+
super(apiKey);
|
|
22
|
+
Object.defineProperty(this, "promptId", {
|
|
23
|
+
enumerable: true,
|
|
24
|
+
configurable: true,
|
|
25
|
+
writable: true,
|
|
26
|
+
value: void 0
|
|
27
|
+
});
|
|
28
|
+
Object.defineProperty(this, "conversationId", {
|
|
29
|
+
enumerable: true,
|
|
30
|
+
configurable: true,
|
|
31
|
+
writable: true,
|
|
32
|
+
value: void 0
|
|
33
|
+
});
|
|
34
|
+
Object.defineProperty(this, "lastResponseId", {
|
|
35
|
+
enumerable: true,
|
|
36
|
+
configurable: true,
|
|
37
|
+
writable: true,
|
|
38
|
+
value: void 0
|
|
39
|
+
});
|
|
40
|
+
this.promptId = promptId;
|
|
41
|
+
this.conversationId = conversationId;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Create a new conversation/response chain
|
|
45
|
+
*/
|
|
46
|
+
createConversation() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
// Create a real conversation using the Conversations API
|
|
49
|
+
const openai = new openai_1.default({ apiKey: this.openaiApiKey });
|
|
50
|
+
const conversation = yield openai.conversations.create();
|
|
51
|
+
this.conversationId = conversation.id;
|
|
52
|
+
return this.conversationId;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get the reply using the Response API
|
|
57
|
+
*
|
|
58
|
+
* @param message
|
|
59
|
+
* @param runOptions
|
|
60
|
+
*/
|
|
61
|
+
getReply(message, runOptions = {}) {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
if (!this.promptId) {
|
|
65
|
+
logger_1.default.error('Prompt ID is required for Response API');
|
|
66
|
+
return Promise.reject(new Error('Prompt ID is required for Response API'));
|
|
67
|
+
}
|
|
68
|
+
logger_1.default.info(`New response with message: ${message} & options: ${JSON.stringify(runOptions)}`);
|
|
69
|
+
const openai = new openai_1.default({ apiKey: this.openaiApiKey });
|
|
70
|
+
try {
|
|
71
|
+
if (runOptions.functionOutputs) {
|
|
72
|
+
return yield this.handleFunctionOutputs(openai, runOptions.functionOutputs, runOptions);
|
|
73
|
+
}
|
|
74
|
+
if (!runOptions.conversationId && !this.conversationId) {
|
|
75
|
+
const createdId = yield this.createConversation();
|
|
76
|
+
this.conversationId = createdId;
|
|
77
|
+
}
|
|
78
|
+
const responseRequest = {
|
|
79
|
+
input: message,
|
|
80
|
+
store: true,
|
|
81
|
+
include: ['file_search_call.results'],
|
|
82
|
+
};
|
|
83
|
+
if (this.promptId) {
|
|
84
|
+
responseRequest.prompt = {
|
|
85
|
+
id: this.promptId
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (runOptions.instructions) {
|
|
89
|
+
responseRequest.instructions = runOptions.instructions;
|
|
90
|
+
}
|
|
91
|
+
const conversationIdToUse = runOptions.conversationId || this.conversationId;
|
|
92
|
+
if (conversationIdToUse) {
|
|
93
|
+
responseRequest.conversation = conversationIdToUse;
|
|
94
|
+
}
|
|
95
|
+
if ((_a = runOptions.tools) === null || _a === void 0 ? void 0 : _a.length) {
|
|
96
|
+
responseRequest.tools = runOptions.tools;
|
|
97
|
+
}
|
|
98
|
+
if (runOptions.definedSchema) {
|
|
99
|
+
responseRequest.text = {
|
|
100
|
+
format: runOptions.definedSchema
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const response = yield openai.responses.create(responseRequest);
|
|
104
|
+
this.lastResponseId = response.id;
|
|
105
|
+
if ((_b = response.conversation) === null || _b === void 0 ? void 0 : _b.id) {
|
|
106
|
+
this.conversationId = response.conversation.id;
|
|
107
|
+
}
|
|
108
|
+
else if (runOptions.conversationId) {
|
|
109
|
+
this.conversationId = runOptions.conversationId;
|
|
110
|
+
}
|
|
111
|
+
return this.processResponseOutput(response);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
logger_1.default.error('Error in ResponseService.getReply:', error);
|
|
115
|
+
return Promise.reject(error);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
handleFunctionOutputs(openai, functionOutputs, runOptions = {}) {
|
|
120
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
+
try {
|
|
122
|
+
const toolOutputs = JSON.parse(functionOutputs);
|
|
123
|
+
const formattedInputs = toolOutputs.map((output) => ({
|
|
124
|
+
type: 'function_call_output',
|
|
125
|
+
call_id: output.call_id,
|
|
126
|
+
output: output.output
|
|
127
|
+
}));
|
|
128
|
+
const responseRequest = {
|
|
129
|
+
input: formattedInputs,
|
|
130
|
+
store: true,
|
|
131
|
+
};
|
|
132
|
+
const conversationIdToUse = runOptions.conversationId || this.conversationId;
|
|
133
|
+
if (!conversationIdToUse) {
|
|
134
|
+
const createdId = yield this.createConversation();
|
|
135
|
+
this.conversationId = createdId;
|
|
136
|
+
}
|
|
137
|
+
responseRequest.conversation = runOptions.conversationId || this.conversationId;
|
|
138
|
+
if (this.promptId) {
|
|
139
|
+
responseRequest.prompt = {
|
|
140
|
+
id: this.promptId
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const response = yield openai.responses.create(responseRequest);
|
|
144
|
+
this.lastResponseId = response.id;
|
|
145
|
+
return this.processResponseOutput(response);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
logger_1.default.error('Error handling function outputs:', error);
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
processResponseOutput(response) {
|
|
154
|
+
const output = response.output || [];
|
|
155
|
+
const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
|
|
156
|
+
const functionCalls = output.filter((item) => item.type === 'function_call');
|
|
157
|
+
if (functionCalls.length > 0) {
|
|
158
|
+
return {
|
|
159
|
+
requiredActions: JSON.stringify(functionCalls),
|
|
160
|
+
threadId: this.conversationId,
|
|
161
|
+
usageTokens: response.usage,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
if (assistantMessages.length > 0) {
|
|
165
|
+
const textContent = assistantMessages
|
|
166
|
+
.flatMap((msg) => msg.content || [])
|
|
167
|
+
.filter((content) => content.type === 'output_text' || content.type === 'text')
|
|
168
|
+
.map((content) => content.text || content.value)
|
|
169
|
+
.filter((text) => text);
|
|
170
|
+
if (textContent) {
|
|
171
|
+
return {
|
|
172
|
+
firstChoice: textContent.pop().replace(/【.*?】/g, ''),
|
|
173
|
+
threadId: this.conversationId,
|
|
174
|
+
usageTokens: response.usage,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (response.output_text) {
|
|
179
|
+
return {
|
|
180
|
+
firstChoice: response.output_text.replace(/【.*?】/g, ''),
|
|
181
|
+
threadId: this.conversationId,
|
|
182
|
+
usageTokens: response.usage,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
threadId: this.conversationId,
|
|
187
|
+
usageTokens: response.usage,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
reset() {
|
|
191
|
+
this.lastResponseId = undefined;
|
|
192
|
+
this.conversationId = undefined;
|
|
193
|
+
}
|
|
194
|
+
getConversationId() {
|
|
195
|
+
return this.conversationId;
|
|
196
|
+
}
|
|
197
|
+
getLastResponseId() {
|
|
198
|
+
return this.lastResponseId;
|
|
199
|
+
}
|
|
200
|
+
getPromptId() {
|
|
201
|
+
return this.promptId;
|
|
202
|
+
}
|
|
203
|
+
setPromptId(promptId) {
|
|
204
|
+
this.promptId = promptId;
|
|
205
|
+
}
|
|
206
|
+
setConversationId(conversationId) {
|
|
207
|
+
this.conversationId = conversationId;
|
|
208
|
+
}
|
|
209
|
+
setLastResponseId(lastResponseId) {
|
|
210
|
+
this.lastResponseId = lastResponseId;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.ResponseService = ResponseService;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import BaseService from '../BaseService/BaseService';
|
|
2
|
-
import
|
|
2
|
+
import ChatGptResponse from '../../models/ChatGptResponse';
|
|
3
3
|
export declare class TranslationService extends BaseService {
|
|
4
4
|
constructor(apiKey?: string, model?: string, apiUrl?: string, maxNumberOfChoices?: number);
|
|
5
5
|
/**
|
|
@@ -9,17 +9,17 @@ export declare class TranslationService extends BaseService {
|
|
|
9
9
|
* @param toLanguage the desired language to translate to ( English is the default )
|
|
10
10
|
* @param fromLanguage if we want to specify the language of the text, we can use this ( optional)
|
|
11
11
|
*/
|
|
12
|
-
translate(text: string, toLanguage?: string, fromLanguage?: string): Promise<
|
|
12
|
+
translate(text: string, toLanguage?: string, fromLanguage?: string): Promise<ChatGptResponse | undefined>;
|
|
13
13
|
/**
|
|
14
14
|
* Detects the ISO language code of a text
|
|
15
15
|
*
|
|
16
16
|
* @param text text to detect
|
|
17
17
|
*/
|
|
18
|
-
findTextLanguage(text: string): Promise<
|
|
18
|
+
findTextLanguage(text: string): Promise<ChatGptResponse | undefined>;
|
|
19
19
|
/**
|
|
20
20
|
* Detects the ISO language code of a text based on frequency of words
|
|
21
21
|
*
|
|
22
22
|
* @param text text to detect
|
|
23
23
|
*/
|
|
24
|
-
findTextLanguageBasedOnFrequency(text: string): Promise<
|
|
24
|
+
findTextLanguageBasedOnFrequency(text: string): Promise<ChatGptResponse | undefined>;
|
|
25
25
|
}
|
|
@@ -52,13 +52,11 @@ class TranslationService extends BaseService_1.default {
|
|
|
52
52
|
],
|
|
53
53
|
};
|
|
54
54
|
try {
|
|
55
|
-
logger_1.default.info({ requestBody }, ':: TranslationServicee.translate :: Translating ::');
|
|
56
55
|
const response = yield this.request.post('', requestBody);
|
|
57
56
|
return {
|
|
58
|
-
|
|
57
|
+
firstChoice: this.getResponseFirstChoice(response),
|
|
59
58
|
usageTokens: this.getResponseUsageTokens(response),
|
|
60
59
|
};
|
|
61
|
-
// return response.data;
|
|
62
60
|
}
|
|
63
61
|
catch (e) {
|
|
64
62
|
this.handleErrors(e);
|
|
@@ -92,10 +90,9 @@ class TranslationService extends BaseService_1.default {
|
|
|
92
90
|
],
|
|
93
91
|
};
|
|
94
92
|
try {
|
|
95
|
-
logger_1.default.info({ requestBody }, ':: TranslationServicee.findTextLanguage :: Finding text language ::');
|
|
96
93
|
const response = yield this.request.post('', requestBody);
|
|
97
94
|
return {
|
|
98
|
-
|
|
95
|
+
firstChoice: this.getResponseFirstChoice(response),
|
|
99
96
|
usageTokens: this.getResponseUsageTokens(response),
|
|
100
97
|
};
|
|
101
98
|
}
|
|
@@ -131,10 +128,9 @@ class TranslationService extends BaseService_1.default {
|
|
|
131
128
|
],
|
|
132
129
|
};
|
|
133
130
|
try {
|
|
134
|
-
logger_1.default.info({ requestBody }, ':: TranslationServicee.findTextLanguageBasedOnFrequency :: Finding text language ::');
|
|
135
131
|
const response = yield this.request.post('', requestBody);
|
|
136
132
|
return {
|
|
137
|
-
|
|
133
|
+
firstChoice: this.getResponseFirstChoice(response),
|
|
138
134
|
usageTokens: this.getResponseUsageTokens(response),
|
|
139
135
|
};
|
|
140
136
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cobrowser/chatgpt",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.32-dev.0",
|
|
4
4
|
"description": "chatgpt services to connect our projects with chatgpt api",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatgpt",
|
|
@@ -21,11 +21,10 @@
|
|
|
21
21
|
"precommit": "npm run lint && npm run test && npm run upgrade && npm run security"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@cobrowser/logger": "^2.0.
|
|
25
|
-
"@cobrowser/xss-validation": "^2.0.1",
|
|
24
|
+
"@cobrowser/logger": "^2.0.6",
|
|
26
25
|
"axios": "^1.6.1",
|
|
27
26
|
"axios-mock-adapter": "^1.22.0",
|
|
28
|
-
"openai": "^
|
|
27
|
+
"openai": "^6.3.0"
|
|
29
28
|
},
|
|
30
29
|
"directories": {
|
|
31
30
|
"dist": "dist"
|
|
@@ -40,5 +39,5 @@
|
|
|
40
39
|
"bugs": {
|
|
41
40
|
"url": "https://bitbucket.org/cobrowser/cb_utils/issues"
|
|
42
41
|
},
|
|
43
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "246db1800e2c2238ae01d99a69c971fe6ecd4795"
|
|
44
43
|
}
|