Merge branch 'staging' of https://github.com/SillyTavern/SillyTavern into mancer-api

This commit is contained in:
50h100a
2023-08-02 23:46:03 -04:00
55 changed files with 2118 additions and 5040 deletions

View File

@ -186,13 +186,19 @@ async function loadSentencepieceTokenizer(modelPath) {
async function countSentencepieceTokens(spp, text) {
// Fallback to strlen estimation
if (!spp) {
return Math.ceil(text.length / CHARS_PER_TOKEN);
return {
ids: [],
count: Math.ceil(text.length / CHARS_PER_TOKEN)
};
}
let cleaned = cleanText(text);
let cleaned = text; // cleanText(text); <-- cleaning text can result in an incorrect tokenization
let ids = spp.encodeIds(cleaned);
return ids.length;
return {
ids,
count: ids.length
};
}
async function loadClaudeTokenizer(modelPath) {
@ -298,6 +304,7 @@ const directories = {
instruct: 'public/instruct',
context: 'public/context',
backups: 'backups/',
quickreplies: 'public/QuickReplies'
};
// CSRF Protection //
@ -513,8 +520,16 @@ app.post("/generate", jsonParser, async function (request, response_generate = r
return response.body.pipe(response_generate);
} else {
if (!response.ok) {
console.log(`Kobold returned error: ${response.status} ${response.statusText} ${await response.text()}`);
return response.status(response.status).send({ error: true });
const errorText = await response.text();
console.log(`Kobold returned error: ${response.status} ${response.statusText} ${errorText}`);
try {
const errorJson = JSON.parse(errorText);
const message = errorJson?.detail?.msg || errorText;
return response_generate.status(400).send({ error: { message } });
} catch {
return response_generate.status(400).send({ error: { message: errorText } });
}
}
const data = await response.json();
@ -1617,6 +1632,8 @@ app.post('/getsettings', jsonParser, (request, response) => {
const themes = readAndParseFromDirectory(directories.themes);
const movingUIPresets = readAndParseFromDirectory(directories.movingUI);
const quickReplyPresets = readAndParseFromDirectory(directories.quickreplies);
const instruct = readAndParseFromDirectory(directories.instruct);
const context = readAndParseFromDirectory(directories.context);
@ -1633,6 +1650,7 @@ app.post('/getsettings', jsonParser, (request, response) => {
textgenerationwebui_preset_names,
themes,
movingUIPresets,
quickReplyPresets,
instruct,
context,
enable_extensions: enableExtensions,
@ -1689,6 +1707,17 @@ app.post('/savemovingui', jsonParser, (request, response) => {
return response.sendStatus(200);
});
app.post('/savequickreply', jsonParser, (request, response) => {
if (!request.body || !request.body.name) {
return response.sendStatus(400);
}
const filename = path.join(directories.quickreplies, sanitize(request.body.name) + '.json');
fs.writeFileSync(filename, JSON.stringify(request.body, null, 4), 'utf8');
return response.sendStatus(200);
});
function convertWorldInfoToCharacterBook(name, entries) {
const result = { entries: [], name };
@ -1801,9 +1830,9 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
controller.abort();
});
console.log(request.body);
const bw = require('./src/bad-words');
const bad_words_ids = request.body.model.includes('clio') ? bw.clioBadWordsId : bw.badWordIds;
const novelai = require('./src/novelai');
const isNewModel = (request.body.model.includes('clio') || request.body.model.includes('kayra'));
const isKrake = request.body.model.includes('krake');
const data = {
"input": request.body.input,
"model": request.body.model,
@ -1818,12 +1847,18 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
"repetition_penalty_slope": request.body.repetition_penalty_slope,
"repetition_penalty_frequency": request.body.repetition_penalty_frequency,
"repetition_penalty_presence": request.body.repetition_penalty_presence,
"repetition_penalty_whitelist": isNewModel ? novelai.repPenaltyAllowList : null,
"top_a": request.body.top_a,
"top_p": request.body.top_p,
"top_k": request.body.top_k,
"typical_p": request.body.typical_p,
"cfg_scale": request.body.cfg_scale,
"cfg_uc": request.body.cfg_uc,
"phrase_rep_pen": request.body.phrase_rep_pen,
"stop_sequences": request.body.stop_sequences,
//"stop_sequences": {{187}},
"bad_words_ids": bad_words_ids,
"bad_words_ids": isNewModel ? novelai.badWordsList : (isKrake ? novelai.krakeBadWordsList : novelai.euterpeBadWordsList),
"logit_bias_exp": isNewModel ? novelai.logitBiasExp : null,
//generate_until_sentence = true;
"use_cache": request.body.use_cache,
"use_string": true,
@ -1832,6 +1867,8 @@ app.post("/generate_novelai", jsonParser, async function (request, response_gene
"order": request.body.order
}
};
const util = require('util');
console.log(util.inspect(data, { depth: 4 }))
const args = {
body: JSON.stringify(data),
@ -3091,7 +3128,12 @@ async function sendClaudeRequest(request, response) {
controller.abort();
});
const requestPrompt = convertClaudePrompt(request.body.messages, true, true);
let requestPrompt = convertClaudePrompt(request.body.messages, true, true);
if (request.body.assistant_prefill) {
requestPrompt += request.body.assistant_prefill;
}
console.log('Claude request:', requestPrompt);
const generateResponse = await fetch(api_url + '/complete', {
@ -3164,16 +3206,19 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
let api_url;
let api_key_openai;
let headers;
let bodyParams;
if (!request.body.use_openrouter) {
api_url = new URL(request.body.reverse_proxy || api_openai).toString();
api_key_openai = request.body.reverse_proxy ? request.body.proxy_password : readSecret(SECRET_KEYS.OPENAI);
headers = {};
bodyParams = {};
} else {
api_url = 'https://openrouter.ai/api/v1';
api_key_openai = readSecret(SECRET_KEYS.OPENROUTER);
// OpenRouter needs to pass the referer: https://openrouter.ai/docs
headers = { 'HTTP-Referer': request.headers.referer };
bodyParams = { 'transforms': ["middle-out"] };
}
if (!api_key_openai && !request.body.reverse_proxy) {
@ -3210,7 +3255,8 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
"top_p": request.body.top_p,
"top_k": request.body.top_k,
"stop": request.body.stop,
"logit_bias": request.body.logit_bias
"logit_bias": request.body.logit_bias,
...bodyParams,
},
signal: controller.signal,
};
@ -3267,11 +3313,15 @@ app.post("/generate_openai", jsonParser, function (request, response_generate_op
switch (error?.response?.status) {
case 402:
message = 'Credit limit reached';
message = error?.response?.data?.error?.message || 'Credit limit reached';
console.log(message);
break;
case 403:
message = 'API key disabled or exhausted';
message = error?.response?.data?.error?.message || 'API key disabled or exhausted';
console.log(message);
break;
case 451:
message = error?.response?.data?.error?.message || 'Unavailable for legal reasons';
console.log(message);
break;
}
@ -3401,8 +3451,8 @@ function createTokenizationHandler(getTokenizerFn) {
const text = request.body.text || '';
const tokenizer = getTokenizerFn();
const count = await countSentencepieceTokens(tokenizer, text);
return response.send({ count });
const { ids, count } = await countSentencepieceTokens(tokenizer, text);
return response.send({ ids, count });
};
}