Refactor generateRaw/generateQuietPrompt calls (#4277) * generateQuietPrompt: Update to object arguments * generateRaw: Update to object arguments * Fix jsdoc * Fix lint * Unwrap JSON schema options * Remove default args from gen call
Signed| @@ -2330,37 +2330,43 @@ export function getStoppingStrings(isImpersonate, isContinue) { | ||
| 2330 | 2330 | |
| 2331 | 2331 | /** |
| 2332 | 2332 | * Background generation based on the provided prompt. |
| 2333 | 2333 | * @paramtypedef {stringobject} quietPrompt Instruction prompt for the AIGenerateQuietPromptParams |
| 2334 | - * @param {boolean} [quietToLoud] Whether the message should be sent in a foreground (loud) or background (quiet) mode | |
| 2334 | + * @prop {string} [quietPrompt] Instruction prompt for the AI | |
| 2335 | 2335 | * @paramprop {boolean} [skipWIANquietToLoud] Whether tothe skipmessage additionshould ofbe Worldsent Infoin anda Author'sforeground Note(loud) intoor thebackground prompt(quiet) mode |
| 2336 | 2336 | * @paramprop {stringboolean} [quietImageskipWIAN] ImageWhether to useskip foraddition theof quietWorld Info and Author's Note into the prompt |
| 2337 | 2337 | * @paramprop {string} [quietNamequietImage] NameImage to use for the quiet prompt (defaults to "System:") |
| 2338 | 2338 | * @paramprop {numberstring} [responseLengthquietName] Maximum responseName length.to Ifuse unset,for the globalquiet defaultprompt value(defaults isto used."System:") |
| 2339 | 2339 | * @paramprop {number} [forceChIdresponseLength] Character IDMaximum toresponse uselength. forIf thisunset, generationthe run.global Worksdefault invalue groupsis onlyused. |
| 2340 | 2340 | * @paramprop {AdditionalRequestOptionsnumber} [options={}forceChId] AdditionalCharacter ID to use for this generation requestrun. optionsWorks in groups only. |
| 2341 | + * @prop {object} [jsonSchema] JSON schema to use for the structured generation. Usually requires a special instruction. | |
| 2342 | + * @param {GenerateQuietPromptParams} params Parameters for the quiet prompt generation | |
| 2341 | 2343 | * @returns {Promise<string>} Generated text. If using structured output, will contain a serialized JSON object. |
| 2342 | 2344 | */ |
| 2343 | 2345 | export async function generateQuietPrompt({ quietPrompt = '', quietToLoud = false, skipWIAN = false, quietImage = null, quietName = null, responseLength = null, forceChId = null, { jsonSchema = null } = {}) { |
| 2344 | - console.log('got into genQuietPrompt'); | |
| 2346 | + if (arguments.length > 0 && typeof arguments[0] !== 'object') { | |
| 2347 | + console.trace('generateQuietPrompt called with positional arguments. Please use an object instead.'); | |
| 2348 | + [quietPrompt, quietToLoud, skipWIAN, quietImage, quietName, responseLength, forceChId, jsonSchema] = arguments; | |
| 2349 | + } | |
| 2350 | + | |
| 2345 | 2351 | const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0; |
| 2346 | 2352 | let eventHook = () => { }; |
| 2347 | 2353 | try { |
| 2348 | 2354 | /** @type {GenerateOptions} */ |
| 2349 | 2355 | const optionsgenerateOptions = { |
| 2350 | 2356 | quiet_prompt: quietPrompt ?? '', |
| 2351 | - quietToLoud, | |
| 2357 | + quietToLoud: quietToLoud ?? false, | |
| 2352 | 2358 | skipWIAN: skipWIAN ?? false, |
| 2353 | 2359 | force_name2: true, |
| 2354 | 2360 | quietImage: quietImage ?? null, |
| 2355 | 2361 | quietName: quietName ?? null, |
| 2356 | 2362 | force_chid: forceChId ?? null, |
| 2357 | 2363 | jsonSchema: jsonSchema ?? null, |
| 2358 | 2364 | }; |
| 2359 | 2365 | if (responseLengthCustomized) { |
| 2360 | 2366 | TempResponseLength.save(main_api, responseLength); |
| 2361 | 2367 | eventHook = TempResponseLength.setupEventHook(main_api); |
| 2362 | 2368 | } |
| 2363 | 2369 | const result = await Generate('quiet', optionsgenerateOptions); |
| 2364 | 2370 | return removeReasoningFromString(result); |
| 2365 | 2371 | } finally { |
| 2366 | 2372 | if (responseLengthCustomized && TempResponseLength.isCustomized()) { |
| @@ -3121,18 +3127,25 @@ export function createRawPrompt(prompt, api, instructOverride, quietToLoud, syst | ||
| 3121 | 3127 | /** |
| 3122 | 3128 | * Generates a message using the provided prompt. |
| 3123 | 3129 | * If the prompt is an array of chat-style messages and not using chat completion, it will be converted to a text prompt. |
| 3124 | - * @param {string | object[]} prompt Prompt to generate a message from. Can be a string or an array of chat-style messages, i.e. [{role: '', content: ''}, ...] | |
| 3130 | + * @typedef {object} GenerateRawParams | |
| 3125 | - * @param {string} api API to use. Main API is used if not specified. | |
| 3131 | + * @prop {string | object[]} [prompt] Prompt to generate a message from. Can be a string or an array of chat-style messages, i.e. [{role: '', content: ''}, ...] | |
| 3126 | 3132 | * @paramprop {booleanstring} instructOverride[api] trueAPI to override instructuse. mode,Main falseAPI tois useused theif defaultnot valuespecified. |
| 3127 | 3133 | * @paramprop {boolean} quietToLoud[instructOverride] true to generate a message inoverride systeminstruct mode, false to generate a messageuse inthe characterdefault modevalue |
| 3128 | - * @param {string} [systemPrompt] System prompt to use. | |
| 3134 | + * @prop {boolean} [quietToLoud] true to generate a message in system mode, false to generate a message in character mode | |
| 3129 | 3135 | * @paramprop {numberstring} [responseLengthsystemPrompt] Maximum response length. If unset, the global defaultSystem valueprompt isto useduse. |
| 3130 | - * @param {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response. | |
| 3136 | + * @prop {number} [responseLength] Maximum response length. If unset, the global default value is used. | |
| 3131 | - * @param {string} [prefill] An optional prefill for the prompt. | |
| 3137 | + * @prop {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response. | |
| 3132 | 3138 | * @paramprop {AdditionalRequestOptionsstring} [optionsprefill] AdditionalAn optionsoptional prefill for generationthe prompt. |
| 3139 | + * @prop {object} [jsonSchema] JSON schema to use for the structured generation. Usually requires a special instruction. | |
| 3140 | + * @param {GenerateRawParams} params Parameters for generating a message | |
| 3133 | 3141 | * @returns {Promise<string>} Generated message |
| 3134 | 3142 | */ |
| 3135 | 3143 | export async function generateRaw({ prompt = '', api = null, instructOverride = false, quietToLoud = false, systemPrompt = '', responseLength = null, trimNames = true, prefill = '', optionsjsonSchema = null } = {}) { |
| 3144 | + if (arguments.length > 0 && typeof arguments[0] !== 'object') { | |
| 3145 | + console.trace('generateRaw called with positional arguments. Please use an object instead.'); | |
| 3146 | + [prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames, prefill, jsonSchema] = arguments; | |
| 3147 | + } | |
| 3148 | + | |
| 3136 | 3149 | if (!api) { |
| 3137 | 3150 | api = main_api; |
| 3138 | 3151 | } |
| @@ -3184,7 +3197,7 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | ||
| 3184 | 3197 | if (api === 'koboldhorde') { |
| 3185 | 3198 | data = await generateHorde(prompt.toString(), generateData, abortController.signal, false); |
| 3186 | 3199 | } else if (api === 'openai') { |
| 3187 | 3200 | data = await sendOpenAIRequest('quiet', generateData, abortController.signal, options{ jsonSchema }); |
| 3188 | 3201 | } else { |
| 3189 | 3202 | const generateUrl = getGenerateUrl(api); |
| 3190 | 3203 | const response = await fetch(generateUrl, { |
| @@ -3209,7 +3222,7 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy | ||
| 3209 | 3222 | throw new Error(data.response); |
| 3210 | 3223 | } |
| 3211 | 3224 | |
| 3212 | 3225 | if (options?.jsonSchema) { |
| 3213 | 3226 | return extractJsonFromData(data, { mainApi: api }); |
| 3214 | 3227 | } |
| 3215 | 3228 | |
| @@ -9315,7 +9328,7 @@ function addDebugFunctions() { | ||
| 9315 | 9328 | registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => { |
| 9316 | 9329 | const text = prompt('Input text:', 'Hello'); |
| 9317 | 9330 | toastr.info('Working on it...'); |
| 9318 | 9331 | const message = await generateRaw(text,{ null,prompt: false,text false}); |
| 9319 | 9332 | alert(message); |
| 9320 | 9333 | }); |
| 9321 | 9334 | registerDebugFunction('toggleEventTracing', 'Toggle event tracing', 'Useful to see what triggered a certain event.', () => { |
| @@ -421,7 +421,7 @@ async function autoBackgroundCommand() { | ||
| 421 | 421 | |
| 422 | 422 | const list = options.map(option => `- ${option.text}`).join('\n'); |
| 423 | 423 | const prompt = stringFormat(autoBgPrompt, list); |
| 424 | 424 | const reply = await generateQuietPrompt(prompt,{ false,quietPrompt: falseprompt }); |
| 425 | 425 | const fuse = new Fuse(options, { keys: ['text'] }); |
| 426 | 426 | const bestMatch = fuse.search(reply, { limit: 1 }); |
| 427 | 427 | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import { Fuse } from '../../../lib.js'; |
| 2 | 2 | |
| 3 | 3 | import { characters, eventSource, event_types, generateQuietPrompt, generateRaw, getRequestHeaders, main_api, online_status, saveSettingsDebounced, substituteParams, substituteParamsExtended, system_message_types, this_chid } from '../../../script.js'; |
| 4 | 4 | import { dragElement, isMobile } from '../../RossAscends-mods.js'; |
| 5 | 5 | import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js'; |
| 6 | 6 | import { loadMovingUIState, performFuzzySearch, power_user } from '../../power-user.js'; |
| @@ -1056,10 +1056,10 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin | ||
| 1056 | 1056 | inApiCall = true; |
| 1057 | 1057 | switch (extension_settings.expressions.promptType) { |
| 1058 | 1058 | case PROMPT_TYPE.raw: |
| 1059 | 1059 | emotionResponse = await generateRaw(text,{ main_api,prompt: falsetext, false,systemPrompt: prompt }); |
| 1060 | 1060 | break; |
| 1061 | 1061 | case PROMPT_TYPE.full: |
| 1062 | 1062 | emotionResponse = await generateQuietPrompt(prompt,{ false,quietPrompt: falseprompt }); |
| 1063 | 1063 | break; |
| 1064 | 1064 | } |
| 1065 | 1065 | } finally { |
| @@ -506,7 +506,7 @@ async function summarizeCallback(args, text) { | ||
| 506 | 506 | case summary_sources.extras: |
| 507 | 507 | return await callExtrasSummarizeAPI(text); |
| 508 | 508 | case summary_sources.main: |
| 509 | 509 | return removeReasoningFromString(await generateRaw(text,{ '',prompt: falsetext, false,systemPrompt: prompt, responseLength: extension_settings.memory.overrideResponseLength })); |
| 510 | 510 | case summary_sources.webllm: { |
| 511 | 511 | const messages = [{ role: 'system', content: prompt }, { role: 'user', content: text }].filter(m => m.content); |
| 512 | 512 | const params = extension_settings.memory.overrideResponseLength > 0 ? { max_tokens: extension_settings.memory.overrideResponseLength } : {}; |
| @@ -677,7 +677,13 @@ async function summarizeChatMain(context, force, skipWIAN) { | ||
| 677 | 677 | if (prompt_builders.DEFAULT === extension_settings.memory.prompt_builder) { |
| 678 | 678 | try { |
| 679 | 679 | inApiCall = true; |
| 680 | - summary = await generateQuietPrompt(prompt, false, skipWIAN, '', '', extension_settings.memory.overrideResponseLength); | |
| 680 | + /** @type {import('../../../script.js').GenerateQuietPromptParams} */ | |
| 681 | + const params = { | |
| 682 | + quietPrompt: prompt, | |
| 683 | + skipWIAN: skipWIAN, | |
| 684 | + responseLength: extension_settings.memory.overrideResponseLength, | |
| 685 | + }; | |
| 686 | + summary = await generateQuietPrompt(params); | |
| 681 | 687 | } finally { |
| 682 | 688 | inApiCall = false; |
| 683 | 689 | } |
| @@ -701,7 +707,13 @@ async function summarizeChatMain(context, force, skipWIAN) { | ||
| 701 | 707 | return null; |
| 702 | 708 | } |
| 703 | 709 | |
| 704 | - const rawSummary = await generateRaw(rawPrompt, '', false, false, prompt, extension_settings.memory.overrideResponseLength); | |
| 710 | + /** @type {import('../../../script.js').GenerateRawParams} */ | |
| 711 | + const params = { | |
| 712 | + prompt: rawPrompt, | |
| 713 | + systemPrompt: prompt, | |
| 714 | + responseLength: extension_settings.memory.overrideResponseLength, | |
| 715 | + }; | |
| 716 | + const rawSummary = await generateRaw(params); | |
| 705 | 717 | summary = removeReasoningFromString(rawSummary); |
| 706 | 718 | index = lastUsedIndex; |
| 707 | 719 | } finally { |
| @@ -2726,7 +2726,7 @@ function getUserAvatarUrl() { | ||
| 2726 | 2726 | * @returns {Promise<string>} - A promise that resolves when the prompt generation completes. |
| 2727 | 2727 | */ |
| 2728 | 2728 | async function generatePrompt(quietPrompt) { |
| 2729 | 2729 | const reply = await generateQuietPrompt(quietPrompt,{ false,quietPrompt false}); |
| 2730 | 2730 | const processedReply = processReply(reply); |
| 2731 | 2731 | |
| 2732 | 2732 | if (!processedReply) { |
| @@ -257,17 +257,17 @@ async function summarizeExtra(element) { | ||
| 257 | 257 | /** |
| 258 | 258 | * Summarizes messages using the main API method. |
| 259 | 259 | * @param {HashedMessage} element hashed message |
| 260 | 260 | * @returns {Promise<boolean>} SucessSuccess |
| 261 | 261 | */ |
| 262 | 262 | async function summarizeMain(element) { |
| 263 | 263 | element.text = removeReasoningFromString(await generateRaw({ prompt: element.text, '', false, false,systemPrompt: settings.summary_prompt })); |
| 264 | 264 | return true; |
| 265 | 265 | } |
| 266 | 266 | |
| 267 | 267 | /** |
| 268 | 268 | * Summarizes messages using WebLLM. |
| 269 | 269 | * @param {HashedMessage} element hashed message |
| 270 | 270 | * @returns {Promise<boolean>} SucessSuccess |
| 271 | 271 | */ |
| 272 | 272 | async function summarizeWebLLM(element) { |
| 273 | 273 | if (!isWebLlmSupported()) { |
| @@ -1751,7 +1751,7 @@ jQuery(async () => { | ||
| 1751 | 1751 | |
| 1752 | 1752 | $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); |
| 1753 | 1753 | [event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => { |
| 1754 | 1754 | eventSource.on(event, (/** @type {string} */ key) => { |
| 1755 | 1755 | if (key !== SECRET_KEYS.NOMICAI) return; |
| 1756 | 1756 | $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); |
| 1757 | 1757 | }); |
| @@ -3645,7 +3645,17 @@ async function generateRawCallback(args, value) { | ||
| 3645 | 3645 | } |
| 3646 | 3646 | |
| 3647 | 3647 | setEphemeralStopStrings(resolveVariable(args?.stop)); |
| 3648 | - const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud, systemPrompt, length, trimNames, prefillPrompt); | |
| 3648 | + /** @type {import('../script.js').GenerateRawParams} */ | |
| 3649 | + const params = { | |
| 3650 | + prompt: value, | |
| 3651 | + instructOverride: isFalseBoolean(args?.instruct), | |
| 3652 | + quietToLoud: quietToLoud, | |
| 3653 | + systemPrompt: systemPrompt, | |
| 3654 | + responseLength: length, | |
| 3655 | + trimNames: trimNames, | |
| 3656 | + prefill: prefillPrompt, | |
| 3657 | + }; | |
| 3658 | + const result = await generateRaw(params); | |
| 3649 | 3659 | return result; |
| 3650 | 3660 | } catch (err) { |
| 3651 | 3661 | console.error('Error on /genraw generation', err); |
| @@ -3681,7 +3691,14 @@ async function generateCallback(args, value) { | ||
| 3681 | 3691 | setEphemeralStopStrings(resolveVariable(args?.stop)); |
| 3682 | 3692 | const name = args?.name; |
| 3683 | 3693 | const char = findChar({ name: name }); |
| 3684 | - const result = await generateQuietPrompt(value, quietToLoud, false, '', char?.name ?? name, length); | |
| 3694 | + /** @type {import('../script.js').GenerateQuietPromptParams} */ | |
| 3695 | + const params = { | |
| 3696 | + quietPrompt: value, | |
| 3697 | + quietToLoud: quietToLoud, | |
| 3698 | + quietName: char?.name ?? name, | |
| 3699 | + responseLength: length, | |
| 3700 | + }; | |
| 3701 | + const result = await generateQuietPrompt(params); | |
| 3685 | 3702 | return result; |
| 3686 | 3703 | } catch (err) { |
| 3687 | 3704 | console.error('Error on /gen generation', err); |
| @@ -4352,7 +4369,7 @@ export async function generateSystemMessage(_, prompt) { | ||
| 4352 | 4369 | |
| 4353 | 4370 | // Generate and regex the output if applicable |
| 4354 | 4371 | toastr.info('Please wait', 'Generating...'); |
| 4355 | 4372 | let message = await generateQuietPrompt(prompt,{ false,quietPrompt: falseprompt }); |
| 4356 | 4373 | message = getRegexedString(message, regex_placement.SLASH_COMMAND); |
| 4357 | 4374 | |
| 4358 | 4375 | sendNarratorMessage(_, message); |
| @@ -4609,7 +4626,7 @@ export async function promptQuietForLoudResponse(who, text) { | ||
| 4609 | 4626 | |
| 4610 | 4627 | //text = `${text}${power_user.instruct.enabled ? '' : '\n'}${(power_user.always_force_name2 && who != 'raw') ? characters[character_id].name + ":" : ""}` |
| 4611 | 4628 | |
| 4612 | 4629 | let reply = await generateQuietPrompt({ quietPrompt: text, quietToLoud: true, false}); |
| 4613 | 4630 | text = await getRegexedString(reply, regex_placement.SLASH_COMMAND); |
| 4614 | 4631 | |
| 4615 | 4632 | const message = { |