Require single quotes

This commit is contained in:
valadaptive
2023-12-02 13:04:51 -05:00
parent a06f1e8ad6
commit a37f874e38
76 changed files with 4135 additions and 4134 deletions

View File

@@ -6,7 +6,7 @@ const { finished } = require('stream/promises');
const writeFileSyncAtomic = require('write-file-atomic').sync;
const { DIRECTORIES, UNSAFE_EXTENSIONS } = require('./constants');
const VALID_CATEGORIES = ["bgm", "ambient", "blip", "live2d"];
const VALID_CATEGORIES = ['bgm', 'ambient', 'blip', 'live2d'];
/**
* Sanitizes the input filename for theasset.
@@ -16,22 +16,22 @@ const VALID_CATEGORIES = ["bgm", "ambient", "blip", "live2d"];
function checkAssetFileName(inputFilename) {
// Sanitize filename
if (inputFilename.indexOf('\0') !== -1) {
console.debug("Bad request: poisong null bytes in filename.");
console.debug('Bad request: poisong null bytes in filename.');
return '';
}
if (!/^[a-zA-Z0-9_\-.]+$/.test(inputFilename)) {
console.debug("Bad request: illegal character in filename, only alphanumeric, '_', '-' are accepted.");
console.debug('Bad request: illegal character in filename, only alphanumeric, \'_\', \'-\' are accepted.');
return '';
}
if (UNSAFE_EXTENSIONS.some(ext => inputFilename.toLowerCase().endsWith(ext))) {
console.debug("Bad request: forbidden file extension.");
console.debug('Bad request: forbidden file extension.');
return '';
}
if (inputFilename.startsWith('.')) {
console.debug("Bad request: filename cannot start with '.'");
console.debug('Bad request: filename cannot start with \'.\'');
return '';
}
@@ -84,18 +84,18 @@ function registerEndpoints(app, jsonParser) {
});
for (const folder of folders) {
if (folder == "temp")
if (folder == 'temp')
continue;
// Live2d assets
if (folder == "live2d") {
if (folder == 'live2d') {
output[folder] = [];
const live2d_folder = path.normalize(path.join(folderPath, folder));
const files = getFiles(live2d_folder);
//console.debug("FILE FOUND:",files)
for (let file of files) {
file = path.normalize(file.replace('public' + path.sep, ''));
if (file.includes("model") && file.endsWith(".json")) {
if (file.includes('model') && file.endsWith('.json')) {
//console.debug("Asset live2d model found:",file)
output[folder].push(path.normalize(path.join(file)));
}
@@ -106,11 +106,11 @@ function registerEndpoints(app, jsonParser) {
// Other assets (bgm/ambient/blip)
const files = fs.readdirSync(path.join(folderPath, folder))
.filter(filename => {
return filename != ".placeholder";
return filename != '.placeholder';
});
output[folder] = [];
for (const file of files) {
output[folder].push(path.join("assets", folder, file));
output[folder].push(path.join('assets', folder, file));
}
}
}
@@ -141,7 +141,7 @@ function registerEndpoints(app, jsonParser) {
category = i;
if (category === null) {
console.debug("Bad request: unsuported asset category.");
console.debug('Bad request: unsuported asset category.');
return response.sendStatus(400);
}
@@ -150,9 +150,9 @@ function registerEndpoints(app, jsonParser) {
if (safe_input == '')
return response.sendStatus(400);
const temp_path = path.join(DIRECTORIES.assets, "temp", safe_input)
const temp_path = path.join(DIRECTORIES.assets, 'temp', safe_input)
const file_path = path.join(DIRECTORIES.assets, category, safe_input)
console.debug("Request received to download", url, "to", file_path);
console.debug('Request received to download', url, 'to', file_path);
try {
// Download to temp
@@ -171,7 +171,7 @@ function registerEndpoints(app, jsonParser) {
await finished(res.body.pipe(fileStream));
// Move into asset place
console.debug("Download finished, moving file from", temp_path, "to", file_path);
console.debug('Download finished, moving file from', temp_path, 'to', file_path);
fs.renameSync(temp_path, file_path);
response.sendStatus(200);
}
@@ -200,7 +200,7 @@ function registerEndpoints(app, jsonParser) {
category = i;
if (category === null) {
console.debug("Bad request: unsuported asset category.");
console.debug('Bad request: unsuported asset category.');
return response.sendStatus(400);
}
@@ -210,7 +210,7 @@ function registerEndpoints(app, jsonParser) {
return response.sendStatus(400);
const file_path = path.join(DIRECTORIES.assets, category, safe_input)
console.debug("Request received to delete", category, file_path);
console.debug('Request received to delete', category, file_path);
try {
// Delete if previous download failed
@@ -218,10 +218,10 @@ function registerEndpoints(app, jsonParser) {
fs.unlink(file_path, (err) => {
if (err) throw err;
});
console.debug("Asset deleted.");
console.debug('Asset deleted.');
}
else {
console.debug("Asset not found.");
console.debug('Asset not found.');
response.sendStatus(400);
}
// Move into asset place
@@ -254,7 +254,7 @@ function registerEndpoints(app, jsonParser) {
category = i
if (category === null) {
console.debug("Bad request: unsuported asset category.");
console.debug('Bad request: unsuported asset category.');
return response.sendStatus(400);
}
@@ -265,15 +265,15 @@ function registerEndpoints(app, jsonParser) {
if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {
// Live2d assets
if (category == "live2d") {
if (category == 'live2d') {
const folders = fs.readdirSync(folderPath)
for (let modelFolder of folders) {
const live2dModelPath = path.join(folderPath, modelFolder);
if (fs.statSync(live2dModelPath).isDirectory()) {
for (let file of fs.readdirSync(live2dModelPath)) {
//console.debug("Character live2d model found:", file)
if (file.includes("model") && file.endsWith(".json"))
output.push(path.join("characters", name, category, modelFolder, file));
if (file.includes('model') && file.endsWith('.json'))
output.push(path.join('characters', name, category, modelFolder, file));
}
}
}
@@ -283,7 +283,7 @@ function registerEndpoints(app, jsonParser) {
// Other assets
const files = fs.readdirSync(folderPath)
.filter(filename => {
return filename != ".placeholder";
return filename != '.placeholder';
});
for (let i of files)
@@ -300,17 +300,17 @@ function registerEndpoints(app, jsonParser) {
app.post('/api/file/upload', jsonParser, async (request, response) => {
try {
if (!request.body.name) {
return response.status(400).send("No upload name specified");
return response.status(400).send('No upload name specified');
}
if (!request.body.data) {
return response.status(400).send("No upload data specified");
return response.status(400).send('No upload data specified');
}
const safeInput = checkAssetFileName(request.body.name);
if (!safeInput) {
return response.status(400).send("Invalid upload name");
return response.status(400).send('Invalid upload name');
}
const pathToUpload = path.join(DIRECTORIES.files, safeInput);

View File

@@ -10,8 +10,8 @@
function convertClaudePrompt(messages, addHumanPrefix, addAssistantPostfix, withSystemPrompt) {
// Claude doesn't support message names, so we'll just add them to the message content.
for (const message of messages) {
if (message.name && message.role !== "system") {
message.content = message.name + ": " + message.content;
if (message.name && message.role !== 'system') {
message.content = message.name + ': ' + message.content;
delete message.name;
}
}
@@ -22,7 +22,7 @@ function convertClaudePrompt(messages, addHumanPrefix, addAssistantPostfix, with
for (let i = 0; i < messages.length - 1; i++) {
const message = messages[i];
if (message.role === "system" && !message.name) {
if (message.role === 'system' && !message.name) {
systemPrompt += message.content + '\n\n';
} else {
lastSystemIdx = i - 1;
@@ -37,20 +37,20 @@ function convertClaudePrompt(messages, addHumanPrefix, addAssistantPostfix, with
let requestPrompt = messages.map((v) => {
let prefix = '';
switch (v.role) {
case "assistant":
prefix = "\n\nAssistant: ";
case 'assistant':
prefix = '\n\nAssistant: ';
break
case "user":
prefix = "\n\nHuman: ";
case 'user':
prefix = '\n\nHuman: ';
break
case "system":
case 'system':
// According to the Claude docs, H: and A: should be used for example conversations.
if (v.name === "example_assistant") {
prefix = "\n\nA: ";
} else if (v.name === "example_user") {
prefix = "\n\nH: ";
if (v.name === 'example_assistant') {
prefix = '\n\nA: ';
} else if (v.name === 'example_user') {
prefix = '\n\nH: ';
} else {
prefix = "\n\n";
prefix = '\n\n';
}
break
}
@@ -58,7 +58,7 @@ function convertClaudePrompt(messages, addHumanPrefix, addAssistantPostfix, with
}).join('');
if (addHumanPrefix) {
requestPrompt = "\n\nHuman: " + requestPrompt;
requestPrompt = '\n\nHuman: ' + requestPrompt;
}
if (addAssistantPostfix) {

View File

@@ -28,106 +28,106 @@ const DIRECTORIES = {
};
const UNSAFE_EXTENSIONS = [
".php",
".exe",
".com",
".dll",
".pif",
".application",
".gadget",
".msi",
".jar",
".cmd",
".bat",
".reg",
".sh",
".py",
".js",
".jse",
".jsp",
".pdf",
".html",
".htm",
".hta",
".vb",
".vbs",
".vbe",
".cpl",
".msc",
".scr",
".sql",
".iso",
".img",
".dmg",
".ps1",
".ps1xml",
".ps2",
".ps2xml",
".psc1",
".psc2",
".msh",
".msh1",
".msh2",
".mshxml",
".msh1xml",
".msh2xml",
".scf",
".lnk",
".inf",
".reg",
".doc",
".docm",
".docx",
".dot",
".dotm",
".dotx",
".xls",
".xlsm",
".xlsx",
".xlt",
".xltm",
".xltx",
".xlam",
".ppt",
".pptm",
".pptx",
".pot",
".potm",
".potx",
".ppam",
".ppsx",
".ppsm",
".pps",
".ppam",
".sldx",
".sldm",
".ws",
'.php',
'.exe',
'.com',
'.dll',
'.pif',
'.application',
'.gadget',
'.msi',
'.jar',
'.cmd',
'.bat',
'.reg',
'.sh',
'.py',
'.js',
'.jse',
'.jsp',
'.pdf',
'.html',
'.htm',
'.hta',
'.vb',
'.vbs',
'.vbe',
'.cpl',
'.msc',
'.scr',
'.sql',
'.iso',
'.img',
'.dmg',
'.ps1',
'.ps1xml',
'.ps2',
'.ps2xml',
'.psc1',
'.psc2',
'.msh',
'.msh1',
'.msh2',
'.mshxml',
'.msh1xml',
'.msh2xml',
'.scf',
'.lnk',
'.inf',
'.reg',
'.doc',
'.docm',
'.docx',
'.dot',
'.dotm',
'.dotx',
'.xls',
'.xlsm',
'.xlsx',
'.xlt',
'.xltm',
'.xltx',
'.xlam',
'.ppt',
'.pptm',
'.pptx',
'.pot',
'.potm',
'.potx',
'.ppam',
'.ppsx',
'.ppsm',
'.pps',
'.ppam',
'.sldx',
'.sldm',
'.ws',
];
const PALM_SAFETY = [
{
category: "HARM_CATEGORY_DEROGATORY",
threshold: "BLOCK_NONE"
category: 'HARM_CATEGORY_DEROGATORY',
threshold: 'BLOCK_NONE'
},
{
category: "HARM_CATEGORY_TOXICITY",
threshold: "BLOCK_NONE"
category: 'HARM_CATEGORY_TOXICITY',
threshold: 'BLOCK_NONE'
},
{
category: "HARM_CATEGORY_VIOLENCE",
threshold: "BLOCK_NONE"
category: 'HARM_CATEGORY_VIOLENCE',
threshold: 'BLOCK_NONE'
},
{
category: "HARM_CATEGORY_SEXUAL",
threshold: "BLOCK_NONE"
category: 'HARM_CATEGORY_SEXUAL',
threshold: 'BLOCK_NONE'
},
{
category: "HARM_CATEGORY_MEDICAL",
threshold: "BLOCK_NONE"
category: 'HARM_CATEGORY_MEDICAL',
threshold: 'BLOCK_NONE'
},
{
category: "HARM_CATEGORY_DANGEROUS",
threshold: "BLOCK_NONE"
category: 'HARM_CATEGORY_DANGEROUS',
threshold: 'BLOCK_NONE'
}
];

View File

@@ -92,8 +92,8 @@ async function downloadChubLorebook(id) {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
"fullPath": id,
"format": "SILLYTAVERN",
'fullPath': id,
'format': 'SILLYTAVERN',
}),
});
@@ -116,8 +116,8 @@ async function downloadChubCharacter(id) {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
"format": "tavern",
"fullPath": id,
'format': 'tavern',
'fullPath': id,
})
});
@@ -185,7 +185,7 @@ async function downloadJannyCharacter(uuid) {
method: 'POST',
headers: { 'Content-Type': 'application/json'},
body: JSON.stringify({
"characterId": uuid,
'characterId': uuid,
})
});

View File

@@ -1,9 +1,9 @@
const fetch = require('node-fetch').default;
const AIHorde = require("./ai_horde");
const { getVersion, delay } = require("./util");
const { readSecret, SECRET_KEYS } = require("./secrets");
const AIHorde = require('./ai_horde');
const { getVersion, delay } = require('./util');
const { readSecret, SECRET_KEYS } = require('./secrets');
const ANONYMOUS_KEY = "0000000000";
const ANONYMOUS_KEY = '0000000000';
/**
* Returns the AIHorde client.
@@ -26,27 +26,27 @@ async function getHordeClient() {
*/
function sanitizeHordeImagePrompt(prompt) {
if (!prompt) {
return "";
return '';
}
//to avoid flagging from some image models, always swap these words
prompt = prompt.replace(/\b(girl)\b/gmi, "woman");
prompt = prompt.replace(/\b(boy)\b/gmi, "man");
prompt = prompt.replace(/\b(girls)\b/gmi, "women");
prompt = prompt.replace(/\b(boys)\b/gmi, "men");
prompt = prompt.replace(/\b(girl)\b/gmi, 'woman');
prompt = prompt.replace(/\b(boy)\b/gmi, 'man');
prompt = prompt.replace(/\b(girls)\b/gmi, 'women');
prompt = prompt.replace(/\b(boys)\b/gmi, 'men');
//always remove these high risk words from prompt, as they add little value to image gen while increasing the risk the prompt gets flagged
prompt = prompt.replace(/\b(under.age|under.aged|underage|underaged|loli|pedo|pedophile|(\w+).year.old|(\w+).years.old|minor|prepubescent|minors|shota)\b/gmi, "");
prompt = prompt.replace(/\b(under.age|under.aged|underage|underaged|loli|pedo|pedophile|(\w+).year.old|(\w+).years.old|minor|prepubescent|minors|shota)\b/gmi, '');
//if nsfw is detected, do not remove it but apply additional precautions
let isNsfw = prompt.match(/\b(cock|ahegao|hentai|uncensored|lewd|cocks|deepthroat|deepthroating|dick|dicks|cumshot|lesbian|fuck|fucked|fucking|sperm|naked|nipples|tits|boobs|breasts|boob|breast|topless|ass|butt|fingering|masturbate|masturbating|bitch|blowjob|pussy|piss|asshole|dildo|dildos|vibrator|erection|foreskin|handjob|nude|penis|porn|vibrator|virgin|vagina|vulva|threesome|orgy|bdsm|hickey|condom|testicles|anal|bareback|bukkake|creampie|stripper|strap-on|missionary|clitoris|clit|clitty|cowgirl|fleshlight|sex|buttplug|milf|oral|sucking|bondage|orgasm|scissoring|railed|slut|sluts|slutty|cumming|cunt|faggot|sissy|anal|anus|cum|semen|scat|nsfw|xxx|explicit|erotic|horny|aroused|jizz|moan|rape|raped|raping|throbbing|humping)\b/gmi);
if (isNsfw) {
//replace risky subject nouns with person
prompt = prompt.replace(/\b(youngster|infant|baby|toddler|child|teen|kid|kiddie|kiddo|teenager|student|preteen|pre.teen)\b/gmi, "person");
prompt = prompt.replace(/\b(youngster|infant|baby|toddler|child|teen|kid|kiddie|kiddo|teenager|student|preteen|pre.teen)\b/gmi, 'person');
//remove risky adjectives and related words
prompt = prompt.replace(/\b(young|younger|youthful|youth|small|smaller|smallest|girly|boyish|lil|tiny|teenaged|lit[tl]le|school.aged|school|highschool|kindergarten|teens|children|kids)\b/gmi, "");
prompt = prompt.replace(/\b(young|younger|youthful|youth|small|smaller|smallest|girly|boyish|lil|tiny|teenaged|lit[tl]le|school.aged|school|highschool|kindergarten|teens|children|kids)\b/gmi, '');
}
return prompt;
@@ -68,8 +68,8 @@ function registerEndpoints(app, jsonParser) {
method: 'POST',
body: JSON.stringify(request.body),
headers: {
"Content-Type": "application/json",
"apikey": api_key_horde,
'Content-Type': 'application/json',
'apikey': api_key_horde,
'Client-Agent': String(request.header('Client-Agent')),
}
});

