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