Merge branch 'staging' into small-bookmark-updates

917a994ca84de755238c569a6d2a814f1097d52f

Cohee <18619528+Cohee1207@users.noreply.github.com>

10 files changed, +95 -84Ignore whitespace
package-lock.json+5 -4
@@ -46,7 +46,7 @@
46 "sanitize-filename": "^1.6.3",46 "sanitize-filename": "^1.6.3",
47 "sillytavern-transformers": "2.14.6",47 "sillytavern-transformers": "2.14.6",
48 "simple-git": "^3.19.1",48 "simple-git": "^3.19.1",
49 "tiktoken": "^1.0.15",49 "tiktoken": "^1.0.16",
50 "vectra": "^0.2.2",50 "vectra": "^0.2.2",
51 "wavefile": "^11.0.0",51 "wavefile": "^11.0.0",
52 "write-file-atomic": "^5.0.1",52 "write-file-atomic": "^5.0.1",
@@ -5751,9 +5751,10 @@
5751 "license": "MIT"5751 "license": "MIT"
5752 },5752 },
5753 "node_modules/tiktoken": {5753 "node_modules/tiktoken": {
5754 "version": "1.0.15",5754 "version": "1.0.16",
5755 "resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.15.tgz",5755 "resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.16.tgz",
5756 "integrity": "sha512-sCsrq/vMWUSEW29CJLNmPvWxlVp7yh2tlkAjpJltIKqp5CKf98ZNpdeHRmAlPVFlGEbswDc6SmI8vz64W/qErw=="5756 "integrity": "sha512-hRcORIGF2YlAgWx3nzrGJOrKSJwLoc81HpXmMQk89632XAgURc7IeV2FgQ2iXo9z/J96fCvpsHg2kWoHcbj9fg==",
5757 "license": "MIT"
5757 },5758 },
5758 "node_modules/timm": {5759 "node_modules/timm": {
5759 "version": "1.7.1",5760 "version": "1.7.1",
package.json+1 -1
@@ -36,7 +36,7 @@
36 "sanitize-filename": "^1.6.3",36 "sanitize-filename": "^1.6.3",
37 "sillytavern-transformers": "2.14.6",37 "sillytavern-transformers": "2.14.6",
38 "simple-git": "^3.19.1",38 "simple-git": "^3.19.1",
39 "tiktoken": "^1.0.15",39 "tiktoken": "^1.0.16",
40 "vectra": "^0.2.2",40 "vectra": "^0.2.2",
41 "wavefile": "^11.0.0",41 "wavefile": "^11.0.0",
42 "write-file-atomic": "^5.0.1",42 "write-file-atomic": "^5.0.1",
public/index.html+5 -1
@@ -383,7 +383,7 @@
383 Max Response Length (tokens)383 Max Response Length (tokens)
384 </div>384 </div>
385 <div class="wide100p">385 <div class="wide100p">
386 <input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="16384">386 <input type="number" id="openai_max_tokens" name="openai_max_tokens" class="text_pole" min="1" max="65536">
387 </div>387 </div>
388 </div>388 </div>
389 <div class="range-block" data-source="openai,custom">389 <div class="range-block" data-source="openai,custom">
@@ -2611,6 +2611,10 @@
2611 <option value="gpt-4-0125-preview">gpt-4-0125-preview (2024)</option>2611 <option value="gpt-4-0125-preview">gpt-4-0125-preview (2024)</option>
2612 <option value="gpt-4-1106-preview">gpt-4-1106-preview (2023)</option>2612 <option value="gpt-4-1106-preview">gpt-4-1106-preview (2023)</option>
2613 </optgroup>2613 </optgroup>
2614 <optgroup label="o1">
2615 <option value="o1-preview">o1-preview</option>
2616 <option value="o1-mini">o1-mini</option>
2617 </optgroup>
2614 <optgroup label="Other">2618 <optgroup label="Other">
2615 <option value="text-davinci-003">text-davinci-003</option>2619 <option value="text-davinci-003">text-davinci-003</option>
2616 <option value="text-davinci-002">text-davinci-002</option>2620 <option value="text-davinci-002">text-davinci-002</option>
public/script.js+32 -56
@@ -865,7 +865,6 @@ let abortController;
865865
866//css866//css
867var css_send_form_display = $('<div id=send_form></div>').css('display');867var css_send_form_display = $('<div id=send_form></div>').css('display');
868const MAX_GENERATION_LOOPS = 5;
869868
870var kobold_horde_model = '';869var kobold_horde_model = '';
871870
@@ -2848,7 +2847,12 @@ export function getCharacterCardFields() {
28482847
2849export function isStreamingEnabled() {2848export function isStreamingEnabled() {
2850 const noStreamSources = [chat_completion_sources.SCALE];2849 const noStreamSources = [chat_completion_sources.SCALE];
2851 return ((main_api == 'openai' && oai_settings.stream_openai && !noStreamSources.includes(oai_settings.chat_completion_source) && !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison')))2850 return (
2851 (main_api == 'openai' &&
2852 oai_settings.stream_openai &&
2853 !noStreamSources.includes(oai_settings.chat_completion_source) &&
2854 !(oai_settings.chat_completion_source == chat_completion_sources.OPENAI && oai_settings.openai_model.startsWith('o1-')) &&
2855 !(oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE && oai_settings.google_model.includes('bison')))
2852 || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)2856 || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)
2853 || (main_api == 'novel' && nai_settings.streaming_novel)2857 || (main_api == 'novel' && nai_settings.streaming_novel)
2854 || (main_api == 'textgenerationwebui' && textgen_settings.streaming));2858 || (main_api == 'textgenerationwebui' && textgen_settings.streaming));
@@ -3251,7 +3255,7 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
3251 }3255 }
32523256
3253 if (data.error) {3257 if (data.error) {
3254 throw new Error(data.error);3258 throw new Error(data.response);
3255 }3259 }
32563260
3257 const message = cleanUpMessage(extractMessageFromData(data), false, false, true);3261 const message = cleanUpMessage(extractMessageFromData(data), false, false, true);
@@ -3323,11 +3327,11 @@ function removeLastMessage() {
3323 * @param {GenerateOptions} options Generation options3327 * @param {GenerateOptions} options Generation options
3324 * @param {boolean} dryRun Whether to actually generate a message or just assemble the prompt3328 * @param {boolean} dryRun Whether to actually generate a message or just assemble the prompt
3325 * @returns {Promise<any>} Returns a promise that resolves when the text is done generating.3329 * @returns {Promise<any>} Returns a promise that resolves when the text is done generating.
3326 * @typedef {{automatic_trigger?: boolean, force_name2?: boolean, quiet_prompt?: string, quietToLoud?: boolean, skipWIAN?: boolean, force_chid?: number, signal?: AbortSignal, quietImage?: string, maxLoops?: number, quietName?: string }} GenerateOptions3330 * @typedef {{automatic_trigger?: boolean, force_name2?: boolean, quiet_prompt?: string, quietToLoud?: boolean, skipWIAN?: boolean, force_chid?: number, signal?: AbortSignal, quietImage?: string, quietName?: string }} GenerateOptions
3327 */3331 */
3328export async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, maxLoops, quietName } = {}, dryRun = false) {3332export async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, quietName } = {}, dryRun = false) {
3329 console.log('Generate entered');3333 console.log('Generate entered');
3330 await eventSource.emit(event_types.GENERATION_STARTED, type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, maxLoops }, dryRun);3334 await eventSource.emit(event_types.GENERATION_STARTED, type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage }, dryRun);
3331 setGenerationProgress(0);3335 setGenerationProgress(0);
3332 generation_started = new Date();3336 generation_started = new Date();
33333337
@@ -3389,7 +3393,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
3389 if (selected_group && !is_group_generating) {3393 if (selected_group && !is_group_generating) {
3390 if (!dryRun) {3394 if (!dryRun) {
3391 // Returns the promise that generateGroupWrapper returns; resolves when generation is done3395 // Returns the promise that generateGroupWrapper returns; resolves when generation is done
3392 return generateGroupWrapper(false, type, { quiet_prompt, force_chid, signal: abortController.signal, quietImage, maxLoops });3396 return generateGroupWrapper(false, type, { quiet_prompt, force_chid, signal: abortController.signal, quietImage });
3393 }3397 }
33943398
3395 const characterIndexMap = new Map(characters.map((char, index) => [char.avatar, index]));3399 const characterIndexMap = new Map(characters.map((char, index) => [char.avatar, index]));
@@ -4399,9 +4403,9 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
4399 generatedPromptCache = '';4403 generatedPromptCache = '';
44004404
4401 if (data?.response) {4405 if (data?.response) {
4402 toastr.error(data.response, 'API Error');4406 toastr.error(data.response, 'API Error', { preventDuplicates: true });
4403 }4407 }
4404 throw data?.response;4408 throw new Error(data?.response);
4405 }4409 }
44064410
4407 //const getData = await response.json();4411 //const getData = await response.json();
@@ -4421,53 +4425,30 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
4421 const displayIncomplete = type === 'quiet' && !quietToLoud;4425 const displayIncomplete = type === 'quiet' && !quietToLoud;
4422 getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete);4426 getMessage = cleanUpMessage(getMessage, isImpersonate, isContinue, displayIncomplete);
44234427
4424 if (getMessage.length > 0 || data.allowEmptyResponse) {4428 if (isImpersonate) {
4425 if (isImpersonate) {4429 $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true }));
4426 $('#send_textarea').val(getMessage)[0].dispatchEvent(new Event('input', { bubbles: true }));4430 generatedPromptCache = '';
4427 generatedPromptCache = '';4431 await eventSource.emit(event_types.IMPERSONATE_READY, getMessage);
4428 await eventSource.emit(event_types.IMPERSONATE_READY, getMessage);4432 }
4429 }4433 else if (type == 'quiet') {
4430 else if (type == 'quiet') {4434 unblockGeneration(type);
4431 unblockGeneration(type);4435 return getMessage;
4432 return getMessage;4436 }
4437 else {
4438 // Without streaming we'll be having a full message on continuation. Treat it as a last chunk.
4439 if (originalType !== 'continue') {
4440 ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes));
4433 }4441 }
4434 else {4442 else {
4435 // Without streaming we'll be having a full message on continuation. Treat it as a last chunk.4443 ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes));
4436 if (originalType !== 'continue') {
4437 ({ type, getMessage } = await saveReply(type, getMessage, false, title, swipes));
4438 }
4439 else {
4440 ({ type, getMessage } = await saveReply('appendFinal', getMessage, false, title, swipes));
4441 }
4442
4443 // This relies on `saveReply` having been called to add the message to the chat, so it must be last.
4444 parseAndSaveLogprobs(data, continue_mag);
4445 }4444 }
44464445
4447 if (type !== 'quiet') {4446 // This relies on `saveReply` having been called to add the message to the chat, so it must be last.
4448 playMessageSound();4447 parseAndSaveLogprobs(data, continue_mag);
4449 }4448 }
4450 } else {
4451 // If maxLoops is not passed in (e.g. first time generating), set it to MAX_GENERATION_LOOPS
4452 maxLoops ??= MAX_GENERATION_LOOPS;
4453
4454 if (maxLoops === 0) {
4455 if (type !== 'quiet') {
4456 throwCircuitBreakerError();
4457 }
4458 throw new Error('Generate circuit breaker interruption');
4459 }
44604449
4461 // regenerate with character speech reenforced4450 if (type !== 'quiet') {
4462 // to make sure we leave on swipe type while also adding the name2 appendage4451 playMessageSound();
4463 await delay(1000);
4464 // A message was already deleted on regeneration, so instead treat is as a normal gen
4465 if (type === 'regenerate') {
4466 type = 'normal';
4467 }
4468 // The first await is for waiting for the generate to start. The second one is waiting for it to finish
4469 const result = await await Generate(type, { automatic_trigger, force_name2: true, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, quietName, maxLoops: maxLoops - 1 });
4470 return result;
4471 }4452 }
44724453
4473 if (power_user.auto_swipe) {4454 if (power_user.auto_swipe) {
@@ -5240,11 +5221,6 @@ function getGenerateUrl(api) {
5240 }5221 }
5241}5222}
52425223
5243function throwCircuitBreakerError() {
5244 callPopup(`Could not extract reply in ${MAX_GENERATION_LOOPS} attempts. Try generating again`, 'text');
5245 unblockGeneration();
5246}
5247
5248function extractTitleFromData(data) {5224function extractTitleFromData(data) {
5249 if (main_api == 'koboldhorde') {5225 if (main_api == 'koboldhorde') {
5250 return data.workerName;5226 return data.workerName;
public/scripts/openai.js+29 -6
@@ -1797,7 +1797,7 @@ async function sendOpenAIRequest(type, messages, signal) {
1797 const isQuiet = type === 'quiet';1797 const isQuiet = type === 'quiet';
1798 const isImpersonate = type === 'impersonate';1798 const isImpersonate = type === 'impersonate';
1799 const isContinue = type === 'continue';1799 const isContinue = type === 'continue';
1800 const stream = oai_settings.stream_openai && !isQuiet && !isScale && !(isGoogle && oai_settings.google_model.includes('bison'));1800 const stream = oai_settings.stream_openai && !isQuiet && !isScale && !(isGoogle && oai_settings.google_model.includes('bison')) && !(isOAI && oai_settings.openai_model.startsWith('o1-'));
1801 const useLogprobs = !!power_user.request_token_probabilities;1801 const useLogprobs = !!power_user.request_token_probabilities;
1802 const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom);1802 const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom);
18031803
@@ -1960,12 +1960,35 @@ async function sendOpenAIRequest(type, messages, signal) {
1960 generate_data['seed'] = oai_settings.seed;1960 generate_data['seed'] = oai_settings.seed;
1961 }1961 }
19621962
1963 await eventSource.emit(event_types.CHAT_COMPLETION_SETTINGS_READY, generate_data);
1964
1965 if (isFunctionCallingSupported() && !stream) {1963 if (isFunctionCallingSupported() && !stream) {
1966 await registerFunctionTools(type, generate_data);1964 await registerFunctionTools(type, generate_data);
1967 }1965 }
19681966
1967 if (isOAI && oai_settings.openai_model.startsWith('o1-')) {
1968 generate_data.messages.forEach((msg) => {
1969 if (msg.role === 'system') {
1970 msg.role = 'user';
1971 }
1972 });
1973 generate_data.max_completion_tokens = generate_data.max_tokens;
1974 delete generate_data.max_tokens;
1975 delete generate_data.stream;
1976 delete generate_data.logprobs;
1977 delete generate_data.top_logprobs;
1978 delete generate_data.n;
1979 delete generate_data.temperature;
1980 delete generate_data.top_p;
1981 delete generate_data.frequency_penalty;
1982 delete generate_data.presence_penalty;
1983 delete generate_data.tools;
1984 delete generate_data.tool_choice;
1985 delete generate_data.stop;
1986 // It does support logit_bias, but the tokenizer used and its effect is yet unknown.
1987 // delete generate_data.logit_bias;
1988 }
1989
1990 await eventSource.emit(event_types.CHAT_COMPLETION_SETTINGS_READY, generate_data);
1991
1969 const generate_url = '/api/backends/chat-completions/generate';1992 const generate_url = '/api/backends/chat-completions/generate';
1970 const response = await fetch(generate_url, {1993 const response = await fetch(generate_url, {
1971 method: 'POST',1994 method: 'POST',
@@ -2111,7 +2134,6 @@ async function checkFunctionToolCalls(data) {
2111 const args = toolCall.function;2134 const args = toolCall.function;
2112 console.log('Function tool call:', toolCall);2135 console.log('Function tool call:', toolCall);
2113 await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);2136 await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);
2114 data.allowEmptyResponse = true;
2115 }2137 }
2116 }2138 }
21172139
@@ -2125,7 +2147,6 @@ async function checkFunctionToolCalls(data) {
2125 /** @type {FunctionToolCall} */2147 /** @type {FunctionToolCall} */
2126 const args = { name: content.name, arguments: JSON.stringify(content.input) };2148 const args = { name: content.name, arguments: JSON.stringify(content.input) };
2127 await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);2149 await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);
2128 data.allowEmptyResponse = true;
2129 }2150 }
2130 }2151 }
2131 }2152 }
@@ -2140,7 +2161,6 @@ async function checkFunctionToolCalls(data) {
2140 const args = { name: toolCall.name, arguments: JSON.stringify(toolCall.parameters) };2161 const args = { name: toolCall.name, arguments: JSON.stringify(toolCall.parameters) };
2141 console.log('Function tool call:', toolCall);2162 console.log('Function tool call:', toolCall);
2142 await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);2163 await eventSource.emit(event_types.LLM_FUNCTION_TOOL_CALL, args);
2143 data.allowEmptyResponse = true;
2144 }2164 }
2145 }2165 }
2146}2166}
@@ -3905,6 +3925,9 @@ function getMaxContextOpenAI(value) {
3905 if (oai_settings.max_context_unlocked) {3925 if (oai_settings.max_context_unlocked) {
3906 return unlocked_max;3926 return unlocked_max;
3907 }3927 }
3928 else if (value.startsWith('o1-')) {
3929 return max_128k;
3930 }
3908 else if (value.includes('chatgpt-4o-latest') || value.includes('gpt-4-turbo') || value.includes('gpt-4o') || value.includes('gpt-4-1106') || value.includes('gpt-4-0125') || value.includes('gpt-4-vision')) {3931 else if (value.includes('chatgpt-4o-latest') || value.includes('gpt-4-turbo') || value.includes('gpt-4o') || value.includes('gpt-4-1106') || value.includes('gpt-4-0125') || value.includes('gpt-4-vision')) {
3909 return max_128k;3932 return max_128k;
3910 }3933 }
public/scripts/slash-commands.js+9 -1
@@ -2241,7 +2241,7 @@ function setEphemeralStopStrings(value) {
2241async function generateRawCallback(args, value) {2241async function generateRawCallback(args, value) {
2242 if (!value) {2242 if (!value) {
2243 console.warn('WARN: No argument provided for /genraw command');2243 console.warn('WARN: No argument provided for /genraw command');
2244 return;2244 return '';
2245 }2245 }
22462246
2247 // Prevent generate recursion2247 // Prevent generate recursion
@@ -2260,12 +2260,16 @@ async function generateRawCallback(args, value) {
2260 setEphemeralStopStrings(resolveVariable(args?.stop));2260 setEphemeralStopStrings(resolveVariable(args?.stop));
2261 const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud, systemPrompt, length);2261 const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud, systemPrompt, length);
2262 return result;2262 return result;
2263 } catch (err) {
2264 console.error('Error on /genraw generation', err);
2265 toastr.error(err.message, 'API Error', { preventDuplicates: true });
2263 } finally {2266 } finally {
2264 if (lock) {2267 if (lock) {
2265 activateSendButtons();2268 activateSendButtons();
2266 }2269 }
2267 flushEphemeralStoppingStrings();2270 flushEphemeralStoppingStrings();
2268 }2271 }
2272 return '';
2269}2273}
22702274
2271/**2275/**
@@ -2291,12 +2295,16 @@ async function generateCallback(args, value) {
2291 const name = args?.name;2295 const name = args?.name;
2292 const result = await generateQuietPrompt(value, quietToLoud, false, '', name, length);2296 const result = await generateQuietPrompt(value, quietToLoud, false, '', name, length);
2293 return result;2297 return result;
2298 } catch (err) {
2299 console.error('Error on /gen generation', err);
2300 toastr.error(err.message, 'API Error', { preventDuplicates: true });
2294 } finally {2301 } finally {
2295 if (lock) {2302 if (lock) {
2296 activateSendButtons();2303 activateSendButtons();
2297 }2304 }
2298 flushEphemeralStoppingStrings();2305 flushEphemeralStoppingStrings();
2299 }2306 }
2307 return '';
2300}2308}
23012309
2302/**2310/**
public/scripts/world-info.js+6 -14
@@ -108,6 +108,7 @@ const KNOWN_DECORATORS = ['@@activate', '@@dont_activate'];
108 * @property {number} [cooldown] The cooldown of the entry108 * @property {number} [cooldown] The cooldown of the entry
109 * @property {number} [delay] The delay of the entry109 * @property {number} [delay] The delay of the entry
110 * @property {string[]} [decorators] Array of decorators for the entry110 * @property {string[]} [decorators] Array of decorators for the entry
111 * @property {number} [hash] The hash of the entry
111 */112 */
112113
113/**114/**
@@ -383,12 +384,6 @@ class WorldInfoBuffer {
383 */384 */
384class WorldInfoTimedEffects {385class WorldInfoTimedEffects {
385 /**386 /**
386 * Cache for entry hashes. Uses weak map to avoid memory leaks.
387 * @type {WeakMap<WIScanEntry, number>}
388 */
389 #entryHashCache = new WeakMap();
390
391 /**
392 * Array of chat messages.387 * Array of chat messages.
393 * @type {string[]}388 * @type {string[]}
394 */389 */
@@ -485,13 +480,7 @@ class WorldInfoTimedEffects {
485 * @returns {number} String hash480 * @returns {number} String hash
486 */481 */
487 #getEntryHash(entry) {482 #getEntryHash(entry) {
488 if (this.#entryHashCache.has(entry)) {483 return entry.hash;
489 return this.#entryHashCache.get(entry);
490 }
491
492 const hash = getStringHash(JSON.stringify(entry));
493 this.#entryHashCache.set(entry, hash);
494 return hash;
495 }484 }
496485
497 /**486 /**
@@ -3603,10 +3592,13 @@ export async function getSortedEntries() {
3603 // Chat lore always goes first3592 // Chat lore always goes first
3604 entries = [...chatLore.sort(sortFn), ...entries];3593 entries = [...chatLore.sort(sortFn), ...entries];
36053594
3606 // Parse decorators3595 // Calculate hash and parse decorators. Split maps to preserve old hashes.
3607 entries = entries.map((entry) => {3596 entries = entries.map((entry) => {
3608 const [decorators, content] = parseDecorators(entry.content || '');3597 const [decorators, content] = parseDecorators(entry.content || '');
3609 return { ...entry, decorators, content };3598 return { ...entry, decorators, content };
3599 }).map((entry) => {
3600 const hash = getStringHash(JSON.stringify(entry));
3601 return { ...entry, hash };
3610 });3602 });
36113603
3612 console.debug(`[WI] Found ${entries.length} world lore entries. Sorted by strategy`, Object.entries(world_info_insertion_strategy).find((x) => x[1] === world_info_character_strategy));3604 console.debug(`[WI] Found ${entries.length} world lore entries. Sorted by strategy`, Object.entries(world_info_insertion_strategy).find((x) => x[1] === world_info_character_strategy));
src/endpoints/backends/chat-completions.js+1 -0
@@ -965,6 +965,7 @@ router.post('/generate', jsonParser, function (request, response) {
965 'model': request.body.model,965 'model': request.body.model,
966 'temperature': request.body.temperature,966 'temperature': request.body.temperature,
967 'max_tokens': request.body.max_tokens,967 'max_tokens': request.body.max_tokens,
968 'max_completion_tokens': request.body.max_completion_tokens,
968 'stream': request.body.stream,969 'stream': request.body.stream,
969 'presence_penalty': request.body.presence_penalty,970 'presence_penalty': request.body.presence_penalty,
970 'frequency_penalty': request.body.frequency_penalty,971 'frequency_penalty': request.body.frequency_penalty,
src/endpoints/backends/text-completions.js+3 -1
@@ -375,7 +375,9 @@ router.post('/generate', jsonParser, async function (request, response) {
375 }375 }
376 }376 }
377 } catch (error) {377 } catch (error) {
378 let value = { error: true, status: error?.status, response: error?.statusText };378 const status = error?.status ?? error?.code ?? 'UNKNOWN';
379 const text = error?.error ?? error?.statusText ?? error?.message ?? 'Unknown error on /generate endpoint';
380 let value = { error: true, status: status, response: text };
379 console.log('Endpoint error:', error);381 console.log('Endpoint error:', error);
380382
381 if (!response.headersSent) {383 if (!response.headersSent) {
src/endpoints/tokenizers.js+4 -0
@@ -350,6 +350,10 @@ function getWebTokenizersChunks(tokenizer, ids) {
350 * @returns {string} Tokenizer model to use350 * @returns {string} Tokenizer model to use
351 */351 */
352function getTokenizerModel(requestModel) {352function getTokenizerModel(requestModel) {
353 if (requestModel.includes('o1-preview') || requestModel.includes('o1-mini')) {
354 return 'gpt-4o';
355 }
356
353 if (requestModel.includes('gpt-4o')) {357 if (requestModel.includes('gpt-4o')) {
354 return 'gpt-4o';358 return 'gpt-4o';
355 }359 }