Merge pull request #3181 from SillyTavern/tc-split-generic Add generic text completion API type (100% OAI compatible)
Signed| @@ -1235,7 +1235,8 @@ | ||
| 1235 | 1235 | <input class="neo-range-slider" type="range" id="temp_textgenerationwebui" name="volume" min="0.0" max="5.0" step="0.01" x-setting-id="temp"> |
| 1236 | 1236 | <input class="neo-range-input" type="number" min="0.0" max="5.0" step="0.01" data-for="temp_textgenerationwebui" id="temp_counter_textgenerationwebui"> |
| 1237 | 1237 | </div> |
| 1238 | - <div class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> | |
| 1238 | + <!-- Note: "except" mode = show for all BUT types in data-tg-type --> | |
| 1239 | + <div data-tg-type-mode="except" data-tg-type="generic" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> | |
| 1239 | 1240 | <small> |
| 1240 | 1241 | <span data-i18n="Top K">Top K</span> |
| 1241 | 1242 | <div class="fa-solid fa-circle-info opacity50p" title="Top K sets a maximum amount of top tokens that can be chosen from. E.g Top K is 20, this means only the 20 highest ranking tokens will be kept (regardless of their probabilities being diverse or limited). Set to 0 (or -1, depending on your backend) to disable." data-i18n="[title]Top_K_desc"></div> |
| @@ -1251,7 +1252,7 @@ | ||
| 1251 | 1252 | <input class="neo-range-slider" type="range" id="top_p_textgenerationwebui" name="volume" min="0" max="1" step="0.01"> |
| 1252 | 1253 | <input class="neo-range-input" type="number" min="0" max="1" step="0.01" data-for="top_p_textgenerationwebui" id="top_p_counter_textgenerationwebui"> |
| 1253 | 1254 | </div> |
| 1254 | 1255 | <div data-tg-type-mode="except" data-tg-type="generic" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> |
| 1255 | 1256 | <small> |
| 1256 | 1257 | <span data-i18n="Typical P">Typical P</span> |
| 1257 | 1258 | <div class="fa-solid fa-circle-info opacity50p" title="Typical P Sampling prioritizes tokens based on their deviation from the average entropy of the set. It maintains tokens whose cumulative probability is close to a predefined threshold (e.g., 0.5), emphasizing those with average information content. Set to 1.0 to disable." data-i18n="[title]Typical_P_desc"></div> |
| @@ -1259,7 +1260,7 @@ | ||
| 1259 | 1260 | <input class="neo-range-slider" type="range" id="typical_p_textgenerationwebui" name="volume" min="0" max="1" step="0.01"> |
| 1260 | 1261 | <input class="neo-range-input" type="number" min="0" max="1" step="0.01" data-for="typical_p_textgenerationwebui" id="typical_p_counter_textgenerationwebui"> |
| 1261 | 1262 | </div> |
| 1262 | 1263 | <div data-tg-type-mode="except" data-tg-type="generic" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> |
| 1263 | 1264 | <small> |
| 1264 | 1265 | <span data-i18n="Min P">Min P</span> |
| 1265 | 1266 | <div class="fa-solid fa-circle-info opacity50p" data-i18n="[title]Min_P_desc" title="Min P sets a base minimum probability. This is scaled according to the top token's probability. E.g If Top token is 80% probability, and Min P is 0.1, only tokens higher than 8% would be considered. Set to 0 to disable."></div> |
| @@ -1267,7 +1268,7 @@ | ||
| 1267 | 1268 | <input class="neo-range-slider" type="range" id="min_p_textgenerationwebui" name="volume" min="0" max="1" step="0.001"> |
| 1268 | 1269 | <input class="neo-range-input" type="number" min="0" max="1" step="0.001" data-for="min_p_textgenerationwebui" id="min_p_counter_textgenerationwebui"> |
| 1269 | 1270 | </div> |
| 1270 | 1271 | <div data-tg-type-mode="except" data-tg-type="generic" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> |
| 1271 | 1272 | <small> |
| 1272 | 1273 | <span data-i18n="Top A">Top A</span> |
| 1273 | 1274 | <div class="fa-solid fa-circle-info opacity50p" title="Top A sets a threshold for token selection based on the square of the highest token probability. E.g if the Top-A value is 0.2 and the top token's probability is 50%, tokens with probabilities below 5% (0.2 * 0.5^2) are excluded. Set to 0 to disable." data-i18n="[title]Top_A_desc"></div> |
| @@ -1275,7 +1276,7 @@ | ||
| 1275 | 1276 | <input class="neo-range-slider" type="range" id="top_a_textgenerationwebui" name="volume" min="0" max="1" step="0.01"> |
| 1276 | 1277 | <input class="neo-range-input" type="number" min="0" max="1" step="0.01" data-for="top_a_textgenerationwebui" id="top_a_counter_textgenerationwebui"> |
| 1277 | 1278 | </div> |
| 1278 | 1279 | <div data-tg-type-mode="except" data-tg-type="generic" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> |
| 1279 | 1280 | <small> |
| 1280 | 1281 | <span data-i18n="TFS">TFS</span> |
| 1281 | 1282 | <div class="fa-solid fa-circle-info opacity50p" data-i18n="[title]Tail_Free_Sampling_desc" title="Tail-Free Sampling (TFS) searches for a tail of low-probability tokens in the distribution, by analyzing the rate of change in token probabilities using derivatives. It retains tokens up to a threshold (e.g., 0.3) based on the normalized second derivative. The closer to 0, the more discarded tokens. Set to 1.0 to disable."></div> |
| @@ -1307,7 +1308,7 @@ | ||
| 1307 | 1308 | <input class="neo-range-slider" type="range" id="eta_cutoff_textgenerationwebui" name="volume" min="0" max="20" step="0.01"> |
| 1308 | 1309 | <input class="neo-range-input" type="number" min="0" max="20" step="0.01" data-for="eta_cutoff_textgenerationwebui" id="eta_cutoff_counter_textgenerationwebui"> |
| 1309 | 1310 | </div> |
| 1310 | 1311 | <div data-tg-type-mode="except" data-tg-type="generic" class="alignitemscenter flex-container flexFlowColumn flexBasis30p flexGrow flexShrink gap0"> |
| 1311 | 1312 | <small data-i18n="rep.pen">Repetition Penalty</small> |
| 1312 | 1313 | <input class="neo-range-slider" type="range" id="rep_pen_textgenerationwebui" name="volume" min="1" max="3" step="0.01"> |
| 1313 | 1314 | <input class="neo-range-input" type="number" min="1" max="3" step="0.01" data-for="rep_pen_textgenerationwebui" id="rep_pen_counter_textgenerationwebui"> |
| @@ -1569,7 +1570,7 @@ | ||
| 1569 | 1570 | <small data-i18n="Ignore EOS Token">Ignore EOS Token</small> |
| 1570 | 1571 | <div class="fa-solid fa-circle-info opacity50p " data-i18n="[title]Ignore the EOS Token even if it generates." title="Ignore the EOS Token even if it generates."></div> |
| 1571 | 1572 | </label> |
| 1572 | 1573 | <label data-tg-type-mode="except" data-tg-type="generic" class="checkbox_label flexGrow flexShrink" for="skip_special_tokens_textgenerationwebui"> |
| 1573 | 1574 | <input type="checkbox" id="skip_special_tokens_textgenerationwebui" /> |
| 1574 | 1575 | <small data-i18n="Skip Special Tokens">Skip Special Tokens</small> |
| 1575 | 1576 | </label> |
| @@ -1594,14 +1595,14 @@ | ||
| 1594 | 1595 | </label> |
| 1595 | 1596 | </div> |
| 1596 | 1597 | </div> |
| 1597 | 1598 | <div data-tg-type="mancer, ooba, koboldcpp, vllm, aphrodite, llamacpp, ollama, infermaticai, huggingface, generic" class="flex-container flexFlowColumn alignitemscenter flexBasis48p flexGrow flexShrink gap0"> |
| 1598 | 1599 | <label> |
| 1599 | 1600 | <small data-i18n="Seed">Seed</small> |
| 1600 | 1601 | <div class="fa-solid fa-circle-info opacity50p " data-i18n="[title]Seed_desc" title="A random seed to use for deterministic and reproducable outputs. Set to -1 to use a random seed."></div> |
| 1601 | 1602 | </label> |
| 1602 | 1603 | <input type="number" id="seed_textgenerationwebui" class="text_pole textAlignCenter" min="-1" value="-1" /> |
| 1603 | 1604 | </div> |
| 1604 | 1605 | <div data-tg-type-mode="except" data-tg-type="generic" id="banned_tokens_block_ooba" class="wide100p"> |
| 1605 | 1606 | <hr class="width100p"> |
| 1606 | 1607 | <h4 class="range-block-title justifyCenter"> |
| 1607 | 1608 | <span data-i18n="Banned Tokens">Banned Tokens/Strings</span> |
| @@ -2187,10 +2188,10 @@ | ||
| 2187 | 2188 | <div> |
| 2188 | 2189 | <h4 data-i18n="API Type">API Type</h4> |
| 2189 | 2190 | <select id="textgen_type"> |
| 2190 | - <option value="ooba" data-i18n="Default (completions compatible)">Default [OpenAI /completions compatible: oobabooga, LM Studio, etc.]</option> | |
| 2191 | 2191 | <option value="aphrodite">Aphrodite</option> |
| 2192 | 2192 | <option value="dreamgen">DreamGen</option> |
| 2193 | 2193 | <option value="featherless">Featherless</option> |
| 2194 | + <option value="generic" data-i18n="Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]">Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]</option> | |
| 2194 | 2195 | <option value="huggingface">HuggingFace (Inference Endpoint)</option> |
| 2195 | 2196 | <option value="infermaticai">InfermaticAI</option> |
| 2196 | 2197 | <option value="koboldcpp">KoboldCpp</option> |
| @@ -2199,6 +2200,7 @@ | ||
| 2199 | 2200 | <option value="ollama">Ollama</option> |
| 2200 | 2201 | <option value="openrouter">OpenRouter</option> |
| 2201 | 2202 | <option value="tabby">TabbyAPI</option> |
| 2203 | + <option value="ooba">Text Generation WebUI (oobabooga)</option> | |
| 2202 | 2204 | <option value="togetherai">TogetherAI</option> |
| 2203 | 2205 | <option value="vllm">vLLM</option> |
| 2204 | 2206 | </select> |
| @@ -2321,6 +2323,24 @@ | ||
| 2321 | 2323 | </select> |
| 2322 | 2324 | </div> |
| 2323 | 2325 | </div> |
| 2326 | + <div data-tg-type="generic" class="flex-container flexFlowColumn"> | |
| 2327 | + <h4 data-i18n="API key (optional)">API key (optional)</h4> | |
| 2328 | + <div class="flex-container"> | |
| 2329 | + <input id="api_key_generic" name="api_key_generic" class="text_pole flex1 wide100p" type="text" autocomplete="off"> | |
| 2330 | + <div title="Clear your API key" data-i18n="[title]Clear your API key" class="menu_button fa-solid fa-circle-xmark clear-api-key" data-key="api_key_generic"> | |
| 2331 | + </div> | |
| 2332 | + </div> | |
| 2333 | + <div data-for="api_key_generic" class="neutral_warning" data-i18n="For privacy reasons, your API key will be hidden after you reload the page."> | |
| 2334 | + For privacy reasons, your API key will be hidden after you reload the page. | |
| 2335 | + </div> | |
| 2336 | + <div class="flex1"> | |
| 2337 | + <h4 data-i18n="Server url">Server URL</h4> | |
| 2338 | + <small data-i18n="Example: 127.0.0.1:5000">Example: http://127.0.0.1:5000</small> | |
| 2339 | + <input id="generic_api_url_text" name="generic_api_url" class="text_pole wide100p" value="" autocomplete="off" data-server-history="generic"> | |
| 2340 | + </div> | |
| 2341 | + <datalist id="generic_model_fill"></datalist> | |
| 2342 | + <input id="generic_model_textgenerationwebui" list="generic_model_fill" class="text_pole wide100p" placeholder="Model ID (optional)" data-i18n="[placeholder]Model ID (optional)" type="text"> | |
| 2343 | + </div> | |
| 2324 | 2344 | <div data-tg-type="ooba" class="flex-container flexFlowColumn"> |
| 2325 | 2345 | <div class="flex-container flexFlowColumn"> |
| 2326 | 2346 | <a href="https://github.com/oobabooga/text-generation-webui" target="_blank"> |
| @@ -234,7 +234,7 @@ import { | ||
| 234 | 234 | import { getBackgrounds, initBackgrounds, loadBackgroundSettings, background_settings } from './scripts/backgrounds.js'; |
| 235 | 235 | import { hideLoader, showLoader } from './scripts/loader.js'; |
| 236 | 236 | import { BulkEditOverlay, CharacterContextMenu } from './scripts/BulkEditOverlay.js'; |
| 237 | 237 | import { loadFeatherlessModels, loadMancerModels, loadOllamaModels, loadTogetherAIModels, loadInfermaticAIModels, loadOpenRouterModels, loadVllmModels, loadAphroditeModels, loadDreamGenModels, initTextGenModels, loadTabbyModels, loadGenericModels } from './scripts/textgen-models.js'; |
| 238 | 238 | import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, decodeStyleTags, encodeStyleTags, isExternalMediaAllowed, getCurrentEntityId, preserveNeutralChat, restoreNeutralChat } from './scripts/chats.js'; |
| 239 | 239 | import { getPresetManager, initPresetManager } from './scripts/preset-manager.js'; |
| 240 | 240 | import { evaluateMacros, getLastMessageId, initMacros } from './scripts/macros.js'; |
| @@ -1221,6 +1221,9 @@ async function getStatusTextgen() { | ||
| 1221 | 1221 | } else if (textgen_settings.type === textgen_types.TABBY) { |
| 1222 | 1222 | loadTabbyModels(data?.data); |
| 1223 | 1223 | setOnlineStatus(textgen_settings.tabby_model || data?.result); |
| 1224 | + } else if (textgen_settings.type === textgen_types.GENERIC) { | |
| 1225 | + loadGenericModels(data?.data); | |
| 1226 | + setOnlineStatus(textgen_settings.generic_model || 'Connected'); | |
| 1224 | 1227 | } else { |
| 1225 | 1228 | setOnlineStatus(data?.result); |
| 1226 | 1229 | } |
| @@ -10042,6 +10045,7 @@ jQuery(async function () { | ||
| 10042 | 10045 | { id: 'api_key_llamacpp', secret: SECRET_KEYS.LLAMACPP }, |
| 10043 | 10046 | { id: 'api_key_featherless', secret: SECRET_KEYS.FEATHERLESS }, |
| 10044 | 10047 | { id: 'api_key_huggingface', secret: SECRET_KEYS.HUGGINGFACE }, |
| 10048 | + { id: 'api_key_generic', secret: SECRET_KEYS.GENERIC }, | |
| 10045 | 10049 | ]; |
| 10046 | 10050 | |
| 10047 | 10051 | for (const key of keys) { |
| @@ -585,6 +585,7 @@ class PresetManager { | ||
| 585 | 585 | 'openrouter_allow_fallbacks', |
| 586 | 586 | 'tabby_model', |
| 587 | 587 | 'derived', |
| 588 | + 'generic_model', | |
| 588 | 589 | ]; |
| 589 | 590 | const settings = Object.assign({}, getSettingsByApiId(this.apiId)); |
| 590 | 591 | |
| @@ -38,6 +38,7 @@ export const SECRET_KEYS = { | ||
| 38 | 38 | NANOGPT: 'api_key_nanogpt', |
| 39 | 39 | TAVILY: 'api_key_tavily', |
| 40 | 40 | BFL: 'api_key_bfl', |
| 41 | + GENERIC: 'api_key_generic', | |
| 41 | 42 | }; |
| 42 | 43 | |
| 43 | 44 | const INPUT_MAP = { |
| @@ -71,6 +72,7 @@ const INPUT_MAP = { | ||
| 71 | 72 | [SECRET_KEYS.HUGGINGFACE]: '#api_key_huggingface', |
| 72 | 73 | [SECRET_KEYS.BLOCKENTROPY]: '#api_key_blockentropy', |
| 73 | 74 | [SECRET_KEYS.NANOGPT]: '#api_key_nanogpt', |
| 75 | + [SECRET_KEYS.GENERIC]: '#api_key_generic', | |
| 74 | 76 | }; |
| 75 | 77 | |
| 76 | 78 | async function clearSecret() { |
| @@ -3743,6 +3743,7 @@ function setBackgroundCallback(_, bg) { | ||
| 3743 | 3743 | function getModelOptions(quiet) { |
| 3744 | 3744 | const nullResult = { control: null, options: null }; |
| 3745 | 3745 | const modelSelectMap = [ |
| 3746 | + { id: 'generic_model_textgenerationwebui', api: 'textgenerationwebui', type: textgen_types.GENERIC }, | |
| 3746 | 3747 | { id: 'custom_model_textgenerationwebui', api: 'textgenerationwebui', type: textgen_types.OOBA }, |
| 3747 | 3748 | { id: 'model_togetherai_select', api: 'textgenerationwebui', type: textgen_types.TOGETHERAI }, |
| 3748 | 3749 | { id: 'openrouter_model', api: 'textgenerationwebui', type: textgen_types.OPENROUTER }, |
| @@ -160,6 +160,24 @@ export async function loadInfermaticAIModels(data) { | ||
| 160 | 160 | } |
| 161 | 161 | } |
| 162 | 162 | |
| 163 | +export function loadGenericModels(data) { | |
| 164 | + if (!Array.isArray(data)) { | |
| 165 | + console.error('Invalid Generic models data', data); | |
| 166 | + return; | |
| 167 | + } | |
| 168 | + | |
| 169 | + data.sort((a, b) => a.id.localeCompare(b.id)); | |
| 170 | + const dataList = $('#generic_model_fill'); | |
| 171 | + dataList.empty(); | |
| 172 | + | |
| 173 | + for (const model of data) { | |
| 174 | + const option = document.createElement('option'); | |
| 175 | + option.value = model.id; | |
| 176 | + option.text = model.id; | |
| 177 | + dataList.append(option); | |
| 178 | + } | |
| 179 | +} | |
| 180 | + | |
| 163 | 181 | export async function loadDreamGenModels(data) { |
| 164 | 182 | if (!Array.isArray(data)) { |
| 165 | 183 | console.error('Invalid DreamGen models data', data); |
| @@ -33,9 +33,11 @@ export const textgen_types = { | ||
| 33 | 33 | OPENROUTER: 'openrouter', |
| 34 | 34 | FEATHERLESS: 'featherless', |
| 35 | 35 | HUGGINGFACE: 'huggingface', |
| 36 | + GENERIC: 'generic', | |
| 36 | 37 | }; |
| 37 | 38 | |
| 38 | 39 | const { |
| 40 | + GENERIC, | |
| 39 | 41 | MANCER, |
| 40 | 42 | VLLM, |
| 41 | 43 | APHRODITE, |
| @@ -120,6 +122,7 @@ export const SERVER_INPUTS = { | ||
| 120 | 122 | [textgen_types.LLAMACPP]: '#llamacpp_api_url_text', |
| 121 | 123 | [textgen_types.OLLAMA]: '#ollama_api_url_text', |
| 122 | 124 | [textgen_types.HUGGINGFACE]: '#huggingface_api_url_text', |
| 125 | + [textgen_types.GENERIC]: '#generic_api_url_text', | |
| 123 | 126 | }; |
| 124 | 127 | |
| 125 | 128 | const KOBOLDCPP_ORDER = [6, 0, 1, 3, 4, 2, 5]; |
| @@ -205,6 +208,7 @@ const settings = { | ||
| 205 | 208 | xtc_probability: 0, |
| 206 | 209 | nsigma: 0.0, |
| 207 | 210 | featherless_model: '', |
| 211 | + generic_model: '', | |
| 208 | 212 | }; |
| 209 | 213 | |
| 210 | 214 | export { |
| @@ -282,6 +286,7 @@ export const setting_names = [ | ||
| 282 | 286 | 'xtc_threshold', |
| 283 | 287 | 'xtc_probability', |
| 284 | 288 | 'nsigma', |
| 289 | + 'generic_model', | |
| 285 | 290 | ]; |
| 286 | 291 | |
| 287 | 292 | const DYNATEMP_BLOCK = document.getElementById('dynatemp_block_ooba'); |
| @@ -833,7 +838,14 @@ jQuery(function () { | ||
| 833 | 838 | |
| 834 | 839 | function showTypeSpecificControls(type) { |
| 835 | 840 | $('[data-tg-type]').each(function () { |
| 841 | + const mode = String($(this).attr('data-tg-type-mode') ?? '').toLowerCase().trim(); | |
| 836 | 842 | const tgTypes = $(this).attr('data-tg-type').split(',').map(x => x.trim()); |
| 843 | + | |
| 844 | + if (mode === 'except') { | |
| 845 | + $(this)[tgTypes.includes(type) ? 'hide' : 'show'](); | |
| 846 | + return; | |
| 847 | + } | |
| 848 | + | |
| 837 | 849 | for (const tgType of tgTypes) { |
| 838 | 850 | if (tgType === type || tgType == 'all') { |
| 839 | 851 | $(this).show(); |
| @@ -1100,6 +1112,11 @@ export function getTextGenModel() { | ||
| 1100 | 1112 | return settings.custom_model; |
| 1101 | 1113 | } |
| 1102 | 1114 | break; |
| 1115 | + case GENERIC: | |
| 1116 | + if (settings.generic_model) { | |
| 1117 | + return settings.generic_model; | |
| 1118 | + } | |
| 1119 | + break; | |
| 1103 | 1120 | case MANCER: |
| 1104 | 1121 | return settings.mancer_model; |
| 1105 | 1122 | case TOGETHERAI: |
| @@ -172,6 +172,19 @@ function getHuggingFaceHeaders(directories) { | ||
| 172 | 172 | }) : {}; |
| 173 | 173 | } |
| 174 | 174 | |
| 175 | +/** | |
| 176 | + * Gets the headers for the Generic text completion API. | |
| 177 | + * @param {import('./users.js').UserDirectoryList} directories | |
| 178 | + * @returns {object} Headers for the request | |
| 179 | + */ | |
| 180 | +function getGenericHeaders(directories) { | |
| 181 | + const apiKey = readSecret(directories, SECRET_KEYS.GENERIC); | |
| 182 | + | |
| 183 | + return apiKey ? ({ | |
| 184 | + 'Authorization': `Bearer ${apiKey}`, | |
| 185 | + }) : {}; | |
| 186 | +} | |
| 187 | + | |
| 175 | 188 | export function getOverrideHeaders(urlHost) { |
| 176 | 189 | const requestOverrides = getConfigValue('requestOverrides', []); |
| 177 | 190 | const overrideHeaders = requestOverrides?.find((e) => e.hosts?.includes(urlHost))?.headers; |
| @@ -214,6 +227,7 @@ export function setAdditionalHeadersByType(requestHeaders, type, server, directo | ||
| 214 | 227 | [TEXTGEN_TYPES.LLAMACPP]: getLlamaCppHeaders, |
| 215 | 228 | [TEXTGEN_TYPES.FEATHERLESS]: getFeatherlessHeaders, |
| 216 | 229 | [TEXTGEN_TYPES.HUGGINGFACE]: getHuggingFaceHeaders, |
| 230 | + [TEXTGEN_TYPES.GENERIC]: getGenericHeaders, | |
| 217 | 231 | }; |
| 218 | 232 | |
| 219 | 233 | const getHeaders = headerGetters[type]; |
| @@ -225,6 +225,7 @@ export const TEXTGEN_TYPES = { | ||
| 225 | 225 | OPENROUTER: 'openrouter', |
| 226 | 226 | FEATHERLESS: 'featherless', |
| 227 | 227 | HUGGINGFACE: 'huggingface', |
| 228 | + GENERIC: 'generic', | |
| 228 | 229 | }; |
| 229 | 230 | |
| 230 | 231 | export const INFERMATICAI_KEYS = [ |
| @@ -346,6 +347,24 @@ export const OLLAMA_KEYS = [ | ||
| 346 | 347 | 'min_p', |
| 347 | 348 | ]; |
| 348 | 349 | |
| 350 | +// https://platform.openai.com/docs/api-reference/completions | |
| 351 | +export const OPENAI_KEYS = [ | |
| 352 | + 'model', | |
| 353 | + 'prompt', | |
| 354 | + 'stream', | |
| 355 | + 'temperature', | |
| 356 | + 'top_p', | |
| 357 | + 'frequency_penalty', | |
| 358 | + 'presence_penalty', | |
| 359 | + 'stop', | |
| 360 | + 'seed', | |
| 361 | + 'logit_bias', | |
| 362 | + 'logprobs', | |
| 363 | + 'max_tokens', | |
| 364 | + 'n', | |
| 365 | + 'best_of', | |
| 366 | +]; | |
| 367 | + | |
| 349 | 368 | export const AVATAR_WIDTH = 512; |
| 350 | 369 | export const AVATAR_HEIGHT = 768; |
| 351 | 370 | |
| @@ -13,6 +13,7 @@ import { | ||
| 13 | 13 | VLLM_KEYS, |
| 14 | 14 | DREAMGEN_KEYS, |
| 15 | 15 | FEATHERLESS_KEYS, |
| 16 | + OPENAI_KEYS, | |
| 16 | 17 | } from '../../constants.js'; |
| 17 | 18 | import { forwardFetchResponse, trimV1, getConfigValue } from '../../util.js'; |
| 18 | 19 | import { setAdditionalHeaders } from '../../additional-headers.js'; |
| @@ -113,8 +114,8 @@ router.post('/status', jsonParser, async function (request, response) { | ||
| 113 | 114 | let url = baseUrl; |
| 114 | 115 | let result = ''; |
| 115 | 116 | |
| 116 | - | |
| 117 | 117 | switch (apiType) { |
| 118 | + case TEXTGEN_TYPES.GENERIC: | |
| 118 | 119 | case TEXTGEN_TYPES.OOBA: |
| 119 | 120 | case TEXTGEN_TYPES.VLLM: |
| 120 | 121 | case TEXTGEN_TYPES.APHRODITE: |
| @@ -287,6 +288,7 @@ router.post('/generate', jsonParser, async function (request, response) { | ||
| 287 | 288 | let url = trimV1(baseUrl); |
| 288 | 289 | |
| 289 | 290 | switch (request.body.api_type) { |
| 291 | + case TEXTGEN_TYPES.GENERIC: | |
| 290 | 292 | case TEXTGEN_TYPES.VLLM: |
| 291 | 293 | case TEXTGEN_TYPES.FEATHERLESS: |
| 292 | 294 | case TEXTGEN_TYPES.APHRODITE: |
| @@ -347,6 +349,12 @@ router.post('/generate', jsonParser, async function (request, response) { | ||
| 347 | 349 | args.body = JSON.stringify(request.body); |
| 348 | 350 | } |
| 349 | 351 | |
| 352 | + if (request.body.api_type === TEXTGEN_TYPES.GENERIC) { | |
| 353 | + request.body = _.pickBy(request.body, (_, key) => OPENAI_KEYS.includes(key)); | |
| 354 | + if (Array.isArray(request.body.stop)) { request.body.stop = request.body.stop.slice(0, 4); } | |
| 355 | + args.body = JSON.stringify(request.body); | |
| 356 | + } | |
| 357 | + | |
| 350 | 358 | if (request.body.api_type === TEXTGEN_TYPES.OPENROUTER) { |
| 351 | 359 | if (Array.isArray(request.body.provider) && request.body.provider.length > 0) { |
| 352 | 360 | request.body.provider = { |
| @@ -50,6 +50,7 @@ export const SECRET_KEYS = { | ||
| 50 | 50 | TAVILY: 'api_key_tavily', |
| 51 | 51 | NANOGPT: 'api_key_nanogpt', |
| 52 | 52 | BFL: 'api_key_bfl', |
| 53 | + GENERIC: 'api_key_generic', | |
| 53 | 54 | }; |
| 54 | 55 | |
| 55 | 56 | // These are the keys that are safe to expose, even if allowKeysExposure is false |