Merge pull request #2712 from SillyTavern/ai21-jamba New AI21 Jamba + tokenizer

3700396b145a4576836e8842b4dc57d673deb420

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

Signed
10 files changed, +192 -266Ignore whitespace
default/content/presets/openai/Default.json+1 -4
@@ -8,7 +8,7 @@
8 "openrouter_force_instruct": false,8 "openrouter_force_instruct": false,
9 "openrouter_group_models": false,9 "openrouter_group_models": false,
10 "openrouter_sort_models": "alphabetically",10 "openrouter_sort_models": "alphabetically",
11 "ai21_model": "j2-ultra",11 "ai21_model": "jamba-1.5-large",
12 "mistralai_model": "mistral-large-latest",12 "mistralai_model": "mistral-large-latest",
13 "custom_model": "",13 "custom_model": "",
14 "custom_url": "",14 "custom_url": "",
@@ -19,7 +19,6 @@
19 "temperature": 1,19 "temperature": 1,
20 "frequency_penalty": 0,20 "frequency_penalty": 0,
21 "presence_penalty": 0,21 "presence_penalty": 0,
22 "count_penalty": 0,
23 "top_p": 1,22 "top_p": 1,
24 "top_k": 0,23 "top_k": 0,
25 "top_a": 0,24 "top_a": 0,
@@ -233,8 +232,6 @@
233 "assistant_prefill": "",232 "assistant_prefill": "",
234 "assistant_impersonation": "",233 "assistant_impersonation": "",
235 "human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.",234 "human_sysprompt_message": "Let's get started. Please generate your response based on the information and instructions provided above.",
236 "use_ai21_tokenizer": false,
237 "use_google_tokenizer": false,
238 "claude_use_sysprompt": false,235 "claude_use_sysprompt": false,
239 "use_alt_scale": false,236 "use_alt_scale": false,
240 "squash_system_messages": false,237 "squash_system_messages": false,
default/content/settings.json+2 -4
@@ -452,7 +452,6 @@
452 "temp_openai": 1.0,452 "temp_openai": 1.0,
453 "freq_pen_openai": 0,453 "freq_pen_openai": 0,
454 "pres_pen_openai": 0,454 "pres_pen_openai": 0,
455 "count_pen": 0,
456 "top_p_openai": 1,455 "top_p_openai": 1,
457 "top_k_openai": 0,456 "top_k_openai": 0,
458 "stream_openai": true,457 "stream_openai": true,
@@ -614,7 +613,7 @@
614 "wi_format": "{0}",613 "wi_format": "{0}",
615 "openai_model": "gpt-4-turbo",614 "openai_model": "gpt-4-turbo",
616 "claude_model": "claude-3-5-sonnet-20240620",615 "claude_model": "claude-3-5-sonnet-20240620",
617 "ai21_model": "j2-ultra",616 "ai21_model": "jamba-1.5-large",
618 "windowai_model": "",617 "windowai_model": "",
619 "openrouter_model": "OR_Website",618 "openrouter_model": "OR_Website",
620 "jailbreak_system": true,619 "jailbreak_system": true,
@@ -625,7 +624,6 @@
625 "show_external_models": false,624 "show_external_models": false,
626 "proxy_password": "",625 "proxy_password": "",
627 "assistant_prefill": "",626 "assistant_prefill": "",
628 "assistant_impersonation": "",627 "assistant_impersonation": ""
629 "use_ai21_tokenizer": false
630 }628 }
631}629}
public/index.html+10 -36
@@ -436,7 +436,7 @@
436 </div>436 </div>
437 </div>437 </div>
438 </div>438 </div>
439 <div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq">439 <div data-newbie-hidden class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq">
440 <div class="range-block-title" data-i18n="Frequency Penalty">440 <div class="range-block-title" data-i18n="Frequency Penalty">
441 Frequency Penalty441 Frequency Penalty
442 </div>442 </div>
@@ -449,7 +449,7 @@
449 </div>449 </div>
450 </div>450 </div>
451 </div>451 </div>
452 <div data-newbie-hidden class="range-block" data-source="openai,openrouter,ai21,custom,cohere,perplexity,groq">452 <div data-newbie-hidden class="range-block" data-source="openai,openrouter,custom,cohere,perplexity,groq">
453 <div class="range-block-title" data-i18n="Presence Penalty">453 <div class="range-block-title" data-i18n="Presence Penalty">
454 Presence Penalty454 Presence Penalty
455 </div>455 </div>
@@ -462,20 +462,7 @@
462 </div>462 </div>
463 </div>463 </div>
464 </div>464 </div>
465 <div data-newbie-hidden class="range-block" data-source="ai21">465 <div data-newbie-hidden class="range-block" data-source="claude,openrouter,makersuite,cohere,perplexity">
466 <div class="range-block-title" data-i18n="Count Penalty">
467 Count Penalty
468 </div>
469 <div class="range-block-range-and-counter">
470 <div class="range-block-range">
471 <input type="range" id="count_pen" name="volume" min="0" max="1" step="0.01">
472 </div>
473 <div class="range-block-counter">
474 <input type="number" min="0" max="1" step="0.01" data-for="count_pen" id="count_pen_counter">
475 </div>
476 </div>
477 </div>
478 <div data-newbie-hidden class="range-block" data-source="claude,openrouter,ai21,makersuite,cohere,perplexity">
479 <div class="range-block-title" data-i18n="Top K">466 <div class="range-block-title" data-i18n="Top K">
480 Top K467 Top K
481 </div>468 </div>
@@ -1791,22 +1778,6 @@
1791 </select>1778 </select>
1792 </div>1779 </div>
1793 </div>1780 </div>
1794 <div class="range-block" data-source="ai21">
1795 <label for="use_ai21_tokenizer" title="Use AI21 Tokenizer" data-i18n="[title]Use AI21 Tokenizer" class="checkbox_label widthFreeExpand">
1796 <input id="use_ai21_tokenizer" type="checkbox" /><span data-i18n="Use AI21 Tokenizer">Use AI21 Tokenizer</span>
1797 </label>
1798 <div class="toggle-description justifyLeft">
1799 <span data-i18n="Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.">Use the appropriate tokenizer for Jurassic models, which is more efficient than GPT's.</span>
1800 </div>
1801 </div>
1802 <div class="range-block" data-source="makersuite">
1803 <label for="use_google_tokenizer" title="Use Google Tokenizer" data-i18n="[title]Use Google Tokenizer" class="checkbox_label widthFreeExpand">
1804 <input id="use_google_tokenizer" type="checkbox" /><span data-i18n="Use Google Tokenizer">Use Google Tokenizer</span>
1805 </label>
1806 <div class="toggle-description justifyLeft">
1807 <span data-i18n="Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.">Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.</span>
1808 </div>
1809 </div>
1810 <div class="range-block" data-source="makersuite">1781 <div class="range-block" data-source="makersuite">
1811 <label for="use_makersuite_sysprompt" class="checkbox_label widthFreeExpand">1782 <label for="use_makersuite_sysprompt" class="checkbox_label widthFreeExpand">
1812 <input id="use_makersuite_sysprompt" type="checkbox" />1783 <input id="use_makersuite_sysprompt" type="checkbox" />
@@ -2791,10 +2762,12 @@
2791 <div>2762 <div>
2792 <h4 data-i18n="AI21 Model">AI21 Model</h4>2763 <h4 data-i18n="AI21 Model">AI21 Model</h4>
2793 <select id="model_ai21_select">2764 <select id="model_ai21_select">
2794 <optgroup label="Latest">2765 <optgroup label="Jamba 1.5">
2795 <option value="j2-ultra">j2-ultra</option>2766 <option value="jamba-1.5-mini">jamba-1.5-mini</option>
2796 <option value="j2-mid">j2-mid</option>2767 <option value="jamba-1.5-large">jamba-1.5-large</option>
2797 <option value="j2-light">j2-light</option>2768 </optgroup>
2769 <optgroup label="Jamba-Instruct (Deprecated)">
2770 <option value="jamba-instruct-preview">jamba-instruct-preview</option>
2798 </optgroup>2771 </optgroup>
2799 </select>2772 </select>
2800 </div>2773 </div>
@@ -3450,6 +3423,7 @@
3450 <option value="3">Llama 1/2</option>3423 <option value="3">Llama 1/2</option>
3451 <option value="12">Llama 3</option>3424 <option value="12">Llama 3</option>
3452 <option value="13">Gemma / Gemini</option>3425 <option value="13">Gemma / Gemini</option>
3426 <option value="14">Jamba</option>
3453 <option value="4">NerdStash (NovelAI Clio)</option>3427 <option value="4">NerdStash (NovelAI Clio)</option>
3454 <option value="5">NerdStash v2 (NovelAI Kayra)</option>3428 <option value="5">NerdStash v2 (NovelAI Kayra)</option>
3455 <option value="7">Mistral</option>3429 <option value="7">Mistral</option>
public/script.js+1 -1
@@ -2826,7 +2826,7 @@ export function getCharacterCardFields() {
2826}2826}
28272827
2828export function isStreamingEnabled() {2828export function isStreamingEnabled() {
2829 const noStreamSources = [chat_completion_sources.SCALE, chat_completion_sources.AI21];2829 const noStreamSources = [chat_completion_sources.SCALE];
2830 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')))2830 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')))
2831 || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)2831 || (main_api == 'kobold' && kai_settings.streaming_kobold && kai_flags.can_use_streaming)
2832 || (main_api == 'novel' && nai_settings.streaming_novel)2832 || (main_api == 'novel' && nai_settings.streaming_novel)
public/scripts/openai.js+17 -101
@@ -132,13 +132,9 @@ const max_2mil = 2000 * 1000;
132const scale_max = 8191;132const scale_max = 8191;
133const claude_max = 9000; // We have a proper tokenizer, so theoretically could be larger (up to 9k)133const claude_max = 9000; // We have a proper tokenizer, so theoretically could be larger (up to 9k)
134const claude_100k_max = 99000;134const claude_100k_max = 99000;
135let ai21_max = 9200; //can easily fit 9k gpt tokens because j2's tokenizer is efficient af
136const unlocked_max = max_200k;135const unlocked_max = max_200k;
137const oai_max_temp = 2.0;136const oai_max_temp = 2.0;
138const claude_max_temp = 1.0; //same as j2137const claude_max_temp = 1.0;
139const j2_max_topk = 10.0;
140const j2_max_freq = 5.0;
141const j2_max_pres = 5.0;
142const openrouter_website_model = 'OR_Website';138const openrouter_website_model = 'OR_Website';
143const openai_max_stop_strings = 4;139const openai_max_stop_strings = 4;
144140
@@ -218,25 +214,11 @@ const sensitiveFields = [
218 'custom_include_headers',214 'custom_include_headers',
219];215];
220216
221function getPrefixMap() {
222 return selected_group ? {
223 assistant: '',
224 user: '',
225 system: 'OOC: ',
226 }
227 : {
228 assistant: '{{char}}:',
229 user: '{{user}}:',
230 system: '',
231 };
232}
233
234const default_settings = {217const default_settings = {
235 preset_settings_openai: 'Default',218 preset_settings_openai: 'Default',
236 temp_openai: 1.0,219 temp_openai: 1.0,
237 freq_pen_openai: 0,220 freq_pen_openai: 0,
238 pres_pen_openai: 0,221 pres_pen_openai: 0,
239 count_pen: 0.0,
240 top_p_openai: 1.0,222 top_p_openai: 1.0,
241 top_k_openai: 0,223 top_k_openai: 0,
242 min_p_openai: 0,224 min_p_openai: 0,
@@ -264,7 +246,7 @@ const default_settings = {
264 openai_model: 'gpt-4-turbo',246 openai_model: 'gpt-4-turbo',
265 claude_model: 'claude-3-5-sonnet-20240620',247 claude_model: 'claude-3-5-sonnet-20240620',
266 google_model: 'gemini-1.5-pro',248 google_model: 'gemini-1.5-pro',
267 ai21_model: 'j2-ultra',249 ai21_model: 'jamba-1.5-large',
268 mistralai_model: 'mistral-large-latest',250 mistralai_model: 'mistral-large-latest',
269 cohere_model: 'command-r-plus',251 cohere_model: 'command-r-plus',
270 perplexity_model: 'llama-3.1-70b-instruct',252 perplexity_model: 'llama-3.1-70b-instruct',
@@ -294,8 +276,6 @@ const default_settings = {
294 assistant_prefill: '',276 assistant_prefill: '',
295 assistant_impersonation: '',277 assistant_impersonation: '',
296 human_sysprompt_message: default_claude_human_sysprompt_message,278 human_sysprompt_message: default_claude_human_sysprompt_message,
297 use_ai21_tokenizer: false,
298 use_google_tokenizer: false,
299 claude_use_sysprompt: false,279 claude_use_sysprompt: false,
300 use_makersuite_sysprompt: true,280 use_makersuite_sysprompt: true,
301 use_alt_scale: false,281 use_alt_scale: false,
@@ -317,7 +297,6 @@ const oai_settings = {
317 temp_openai: 1.0,297 temp_openai: 1.0,
318 freq_pen_openai: 0,298 freq_pen_openai: 0,
319 pres_pen_openai: 0,299 pres_pen_openai: 0,
320 count_pen: 0.0,
321 top_p_openai: 1.0,300 top_p_openai: 1.0,
322 top_k_openai: 0,301 top_k_openai: 0,
323 min_p_openai: 0,302 min_p_openai: 0,
@@ -345,7 +324,7 @@ const oai_settings = {
345 openai_model: 'gpt-4-turbo',324 openai_model: 'gpt-4-turbo',
346 claude_model: 'claude-3-5-sonnet-20240620',325 claude_model: 'claude-3-5-sonnet-20240620',
347 google_model: 'gemini-1.5-pro',326 google_model: 'gemini-1.5-pro',
348 ai21_model: 'j2-ultra',327 ai21_model: 'jamba-1.5-large',
349 mistralai_model: 'mistral-large-latest',328 mistralai_model: 'mistral-large-latest',
350 cohere_model: 'command-r-plus',329 cohere_model: 'command-r-plus',
351 perplexity_model: 'llama-3.1-70b-instruct',330 perplexity_model: 'llama-3.1-70b-instruct',
@@ -375,8 +354,6 @@ const oai_settings = {
375 assistant_prefill: '',354 assistant_prefill: '',
376 assistant_impersonation: '',355 assistant_impersonation: '',
377 human_sysprompt_message: default_claude_human_sysprompt_message,356 human_sysprompt_message: default_claude_human_sysprompt_message,
378 use_ai21_tokenizer: false,
379 use_google_tokenizer: false,
380 claude_use_sysprompt: false,357 claude_use_sysprompt: false,
381 use_makersuite_sysprompt: true,358 use_makersuite_sysprompt: true,
382 use_alt_scale: false,359 use_alt_scale: false,
@@ -1802,7 +1779,6 @@ async function sendOpenAIRequest(type, messages, signal) {
1802 const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE;1779 const isClaude = oai_settings.chat_completion_source == chat_completion_sources.CLAUDE;
1803 const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER;1780 const isOpenRouter = oai_settings.chat_completion_source == chat_completion_sources.OPENROUTER;
1804 const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE;1781 const isScale = oai_settings.chat_completion_source == chat_completion_sources.SCALE;
1805 const isAI21 = oai_settings.chat_completion_source == chat_completion_sources.AI21;
1806 const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE;1782 const isGoogle = oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE;
1807 const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI;1783 const isOAI = oai_settings.chat_completion_source == chat_completion_sources.OPENAI;
1808 const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI;1784 const isMistral = oai_settings.chat_completion_source == chat_completion_sources.MISTRALAI;
@@ -1815,7 +1791,7 @@ async function sendOpenAIRequest(type, messages, signal) {
1815 const isQuiet = type === 'quiet';1791 const isQuiet = type === 'quiet';
1816 const isImpersonate = type === 'impersonate';1792 const isImpersonate = type === 'impersonate';
1817 const isContinue = type === 'continue';1793 const isContinue = type === 'continue';
1818 const stream = oai_settings.stream_openai && !isQuiet && !isScale && !isAI21 && !(isGoogle && oai_settings.google_model.includes('bison'));1794 const stream = oai_settings.stream_openai && !isQuiet && !isScale && !(isGoogle && oai_settings.google_model.includes('bison'));
1819 const useLogprobs = !!power_user.request_token_probabilities;1795 const useLogprobs = !!power_user.request_token_probabilities;
1820 const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom);1796 const canMultiSwipe = oai_settings.n > 1 && !isContinue && !isImpersonate && !isQuiet && (isOAI || isCustom);
18211797
@@ -1824,15 +1800,6 @@ async function sendOpenAIRequest(type, messages, signal) {
1824 replaceItemizedPromptText(messageId, messages);1800 replaceItemizedPromptText(messageId, messages);
1825 }1801 }
18261802
1827 if (isAI21) {
1828 const joinedMsgs = messages.reduce((acc, obj) => {
1829 const prefix = getPrefixMap()[obj.role];
1830 return acc + (prefix ? (selected_group ? '\n' : prefix + ' ') : '') + obj.content + '\n';
1831 }, '');
1832 messages = substituteParams(joinedMsgs) + (isImpersonate ? `${name1}:` : `${name2}:`);
1833 replaceItemizedPromptText(messageId, messages);
1834 }
1835
1836 // If we're using the window.ai extension, use that instead1803 // If we're using the window.ai extension, use that instead
1837 // Doesn't support logit bias yet1804 // Doesn't support logit bias yet
1838 if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) {1805 if (oai_settings.chat_completion_source == chat_completion_sources.WINDOWAI) {
@@ -1931,12 +1898,6 @@ async function sendOpenAIRequest(type, messages, signal) {
1931 generate_data['use_makersuite_sysprompt'] = oai_settings.use_makersuite_sysprompt;1898 generate_data['use_makersuite_sysprompt'] = oai_settings.use_makersuite_sysprompt;
1932 }1899 }
19331900
1934 if (isAI21) {
1935 generate_data['top_k'] = Number(oai_settings.top_k_openai);
1936 generate_data['count_pen'] = Number(oai_settings.count_pen);
1937 generate_data['stop_tokens'] = [name1 + ':', substituteParams(oai_settings.new_chat_prompt), substituteParams(oai_settings.new_group_chat_prompt)];
1938 }
1939
1940 if (isMistral) {1901 if (isMistral) {
1941 generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future.1902 generate_data['safe_prompt'] = false; // already defaults to false, but just incase they change that in the future.
1942 }1903 }
@@ -3008,7 +2969,6 @@ function loadOpenAISettings(data, settings) {
3008 oai_settings.temp_openai = settings.temp_openai ?? default_settings.temp_openai;2969 oai_settings.temp_openai = settings.temp_openai ?? default_settings.temp_openai;
3009 oai_settings.freq_pen_openai = settings.freq_pen_openai ?? default_settings.freq_pen_openai;2970 oai_settings.freq_pen_openai = settings.freq_pen_openai ?? default_settings.freq_pen_openai;
3010 oai_settings.pres_pen_openai = settings.pres_pen_openai ?? default_settings.pres_pen_openai;2971 oai_settings.pres_pen_openai = settings.pres_pen_openai ?? default_settings.pres_pen_openai;
3011 oai_settings.count_pen = settings.count_pen ?? default_settings.count_pen;
3012 oai_settings.top_p_openai = settings.top_p_openai ?? default_settings.top_p_openai;2972 oai_settings.top_p_openai = settings.top_p_openai ?? default_settings.top_p_openai;
3013 oai_settings.top_k_openai = settings.top_k_openai ?? default_settings.top_k_openai;2973 oai_settings.top_k_openai = settings.top_k_openai ?? default_settings.top_k_openai;
3014 oai_settings.top_a_openai = settings.top_a_openai ?? default_settings.top_a_openai;2974 oai_settings.top_a_openai = settings.top_a_openai ?? default_settings.top_a_openai;
@@ -3080,10 +3040,12 @@ function loadOpenAISettings(data, settings) {
3080 oai_settings.names_behavior = character_names_behavior.COMPLETION;3040 oai_settings.names_behavior = character_names_behavior.COMPLETION;
3081 }3041 }
30823042
3043 if (oai_settings.ai21_model.startsWith('j2-')) {
3044 oai_settings.ai21_model = 'jamba-1.5-large';
3045 }
3046
3083 if (settings.wrap_in_quotes !== undefined) oai_settings.wrap_in_quotes = !!settings.wrap_in_quotes;3047 if (settings.wrap_in_quotes !== undefined) oai_settings.wrap_in_quotes = !!settings.wrap_in_quotes;
3084 if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model;3048 if (settings.openai_model !== undefined) oai_settings.openai_model = settings.openai_model;
3085 if (settings.use_ai21_tokenizer !== undefined) { oai_settings.use_ai21_tokenizer = !!settings.use_ai21_tokenizer; oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200; }
3086 if (settings.use_google_tokenizer !== undefined) oai_settings.use_google_tokenizer = !!settings.use_google_tokenizer;
3087 if (settings.claude_use_sysprompt !== undefined) oai_settings.claude_use_sysprompt = !!settings.claude_use_sysprompt;3049 if (settings.claude_use_sysprompt !== undefined) oai_settings.claude_use_sysprompt = !!settings.claude_use_sysprompt;
3088 if (settings.use_makersuite_sysprompt !== undefined) oai_settings.use_makersuite_sysprompt = !!settings.use_makersuite_sysprompt;3050 if (settings.use_makersuite_sysprompt !== undefined) oai_settings.use_makersuite_sysprompt = !!settings.use_makersuite_sysprompt;
3089 if (settings.use_alt_scale !== undefined) { oai_settings.use_alt_scale = !!settings.use_alt_scale; updateScaleForm(); }3051 if (settings.use_alt_scale !== undefined) { oai_settings.use_alt_scale = !!settings.use_alt_scale; updateScaleForm(); }
@@ -3133,8 +3095,6 @@ function loadOpenAISettings(data, settings) {
3133 $('#jailbreak_system').prop('checked', oai_settings.jailbreak_system);3095 $('#jailbreak_system').prop('checked', oai_settings.jailbreak_system);
3134 $('#openai_show_external_models').prop('checked', oai_settings.show_external_models);3096 $('#openai_show_external_models').prop('checked', oai_settings.show_external_models);
3135 $('#openai_external_category').toggle(oai_settings.show_external_models);3097 $('#openai_external_category').toggle(oai_settings.show_external_models);
3136 $('#use_ai21_tokenizer').prop('checked', oai_settings.use_ai21_tokenizer);
3137 $('#use_google_tokenizer').prop('checked', oai_settings.use_google_tokenizer);
3138 $('#claude_use_sysprompt').prop('checked', oai_settings.claude_use_sysprompt);3098 $('#claude_use_sysprompt').prop('checked', oai_settings.claude_use_sysprompt);
3139 $('#use_makersuite_sysprompt').prop('checked', oai_settings.use_makersuite_sysprompt);3099 $('#use_makersuite_sysprompt').prop('checked', oai_settings.use_makersuite_sysprompt);
3140 $('#scale-alt').prop('checked', oai_settings.use_alt_scale);3100 $('#scale-alt').prop('checked', oai_settings.use_alt_scale);
@@ -3170,9 +3130,6 @@ function loadOpenAISettings(data, settings) {
3170 $('#pres_pen_openai').val(oai_settings.pres_pen_openai);3130 $('#pres_pen_openai').val(oai_settings.pres_pen_openai);
3171 $('#pres_pen_counter_openai').val(Number(oai_settings.pres_pen_openai).toFixed(2));3131 $('#pres_pen_counter_openai').val(Number(oai_settings.pres_pen_openai).toFixed(2));
31723132
3173 $('#count_pen').val(oai_settings.count_pen);
3174 $('#count_pen_counter').val(Number(oai_settings.count_pen).toFixed(2));
3175
3176 $('#top_p_openai').val(oai_settings.top_p_openai);3133 $('#top_p_openai').val(oai_settings.top_p_openai);
3177 $('#top_p_counter_openai').val(Number(oai_settings.top_p_openai).toFixed(2));3134 $('#top_p_counter_openai').val(Number(oai_settings.top_p_openai).toFixed(2));
31783135
@@ -3392,7 +3349,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
3392 temperature: settings.temp_openai,3349 temperature: settings.temp_openai,
3393 frequency_penalty: settings.freq_pen_openai,3350 frequency_penalty: settings.freq_pen_openai,
3394 presence_penalty: settings.pres_pen_openai,3351 presence_penalty: settings.pres_pen_openai,
3395 count_penalty: settings.count_pen,
3396 top_p: settings.top_p_openai,3352 top_p: settings.top_p_openai,
3397 top_k: settings.top_k_openai,3353 top_k: settings.top_k_openai,
3398 top_a: settings.top_a_openai,3354 top_a: settings.top_a_openai,
@@ -3427,8 +3383,6 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
3427 assistant_prefill: settings.assistant_prefill,3383 assistant_prefill: settings.assistant_prefill,
3428 assistant_impersonation: settings.assistant_impersonation,3384 assistant_impersonation: settings.assistant_impersonation,
3429 human_sysprompt_message: settings.human_sysprompt_message,3385 human_sysprompt_message: settings.human_sysprompt_message,
3430 use_ai21_tokenizer: settings.use_ai21_tokenizer,
3431 use_google_tokenizer: settings.use_google_tokenizer,
3432 claude_use_sysprompt: settings.claude_use_sysprompt,3386 claude_use_sysprompt: settings.claude_use_sysprompt,
3433 use_makersuite_sysprompt: settings.use_makersuite_sysprompt,3387 use_makersuite_sysprompt: settings.use_makersuite_sysprompt,
3434 use_alt_scale: settings.use_alt_scale,3388 use_alt_scale: settings.use_alt_scale,
@@ -3799,7 +3753,6 @@ function onSettingsPresetChange() {
3799 temperature: ['#temp_openai', 'temp_openai', false],3753 temperature: ['#temp_openai', 'temp_openai', false],
3800 frequency_penalty: ['#freq_pen_openai', 'freq_pen_openai', false],3754 frequency_penalty: ['#freq_pen_openai', 'freq_pen_openai', false],
3801 presence_penalty: ['#pres_pen_openai', 'pres_pen_openai', false],3755 presence_penalty: ['#pres_pen_openai', 'pres_pen_openai', false],
3802 count_penalty: ['#count_pen', 'count_pen', false],
3803 top_p: ['#top_p_openai', 'top_p_openai', false],3756 top_p: ['#top_p_openai', 'top_p_openai', false],
3804 top_k: ['#top_k_openai', 'top_k_openai', false],3757 top_k: ['#top_k_openai', 'top_k_openai', false],
3805 top_a: ['#top_a_openai', 'top_a_openai', false],3758 top_a: ['#top_a_openai', 'top_a_openai', false],
@@ -3856,8 +3809,6 @@ function onSettingsPresetChange() {
3856 assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false],3809 assistant_prefill: ['#claude_assistant_prefill', 'assistant_prefill', false],
3857 assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false],3810 assistant_impersonation: ['#claude_assistant_impersonation', 'assistant_impersonation', false],
3858 human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false],3811 human_sysprompt_message: ['#claude_human_sysprompt_textarea', 'human_sysprompt_message', false],
3859 use_ai21_tokenizer: ['#use_ai21_tokenizer', 'use_ai21_tokenizer', true],
3860 use_google_tokenizer: ['#use_google_tokenizer', 'use_google_tokenizer', true],
3861 claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true],3812 claude_use_sysprompt: ['#claude_use_sysprompt', 'claude_use_sysprompt', true],
3862 use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true],3813 use_makersuite_sysprompt: ['#use_makersuite_sysprompt', 'use_makersuite_sysprompt', true],
3863 use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true],3814 use_alt_scale: ['#use_alt_scale', 'use_alt_scale', true],
@@ -4028,6 +3979,11 @@ async function onModelChange() {
4028 }3979 }
40293980
4030 if ($(this).is('#model_ai21_select')) {3981 if ($(this).is('#model_ai21_select')) {
3982 if (value === '' || value.startsWith('j2-')) {
3983 value = 'jamba-1.5-large';
3984 $('#model_ai21_select').val(value);
3985 }
3986
4031 console.log('AI21 model changed to', value);3987 console.log('AI21 model changed to', value);
4032 oai_settings.ai21_model = value;3988 oai_settings.ai21_model = value;
4033 }3989 }
@@ -4305,33 +4261,13 @@ async function onModelChange() {
4305 if (oai_settings.chat_completion_source == chat_completion_sources.AI21) {4261 if (oai_settings.chat_completion_source == chat_completion_sources.AI21) {
4306 if (oai_settings.max_context_unlocked) {4262 if (oai_settings.max_context_unlocked) {
4307 $('#openai_max_context').attr('max', unlocked_max);4263 $('#openai_max_context').attr('max', unlocked_max);
4308 } else {4264 } else if (oai_settings.ai21_model.includes('jamba-1.5') || oai_settings.ai21_model.includes('jamba-instruct')) {
4309 $('#openai_max_context').attr('max', ai21_max);4265 $('#openai_max_context').attr('max', max_256k);
4310 }4266 }
43114267
4312 oai_settings.openai_max_context = Math.min(oai_settings.openai_max_context, Number($('#openai_max_context').attr('max')));4268 oai_settings.openai_max_context = Math.min(Number($('#openai_max_context').attr('max')), oai_settings.openai_max_context);
4313 $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');4269 $('#openai_max_context').val(oai_settings.openai_max_context).trigger('input');
43144270 $('#temp_openai').attr('max', oai_max_temp).val(oai_settings.temp_openai).trigger('input');
4315 oai_settings.temp_openai = Math.min(claude_max_temp, oai_settings.temp_openai);
4316 $('#temp_openai').attr('max', claude_max_temp).val(oai_settings.temp_openai).trigger('input');
4317
4318 oai_settings.freq_pen_openai = Math.min(j2_max_freq, oai_settings.freq_pen_openai < 0 ? 0 : oai_settings.freq_pen_openai);
4319 $('#freq_pen_openai').attr('min', 0).attr('max', j2_max_freq).val(oai_settings.freq_pen_openai).trigger('input');
4320
4321 oai_settings.pres_pen_openai = Math.min(j2_max_pres, oai_settings.pres_pen_openai < 0 ? 0 : oai_settings.pres_pen_openai);
4322 $('#pres_pen_openai').attr('min', 0).attr('max', j2_max_pres).val(oai_settings.pres_pen_openai).trigger('input');
4323
4324 oai_settings.top_k_openai = Math.min(j2_max_topk, oai_settings.top_k_openai);
4325 $('#top_k_openai').attr('max', j2_max_topk).val(oai_settings.top_k_openai).trigger('input');
4326 } else if (oai_settings.chat_completion_source != chat_completion_sources.AI21) {
4327 oai_settings.freq_pen_openai = Math.min(2.0, oai_settings.freq_pen_openai);
4328 $('#freq_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.freq_pen_openai).trigger('input');
4329
4330 oai_settings.pres_pen_openai = Math.min(2.0, oai_settings.pres_pen_openai);
4331 $('#pres_pen_openai').attr('min', -2.0).attr('max', 2.0).val(oai_settings.pres_pen_openai).trigger('input');
4332
4333 oai_settings.top_k_openai = Math.min(200, oai_settings.top_k_openai);
4334 $('#top_k_openai').attr('max', 200).val(oai_settings.top_k_openai).trigger('input');
4335 }4271 }
43364272
4337 if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) {4273 if (oai_settings.chat_completion_source == chat_completion_sources.CUSTOM) {
@@ -4953,12 +4889,6 @@ $(document).ready(async function () {
4953 saveSettingsDebounced();4889 saveSettingsDebounced();
4954 });4890 });
49554891
4956 $('#count_pen').on('input', function () {
4957 oai_settings.count_pen = Number($(this).val());
4958 $('#count_pen_counter').val(Number($(this).val()).toFixed(2));
4959 saveSettingsDebounced();
4960 });
4961
4962 $('#top_p_openai').on('input', function () {4892 $('#top_p_openai').on('input', function () {
4963 oai_settings.top_p_openai = Number($(this).val());4893 oai_settings.top_p_openai = Number($(this).val());
4964 $('#top_p_counter_openai').val(Number($(this).val()).toFixed(2));4894 $('#top_p_counter_openai').val(Number($(this).val()).toFixed(2));
@@ -5017,20 +4947,6 @@ $(document).ready(async function () {
5017 saveSettingsDebounced();4947 saveSettingsDebounced();
5018 });4948 });
50194949
5020 $('#use_ai21_tokenizer').on('change', function () {
5021 oai_settings.use_ai21_tokenizer = !!$('#use_ai21_tokenizer').prop('checked');
5022 oai_settings.use_ai21_tokenizer ? ai21_max = 8191 : ai21_max = 9200;
5023 oai_settings.openai_max_context = Math.min(ai21_max, oai_settings.openai_max_context);
5024 $('#openai_max_context').attr('max', ai21_max).val(oai_settings.openai_max_context).trigger('input');
5025 $('#openai_max_context_counter').attr('max', Number($('#openai_max_context').attr('max')));
5026 saveSettingsDebounced();
5027 });
5028
5029 $('#use_google_tokenizer').on('change', function () {
5030 oai_settings.use_google_tokenizer = !!$('#use_google_tokenizer').prop('checked');
5031 saveSettingsDebounced();
5032 });
5033
5034 $('#claude_use_sysprompt').on('change', function () {4950 $('#claude_use_sysprompt').on('change', function () {
5035 oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked');4951 oai_settings.claude_use_sysprompt = !!$('#claude_use_sysprompt').prop('checked');
5036 $('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt);4952 $('#claude_human_sysprompt_message_block').toggle(oai_settings.claude_use_sysprompt);
public/scripts/tokenizers.js+26 -23
@@ -27,6 +27,7 @@ export const tokenizers = {
27 CLAUDE: 11,27 CLAUDE: 11,
28 LLAMA3: 12,28 LLAMA3: 12,
29 GEMMA: 13,29 GEMMA: 13,
30 JAMBA: 14,
30 BEST_MATCH: 99,31 BEST_MATCH: 99,
31};32};
3233
@@ -36,6 +37,7 @@ export const SENTENCEPIECE_TOKENIZERS = [
36 tokenizers.YI,37 tokenizers.YI,
37 tokenizers.LLAMA3,38 tokenizers.LLAMA3,
38 tokenizers.GEMMA,39 tokenizers.GEMMA,
40 tokenizers.JAMBA,
39 // uncomment when NovelAI releases Kayra and Clio weights, lol41 // uncomment when NovelAI releases Kayra and Clio weights, lol
40 //tokenizers.NERD,42 //tokenizers.NERD,
41 //tokenizers.NERD2,43 //tokenizers.NERD2,
@@ -98,6 +100,11 @@ const TOKENIZER_URLS = {
98 decode: '/api/tokenizers/gemma/decode',100 decode: '/api/tokenizers/gemma/decode',
99 count: '/api/tokenizers/gemma/encode',101 count: '/api/tokenizers/gemma/encode',
100 },102 },
103 [tokenizers.JAMBA]: {
104 encode: '/api/tokenizers/jamba/encode',
105 decode: '/api/tokenizers/jamba/decode',
106 count: '/api/tokenizers/jamba/encode',
107 },
101 [tokenizers.API_TEXTGENERATIONWEBUI]: {108 [tokenizers.API_TEXTGENERATIONWEBUI]: {
102 encode: '/api/tokenizers/remote/textgenerationwebui/encode',109 encode: '/api/tokenizers/remote/textgenerationwebui/encode',
103 count: '/api/tokenizers/remote/textgenerationwebui/encode',110 count: '/api/tokenizers/remote/textgenerationwebui/encode',
@@ -164,7 +171,7 @@ export function getAvailableTokenizers() {
164 tokenizerId: Number(tokenizerOption.value),171 tokenizerId: Number(tokenizerOption.value),
165 tokenizerKey: Object.entries(tokenizers).find(([_, value]) => value === Number(tokenizerOption.value))[0].toLocaleLowerCase(),172 tokenizerKey: Object.entries(tokenizers).find(([_, value]) => value === Number(tokenizerOption.value))[0].toLocaleLowerCase(),
166 tokenizerName: tokenizerOption.text,173 tokenizerName: tokenizerOption.text,
167 }))174 }));
168}175}
169176
170/**177/**
@@ -280,6 +287,12 @@ export function getTokenizerBestMatch(forApi) {
280 if (model.includes('gemma')) {287 if (model.includes('gemma')) {
281 return tokenizers.GEMMA;288 return tokenizers.GEMMA;
282 }289 }
290 if (model.includes('yi')) {
291 return tokenizers.YI;
292 }
293 if (model.includes('jamba')) {
294 return tokenizers.JAMBA;
295 }
283 }296 }
284297
285 return tokenizers.LLAMA;298 return tokenizers.LLAMA;
@@ -497,6 +510,7 @@ export function getTokenizerModel() {
497 const mistralTokenizer = 'mistral';510 const mistralTokenizer = 'mistral';
498 const yiTokenizer = 'yi';511 const yiTokenizer = 'yi';
499 const gemmaTokenizer = 'gemma';512 const gemmaTokenizer = 'gemma';
513 const jambaTokenizer = 'jamba';
500514
501 // Assuming no one would use it for different models.. right?515 // Assuming no one would use it for different models.. right?
502 if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) {516 if (oai_settings.chat_completion_source == chat_completion_sources.SCALE) {
@@ -562,12 +576,19 @@ export function getTokenizerModel() {
562 else if (oai_settings.openrouter_model.includes('GPT-NeoXT')) {576 else if (oai_settings.openrouter_model.includes('GPT-NeoXT')) {
563 return gpt2Tokenizer;577 return gpt2Tokenizer;
564 }578 }
579 else if (oai_settings.openrouter_model.includes('jamba')) {
580 return jambaTokenizer;
581 }
565 }582 }
566583
567 if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) {584 if (oai_settings.chat_completion_source == chat_completion_sources.MAKERSUITE) {
568 return gemmaTokenizer;585 return gemmaTokenizer;
569 }586 }
570587
588 if (oai_settings.chat_completion_source == chat_completion_sources.AI21) {
589 return jambaTokenizer;
590 }
591
571 if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {592 if (oai_settings.chat_completion_source == chat_completion_sources.CLAUDE) {
572 return claudeTokenizer;593 return claudeTokenizer;
573 }594 }
@@ -626,16 +647,7 @@ export function getTokenizerModel() {
626 * @deprecated Use countTokensOpenAIAsync instead.647 * @deprecated Use countTokensOpenAIAsync instead.
627 */648 */
628export function countTokensOpenAI(messages, full = false) {649export function countTokensOpenAI(messages, full = false) {
629 const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer;650 const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
630 const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer;
631 let tokenizerEndpoint = '';
632 if (shouldTokenizeAI21) {
633 tokenizerEndpoint = '/api/tokenizers/ai21/count';
634 } else if (shouldTokenizeGoogle) {
635 tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}&reverse_proxy=${oai_settings.reverse_proxy}&proxy_password=${oai_settings.proxy_password}`;
636 } else {
637 tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
638 }
639 const cacheObject = getTokenCacheObject();651 const cacheObject = getTokenCacheObject();
640652
641 if (!Array.isArray(messages)) {653 if (!Array.isArray(messages)) {
@@ -647,7 +659,7 @@ export function countTokensOpenAI(messages, full = false) {
647 for (const message of messages) {659 for (const message of messages) {
648 const model = getTokenizerModel();660 const model = getTokenizerModel();
649661
650 if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) {662 if (model === 'claude') {
651 full = true;663 full = true;
652 }664 }
653665
@@ -687,16 +699,7 @@ export function countTokensOpenAI(messages, full = false) {
687 * @returns {Promise<number>} Token count.699 * @returns {Promise<number>} Token count.
688 */700 */
689export async function countTokensOpenAIAsync(messages, full = false) {701export async function countTokensOpenAIAsync(messages, full = false) {
690 const shouldTokenizeAI21 = oai_settings.chat_completion_source === chat_completion_sources.AI21 && oai_settings.use_ai21_tokenizer;702 const tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
691 const shouldTokenizeGoogle = oai_settings.chat_completion_source === chat_completion_sources.MAKERSUITE && oai_settings.use_google_tokenizer;
692 let tokenizerEndpoint = '';
693 if (shouldTokenizeAI21) {
694 tokenizerEndpoint = '/api/tokenizers/ai21/count';
695 } else if (shouldTokenizeGoogle) {
696 tokenizerEndpoint = `/api/tokenizers/google/count?model=${getTokenizerModel()}`;
697 } else {
698 tokenizerEndpoint = `/api/tokenizers/openai/count?model=${getTokenizerModel()}`;
699 }
700 const cacheObject = getTokenCacheObject();703 const cacheObject = getTokenCacheObject();
701704
702 if (!Array.isArray(messages)) {705 if (!Array.isArray(messages)) {
@@ -708,7 +711,7 @@ export async function countTokensOpenAIAsync(messages, full = false) {
708 for (const message of messages) {711 for (const message of messages) {
709 const model = getTokenizerModel();712 const model = getTokenizerModel();
710713
711 if (model === 'claude' || shouldTokenizeAI21 || shouldTokenizeGoogle) {714 if (model === 'claude') {
712 full = true;715 full = true;
713 }716 }
714717
src/endpoints/backends/chat-completions.js+35 -50
@@ -5,7 +5,7 @@ const Readable = require('stream').Readable;
5const { jsonParser } = require('../../express-common');5const { jsonParser } = require('../../express-common');
6const { CHAT_COMPLETION_SOURCES, GEMINI_SAFETY, BISON_SAFETY, OPENROUTER_HEADERS } = require('../../constants');6const { CHAT_COMPLETION_SOURCES, GEMINI_SAFETY, BISON_SAFETY, OPENROUTER_HEADERS } = require('../../constants');
7const { forwardFetchResponse, getConfigValue, tryParse, uuidv4, mergeObjectWithYaml, excludeKeysByYaml, color } = require('../../util');7const { forwardFetchResponse, getConfigValue, tryParse, uuidv4, mergeObjectWithYaml, excludeKeysByYaml, color } = require('../../util');
8const { convertClaudeMessages, convertGooglePrompt, convertTextCompletionPrompt, convertCohereMessages, convertMistralMessages, convertCohereTools } = require('../../prompt-converters');8const { convertClaudeMessages, convertGooglePrompt, convertTextCompletionPrompt, convertCohereMessages, convertMistralMessages, convertCohereTools, convertAI21Messages } = require('../../prompt-converters');
99
10const { readSecret, SECRET_KEYS } = require('../secrets');10const { readSecret, SECRET_KEYS } = require('../secrets');
11const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sentencepieceTokenizers, TEXT_COMPLETION_MODELS } = require('../tokenizers');11const { getTokenizerModel, getSentencepiceTokenizer, getTiktokenTokenizer, sentencepieceTokenizers, TEXT_COMPLETION_MODELS } = require('../tokenizers');
@@ -19,6 +19,7 @@ const API_GROQ = 'https://api.groq.com/openai/v1';
19const API_MAKERSUITE = 'https://generativelanguage.googleapis.com';19const API_MAKERSUITE = 'https://generativelanguage.googleapis.com';
20const API_01AI = 'https://api.01.ai/v1';20const API_01AI = 'https://api.01.ai/v1';
21const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1';21const API_BLOCKENTROPY = 'https://api.blockentropy.ai/v1';
22const API_AI21 = 'https://api.ai21.com/studio/v1';
2223
23/**24/**
24 * Applies a post-processing step to the generated messages.25 * Applies a post-processing step to the generated messages.
@@ -413,6 +414,16 @@ async function sendAI21Request(request, response) {
413 request.socket.on('close', function () {414 request.socket.on('close', function () {
414 controller.abort();415 controller.abort();
415 });416 });
417 const convertedPrompt = convertAI21Messages(request.body.messages, request.body.char_name, request.body.user_name);
418 const body = {
419 messages: convertedPrompt,
420 model: request.body.model,
421 max_tokens: request.body.max_tokens,
422 temperature: request.body.temperature,
423 top_p: request.body.top_p,
424 stop: request.body.stop,
425 stream: request.body.stream,
426 };
416 const options = {427 const options = {
417 method: 'POST',428 method: 'POST',
418 headers: {429 headers: {
@@ -420,59 +431,33 @@ async function sendAI21Request(request, response) {
420 'content-type': 'application/json',431 'content-type': 'application/json',
421 Authorization: `Bearer ${readSecret(request.user.directories, SECRET_KEYS.AI21)}`,432 Authorization: `Bearer ${readSecret(request.user.directories, SECRET_KEYS.AI21)}`,
422 },433 },
423 body: JSON.stringify({434 body: JSON.stringify(body),
424 numResults: 1,
425 maxTokens: request.body.max_tokens,
426 minTokens: 0,
427 temperature: request.body.temperature,
428 topP: request.body.top_p,
429 stopSequences: request.body.stop_tokens,
430 topKReturn: request.body.top_k,
431 frequencyPenalty: {
432 scale: request.body.frequency_penalty * 100,
433 applyToWhitespaces: false,
434 applyToPunctuations: false,
435 applyToNumbers: false,
436 applyToStopwords: false,
437 applyToEmojis: false,
438 },
439 presencePenalty: {
440 scale: request.body.presence_penalty,
441 applyToWhitespaces: false,
442 applyToPunctuations: false,
443 applyToNumbers: false,
444 applyToStopwords: false,
445 applyToEmojis: false,
446 },
447 countPenalty: {
448 scale: request.body.count_pen,
449 applyToWhitespaces: false,
450 applyToPunctuations: false,
451 applyToNumbers: false,
452 applyToStopwords: false,
453 applyToEmojis: false,
454 },
455 prompt: request.body.messages,
456 }),
457 signal: controller.signal,435 signal: controller.signal,
458 };436 };
459437
460 fetch(`https://api.ai21.com/studio/v1/${request.body.model}/complete`, options)438 console.log('AI21 request:', body);
461 .then(r => r.json())
462 .then(r => {
463 if (r.completions === undefined) {
464 console.log(r);
465 } else {
466 console.log(r.completions[0].data.text);
467 }
468 const reply = { choices: [{ 'message': { 'content': r.completions?.[0]?.data?.text } }] };
469 return response.send(reply);
470 })
471 .catch(err => {
472 console.error(err);
473 return response.send({ error: true });
474 });
475439
440 try{
441 const generateResponse = await fetch(API_AI21 + '/chat/completions', options);
442 if (request.body.stream) {
443 forwardFetchResponse(generateResponse, response);
444 } else {
445 if (!generateResponse.ok) {
446 console.log(`AI21 API returned error: ${generateResponse.status} ${generateResponse.statusText} ${await generateResponse.text()}`);
447 return response.status(500).send({ error: true });
448 }
449 const generateResponseJson = await generateResponse.json();
450 console.log('AI21 response:', generateResponseJson);
451 return response.send(generateResponseJson);
452 }
453 } catch (error) {
454 console.log('Error communicating with MistralAI API: ', error);
455 if (!response.headersSent) {
456 response.send({ error: true });
457 } else {
458 response.end();
459 }
460 }
476}461}
477462
478/**463/**
src/endpoints/tokenizers.js+27 -47
@@ -144,6 +144,7 @@ const spp_nerd_v2 = new SentencePieceTokenizer('src/tokenizers/nerdstash_v2.mode
144const spp_mistral = new SentencePieceTokenizer('src/tokenizers/mistral.model');144const spp_mistral = new SentencePieceTokenizer('src/tokenizers/mistral.model');
145const spp_yi = new SentencePieceTokenizer('src/tokenizers/yi.model');145const spp_yi = new SentencePieceTokenizer('src/tokenizers/yi.model');
146const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model');146const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model');
147const spp_jamba = new SentencePieceTokenizer('src/tokenizers/jamba.model');
147const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json');148const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json');
148const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json');149const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json');
149150
@@ -154,6 +155,7 @@ const sentencepieceTokenizers = [
154 'mistral',155 'mistral',
155 'yi',156 'yi',
156 'gemma',157 'gemma',
158 'jamba',
157];159];
158160
159/**161/**
@@ -186,6 +188,10 @@ function getSentencepiceTokenizer(model) {
186 return spp_gemma;188 return spp_gemma;
187 }189 }
188190
191 if (model.includes('jamba')) {
192 return spp_jamba;
193 }
194
189 return null;195 return null;
190}196}
191197
@@ -322,6 +328,10 @@ function getTokenizerModel(requestModel) {
322 return 'gemma';328 return 'gemma';
323 }329 }
324330
331 if (requestModel.includes('jamba')) {
332 return 'jamba';
333 }
334
325 // default335 // default
326 return 'gpt-3.5-turbo';336 return 'gpt-3.5-turbo';
327}337}
@@ -537,59 +547,13 @@ function createWebTokenizerDecodingHandler(tokenizer) {
537547
538const router = express.Router();548const router = express.Router();
539549
540router.post('/ai21/count', jsonParser, async function (req, res) {
541 if (!req.body) return res.sendStatus(400);
542 const key = readSecret(req.user.directories, SECRET_KEYS.AI21);
543 const options = {
544 method: 'POST',
545 headers: {
546 accept: 'application/json',
547 'content-type': 'application/json',
548 Authorization: `Bearer ${key}`,
549 },
550 body: JSON.stringify({ text: req.body[0].content }),
551 };
552
553 try {
554 const response = await fetch('https://api.ai21.com/studio/v1/tokenize', options);
555 const data = await response.json();
556 return res.send({ 'token_count': data?.tokens?.length || 0 });
557 } catch (err) {
558 console.error(err);
559 return res.send({ 'token_count': 0 });
560 }
561});
562
563router.post('/google/count', jsonParser, async function (req, res) {
564 if (!req.body) return res.sendStatus(400);
565 const options = {
566 method: 'POST',
567 headers: {
568 accept: 'application/json',
569 'content-type': 'application/json',
570 },
571 body: JSON.stringify({ contents: convertGooglePrompt(req.body, String(req.query.model)).contents }),
572 };
573 try {
574 const reverseProxy = req.query.reverse_proxy?.toString() || '';
575 const proxyPassword = req.query.proxy_password?.toString() || '';
576 const apiKey = reverseProxy ? proxyPassword : readSecret(req.user.directories, SECRET_KEYS.MAKERSUITE);
577 const apiUrl = new URL(reverseProxy || API_MAKERSUITE);
578 const response = await fetch(`${apiUrl.origin}/v1beta/models/${req.query.model}:countTokens?key=${apiKey}`, options);
579 const data = await response.json();
580 return res.send({ 'token_count': data?.totalTokens || 0 });
581 } catch (err) {
582 console.error(err);
583 return res.send({ 'token_count': 0 });
584 }
585});
586
587router.post('/llama/encode', jsonParser, createSentencepieceEncodingHandler(spp_llama));550router.post('/llama/encode', jsonParser, createSentencepieceEncodingHandler(spp_llama));
588router.post('/nerdstash/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd));551router.post('/nerdstash/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd));
589router.post('/nerdstash_v2/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2));552router.post('/nerdstash_v2/encode', jsonParser, createSentencepieceEncodingHandler(spp_nerd_v2));
590router.post('/mistral/encode', jsonParser, createSentencepieceEncodingHandler(spp_mistral));553router.post('/mistral/encode', jsonParser, createSentencepieceEncodingHandler(spp_mistral));
591router.post('/yi/encode', jsonParser, createSentencepieceEncodingHandler(spp_yi));554router.post('/yi/encode', jsonParser, createSentencepieceEncodingHandler(spp_yi));
592router.post('/gemma/encode', jsonParser, createSentencepieceEncodingHandler(spp_gemma));555router.post('/gemma/encode', jsonParser, createSentencepieceEncodingHandler(spp_gemma));
556router.post('/jamba/encode', jsonParser, createSentencepieceEncodingHandler(spp_jamba));
593router.post('/gpt2/encode', jsonParser, createTiktokenEncodingHandler('gpt2'));557router.post('/gpt2/encode', jsonParser, createTiktokenEncodingHandler('gpt2'));
594router.post('/claude/encode', jsonParser, createWebTokenizerEncodingHandler(claude_tokenizer));558router.post('/claude/encode', jsonParser, createWebTokenizerEncodingHandler(claude_tokenizer));
595router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llama3_tokenizer));559router.post('/llama3/encode', jsonParser, createWebTokenizerEncodingHandler(llama3_tokenizer));
@@ -599,6 +563,7 @@ router.post('/nerdstash_v2/decode', jsonParser, createSentencepieceDecodingHandl
599router.post('/mistral/decode', jsonParser, createSentencepieceDecodingHandler(spp_mistral));563router.post('/mistral/decode', jsonParser, createSentencepieceDecodingHandler(spp_mistral));
600router.post('/yi/decode', jsonParser, createSentencepieceDecodingHandler(spp_yi));564router.post('/yi/decode', jsonParser, createSentencepieceDecodingHandler(spp_yi));
601router.post('/gemma/decode', jsonParser, createSentencepieceDecodingHandler(spp_gemma));565router.post('/gemma/decode', jsonParser, createSentencepieceDecodingHandler(spp_gemma));
566router.post('/jamba/decode', jsonParser, createSentencepieceDecodingHandler(spp_jamba));
602router.post('/gpt2/decode', jsonParser, createTiktokenDecodingHandler('gpt2'));567router.post('/gpt2/decode', jsonParser, createTiktokenDecodingHandler('gpt2'));
603router.post('/claude/decode', jsonParser, createWebTokenizerDecodingHandler(claude_tokenizer));568router.post('/claude/decode', jsonParser, createWebTokenizerDecodingHandler(claude_tokenizer));
604router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llama3_tokenizer));569router.post('/llama3/decode', jsonParser, createWebTokenizerDecodingHandler(llama3_tokenizer));
@@ -637,6 +602,11 @@ router.post('/openai/encode', jsonParser, async function (req, res) {
637 return handler(req, res);602 return handler(req, res);
638 }603 }
639604
605 if (queryModel.includes('jamba')) {
606 const handler = createSentencepieceEncodingHandler(spp_jamba);
607 return handler(req, res);
608 }
609
640 const model = getTokenizerModel(queryModel);610 const model = getTokenizerModel(queryModel);
641 const handler = createTiktokenEncodingHandler(model);611 const handler = createTiktokenEncodingHandler(model);
642 return handler(req, res);612 return handler(req, res);
@@ -680,6 +650,11 @@ router.post('/openai/decode', jsonParser, async function (req, res) {
680 return handler(req, res);650 return handler(req, res);
681 }651 }
682652
653 if (queryModel.includes('jamba')) {
654 const handler = createSentencepieceDecodingHandler(spp_jamba);
655 return handler(req, res);
656 }
657
683 const model = getTokenizerModel(queryModel);658 const model = getTokenizerModel(queryModel);
684 const handler = createTiktokenDecodingHandler(model);659 const handler = createTiktokenDecodingHandler(model);
685 return handler(req, res);660 return handler(req, res);
@@ -731,6 +706,11 @@ router.post('/openai/count', jsonParser, async function (req, res) {
731 return res.send({ 'token_count': num_tokens });706 return res.send({ 'token_count': num_tokens });
732 }707 }
733708
709 if (model === 'jamba') {
710 num_tokens = await countSentencepieceArrayTokens(spp_jamba, req.body);
711 return res.send({ 'token_count': num_tokens });
712 }
713
734 const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;714 const tokensPerName = queryModel.includes('gpt-3.5-turbo-0301') ? -1 : 1;
735 const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3;715 const tokensPerMessage = queryModel.includes('gpt-3.5-turbo-0301') ? 4 : 3;
736 const tokensPadding = 3;716 const tokensPadding = 3;
src/prompt-converters.js+73 -0
@@ -368,6 +368,78 @@ function convertGooglePrompt(messages, model, useSysPrompt = false, charName = '
368}368}
369369
370/**370/**
371 * Convert AI21 prompt. Classic: system message squash, user/assistant message merge.
372 * @param {object[]} messages Array of messages
373 * @param {string} charName Character name
374 * @param {string} userName User name
375 */
376function convertAI21Messages(messages, charName = '', userName = '') {
377 if (!Array.isArray(messages)) {
378 return [];
379 }
380
381 // Collect all the system messages up until the first instance of a non-system message, and then remove them from the messages array.
382 let i = 0, systemPrompt = '';
383
384 for (i = 0; i < messages.length; i++) {
385 if (messages[i].role !== 'system') {
386 break;
387 }
388 // Append example names if not already done by the frontend (e.g. for group chats).
389 if (userName && messages[i].name === 'example_user') {
390 if (!messages[i].content.startsWith(`${userName}: `)) {
391 messages[i].content = `${userName}: ${messages[i].content}`;
392 }
393 }
394 if (charName && messages[i].name === 'example_assistant') {
395 if (!messages[i].content.startsWith(`${charName}: `)) {
396 messages[i].content = `${charName}: ${messages[i].content}`;
397 }
398 }
399 systemPrompt += `${messages[i].content}\n\n`;
400 }
401
402 messages.splice(0, i);
403
404 // Prevent erroring out if the messages array is empty.
405 if (messages.length === 0) {
406 messages.unshift({
407 role: 'user',
408 content: '[Start a new chat]',
409 });
410 }
411
412 if (systemPrompt) {
413 messages.unshift({
414 role: 'system',
415 content: systemPrompt.trim(),
416 });
417 }
418
419 // Doesn't support completion names, so prepend if not already done by the frontend (e.g. for group chats).
420 messages.forEach(msg => {
421 if ('name' in msg) {
422 if (msg.role !== 'system' && !msg.content.startsWith(`${msg.name}: `)) {
423 msg.content = `${msg.name}: ${msg.content}`;
424 }
425 delete msg.name;
426 }
427 });
428
429 // Since the messaging endpoint only supports alternating turns, we have to merge messages with the same role if they follow each other
430 let mergedMessages = [];
431 messages.forEach((message) => {
432 if (mergedMessages.length > 0 && mergedMessages[mergedMessages.length - 1].role === message.role) {
433 mergedMessages[mergedMessages.length - 1].content += '\n\n' + message.content;
434 } else {
435 mergedMessages.push(message);
436 }
437 });
438
439 return mergedMessages;
440}
441
442/**
371 * Convert a prompt from the ChatML objects to the format used by MistralAI.443 * Convert a prompt from the ChatML objects to the format used by MistralAI.
372 * @param {object[]} messages Array of messages444 * @param {object[]} messages Array of messages
373 * @param {string} charName Character name445 * @param {string} charName Character name
@@ -520,4 +592,5 @@ module.exports = {
520 convertCohereMessages,592 convertCohereMessages,
521 convertMistralMessages,593 convertMistralMessages,
522 convertCohereTools,594 convertCohereTools,
595 convertAI21Messages,
523};596};
src/tokenizers/jamba.model+0 -0

Binary file