Merge branch 'staging' into small-bookmark-updates
| @@ -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", |
| @@ -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", |
| @@ -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> |
| @@ -865,7 +865,6 @@ let abortController; | |||
| 865 | 865 | ||
| 866 | //css | 866 | //css |
| 867 | var css_send_form_display = $('<div id=send_form></div>').css('display'); | 867 | var css_send_form_display = $('<div id=send_form></div>').css('display'); |
| 868 | const MAX_GENERATION_LOOPS = 5; | ||
| 869 | 868 | ||
| 870 | var kobold_horde_model = ''; | 869 | var kobold_horde_model = ''; |
| 871 | 870 | ||
| @@ -2848,7 +2847,12 @@ export function getCharacterCardFields() { | |||
| 2848 | 2847 | ||
| 2849 | export function isStreamingEnabled() { | 2848 | export 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 | } |
| 3252 | 3256 | ||
| 3253 | if (data.error) { | 3257 | if (data.error) { |
| 3254 | throw new Error(data.error); | 3258 | throw new Error(data.response); |
| 3255 | } | 3259 | } |
| 3256 | 3260 | ||
| 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 options | 3327 | * @param {GenerateOptions} options Generation options |
| 3324 | * @param {boolean} dryRun Whether to actually generate a message or just assemble the prompt | 3328 | * @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 }} GenerateOptions | 3330 | * @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 | */ |
| 3328 | export async function Generate(type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage, maxLoops, quietName } = {}, dryRun = false) { | 3332 | export 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(); |
| 3333 | 3337 | ||
| @@ -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 done | 3395 | // 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 | } |
| 3394 | 3398 | ||
| 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 = ''; |
| 4400 | 4404 | ||
| 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 | } |
| 4406 | 4410 | ||
| 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); |
| 4423 | 4427 | ||
| 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 | } |
| 4446 | 4445 | ||
| 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 | } | ||
| 4460 | 4449 | ||
| 4461 | // regenerate with character speech reenforced | 4450 | if (type !== 'quiet') { |
| 4462 | // to make sure we leave on swipe type while also adding the name2 appendage | 4451 | 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 | } |
| 4472 | 4453 | ||
| 4473 | if (power_user.auto_swipe) { | 4454 | if (power_user.auto_swipe) { |
| @@ -5240,11 +5221,6 @@ function getGenerateUrl(api) { | |||
| 5240 | } | 5221 | } |
| 5241 | } | 5222 | } |
| 5242 | 5223 | ||
| 5243 | function throwCircuitBreakerError() { | ||
| 5244 | callPopup(`Could not extract reply in ${MAX_GENERATION_LOOPS} attempts. Try generating again`, 'text'); | ||
| 5245 | unblockGeneration(); | ||
| 5246 | } | ||
| 5247 | |||
| 5248 | function extractTitleFromData(data) { | 5224 | function extractTitleFromData(data) { |
| 5249 | if (main_api == 'koboldhorde') { | 5225 | if (main_api == 'koboldhorde') { |
| 5250 | return data.workerName; | 5226 | return data.workerName; |
| @@ -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); |
| 1803 | 1803 | ||
| @@ -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 | } |
| 1962 | 1962 | ||
| 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 | } |
| 1968 | 1966 | ||
| 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 | } |
| 2117 | 2139 | ||
| @@ -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 | } |
| @@ -2241,7 +2241,7 @@ function setEphemeralStopStrings(value) { | |||
| 2241 | async function generateRawCallback(args, value) { | 2241 | async 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 | } |
| 2246 | 2246 | ||
| 2247 | // Prevent generate recursion | 2247 | // 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 | } |
| 2270 | 2274 | ||
| 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 | } |
| 2301 | 2309 | ||
| 2302 | /** | 2310 | /** |
| @@ -108,6 +108,7 @@ const KNOWN_DECORATORS = ['@@activate', '@@dont_activate']; | |||
| 108 | * @property {number} [cooldown] The cooldown of the entry | 108 | * @property {number} [cooldown] The cooldown of the entry |
| 109 | * @property {number} [delay] The delay of the entry | 109 | * @property {number} [delay] The delay of the entry |
| 110 | * @property {string[]} [decorators] Array of decorators for the entry | 110 | * @property {string[]} [decorators] Array of decorators for the entry |
| 111 | * @property {number} [hash] The hash of the entry | ||
| 111 | */ | 112 | */ |
| 112 | 113 | ||
| 113 | /** | 114 | /** |
| @@ -383,12 +384,6 @@ class WorldInfoBuffer { | |||
| 383 | */ | 384 | */ |
| 384 | class WorldInfoTimedEffects { | 385 | class 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 hash | 480 | * @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 | } |
| 496 | 485 | ||
| 497 | /** | 486 | /** |
| @@ -3603,10 +3592,13 @@ export async function getSortedEntries() { | |||
| 3603 | // Chat lore always goes first | 3592 | // Chat lore always goes first |
| 3604 | entries = [...chatLore.sort(sortFn), ...entries]; | 3593 | entries = [...chatLore.sort(sortFn), ...entries]; |
| 3605 | 3594 | ||
| 3606 | // Parse decorators | 3595 | // 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 | }); |
| 3611 | 3603 | ||
| 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)); |
| @@ -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, |
| @@ -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); |
| 380 | 382 | ||
| 381 | if (!response.headersSent) { | 383 | if (!response.headersSent) { |
| @@ -350,6 +350,10 @@ function getWebTokenizersChunks(tokenizer, ids) { | |||
| 350 | * @returns {string} Tokenizer model to use | 350 | * @returns {string} Tokenizer model to use |
| 351 | */ | 351 | */ |
| 352 | function getTokenizerModel(requestModel) { | 352 | function 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 | } |