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
This commit is contained in:
+45
-32
@@ -2330,37 +2330,43 @@ export function getStoppingStrings(isImpersonate, isContinue) {
|
||||
|
||||
/**
|
||||
* Background generation based on the provided prompt.
|
||||
* @param {string} quietPrompt Instruction prompt for the AI
|
||||
* @param {boolean} [quietToLoud] Whether the message should be sent in a foreground (loud) or background (quiet) mode
|
||||
* @param {boolean} [skipWIAN] Whether to skip addition of World Info and Author's Note into the prompt
|
||||
* @param {string} [quietImage] Image to use for the quiet prompt
|
||||
* @param {string} [quietName] Name to use for the quiet prompt (defaults to "System:")
|
||||
* @param {number} [responseLength] Maximum response length. If unset, the global default value is used.
|
||||
* @param {number} [forceChId] Character ID to use for this generation run. Works in groups only.
|
||||
* @param {AdditionalRequestOptions} [options={}] Additional generation request options.
|
||||
* @typedef {object} GenerateQuietPromptParams
|
||||
* @prop {string} [quietPrompt] Instruction prompt for the AI
|
||||
* @prop {boolean} [quietToLoud] Whether the message should be sent in a foreground (loud) or background (quiet) mode
|
||||
* @prop {boolean} [skipWIAN] Whether to skip addition of World Info and Author's Note into the prompt
|
||||
* @prop {string} [quietImage] Image to use for the quiet prompt
|
||||
* @prop {string} [quietName] Name to use for the quiet prompt (defaults to "System:")
|
||||
* @prop {number} [responseLength] Maximum response length. If unset, the global default value is used.
|
||||
* @prop {number} [forceChId] Character ID to use for this generation run. Works in groups only.
|
||||
* @prop {object} [jsonSchema] JSON schema to use for the structured generation. Usually requires a special instruction.
|
||||
* @param {GenerateQuietPromptParams} params Parameters for the quiet prompt generation
|
||||
* @returns {Promise<string>} Generated text. If using structured output, will contain a serialized JSON object.
|
||||
*/
|
||||
export async function generateQuietPrompt(quietPrompt, quietToLoud = false, skipWIAN = false, quietImage = null, quietName = null, responseLength = null, forceChId = null, { jsonSchema } = {}) {
|
||||
console.log('got into genQuietPrompt');
|
||||
export async function generateQuietPrompt({ quietPrompt = '', quietToLoud = false, skipWIAN = false, quietImage = null, quietName = null, responseLength = null, forceChId = null, jsonSchema = null } = {}) {
|
||||
if (arguments.length > 0 && typeof arguments[0] !== 'object') {
|
||||
console.trace('generateQuietPrompt called with positional arguments. Please use an object instead.');
|
||||
[quietPrompt, quietToLoud, skipWIAN, quietImage, quietName, responseLength, forceChId, jsonSchema] = arguments;
|
||||
}
|
||||
|
||||
const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0;
|
||||
let eventHook = () => { };
|
||||
try {
|
||||
/** @type {GenerateOptions} */
|
||||
const options = {
|
||||
quiet_prompt: quietPrompt,
|
||||
quietToLoud,
|
||||
skipWIAN: skipWIAN,
|
||||
const generateOptions = {
|
||||
quiet_prompt: quietPrompt ?? '',
|
||||
quietToLoud: quietToLoud ?? false,
|
||||
skipWIAN: skipWIAN ?? false,
|
||||
force_name2: true,
|
||||
quietImage: quietImage,
|
||||
quietName: quietName,
|
||||
force_chid: forceChId,
|
||||
jsonSchema: jsonSchema,
|
||||
quietImage: quietImage ?? null,
|
||||
quietName: quietName ?? null,
|
||||
force_chid: forceChId ?? null,
|
||||
jsonSchema: jsonSchema ?? null,
|
||||
};
|
||||
if (responseLengthCustomized) {
|
||||
TempResponseLength.save(main_api, responseLength);
|
||||
eventHook = TempResponseLength.setupEventHook(main_api);
|
||||
}
|
||||
const result = await Generate('quiet', options);
|
||||
const result = await Generate('quiet', generateOptions);
|
||||
return removeReasoningFromString(result);
|
||||
} finally {
|
||||
if (responseLengthCustomized && TempResponseLength.isCustomized()) {
|
||||
@@ -3121,18 +3127,25 @@ export function createRawPrompt(prompt, api, instructOverride, quietToLoud, syst
|
||||
/**
|
||||
* Generates a message using the provided prompt.
|
||||
* If the prompt is an array of chat-style messages and not using chat completion, it will be converted to a text prompt.
|
||||
* @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: ''}, ...]
|
||||
* @param {string} api API to use. Main API is used if not specified.
|
||||
* @param {boolean} instructOverride true to override instruct mode, false to use the default value
|
||||
* @param {boolean} quietToLoud true to generate a message in system mode, false to generate a message in character mode
|
||||
* @param {string} [systemPrompt] System prompt to use.
|
||||
* @param {number} [responseLength] Maximum response length. If unset, the global default value is used.
|
||||
* @param {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response.
|
||||
* @param {string} [prefill] An optional prefill for the prompt.
|
||||
* @param {AdditionalRequestOptions} [options] Additional options for generation
|
||||
* @typedef {object} GenerateRawParams
|
||||
* @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: ''}, ...]
|
||||
* @prop {string} [api] API to use. Main API is used if not specified.
|
||||
* @prop {boolean} [instructOverride] true to override instruct mode, false to use the default value
|
||||
* @prop {boolean} [quietToLoud] true to generate a message in system mode, false to generate a message in character mode
|
||||
* @prop {string} [systemPrompt] System prompt to use.
|
||||
* @prop {number} [responseLength] Maximum response length. If unset, the global default value is used.
|
||||
* @prop {boolean} [trimNames] Whether to allow trimming "{{user}}:" and "{{char}}:" from the response.
|
||||
* @prop {string} [prefill] An optional prefill for the prompt.
|
||||
* @prop {object} [jsonSchema] JSON schema to use for the structured generation. Usually requires a special instruction.
|
||||
* @param {GenerateRawParams} params Parameters for generating a message
|
||||
* @returns {Promise<string>} Generated message
|
||||
*/
|
||||
export async function generateRaw(prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames = true, prefill = '', options = {}) {
|
||||
export async function generateRaw({ prompt = '', api = null, instructOverride = false, quietToLoud = false, systemPrompt = '', responseLength = null, trimNames = true, prefill = '', jsonSchema = null } = {}) {
|
||||
if (arguments.length > 0 && typeof arguments[0] !== 'object') {
|
||||
console.trace('generateRaw called with positional arguments. Please use an object instead.');
|
||||
[prompt, api, instructOverride, quietToLoud, systemPrompt, responseLength, trimNames, prefill, jsonSchema] = arguments;
|
||||
}
|
||||
|
||||
if (!api) {
|
||||
api = main_api;
|
||||
}
|
||||
@@ -3184,7 +3197,7 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
|
||||
if (api === 'koboldhorde') {
|
||||
data = await generateHorde(prompt.toString(), generateData, abortController.signal, false);
|
||||
} else if (api === 'openai') {
|
||||
data = await sendOpenAIRequest('quiet', generateData, abortController.signal, options);
|
||||
data = await sendOpenAIRequest('quiet', generateData, abortController.signal, { jsonSchema });
|
||||
} else {
|
||||
const generateUrl = getGenerateUrl(api);
|
||||
const response = await fetch(generateUrl, {
|
||||
@@ -3209,7 +3222,7 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
|
||||
throw new Error(data.response);
|
||||
}
|
||||
|
||||
if (options?.jsonSchema) {
|
||||
if (jsonSchema) {
|
||||
return extractJsonFromData(data, { mainApi: api });
|
||||
}
|
||||
|
||||
@@ -9315,7 +9328,7 @@ function addDebugFunctions() {
|
||||
registerDebugFunction('generationTest', 'Send a generation request', 'Generates text using the currently selected API.', async () => {
|
||||
const text = prompt('Input text:', 'Hello');
|
||||
toastr.info('Working on it...');
|
||||
const message = await generateRaw(text, null, false, false);
|
||||
const message = await generateRaw({ prompt: text });
|
||||
alert(message);
|
||||
});
|
||||
registerDebugFunction('toggleEventTracing', 'Toggle event tracing', 'Useful to see what triggered a certain event.', () => {
|
||||
|
||||
@@ -421,7 +421,7 @@ async function autoBackgroundCommand() {
|
||||
|
||||
const list = options.map(option => `- ${option.text}`).join('\n');
|
||||
const prompt = stringFormat(autoBgPrompt, list);
|
||||
const reply = await generateQuietPrompt(prompt, false, false);
|
||||
const reply = await generateQuietPrompt({ quietPrompt: prompt });
|
||||
const fuse = new Fuse(options, { keys: ['text'] });
|
||||
const bestMatch = fuse.search(reply, { limit: 1 });
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Fuse } from '../../../lib.js';
|
||||
|
||||
import { characters, eventSource, event_types, generateQuietPrompt, generateRaw, getRequestHeaders, main_api, online_status, saveSettingsDebounced, substituteParams, substituteParamsExtended, system_message_types, this_chid } from '../../../script.js';
|
||||
import { characters, eventSource, event_types, generateQuietPrompt, generateRaw, getRequestHeaders, online_status, saveSettingsDebounced, substituteParams, substituteParamsExtended, system_message_types, this_chid } from '../../../script.js';
|
||||
import { dragElement, isMobile } from '../../RossAscends-mods.js';
|
||||
import { getContext, getApiUrl, modules, extension_settings, ModuleWorkerWrapper, doExtrasFetch, renderExtensionTemplateAsync } from '../../extensions.js';
|
||||
import { loadMovingUIState, performFuzzySearch, power_user } from '../../power-user.js';
|
||||
@@ -1056,10 +1056,10 @@ export async function getExpressionLabel(text, expressionsApi = extension_settin
|
||||
inApiCall = true;
|
||||
switch (extension_settings.expressions.promptType) {
|
||||
case PROMPT_TYPE.raw:
|
||||
emotionResponse = await generateRaw(text, main_api, false, false, prompt);
|
||||
emotionResponse = await generateRaw({ prompt: text, systemPrompt: prompt });
|
||||
break;
|
||||
case PROMPT_TYPE.full:
|
||||
emotionResponse = await generateQuietPrompt(prompt, false, false);
|
||||
emotionResponse = await generateQuietPrompt({ quietPrompt: prompt });
|
||||
break;
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -506,7 +506,7 @@ async function summarizeCallback(args, text) {
|
||||
case summary_sources.extras:
|
||||
return await callExtrasSummarizeAPI(text);
|
||||
case summary_sources.main:
|
||||
return removeReasoningFromString(await generateRaw(text, '', false, false, prompt, extension_settings.memory.overrideResponseLength));
|
||||
return removeReasoningFromString(await generateRaw({ prompt: text, systemPrompt: prompt, responseLength: extension_settings.memory.overrideResponseLength }));
|
||||
case summary_sources.webllm: {
|
||||
const messages = [{ role: 'system', content: prompt }, { role: 'user', content: text }].filter(m => m.content);
|
||||
const params = extension_settings.memory.overrideResponseLength > 0 ? { max_tokens: extension_settings.memory.overrideResponseLength } : {};
|
||||
@@ -677,7 +677,13 @@ async function summarizeChatMain(context, force, skipWIAN) {
|
||||
if (prompt_builders.DEFAULT === extension_settings.memory.prompt_builder) {
|
||||
try {
|
||||
inApiCall = true;
|
||||
summary = await generateQuietPrompt(prompt, false, skipWIAN, '', '', extension_settings.memory.overrideResponseLength);
|
||||
/** @type {import('../../../script.js').GenerateQuietPromptParams} */
|
||||
const params = {
|
||||
quietPrompt: prompt,
|
||||
skipWIAN: skipWIAN,
|
||||
responseLength: extension_settings.memory.overrideResponseLength,
|
||||
};
|
||||
summary = await generateQuietPrompt(params);
|
||||
} finally {
|
||||
inApiCall = false;
|
||||
}
|
||||
@@ -701,7 +707,13 @@ async function summarizeChatMain(context, force, skipWIAN) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const rawSummary = await generateRaw(rawPrompt, '', false, false, prompt, extension_settings.memory.overrideResponseLength);
|
||||
/** @type {import('../../../script.js').GenerateRawParams} */
|
||||
const params = {
|
||||
prompt: rawPrompt,
|
||||
systemPrompt: prompt,
|
||||
responseLength: extension_settings.memory.overrideResponseLength,
|
||||
};
|
||||
const rawSummary = await generateRaw(params);
|
||||
summary = removeReasoningFromString(rawSummary);
|
||||
index = lastUsedIndex;
|
||||
} finally {
|
||||
|
||||
@@ -2726,7 +2726,7 @@ function getUserAvatarUrl() {
|
||||
* @returns {Promise<string>} - A promise that resolves when the prompt generation completes.
|
||||
*/
|
||||
async function generatePrompt(quietPrompt) {
|
||||
const reply = await generateQuietPrompt(quietPrompt, false, false);
|
||||
const reply = await generateQuietPrompt({ quietPrompt });
|
||||
const processedReply = processReply(reply);
|
||||
|
||||
if (!processedReply) {
|
||||
|
||||
@@ -257,17 +257,17 @@ async function summarizeExtra(element) {
|
||||
/**
|
||||
* Summarizes messages using the main API method.
|
||||
* @param {HashedMessage} element hashed message
|
||||
* @returns {Promise<boolean>} Sucess
|
||||
* @returns {Promise<boolean>} Success
|
||||
*/
|
||||
async function summarizeMain(element) {
|
||||
element.text = removeReasoningFromString(await generateRaw(element.text, '', false, false, settings.summary_prompt));
|
||||
element.text = removeReasoningFromString(await generateRaw({ prompt: element.text, systemPrompt: settings.summary_prompt }));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Summarizes messages using WebLLM.
|
||||
* @param {HashedMessage} element hashed message
|
||||
* @returns {Promise<boolean>} Sucess
|
||||
* @returns {Promise<boolean>} Success
|
||||
*/
|
||||
async function summarizeWebLLM(element) {
|
||||
if (!isWebLlmSupported()) {
|
||||
@@ -1751,7 +1751,7 @@ jQuery(async () => {
|
||||
|
||||
$('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]);
|
||||
[event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => {
|
||||
eventSource.on(event, (/** @type {string} */ key)=> {
|
||||
eventSource.on(event, (/** @type {string} */ key) => {
|
||||
if (key !== SECRET_KEYS.NOMICAI) return;
|
||||
$('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]);
|
||||
});
|
||||
|
||||
@@ -3645,7 +3645,17 @@ async function generateRawCallback(args, value) {
|
||||
}
|
||||
|
||||
setEphemeralStopStrings(resolveVariable(args?.stop));
|
||||
const result = await generateRaw(value, '', isFalseBoolean(args?.instruct), quietToLoud, systemPrompt, length, trimNames, prefillPrompt);
|
||||
/** @type {import('../script.js').GenerateRawParams} */
|
||||
const params = {
|
||||
prompt: value,
|
||||
instructOverride: isFalseBoolean(args?.instruct),
|
||||
quietToLoud: quietToLoud,
|
||||
systemPrompt: systemPrompt,
|
||||
responseLength: length,
|
||||
trimNames: trimNames,
|
||||
prefill: prefillPrompt,
|
||||
};
|
||||
const result = await generateRaw(params);
|
||||
return result;
|
||||
} catch (err) {
|
||||
console.error('Error on /genraw generation', err);
|
||||
@@ -3681,7 +3691,14 @@ async function generateCallback(args, value) {
|
||||
setEphemeralStopStrings(resolveVariable(args?.stop));
|
||||
const name = args?.name;
|
||||
const char = findChar({ name: name });
|
||||
const result = await generateQuietPrompt(value, quietToLoud, false, '', char?.name ?? name, length);
|
||||
/** @type {import('../script.js').GenerateQuietPromptParams} */
|
||||
const params = {
|
||||
quietPrompt: value,
|
||||
quietToLoud: quietToLoud,
|
||||
quietName: char?.name ?? name,
|
||||
responseLength: length,
|
||||
};
|
||||
const result = await generateQuietPrompt(params);
|
||||
return result;
|
||||
} catch (err) {
|
||||
console.error('Error on /gen generation', err);
|
||||
@@ -4352,7 +4369,7 @@ export async function generateSystemMessage(_, prompt) {
|
||||
|
||||
// Generate and regex the output if applicable
|
||||
toastr.info('Please wait', 'Generating...');
|
||||
let message = await generateQuietPrompt(prompt, false, false);
|
||||
let message = await generateQuietPrompt({ quietPrompt: prompt });
|
||||
message = getRegexedString(message, regex_placement.SLASH_COMMAND);
|
||||
|
||||
sendNarratorMessage(_, message);
|
||||
@@ -4609,7 +4626,7 @@ export async function promptQuietForLoudResponse(who, text) {
|
||||
|
||||
//text = `${text}${power_user.instruct.enabled ? '' : '\n'}${(power_user.always_force_name2 && who != 'raw') ? characters[character_id].name + ":" : ""}`
|
||||
|
||||
let reply = await generateQuietPrompt(text, true, false);
|
||||
let reply = await generateQuietPrompt({ quietPrompt: text, quietToLoud: true });
|
||||
text = await getRegexedString(reply, regex_placement.SLASH_COMMAND);
|
||||
|
||||
const message = {
|
||||
|
||||
Reference in New Issue
Block a user