-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
168 lines (146 loc) · 5.56 KB
/
index.js
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
const functions = require('@google-cloud/functions-framework');
const axios = require('axios');
const gptToken = process.env.GPT_TOKEN;
const huggyApiToken = process.env.HUGGY_TOKEN;
const companyId = process.env.COMPANY_ID;
const flowId = process.env.FLOW_ID;
/* doPost:
- Recebe os eventos do Webhook da Huggy e verifica se é um evento de mensagem recebida (receivedMessage).
- Chama a função 'manageCalls'para gerenciar as chamadas para o chat GPT e para a Huggy.
*/
exports.doPost = async (req, res) => {
const requestData = req.body;
if (requestData.messages && requestData.messages.receivedMessage) {
requestData.messages.receivedMessage.forEach(message => {
const stepsDone = manageCalls(message.body, message.chat.id);
stepsDone === false ? res.json(returnStatus('O chat não pertence a um flow mapeado, ou algum processo falhou.')) : res.json(returnStatus('Sucesso na execução.'));
});
}
};
/* manageCalls:
- Chama a função 'variablesChecker', para saber se a mensagem do chat contém uma variável de contexto relativa ao fluxo mapeado. Caso a variável for identificada, aciona a API do Chat GPT enviando a mensagem como prompt.
- Recebe o retorno do ChatGPT com a resposta e faz a chamada para a API da Huggy, que vai disparar no chat a resposta que veio do GPT.
- Após disparar a mensagem no chat, chama a API da Huggy para executar o flow contendo o menu com mais opções (permitindo continuar interagindo com o ChatGPT ou finalizando a conversa).
- Se todos passos acima forem executados é retornado 'true', caso contrário é retornado 'false'.
*/
async function manageCalls(chatMessage, chatId) {
const monitoredFlow = await variablesChecker(chatId);
const url = 'https://api.openai.com/v1/chat/completions';
const gptModel = 'gpt-3.5-turbo';
const gptHeaders = {Authorization: `Bearer ${gptToken}`, 'Content-Type': 'application/json'}
if (monitoredFlow === true) {
const body = {
model: gptModel,
messages: [
{
role: 'system',
content: 'Você é um profissional com anos de prática em atendimento ao cliente e é formado em Customer Success, é atencioso, empático, com respostas objetivas e rápidas.'
},
{
role: 'user',
content: chatMessage
}
],
};
try {
const response = await axios.post(url, body, {headers: gptHeaders});
let allStepsPerformed = true;
const messageAdded = await addMessageInChat(extractMessage(JSON.stringify(response.data)), chatId);
const flowTriggered = await triggerFlowMenu(chatId, flowId);
messageAdded === false || flowTriggered === false? allStepsPerformed = false: allStepsPerformed = true;
return (allStepsPerformed);
} catch (error) {
console.error('Error calling GPT:', error.message);
return false;
}
} else {
console.log('Nenhuma operação será realizada, pois o flow não está mapeado.');
return false;
}
}
/*variablesChecker:
Verifica se o chat possui uma variável de contexto correspondente ao flow que interage com o ChatGPT. Essa variável está presente no flow chamado de 'ChatGPT | Use como Flow de entrada'.
Detalhes em https://developers.huggy.io/pt/API/api-v3.html#get-chats-id-contextvariables
*/
async function variablesChecker(chatId) {
try {
const response = await axios.get(
`https://api.huggy.app/v3/companies/${companyId}/chats/${chatId}/contextVariables`,
{
headers: {
Authorization: `Bearer ${huggyApiToken}`,
'Content-Type': 'application/json'
}
}
);
const { contextVariables } = response.data;
if (contextVariables.experimentar_gpt === 'Testar o ChatGPT') {// 'experimentar_gpt' é uma variável de contexto e 'Testar o ChatGPT' é o valor dela preenchido na alão Enviar pergunta
return true;
} else {
return false;
}
} catch (error) {
console.error('erro:', error.message);
return false;
}
}
/* addMessageInChat:
Adiciona a resposta do ChatGPT como mensagem no chat da Huggy. Detalhes em: https://developers.huggy.io/pt/API/api-v3.html#post-chats-id-messages
*/
async function addMessageInChat(chatMessage, chatId) {
const data = {
text: chatMessage
};
try {
const response = await axios.post(
`https://api.huggy.app/v3/companies/${companyId}/chats/${chatId}/messages/`,
data,
{
headers: {
Authorization: `Bearer ${huggyApiToken}`,
'Content-Type': 'application/json'
}
}
);
return true;
} catch (error) {
console.error('Error sending message:', error.message);
return false;
}
}
/* triggerFlowMenu:
Dispara o flow de opções adicionais na conversa. É chamada logo após a mensagem do GPT ser disparada. Detalhes em: https://developers.huggy.io/pt/API/api-v3.html#post-chats-id-flow
*/
async function triggerFlowMenu(chatId, flowId) {
let data = {
"flowId": flowId
};
try {
const response = await axios.post(
`https://api.huggy.app/v3/companies/${companyId}/chats/${chatId}/flow/`,
data,
{
headers: {
Authorization: `Bearer ${huggyApiToken}`,
'Content-Type': 'application/json'
}
}
);
return true;
} catch (error) {
console.error('Error triggering flow:', error.message);
return false;
}
}
function extractMessage(jsonString) {
const data = JSON.parse(jsonString);
const message = data.choices[0].message;
return message.content;
}
function returnStatus(message) {
const responseData = {
status: message,
timestamp: Date.now()
};
return responseData;
}