Added command-a-03-2025 and command-a tokenizer
| @@ -3333,6 +3333,7 @@ | ||
| 3333 | 3333 | <option value="command-r-08-2024">command-r-08-2024</option> |
| 3334 | 3334 | <option value="command-r-plus-08-2024">command-r-plus-08-2024</option> |
| 3335 | 3335 | <option value="command-r7b-12-2024">command-r7b-12-2024</option> |
| 3336 | + <option value="command-a-03-2025">command-a-03-2025</option> | |
| 3336 | 3337 | </optgroup> |
| 3337 | 3338 | <optgroup label="Nightly"> |
| 3338 | 3339 | <option value="command-light-nightly">command-light-nightly</option> |
| @@ -4448,6 +4448,9 @@ async function onModelChange() { | ||
| 4448 | 4448 | else if (oai_settings.cohere_model.includes('command-r') || ['c4ai-aya-23', 'c4ai-aya-expanse-32b', 'command-nightly'].includes(oai_settings.cohere_model)) { |
| 4449 | 4449 | $('#openai_max_context').attr('max', max_128k); |
| 4450 | 4450 | } |
| 4451 | + else if (['command-a-03-2025'].includes(oai_settings.cohere_model)) { | |
| 4452 | + $('#openai_max_context').attr('max', max_256k); | |
| 4453 | + } | |
| 4451 | 4454 | else if (['c4ai-aya-23-8b', 'c4ai-aya-expanse-8b'].includes(oai_settings.cohere_model)) { |
| 4452 | 4455 | $('#openai_max_context').attr('max', max_8k); |
| 4453 | 4456 | } |
| @@ -32,6 +32,7 @@ export const tokenizers = { | ||
| 32 | 32 | COMMAND_R: 16, |
| 33 | 33 | NEMO: 17, |
| 34 | 34 | DEEPSEEK: 18, |
| 35 | + COMMAND_A: 19, | |
| 35 | 36 | BEST_MATCH: 99, |
| 36 | 37 | }; |
| 37 | 38 | |
| @@ -45,6 +46,7 @@ export const ENCODE_TOKENIZERS = [ | ||
| 45 | 46 | tokenizers.JAMBA, |
| 46 | 47 | tokenizers.QWEN2, |
| 47 | 48 | tokenizers.COMMAND_R, |
| 49 | + tokenizers.COMMAND_A, | |
| 48 | 50 | tokenizers.NEMO, |
| 49 | 51 | tokenizers.DEEPSEEK, |
| 50 | 52 | // uncomment when NovelAI releases Kayra and Clio weights, lol |
| @@ -129,6 +131,11 @@ const TOKENIZER_URLS = { | ||
| 129 | 131 | decode: '/api/tokenizers/command-r/decode', |
| 130 | 132 | count: '/api/tokenizers/command-r/encode', |
| 131 | 133 | }, |
| 134 | + [tokenizers.COMMAND_A]: { | |
| 135 | + encode: '/api/tokenizers/command-a/encode', | |
| 136 | + decode: '/api/tokenizers/command-a/decode', | |
| 137 | + count: '/api/tokenizers/command-a/encode', | |
| 138 | + }, | |
| 132 | 139 | [tokenizers.NEMO]: { |
| 133 | 140 | encode: '/api/tokenizers/nemo/encode', |
| 134 | 141 | decode: '/api/tokenizers/nemo/decode', |
| @@ -340,6 +347,9 @@ export function getTokenizerBestMatch(forApi) { | ||
| 340 | 347 | if (model.includes('command-r')) { |
| 341 | 348 | return tokenizers.COMMAND_R; |
| 342 | 349 | } |
| 350 | + if (model.includes('command-a')) { | |
| 351 | + return tokenizers.COMMAND_A; | |
| 352 | + } | |
| 343 | 353 | if (model.includes('qwen2')) { |
| 344 | 354 | return tokenizers.QWEN2; |
| 345 | 355 | } |
| @@ -572,6 +582,7 @@ export function getTokenizerModel() { | ||
| 572 | 582 | const jambaTokenizer = 'jamba'; |
| 573 | 583 | const qwen2Tokenizer = 'qwen2'; |
| 574 | 584 | const commandRTokenizer = 'command-r'; |
| 585 | + const commandATokenizer = 'command-a'; | |
| 575 | 586 | const nemoTokenizer = 'nemo'; |
| 576 | 587 | const deepseekTokenizer = 'deepseek'; |
| 577 | 588 | |
| @@ -626,6 +637,9 @@ export function getTokenizerModel() { | ||
| 626 | 637 | return qwen2Tokenizer; |
| 627 | 638 | } |
| 628 | 639 | else if (model?.architecture?.tokenizer === 'Cohere') { |
| 640 | + if (oai_settings.openrouter_model.includes('command-a')) { | |
| 641 | + return commandATokenizer; | |
| 642 | + } | |
| 629 | 643 | return commandRTokenizer; |
| 630 | 644 | } |
| 631 | 645 | else if (oai_settings.openrouter_model.includes('gpt-4o')) { |
| @@ -652,6 +666,9 @@ export function getTokenizerModel() { | ||
| 652 | 666 | } |
| 653 | 667 | |
| 654 | 668 | if (oai_settings.chat_completion_source == chat_completion_sources.COHERE) { |
| 669 | + if (oai_settings.cohere_model.includes('command-a')) { | |
| 670 | + return commandATokenizer; | |
| 671 | + } | |
| 655 | 672 | return commandRTokenizer; |
| 656 | 673 | } |
| 657 | 674 | |
| @@ -222,7 +222,8 @@ const spp_gemma = new SentencePieceTokenizer('src/tokenizers/gemma.model'); | ||
| 222 | 222 | const spp_jamba = new SentencePieceTokenizer('src/tokenizers/jamba.model'); |
| 223 | 223 | const claude_tokenizer = new WebTokenizer('src/tokenizers/claude.json'); |
| 224 | 224 | const llama3_tokenizer = new WebTokenizer('src/tokenizers/llama3.json'); |
| 225 | 225 | const commandTokenizercommandRTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/command-r.json', 'src/tokenizers/llama3.json'); |
| 226 | +const commandATokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/command-a.json', 'src/tokenizers/llama3.json'); | |
| 226 | 227 | const qwen2Tokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/qwen2.json', 'src/tokenizers/llama3.json'); |
| 227 | 228 | const nemoTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/nemo.json', 'src/tokenizers/llama3.json'); |
| 228 | 229 | const deepseekTokenizer = new WebTokenizer('https://github.com/SillyTavern/SillyTavern-Tokenizers/raw/main/deepseek.json', 'src/tokenizers/llama3.json'); |
| @@ -241,6 +242,7 @@ export const webTokenizers = [ | ||
| 241 | 242 | 'claude', |
| 242 | 243 | 'llama3', |
| 243 | 244 | 'command-r', |
| 245 | + 'command-a', | |
| 244 | 246 | 'qwen2', |
| 245 | 247 | 'nemo', |
| 246 | 248 | 'deepseek', |
| @@ -298,7 +300,11 @@ export function getWebTokenizer(model) { | ||
| 298 | 300 | } |
| 299 | 301 | |
| 300 | 302 | if (model.includes('command-r')) { |
| 301 | 303 | return commandTokenizercommandRTokenizer; |
| 304 | + } | |
| 305 | + | |
| 306 | + if (model.includes('command-a')) { | |
| 307 | + return commandATokenizer; | |
| 302 | 308 | } |
| 303 | 309 | |
| 304 | 310 | if (model.includes('qwen2')) { |
| @@ -469,6 +475,10 @@ export function getTokenizerModel(requestModel) { | ||
| 469 | 475 | return 'command-r'; |
| 470 | 476 | } |
| 471 | 477 | |
| 478 | + if (requestModel.includes('command-a')) { | |
| 479 | + return 'command-a'; | |
| 480 | + } | |
| 481 | + | |
| 472 | 482 | if (requestModel.includes('nemo')) { |
| 473 | 483 | return 'nemo'; |
| 474 | 484 | } |
| @@ -699,7 +709,8 @@ router.post('/gpt2/encode', createTiktokenEncodingHandler('gpt2')); | ||
| 699 | 709 | router.post('/claude/encode', createWebTokenizerEncodingHandler(claude_tokenizer)); |
| 700 | 710 | router.post('/llama3/encode', createWebTokenizerEncodingHandler(llama3_tokenizer)); |
| 701 | 711 | router.post('/qwen2/encode', createWebTokenizerEncodingHandler(qwen2Tokenizer)); |
| 702 | 712 | router.post('/command-r/encode', createWebTokenizerEncodingHandler(commandTokenizercommandRTokenizer)); |
| 713 | +router.post('/command-a/encode', createWebTokenizerEncodingHandler(commandATokenizer)); | |
| 703 | 714 | router.post('/nemo/encode', createWebTokenizerEncodingHandler(nemoTokenizer)); |
| 704 | 715 | router.post('/deepseek/encode', createWebTokenizerEncodingHandler(deepseekTokenizer)); |
| 705 | 716 | router.post('/llama/decode', createSentencepieceDecodingHandler(spp_llama)); |
| @@ -713,7 +724,8 @@ router.post('/gpt2/decode', createTiktokenDecodingHandler('gpt2')); | ||
| 713 | 724 | router.post('/claude/decode', createWebTokenizerDecodingHandler(claude_tokenizer)); |
| 714 | 725 | router.post('/llama3/decode', createWebTokenizerDecodingHandler(llama3_tokenizer)); |
| 715 | 726 | router.post('/qwen2/decode', createWebTokenizerDecodingHandler(qwen2Tokenizer)); |
| 716 | 727 | router.post('/command-r/decode', createWebTokenizerDecodingHandler(commandTokenizercommandRTokenizer)); |
| 728 | +router.post('/command-a/decode', createWebTokenizerDecodingHandler(commandATokenizer)); | |
| 717 | 729 | router.post('/nemo/decode', createWebTokenizerDecodingHandler(nemoTokenizer)); |
| 718 | 730 | router.post('/deepseek/decode', createWebTokenizerDecodingHandler(deepseekTokenizer)); |
| 719 | 731 | |
| @@ -762,7 +774,12 @@ router.post('/openai/encode', async function (req, res) { | ||
| 762 | 774 | } |
| 763 | 775 | |
| 764 | 776 | if (queryModel.includes('command-r')) { |
| 765 | 777 | const handler = createWebTokenizerEncodingHandler(commandTokenizercommandRTokenizer); |
| 778 | + return handler(req, res); | |
| 779 | + } | |
| 780 | + | |
| 781 | + if (queryModel.includes('command-a')) { | |
| 782 | + const handler = createWebTokenizerEncodingHandler(commandATokenizer); | |
| 766 | 783 | return handler(req, res); |
| 767 | 784 | } |
| 768 | 785 | |
| @@ -830,7 +847,12 @@ router.post('/openai/decode', async function (req, res) { | ||
| 830 | 847 | } |
| 831 | 848 | |
| 832 | 849 | if (queryModel.includes('command-r')) { |
| 833 | 850 | const handler = createWebTokenizerDecodingHandler(commandTokenizercommandRTokenizer); |
| 851 | + return handler(req, res); | |
| 852 | + } | |
| 853 | + | |
| 854 | + if (queryModel.includes('command-a')) { | |
| 855 | + const handler = createWebTokenizerDecodingHandler(commandATokenizer); | |
| 834 | 856 | return handler(req, res); |
| 835 | 857 | } |
| 836 | 858 | |
| @@ -908,12 +930,19 @@ router.post('/openai/count', async function (req, res) { | ||
| 908 | 930 | } |
| 909 | 931 | |
| 910 | 932 | if (model === 'command-r') { |
| 911 | 933 | const instance = await commandTokenizercommandRTokenizer.get(); |
| 912 | 934 | if (!instance) throw new Error('Failed to load the Command-R tokenizer'); |
| 913 | 935 | num_tokens = countWebTokenizerTokens(instance, req.body); |
| 914 | 936 | return res.send({ 'token_count': num_tokens }); |
| 915 | 937 | } |
| 916 | 938 | |
| 939 | + if (model === 'command-a') { | |
| 940 | + const instance = await commandATokenizer.get(); | |
| 941 | + if (!instance) throw new Error('Failed to load the Command-A tokenizer'); | |
| 942 | + num_tokens = countWebTokenizerTokens(instance, req.body); | |
| 943 | + return res.send({ 'token_count': num_tokens }); | |
| 944 | + } | |
| 945 | + | |
| 917 | 946 | if (model === 'nemo') { |
| 918 | 947 | const instance = await nemoTokenizer.get(); |
| 919 | 948 | if (!instance) throw new Error('Failed to load the Nemo tokenizer'); |