View File

@@ -4,7 +4,7 @@ const { Readable } = require('stream');
const { readSecret, SECRET_KEYS } = require('./secrets');
const { readAllChunks, extractFileFromZipBuffer } = require('./util');
const API_NOVELAI = "https://api.novelai.net";
const API_NOVELAI = 'https://api.novelai.net';
// Ban bracket generation, plus defaults
const badWordsList = [
@@ -41,8 +41,8 @@ const repPenaltyAllowList = [
// Ban the dinkus and asterism
const logitBiasExp = [
{ "sequence": [23], "bias": -0.08, "ensure_sequence_finish": false, "generate_once": false },
{ "sequence": [21], "bias": -0.08, "ensure_sequence_finish": false, "generate_once": false }
{ 'sequence': [23], 'bias': -0.08, 'ensure_sequence_finish': false, 'generate_once': false },
{ 'sequence': [21], 'bias': -0.08, 'ensure_sequence_finish': false, 'generate_once': false }
]
function getBadWordsList(model) {
@@ -66,7 +66,7 @@ function getBadWordsList(model) {
* @param {any} jsonParser - JSON parser middleware
*/
function registerEndpoints(app, jsonParser) {
app.post("/api/novelai/status", jsonParser, async function (req, res) {
app.post('/api/novelai/status', jsonParser, async function (req, res) {
if (!req.body) return res.sendStatus(400);
const api_key_novel = readSecret(SECRET_KEYS.NOVEL);
@@ -75,11 +75,11 @@ function registerEndpoints(app, jsonParser) {
}
try {
const response = await fetch(API_NOVELAI + "/user/subscription", {
const response = await fetch(API_NOVELAI + '/user/subscription', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Authorization': "Bearer " + api_key_novel,
'Authorization': 'Bearer ' + api_key_novel,
},
});
@@ -100,7 +100,7 @@ function registerEndpoints(app, jsonParser) {
}
});
app.post("/api/novelai/generate", jsonParser, async function (req, res) {
app.post('/api/novelai/generate', jsonParser, async function (req, res) {
if (!req.body) return res.sendStatus(400);
const api_key_novel = readSecret(SECRET_KEYS.NOVEL);
@@ -142,37 +142,37 @@ function registerEndpoints(app, jsonParser) {
}
const data = {
"input": req.body.input,
"model": req.body.model,
"parameters": {
"use_string": req.body.use_string ?? true,
"temperature": req.body.temperature,
"max_length": req.body.max_length,
"min_length": req.body.min_length,
"tail_free_sampling": req.body.tail_free_sampling,
"repetition_penalty": req.body.repetition_penalty,
"repetition_penalty_range": req.body.repetition_penalty_range,
"repetition_penalty_slope": req.body.repetition_penalty_slope,
"repetition_penalty_frequency": req.body.repetition_penalty_frequency,
"repetition_penalty_presence": req.body.repetition_penalty_presence,
"repetition_penalty_whitelist": isNewModel ? repPenaltyAllowList : null,
"top_a": req.body.top_a,
"top_p": req.body.top_p,
"top_k": req.body.top_k,
"typical_p": req.body.typical_p,
"mirostat_lr": req.body.mirostat_lr,
"mirostat_tau": req.body.mirostat_tau,
"cfg_scale": req.body.cfg_scale,
"cfg_uc": req.body.cfg_uc,
"phrase_rep_pen": req.body.phrase_rep_pen,
"stop_sequences": req.body.stop_sequences,
"bad_words_ids": badWordsList.length ? badWordsList : null,
"logit_bias_exp": logit_bias_exp,
"generate_until_sentence": req.body.generate_until_sentence,
"use_cache": req.body.use_cache,
"return_full_text": req.body.return_full_text,
"prefix": req.body.prefix,
"order": req.body.order
'input': req.body.input,
'model': req.body.model,
'parameters': {
'use_string': req.body.use_string ?? true,
'temperature': req.body.temperature,
'max_length': req.body.max_length,
'min_length': req.body.min_length,
'tail_free_sampling': req.body.tail_free_sampling,
'repetition_penalty': req.body.repetition_penalty,
'repetition_penalty_range': req.body.repetition_penalty_range,
'repetition_penalty_slope': req.body.repetition_penalty_slope,
'repetition_penalty_frequency': req.body.repetition_penalty_frequency,
'repetition_penalty_presence': req.body.repetition_penalty_presence,
'repetition_penalty_whitelist': isNewModel ? repPenaltyAllowList : null,
'top_a': req.body.top_a,
'top_p': req.body.top_p,
'top_k': req.body.top_k,
'typical_p': req.body.typical_p,
'mirostat_lr': req.body.mirostat_lr,
'mirostat_tau': req.body.mirostat_tau,
'cfg_scale': req.body.cfg_scale,
'cfg_uc': req.body.cfg_uc,
'phrase_rep_pen': req.body.phrase_rep_pen,
'stop_sequences': req.body.stop_sequences,
'bad_words_ids': badWordsList.length ? badWordsList : null,
'logit_bias_exp': logit_bias_exp,
'generate_until_sentence': req.body.generate_until_sentence,
'use_cache': req.body.use_cache,
'return_full_text': req.body.return_full_text,
'prefix': req.body.prefix,
'order': req.body.order
}
};
@@ -180,7 +180,7 @@ function registerEndpoints(app, jsonParser) {
const args = {
body: JSON.stringify(data),
headers: { "Content-Type": "application/json", "Authorization": "Bearer " + api_key_novel },
headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + api_key_novel },
signal: controller.signal,
};
@@ -198,7 +198,7 @@ function registerEndpoints(app, jsonParser) {
});
response.body.on('end', function () {
console.log("Streaming request finished");
console.log('Streaming request finished');
res.end();
});
} else {

View File

@@ -1,4 +1,4 @@
const { readSecret, SECRET_KEYS } = require("./secrets");
const { readSecret, SECRET_KEYS } = require('./secrets');
const fetch = require('node-fetch').default;
const FormData = require('form-data');
const fs = require('fs');
@@ -31,10 +31,10 @@ function registerEndpoints(app, jsonParser, urlencodedParser) {
model: request.body.model,
messages: [
{
role: "user",
role: 'user',
content: [
{ type: "text", text: request.body.prompt },
{ type: "image_url", image_url: { "url": request.body.image } }
{ type: 'text', text: request.body.prompt },
{ type: 'image_url', image_url: { 'url': request.body.image } }
]
}
],

View File

@@ -35,7 +35,7 @@ function getPresetSettingsByAPI(apiId) {
* @param {any} jsonParser JSON parser middleware
*/
function registerEndpoints(app, jsonParser) {
app.post("/api/presets/save", jsonParser, function (request, response) {
app.post('/api/presets/save', jsonParser, function (request, response) {
const name = sanitize(request.body.name);
if (!request.body.preset || !name) {
return response.sendStatus(400);
@@ -53,7 +53,7 @@ function registerEndpoints(app, jsonParser) {
return response.send({ name });
});
app.post("/api/presets/delete", jsonParser, function (request, response) {
app.post('/api/presets/delete', jsonParser, function (request, response) {
const name = sanitize(request.body.name);
if (!name) {
return response.sendStatus(400);
@@ -77,7 +77,7 @@ function registerEndpoints(app, jsonParser) {
});
// TODO: Merge with /api/presets/save
app.post("/api/presets/save-openai", jsonParser, function (request, response) {
app.post('/api/presets/save-openai', jsonParser, function (request, response) {
if (!request.body || typeof request.query.name !== 'string') return response.sendStatus(400);
const name = sanitize(request.query.name);
if (!name) return response.sendStatus(400);
@@ -89,7 +89,7 @@ function registerEndpoints(app, jsonParser) {
});
// TODO: Merge with /api/presets/delete
app.post("/api/presets/delete-openai", jsonParser, function (request, response) {
app.post('/api/presets/delete-openai', jsonParser, function (request, response) {
if (!request.body || !request.body.name) {
return response.sendStatus(400);
}

View File

@@ -33,13 +33,13 @@ const SECRET_KEYS = {
function writeSecret(key, value) {
if (!fs.existsSync(SECRETS_FILE)) {
const emptyFile = JSON.stringify({});
writeFileAtomicSync(SECRETS_FILE, emptyFile, "utf-8");
writeFileAtomicSync(SECRETS_FILE, emptyFile, 'utf-8');
}
const fileContents = fs.readFileSync(SECRETS_FILE, 'utf-8');
const secrets = JSON.parse(fileContents);
secrets[key] = value;
writeFileAtomicSync(SECRETS_FILE, JSON.stringify(secrets, null, 4), "utf-8");
writeFileAtomicSync(SECRETS_FILE, JSON.stringify(secrets, null, 4), 'utf-8');
}
/**
@@ -120,7 +120,7 @@ function migrateSecrets(settingsFile) {
if (modified) {
console.log('Writing updated settings.json...');
const settingsContent = JSON.stringify(settings, null, 4);
writeFileAtomicSync(settingsFile, settingsContent, "utf-8");
writeFileAtomicSync(settingsFile, settingsContent, 'utf-8');
}
}
catch (error) {

View File

@@ -34,7 +34,7 @@ const dangerousPatterns = '[]【】()|:';
function removePattern(x, pattern) {
for (let i = 0; i < pattern.length; i++) {
let p = pattern[i];
let regex = new RegExp("\\" + p, 'g');
let regex = new RegExp('\\' + p, 'g');
x = x.replace(regex, '');
}
return x;
@@ -244,8 +244,8 @@ function registerEndpoints(app, jsonParser) {
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
const progressState = await getProgress();
const progress = progressState["progress"]
const jobCount = progressState["state"]["job_count"];
const progress = progressState['progress']
const jobCount = progressState['state']['job_count'];
if (progress == 0.0 && jobCount === 0) {
break;
}

View File

@@ -53,7 +53,7 @@ function getOriginalFolder(type) {
*/
function invalidateThumbnail(type, file) {
const folder = getThumbnailFolder(type);
if (folder === undefined) throw new Error("Invalid thumbnail type")
if (folder === undefined) throw new Error('Invalid thumbnail type')
const pathToThumbnail = path.join(folder, file);
@@ -71,7 +71,7 @@ function invalidateThumbnail(type, file) {
async function generateThumbnail(type, file) {
let thumbnailFolder = getThumbnailFolder(type)
let originalFolder = getOriginalFolder(type)
if (thumbnailFolder === undefined || originalFolder === undefined) throw new Error("Invalid thumbnail type")
if (thumbnailFolder === undefined || originalFolder === undefined) throw new Error('Invalid thumbnail type')
const pathToCachedFile = path.join(thumbnailFolder, file);
const pathToOriginalFile = path.join(originalFolder, file);

View File

@@ -1,6 +1,6 @@
const fs = require('fs');
const path = require('path');
const { SentencePieceProcessor } = require("@agnai/sentencepiece-js");
const { SentencePieceProcessor } = require('@agnai/sentencepiece-js');
const tiktoken = require('@dqbd/tiktoken');
const { Tokenizer } = require('@agnai/web-tokenizers');
const { convertClaudePrompt } = require('./chat-completion');
@@ -15,31 +15,31 @@ const tokenizersCache = {};
* @type {string[]}
*/
const TEXT_COMPLETION_MODELS = [
"gpt-3.5-turbo-instruct",
"gpt-3.5-turbo-instruct-0914",
"text-davinci-003",
"text-davinci-002",
"text-davinci-001",
"text-curie-001",
"text-babbage-001",
"text-ada-001",
"code-davinci-002",
"code-davinci-001",
"code-cushman-002",
"code-cushman-001",
"text-davinci-edit-001",
"code-davinci-edit-001",
"text-embedding-ada-002",
"text-similarity-davinci-001",
"text-similarity-curie-001",
"text-similarity-babbage-001",
"text-similarity-ada-001",
"text-search-davinci-doc-001",
"text-search-curie-doc-001",
"text-search-babbage-doc-001",
"text-search-ada-doc-001",
"code-search-babbage-code-001",
"code-search-ada-code-001",
'gpt-3.5-turbo-instruct',
'gpt-3.5-turbo-instruct-0914',
'text-davinci-003',
'text-davinci-002',
'text-davinci-001',
'text-curie-001',
'text-babbage-001',
'text-ada-001',
'code-davinci-002',
'code-davinci-001',
'code-cushman-002',
'code-cushman-001',
'text-davinci-edit-001',
'code-davinci-edit-001',
'text-embedding-ada-002',
'text-similarity-davinci-001',
'text-similarity-curie-001',
'text-similarity-babbage-001',
'text-similarity-ada-001',
'text-search-davinci-doc-001',
'text-search-curie-doc-001',
'text-search-babbage-doc-001',
'text-search-ada-doc-001',
'code-search-babbage-code-001',
'code-search-ada-code-001',
];
const CHARS_PER_TOKEN = 3.35;
@@ -66,7 +66,7 @@ class SentencePieceTokenizer {
console.log('Instantiated the tokenizer for', path.parse(this.#model).name);
return this.#instance;
} catch (error) {
console.error("Sentencepiece tokenizer failed to load: " + this.#model, error);
console.error('Sentencepiece tokenizer failed to load: ' + this.#model, error);
return null;
}
}
@@ -239,7 +239,7 @@ async function loadClaudeTokenizer(modelPath) {
const instance = await Tokenizer.fromJSON(arrayBuffer);
return instance;
} catch (error) {
console.error("Claude tokenizer failed to load: " + modelPath, error);
console.error('Claude tokenizer failed to load: ' + modelPath, error);
return null;
}
}
@@ -365,7 +365,7 @@ async function loadTokenizers() {
* @param {any} jsonParser JSON parser middleware
*/
function registerEndpoints(app, jsonParser) {
app.post("/api/tokenize/ai21", jsonParser, async function (req, res) {
app.post('/api/tokenize/ai21', jsonParser, async function (req, res) {
if (!req.body) return res.sendStatus(400);
const options = {
method: 'POST',
@@ -380,27 +380,27 @@ function registerEndpoints(app, jsonParser) {
try {
const response = await fetch('https://api.ai21.com/studio/v1/tokenize', options);
const data = await response.json();
return res.send({ "token_count": data?.tokens?.length || 0 });
return res.send({ 'token_count': data?.tokens?.length || 0 });
} catch (err) {
console.error(err);
return res.send({ "token_count": 0 });
return res.send({ 'token_count': 0 });
}
});
app.post("/api/tokenize/llama", jsonParser, createSentencepieceEncodingHandler(spp_llama));
app.post("/api/tokenize/nerdstash", jsonParser, createSentencepieceEncodingHandler(spp_nerd));
app.post("/api/tokenize/nerdstash_v2", jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2));
app.post("/api/tokenize/mistral", jsonParser, createSentencepieceEncodingHandler(spp_mistral));
app.post("/api/tokenize/yi", jsonParser, createSentencepieceEncodingHandler(spp_yi));
app.post("/api/tokenize/gpt2", jsonParser, createTiktokenEncodingHandler('gpt2'));
app.post("/api/decode/llama", jsonParser, createSentencepieceDecodingHandler(spp_llama));
app.post("/api/decode/nerdstash", jsonParser, createSentencepieceDecodingHandler(spp_nerd));
app.post("/api/decode/nerdstash_v2", jsonParser, createSentencepieceDecodingHandler(spp_nerd_v2));
app.post("/api/decode/mistral", jsonParser, createSentencepieceDecodingHandler(spp_mistral));
app.post("/api/decode/yi", jsonParser, createSentencepieceDecodingHandler(spp_yi));
app.post("/api/decode/gpt2", jsonParser, createTiktokenDecodingHandler('gpt2'));
app.post('/api/tokenize/llama', jsonParser, createSentencepieceEncodingHandler(spp_llama));
app.post('/api/tokenize/nerdstash', jsonParser, createSentencepieceEncodingHandler(spp_nerd));
app.post('/api/tokenize/nerdstash_v2', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2));
app.post('/api/tokenize/mistral', jsonParser, createSentencepieceEncodingHandler(spp_mistral));
app.post('/api/tokenize/yi', jsonParser, createSentencepieceEncodingHandler(spp_yi));
app.post('/api/tokenize/gpt2', jsonParser, createTiktokenEncodingHandler('gpt2'));
app.post('/api/decode/llama', jsonParser, createSentencepieceDecodingHandler(spp_llama));
app.post('/api/decode/nerdstash', jsonParser, createSentencepieceDecodingHandler(spp_nerd));
app.post('/api/decode/nerdstash_v2', jsonParser, createSentencepieceDecodingHandler(spp_nerd_v2));
app.post('/api/decode/mistral', jsonParser, createSentencepieceDecodingHandler(spp_mistral));
app.post('/api/decode/yi', jsonParser, createSentencepieceDecodingHandler(spp_yi));
app.post('/api/decode/gpt2', jsonParser, createTiktokenDecodingHandler('gpt2'));
app.post("/api/tokenize/openai-encode", jsonParser, async function (req, res) {
app.post('/api/tokenize/openai-encode', jsonParser, async function (req, res) {
try {
const queryModel = String(req.query.model || '');
@@ -469,7 +469,7 @@ function registerEndpoints(app, jsonParser) {
}
});
app.post("/api/tokenize/openai", jsonParser, async function (req, res) {
app.post('/api/tokenize/openai', jsonParser, async function (req, res) {
try {
if (!req.body) return res.sendStatus(400);
@@ -479,22 +479,22 @@ function registerEndpoints(app, jsonParser) {
if (model === 'claude') {
num_tokens = countClaudeTokens(claude_tokenizer, req.body);
return res.send({ "token_count": num_tokens });
return res.send({ 'token_count': num_tokens });
}
if (model === 'llama') {
num_tokens = await countSentencepieceArrayTokens(spp_llama, req.body);
return res.send({ "token_count": num_tokens });
return res.send({ 'token_count': num_tokens });
}
if (model === 'mistral') {
num_tokens = await countSentencepieceArrayTokens(spp_mistral, req.body);
return res.send({ "token_count": num_tokens });
return res.send({ 'token_count': num_tokens });
}
if (model === 'yi') {
num_tokens = await countSentencepieceArrayTokens(spp_yi, req.body);
return res.send({ "token_count": num_tokens });
return res.send({ 'token_count': num_tokens });
}
const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;
@@ -508,12 +508,12 @@ function registerEndpoints(app, jsonParser) {
num_tokens += tokensPerMessage;
for (const [key, value] of Object.entries(msg)) {
num_tokens += tokenizer.encode(value).length;
if (key == "name") {
if (key == 'name') {
num_tokens += tokensPerName;
}
}
} catch {
console.warn("Error tokenizing message:", msg);
console.warn('Error tokenizing message:', msg);
}
}
num_tokens += tokensPadding;
@@ -527,12 +527,12 @@ function registerEndpoints(app, jsonParser) {
// not needed for cached tokenizers
//tokenizer.free();
res.send({ "token_count": num_tokens });
res.send({ 'token_count': num_tokens });
} catch (error) {
console.error('An error counting tokens, using fallback estimation method', error);
const jsonBody = JSON.stringify(req.body);
const num_tokens = Math.ceil(jsonBody.length / CHARS_PER_TOKEN);
res.send({ "token_count": num_tokens });
res.send({ 'token_count': num_tokens });
}
});
}

View File

@@ -31,15 +31,15 @@ function registerEndpoints(app, jsonParser) {
try {
const result = await fetch(url, {
method: "POST",
method: 'POST',
body: JSON.stringify({
q: text,
source: "auto",
source: 'auto',
target: lang,
format: "text",
format: 'text',
api_key: key
}),
headers: { "Content-Type": "application/json" }
headers: { 'Content-Type': 'application/json' }
});
if (!result.ok) {
@@ -53,7 +53,7 @@ function registerEndpoints(app, jsonParser) {
return response.send(json.translatedText);
} catch (error) {
console.log("Translation error: " + error.message);
console.log('Translation error: ' + error.message);
return response.sendStatus(500);
}
});
@@ -85,16 +85,16 @@ function registerEndpoints(app, jsonParser) {
console.log('Translated text: ' + result.text);
return response.send(result.text);
} catch (error) {
console.log("Translation error", error);
console.log('Translation error', error);
return response.sendStatus(500);
}
});
}).on("error", (err) => {
console.log("Translation error: " + err.message);
}).on('error', (err) => {
console.log('Translation error: ' + err.message);
return response.sendStatus(500);
});
} catch (error) {
console.log("Translation error", error);
console.log('Translation error', error);
return response.sendStatus(500);
}
});
@@ -148,7 +148,7 @@ function registerEndpoints(app, jsonParser) {
return response.send(json.translations[0].text);
} catch (error) {
console.log("Translation error: " + error.message);
console.log('Translation error: ' + error.message);
return response.sendStatus(500);
}
});
@@ -201,7 +201,7 @@ function registerEndpoints(app, jsonParser) {
return response.send(data.result);
} catch (error) {
console.log("Translation error: " + error.message);
console.log('Translation error: ' + error.message);
return response.sendStatus(500);
}
});
@@ -257,7 +257,7 @@ function registerEndpoints(app, jsonParser) {
return response.send(json.data);
} catch (error) {
console.log("DeepLX translation error: " + error.message);
console.log('DeepLX translation error: ' + error.message);
return response.sendStatus(500);
}
});
@@ -281,7 +281,7 @@ function registerEndpoints(app, jsonParser) {
console.log('Translated text: ' + result.translation);
return response.send(result.translation);
}).catch(err => {
console.log("Translation error: " + err.message);
console.log('Translation error: ' + err.message);
return response.sendStatus(500);
});
});