Last active
December 7, 2022 13:51
-
-
Save rleroi/3b5667983bf0c16172f4ecd5a52a1fda to your computer and use it in GitHub Desktop.
Generate short description for Trengo with GPT3, runs on Cloudflare Workers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
addEventListener("fetch", (event) => { | |
event.respondWith( | |
handleRequest(event.request).catch( | |
(err) => new Response(err.stack, { status: 500 }) | |
) | |
); | |
}); | |
const paused = false; | |
const environments = { | |
'production': { | |
trengoApi: 'https://app.trengo.com/api/v2/ticket_summary/', | |
trengoKey: 'xxx', | |
}, | |
'local': { | |
trengoApi: 'https://ramses-trengo.eu.ngrok.io/api/v2/ticket_summary/', | |
trengoKey: 'xxx', | |
}, | |
'staging': { | |
trengoApi: 'https://app-stg.trengo.eu/api/v2/ticket_summary/', | |
trengoKey: 'xxx', | |
} | |
}; | |
const engine = 'text-davinci-002'; | |
const api = `https://api.openai.com/v1/engines/${engine}/completions`; | |
const key = 'xxx'; | |
const maxTokens = 1000; | |
const temperature = 0; | |
const promptPrefix = `Input: | |
Dear Henk, | |
I am cancelling my flight due to private reasons. | |
Kind regards, | |
Piet | |
Topic: | |
Flight cancelation | |
Input: | |
Hallo, ik ben mijn wachtwoord vergeten. Hoe krijg ik hem terug? | |
Topic: | |
Vergeten wachtwoord | |
Input: | |
Hello Trengo support team, | |
My question is about the flowbot. It generates wrong answers. | |
Topic: | |
Wrong flowbot answers | |
Input:`; | |
const promptPrefixLong = `Input: | |
Dear Henk, | |
I am cancelling my flight due to private reasons. | |
Kind regards, | |
Piet | |
One-sentence summary: | |
Flight will be canceled due to private reasons. | |
Input: | |
Hallo, ik ben mijn wachtwoord vergeten. Hoe krijg ik hem terug? | |
One-sentence summary: | |
Vraag over het terughalen van een vergeten wachtwoord. | |
Input: | |
Hello Trengo support team, | |
My question is about the flowbot. It generates wrong answers. | |
One-sentence summary: | |
Question regarding the flowbot that generates wrong answers. | |
Input:`; | |
/* | |
message_id Message ID | |
ticket_id Ticket ID | |
contact_id Contact ID | |
message Message content | |
contact_name Contact name | |
contact_email Contact email | |
*/ | |
/** | |
* Many more examples available at: | |
* https://developers.cloudflare.com/workers/examples | |
* @param {Request} request | |
* @returns {Promise<Response>} | |
*/ | |
async function handleRequest(request) { | |
const { pathname } = new URL(request.url); | |
// #### hook #### | |
if (pathname.startsWith("/hook")) { | |
if (paused) { | |
return new Response(JSON.stringify({'status': 'paused'})); | |
} | |
const environment = pathname.split("/")[2]; | |
if (!environments[environment]) { | |
return new Response(JSON.stringify({'status': 'environment not found'}), { status: 404 }); | |
} | |
const data = formDataToJson(await request.formData()); | |
if (await SUMMARY_TICKETS.get(parseInt(data.ticket_id))) { | |
return new Response('Already processed'); | |
} | |
let summaryShort = await getSummaryShort(data.message); | |
let summaryLong = await getSummaryLong(data.message); | |
await SUMMARY_TICKETS.put(parseInt(data.ticket_id), summaryShort + summaryLong); | |
const {trengoKey, trengoApi} = environments[environment]; | |
await requestTrengo(trengoApi + data.ticket_id, trengoKey, { | |
'summary_short': summaryShort, | |
'summary_long': summaryLong, | |
}); | |
console.log(environment, data.ticket_id, summaryShort); | |
return new Response(JSON.stringify({environment, ticketId: data.ticket_id, summaryShort})); | |
// #### demo #### | |
} else if (pathname.startsWith("/demo")) { | |
return await demo(request); | |
} | |
return new Response(JSON.stringify({'status': 'route not found'}), { status: 404 }); | |
} | |
function formDataToJson(input) { | |
let output = {}; | |
for (let [key, value] of input) { | |
let tmp = output[key]; | |
if (tmp === undefined) { | |
output[key] = value; | |
} else { | |
output[key] = [].concat(tmp, value); | |
} | |
} | |
return output; | |
} | |
async function requestTrengo(endpoint, trengoKey, body = null) { | |
return await fetch(endpoint, { | |
method: 'POST', | |
body: JSON.stringify(body), | |
headers: { | |
'Authorization': `Bearer ${trengoKey}`, | |
'Content-Type': 'application/json', | |
}, | |
}); | |
} | |
async function getSummaryShort(text) { | |
text = text.replace(/(\r?\n)+/, /\n/).replace(/[^\p{L}\p{N}\s -~]/igu, '').replace(/(<([^>]+)>)/gi, "").substring(0,750); | |
const prompt = `${promptPrefix} | |
${text} | |
Topic: | |
`; | |
const response = await fetch(api, { | |
method: 'POST', | |
body: JSON.stringify({ | |
prompt, | |
'temperature': temperature, | |
'max_tokens': maxTokens | |
}), | |
headers: { | |
'Authorization': `Bearer ${key}`, | |
'Content-Type': 'application/json', | |
}, | |
}); | |
const responseJson = await response.json(); | |
return responseJson.choices[0]?.text; | |
} | |
async function getSummaryLong(text) { | |
text = text.replace(/(\r?\n)+/, /\n/).replace(/[^\p{L}\p{N}\s -~]/igu, '').replace(/(<([^>]+)>)/gi, "").substring(0,750); | |
const prompt = `${promptPrefixLong} | |
${text} | |
One-sentence summary: | |
`; | |
const response = await fetch(api, { | |
method: 'POST', | |
body: JSON.stringify({ | |
prompt, | |
'temperature': temperature, | |
'max_tokens': maxTokens | |
}), | |
headers: { | |
'Authorization': `Bearer ${key}`, | |
'Content-Type': 'application/json', | |
}, | |
}); | |
const responseJson = await response.json(); | |
return responseJson.choices[0]?.text; | |
} | |
async function demo(request) { | |
const { pathname } = new URL(request.url); | |
let text = pathname.split("/")[2]; | |
text = text.replace(/(\r?\n)+/, /\n/); | |
const prompt = `${promptPrefix} | |
${text} | |
Topic: | |
`; | |
const response = await fetch(api, { | |
method: 'POST', | |
body: JSON.stringify({ | |
prompt, | |
'temperature': temperature, | |
'max_tokens': maxTokens | |
}), | |
headers: { | |
'Authorization': `Bearer ${key}`, | |
'Content-Type': 'application/json', | |
}, | |
}); | |
const responseJson = await response.json(); | |
const summaryShort = responseJson.choices[0]?.text; | |
return new Response(JSON.stringify({ | |
'summary_short': summaryShort, | |
})); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment