2023-03-14 15:42:59 -04:00
|
|
|
const _ = require('lodash');
|
2023-03-15 15:44:48 -04:00
|
|
|
const citationRegex = /\[\^\d+?\^]/g;
|
2023-03-21 13:41:31 -04:00
|
|
|
const backtick = /(?<!`)[`](?!`)/g;
|
|
|
|
|
// const singleBacktick = /(?<!`)[`](?!`)/;
|
|
|
|
|
const cursorDefault = '<span class="result-streaming">█</span>';
|
|
|
|
|
const { getCitations, citeText } = require('../../app/');
|
2023-03-14 15:42:59 -04:00
|
|
|
|
2023-03-15 00:50:27 +08:00
|
|
|
const handleError = (res, message) => {
|
|
|
|
|
res.write(`event: error\ndata: ${JSON.stringify(message)}\n\n`);
|
2023-02-25 09:04:32 -05:00
|
|
|
res.end();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const sendMessage = (res, message) => {
|
|
|
|
|
if (message.length === 0) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
res.write(`event: message\ndata: ${JSON.stringify(message)}\n\n`);
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-14 15:42:59 -04:00
|
|
|
const createOnProgress = () => {
|
|
|
|
|
let i = 0;
|
2023-03-21 13:41:31 -04:00
|
|
|
let code = '';
|
2023-03-14 15:42:59 -04:00
|
|
|
let tokens = '';
|
2023-03-21 13:41:31 -04:00
|
|
|
let precode = '';
|
|
|
|
|
let blockCount = 0;
|
|
|
|
|
let codeBlock = false;
|
|
|
|
|
let cursor = cursorDefault;
|
2023-03-14 15:42:59 -04:00
|
|
|
|
|
|
|
|
const progressCallback = async (partial, { res, text, bing = false, ...rest }) => {
|
2023-03-21 13:41:31 -04:00
|
|
|
let chunk = partial === text ? '' : partial;
|
|
|
|
|
tokens += chunk;
|
|
|
|
|
precode += chunk;
|
2023-03-14 15:42:59 -04:00
|
|
|
tokens = tokens.replaceAll('[DONE]', '');
|
2023-03-14 16:05:46 -04:00
|
|
|
|
2023-03-21 13:41:31 -04:00
|
|
|
if (codeBlock) {
|
|
|
|
|
code += chunk;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (precode.includes('```') && codeBlock) {
|
|
|
|
|
codeBlock = false;
|
|
|
|
|
cursor = cursorDefault;
|
|
|
|
|
precode = precode.replace(/```/g, '');
|
|
|
|
|
code = '';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (precode.includes('```') && code === '') {
|
|
|
|
|
precode = precode.replace(/```/g, '');
|
|
|
|
|
codeBlock = true;
|
|
|
|
|
blockCount++;
|
|
|
|
|
cursor = blockCount > 1 ? '█\n\n```' : '█\n\n';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const backticks = precode.match(backtick);
|
|
|
|
|
if (backticks && !codeBlock && cursor === cursorDefault) {
|
|
|
|
|
precode = precode.replace(backtick, '');
|
|
|
|
|
cursor = '█';
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-14 16:05:46 -04:00
|
|
|
if (tokens.match(/^\n/)) {
|
|
|
|
|
tokens = tokens.replace(/^\n/, '');
|
2023-03-14 15:42:59 -04:00
|
|
|
}
|
2023-03-15 14:36:17 -04:00
|
|
|
|
2023-03-14 15:42:59 -04:00
|
|
|
if (bing) {
|
|
|
|
|
tokens = citeText(tokens, true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-21 13:41:31 -04:00
|
|
|
sendMessage(res, { text: tokens + cursor, message: true, initial: i === 0, ...rest });
|
2023-03-14 15:42:59 -04:00
|
|
|
i++;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onProgress = (model, opts) => {
|
|
|
|
|
const bingModels = new Set(['bingai', 'sydney']);
|
|
|
|
|
return _.partialRight(progressCallback, { ...opts, bing: bingModels.has(model) });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return onProgress;
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-15 15:44:48 -04:00
|
|
|
const handleText = async (response, bing = false) => {
|
|
|
|
|
let { text } = response;
|
2023-03-17 09:11:31 -04:00
|
|
|
// text = await detectCode(text);
|
2023-03-15 15:44:48 -04:00
|
|
|
response.text = text;
|
|
|
|
|
|
|
|
|
|
if (bing) {
|
|
|
|
|
// const hasCitations = response.response.match(citationRegex)?.length > 0;
|
|
|
|
|
const links = getCitations(response);
|
|
|
|
|
if (response.text.match(citationRegex)?.length > 0) {
|
|
|
|
|
text = citeText(response);
|
|
|
|
|
}
|
|
|
|
|
text += links?.length > 0 ? `\n<small>${links}</small>` : '';
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-14 16:05:46 -04:00
|
|
|
return text;
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-15 15:21:04 -04:00
|
|
|
module.exports = { handleError, sendMessage, createOnProgress, handleText };
|