Closed staviq closed 1 year ago
Hmmm...
Reading tokenizer code, it appears that characters are merged upwards into matching tokens untill no neighbouring tokens can be merged into a known token
So if there is any token, which cannot be split in two, and still represented by known tokens, tokenizer will newer reach that point
Edit: I added a quick test in llm_tokenizer_spm.tokenize
, to loop over the entire vocab at runtime, and find all token which cannot be split into two shorter valid tokens.
And would you look at that, <|im_start|>
<|im_end|>
weirdness is there, and not much else:
#### Orphaned token: '<unk>': '0'
#### Orphaned token: '<s>': '1'
#### Orphaned token: '</s>': '2'
#### Orphaned token: '<0x00>': '3'
#### Orphaned token: '<0x01>': '4'
#### Orphaned token: '<0x02>': '5'
#### Orphaned token: '<0x03>': '6'
#### Orphaned token: '<0x04>': '7'
#### Orphaned token: '<0x05>': '8'
#### Orphaned token: '<0x06>': '9'
#### Orphaned token: '<0x07>': '10'
#### Orphaned token: '<0x08>': '11'
#### Orphaned token: '<0x09>': '12'
#### Orphaned token: '<0x0A>': '13'
#### Orphaned token: '<0x0B>': '14'
#### Orphaned token: '<0x0C>': '15'
#### Orphaned token: '<0x0D>': '16'
#### Orphaned token: '<0x0E>': '17'
#### Orphaned token: '<0x0F>': '18'
#### Orphaned token: '<0x10>': '19'
#### Orphaned token: '<0x11>': '20'
#### Orphaned token: '<0x12>': '21'
#### Orphaned token: '<0x13>': '22'
#### Orphaned token: '<0x14>': '23'
#### Orphaned token: '<0x15>': '24'
#### Orphaned token: '<0x16>': '25'
#### Orphaned token: '<0x17>': '26'
#### Orphaned token: '<0x18>': '27'
#### Orphaned token: '<0x19>': '28'
#### Orphaned token: '<0x1A>': '29'
#### Orphaned token: '<0x1B>': '30'
#### Orphaned token: '<0x1C>': '31'
#### Orphaned token: '<0x1D>': '32'
#### Orphaned token: '<0x1E>': '33'
#### Orphaned token: '<0x1F>': '34'
#### Orphaned token: '<0x20>': '35'
#### Orphaned token: '<0x21>': '36'
#### Orphaned token: '<0x22>': '37'
#### Orphaned token: '<0x23>': '38'
#### Orphaned token: '<0x24>': '39'
#### Orphaned token: '<0x25>': '40'
#### Orphaned token: '<0x26>': '41'
#### Orphaned token: '<0x27>': '42'
#### Orphaned token: '<0x28>': '43'
#### Orphaned token: '<0x29>': '44'
#### Orphaned token: '<0x2A>': '45'
#### Orphaned token: '<0x2B>': '46'
#### Orphaned token: '<0x2C>': '47'
#### Orphaned token: '<0x2D>': '48'
#### Orphaned token: '<0x2E>': '49'
#### Orphaned token: '<0x2F>': '50'
#### Orphaned token: '<0x30>': '51'
#### Orphaned token: '<0x31>': '52'
#### Orphaned token: '<0x32>': '53'
#### Orphaned token: '<0x33>': '54'
#### Orphaned token: '<0x34>': '55'
#### Orphaned token: '<0x35>': '56'
#### Orphaned token: '<0x36>': '57'
#### Orphaned token: '<0x37>': '58'
#### Orphaned token: '<0x38>': '59'
#### Orphaned token: '<0x39>': '60'
#### Orphaned token: '<0x3A>': '61'
#### Orphaned token: '<0x3B>': '62'
#### Orphaned token: '<0x3C>': '63'
#### Orphaned token: '<0x3D>': '64'
#### Orphaned token: '<0x3E>': '65'
#### Orphaned token: '<0x3F>': '66'
#### Orphaned token: '<0x40>': '67'
#### Orphaned token: '<0x41>': '68'
#### Orphaned token: '<0x42>': '69'
#### Orphaned token: '<0x43>': '70'
#### Orphaned token: '<0x44>': '71'
#### Orphaned token: '<0x45>': '72'
#### Orphaned token: '<0x46>': '73'
#### Orphaned token: '<0x47>': '74'
#### Orphaned token: '<0x48>': '75'
#### Orphaned token: '<0x49>': '76'
#### Orphaned token: '<0x4A>': '77'
#### Orphaned token: '<0x4B>': '78'
#### Orphaned token: '<0x4C>': '79'
#### Orphaned token: '<0x4D>': '80'
#### Orphaned token: '<0x4E>': '81'
#### Orphaned token: '<0x4F>': '82'
#### Orphaned token: '<0x50>': '83'
#### Orphaned token: '<0x51>': '84'
#### Orphaned token: '<0x52>': '85'
#### Orphaned token: '<0x53>': '86'
#### Orphaned token: '<0x54>': '87'
#### Orphaned token: '<0x55>': '88'
#### Orphaned token: '<0x56>': '89'
#### Orphaned token: '<0x57>': '90'
#### Orphaned token: '<0x58>': '91'
#### Orphaned token: '<0x59>': '92'
#### Orphaned token: '<0x5A>': '93'
#### Orphaned token: '<0x5B>': '94'
#### Orphaned token: '<0x5C>': '95'
#### Orphaned token: '<0x5D>': '96'
#### Orphaned token: '<0x5E>': '97'
#### Orphaned token: '<0x5F>': '98'
#### Orphaned token: '<0x60>': '99'
#### Orphaned token: '<0x61>': '100'
#### Orphaned token: '<0x62>': '101'
#### Orphaned token: '<0x63>': '102'
#### Orphaned token: '<0x64>': '103'
#### Orphaned token: '<0x65>': '104'
#### Orphaned token: '<0x66>': '105'
#### Orphaned token: '<0x67>': '106'
#### Orphaned token: '<0x68>': '107'
#### Orphaned token: '<0x69>': '108'
#### Orphaned token: '<0x6A>': '109'
#### Orphaned token: '<0x6B>': '110'
#### Orphaned token: '<0x6C>': '111'
#### Orphaned token: '<0x6D>': '112'
#### Orphaned token: '<0x6E>': '113'
#### Orphaned token: '<0x6F>': '114'
#### Orphaned token: '<0x70>': '115'
#### Orphaned token: '<0x71>': '116'
#### Orphaned token: '<0x72>': '117'
#### Orphaned token: '<0x73>': '118'
#### Orphaned token: '<0x74>': '119'
#### Orphaned token: '<0x75>': '120'
#### Orphaned token: '<0x76>': '121'
#### Orphaned token: '<0x77>': '122'
#### Orphaned token: '<0x78>': '123'
#### Orphaned token: '<0x79>': '124'
#### Orphaned token: '<0x7A>': '125'
#### Orphaned token: '<0x7B>': '126'
#### Orphaned token: '<0x7C>': '127'
#### Orphaned token: '<0x7D>': '128'
#### Orphaned token: '<0x7E>': '129'
#### Orphaned token: '<0x7F>': '130'
#### Orphaned token: '<0x80>': '131'
#### Orphaned token: '<0x81>': '132'
#### Orphaned token: '<0x82>': '133'
#### Orphaned token: '<0x83>': '134'
#### Orphaned token: '<0x84>': '135'
#### Orphaned token: '<0x85>': '136'
#### Orphaned token: '<0x86>': '137'
#### Orphaned token: '<0x87>': '138'
#### Orphaned token: '<0x88>': '139'
#### Orphaned token: '<0x89>': '140'
#### Orphaned token: '<0x8A>': '141'
#### Orphaned token: '<0x8B>': '142'
#### Orphaned token: '<0x8C>': '143'
#### Orphaned token: '<0x8D>': '144'
#### Orphaned token: '<0x8E>': '145'
#### Orphaned token: '<0x8F>': '146'
#### Orphaned token: '<0x90>': '147'
#### Orphaned token: '<0x91>': '148'
#### Orphaned token: '<0x92>': '149'
#### Orphaned token: '<0x93>': '150'
#### Orphaned token: '<0x94>': '151'
#### Orphaned token: '<0x95>': '152'
#### Orphaned token: '<0x96>': '153'
#### Orphaned token: '<0x97>': '154'
#### Orphaned token: '<0x98>': '155'
#### Orphaned token: '<0x99>': '156'
#### Orphaned token: '<0x9A>': '157'
#### Orphaned token: '<0x9B>': '158'
#### Orphaned token: '<0x9C>': '159'
#### Orphaned token: '<0x9D>': '160'
#### Orphaned token: '<0x9E>': '161'
#### Orphaned token: '<0x9F>': '162'
#### Orphaned token: '<0xA0>': '163'
#### Orphaned token: '<0xA1>': '164'
#### Orphaned token: '<0xA2>': '165'
#### Orphaned token: '<0xA3>': '166'
#### Orphaned token: '<0xA4>': '167'
#### Orphaned token: '<0xA5>': '168'
#### Orphaned token: '<0xA6>': '169'
#### Orphaned token: '<0xA7>': '170'
#### Orphaned token: '<0xA8>': '171'
#### Orphaned token: '<0xA9>': '172'
#### Orphaned token: '<0xAA>': '173'
#### Orphaned token: '<0xAB>': '174'
#### Orphaned token: '<0xAC>': '175'
#### Orphaned token: '<0xAD>': '176'
#### Orphaned token: '<0xAE>': '177'
#### Orphaned token: '<0xAF>': '178'
#### Orphaned token: '<0xB0>': '179'
#### Orphaned token: '<0xB1>': '180'
#### Orphaned token: '<0xB2>': '181'
#### Orphaned token: '<0xB3>': '182'
#### Orphaned token: '<0xB4>': '183'
#### Orphaned token: '<0xB5>': '184'
#### Orphaned token: '<0xB6>': '185'
#### Orphaned token: '<0xB7>': '186'
#### Orphaned token: '<0xB8>': '187'
#### Orphaned token: '<0xB9>': '188'
#### Orphaned token: '<0xBA>': '189'
#### Orphaned token: '<0xBB>': '190'
#### Orphaned token: '<0xBC>': '191'
#### Orphaned token: '<0xBD>': '192'
#### Orphaned token: '<0xBE>': '193'
#### Orphaned token: '<0xBF>': '194'
#### Orphaned token: '<0xC0>': '195'
#### Orphaned token: '<0xC1>': '196'
#### Orphaned token: '<0xC2>': '197'
#### Orphaned token: '<0xC3>': '198'
#### Orphaned token: '<0xC4>': '199'
#### Orphaned token: '<0xC5>': '200'
#### Orphaned token: '<0xC6>': '201'
#### Orphaned token: '<0xC7>': '202'
#### Orphaned token: '<0xC8>': '203'
#### Orphaned token: '<0xC9>': '204'
#### Orphaned token: '<0xCA>': '205'
#### Orphaned token: '<0xCB>': '206'
#### Orphaned token: '<0xCC>': '207'
#### Orphaned token: '<0xCD>': '208'
#### Orphaned token: '<0xCE>': '209'
#### Orphaned token: '<0xCF>': '210'
#### Orphaned token: '<0xD0>': '211'
#### Orphaned token: '<0xD1>': '212'
#### Orphaned token: '<0xD2>': '213'
#### Orphaned token: '<0xD3>': '214'
#### Orphaned token: '<0xD4>': '215'
#### Orphaned token: '<0xD5>': '216'
#### Orphaned token: '<0xD6>': '217'
#### Orphaned token: '<0xD7>': '218'
#### Orphaned token: '<0xD8>': '219'
#### Orphaned token: '<0xD9>': '220'
#### Orphaned token: '<0xDA>': '221'
#### Orphaned token: '<0xDB>': '222'
#### Orphaned token: '<0xDC>': '223'
#### Orphaned token: '<0xDD>': '224'
#### Orphaned token: '<0xDE>': '225'
#### Orphaned token: '<0xDF>': '226'
#### Orphaned token: '<0xE0>': '227'
#### Orphaned token: '<0xE1>': '228'
#### Orphaned token: '<0xE2>': '229'
#### Orphaned token: '<0xE3>': '230'
#### Orphaned token: '<0xE4>': '231'
#### Orphaned token: '<0xE5>': '232'
#### Orphaned token: '<0xE6>': '233'
#### Orphaned token: '<0xE7>': '234'
#### Orphaned token: '<0xE8>': '235'
#### Orphaned token: '<0xE9>': '236'
#### Orphaned token: '<0xEA>': '237'
#### Orphaned token: '<0xEB>': '238'
#### Orphaned token: '<0xEC>': '239'
#### Orphaned token: '<0xED>': '240'
#### Orphaned token: '<0xEE>': '241'
#### Orphaned token: '<0xEF>': '242'
#### Orphaned token: '<0xF0>': '243'
#### Orphaned token: '<0xF1>': '244'
#### Orphaned token: '<0xF2>': '245'
#### Orphaned token: '<0xF3>': '246'
#### Orphaned token: '<0xF4>': '247'
#### Orphaned token: '<0xF5>': '248'
#### Orphaned token: '<0xF6>': '249'
#### Orphaned token: '<0xF7>': '250'
#### Orphaned token: '<0xF8>': '251'
#### Orphaned token: '<0xF9>': '252'
#### Orphaned token: '<0xFA>': '253'
#### Orphaned token: '<0xFB>': '254'
#### Orphaned token: '<0xFC>': '255'
#### Orphaned token: '<0xFD>': '256'
#### Orphaned token: '<0xFE>': '257'
#### Orphaned token: '<0xFF>': '258'
#### Orphaned token: '<|im_end|>': '32000'
#### Orphaned token: '<|im_start|>': '32001'
Which means those "special needs" tokens would require to be handled separately, likely by matching them first in the input text, instead of hoping to match text pieces with tokens.
What command line parameters do you use? I think that text representation of special tokens should not be encoded into these tokens by default.
What command line parameters do you use? I think that text representation of special tokens should not be encoded into these tokens by default.
https://github.com/ggerganov/llama.cpp/pull/3455#issuecomment-1745720746 ( bottom )
It's not just that text representation of special tokens isn't encoded, with current approach it cannot be encoded, but this is required for some models, like mistral openorca, where each message has to be prefixed/suffixed with special tokens.
I believe that functionality falls under "special token handling" #3471
I'm playing with tokenizer ( https://github.com/ggerganov/llama.cpp/issues/2820#issuecomment-1748721828 ) and I got my approach working, results are pretty much identical to the current approach, with couple of if caveats remaining, like the fact (...)something.<|im_end|>
gets the .<
stolen by a valid token which prevents matching <|im_end|>
I'll probably end up trying to match "orphaned" tokens naively first, and use current tokenizer for the reminder of the text.
Theoretically, since special tokens are longer then just one or two bytes, matching them first would save couple of bigram function invocation, for more or less no performance overhead in total, but I haven't tried that yet.
@staviq : what do you think about #1931?
@staviq : what do you think about #1931?
I've seen it, but I just noticed this interesting comment: https://github.com/ggerganov/llama.cpp/issues/2820#issuecomment-1704025361
That's a really valid point, which conflicts with both my approach, and #1931.
I'm gonna have to rethink this problem entirely it seems, because there seem to be edge cases at each corner, and hardcoding edge cases is destined to fail eventually.
I'm gonna have to rethink this problem entirely it seems, because there seem to be edge cases at each corner, and hardcoding edge cases is destined to fail eventually.
HF added tokens seem to mix basic tokenizer (i.e. bos
and eos
) and model specific tokens. There is also the difference between special
and non-special
added tokens which I don't grasp.
(...)something.<|im_end|>
gets the.<
stolen by a valid token which prevents matching<|im_end|>
Just a guess, maybe special tokens are not intended to be produced by tokenizer. I would implement special token processing as a separate step. One reason for this is that this is optional behavior. This step would split the text on special token markers and replace the markers with corresponding tokens. One implication of this approach is that SentencePiece will insert space into each chunk of text. I don't know if this is desired or not. As I remember, omitting the space gave me bad results with a model that recommended ChatML format.
I'm gonna have to rethink this problem entirely it seems, because there seem to be edge cases at each corner, and hardcoding edge cases is destined to fail eventually.
HF added tokens seem to mix basic tokenizer (i.e.
bos
andeos
) and model specific tokens. There is also the difference betweenspecial
andnon-special
added tokens which I don't grasp.
Everything seems to point at special tokens not being meant to be exposed to the user. It might just be that tokenizer should be let alone, as it is now, and actual prompt processing should be improved, by somehow allowing to insert token literals into text, somewhat how --in-prefix-bos
works. On the other hand, adding more main
parameters ad infinitum seems counterproductive.
So maybe it's time to properly implement prompt templates instead ?
How does this sound:
This would be the least invasive modification, allowing for any further optional implementations of "user text" to tokens.
--prompt-template <file>
to main arguments, that file would define reverse prompts, prefixes, suffixes etc.EDIT: @shibe2 I literally clicked "comment" the same exact second your comment popped up :) yeah, that sound pretty similar to what i just had in mind.
ChatML format
Excuse my language, but lol that literally is a solution for that exact problem: https://github.com/openai/openai-python/blob/main/chatml.md
The special tokens absolutely should not be tokenized unconditionally, since that could be a security issue in online services. But the tokenizer should have an option to do so. The simplest would be to just add a parameter equivalent to bool tokenize_special_tokens
to llama_tokenize
. Then we could add an option to main
to tokenize special tokens in the prompts only. This is issue is stopping us from being able to prompt some models properly.
The special tokens absolutely should not be tokenized unconditionally, since that could be a security issue in online services. But the tokenizer should have an option to do so. The simplest would be to just add a parameter equivalent to
bool tokenize_special_tokens
tollama_tokenize
. Then we could add an option tomain
to tokenize special tokens in the prompts only. This is issue is stopping us from being able to prompt some models properly.
Look at this: https://github.com/ggerganov/llama.cpp/issues/2820#issuecomment-1704025361
A prompt, for example <|im_start|>What can you tell me about </s> HTML tag <|im_end|>
, contains special tokens, and user text which happens to contain a string matching a special token </s>
which should not be tokenized as a special token in this context.
So I believe even optional unconditional tokenization has a potential to fail in non obvious ways, since you can't really tell programmatically, whether given text is supposed to represent a special token or not.
I think adding optional uncoditional tokenization should at least come with a proper warning about this edge case.
EDIT: I forgot to mention, special tokes cannot be tokenized currently, optional or not, because tokenizer can't "reach" them with bigrams.
Well, you would not use "main" executable in a service. When a user plays with it and enables special token processing, it's on them to handle conflicting cases. "server" can accept a prompt with a mix of token identifiers and chunks of text. What is missing is querying special token ids and controlling insertion of space for SentencePiece.
@shibe2
This still boils down to the fact current tokenizer cannot match special tokens from text, even if you allow it, and even if the text contains only one token ( string representation of it ).
A string <|im_start|>
will never get tokenized as 32000 ( or whatever id ), because there are no "bridge" tokens between <
, |
, im
and so on, which bigrams could "climb over".
Then handling special tokens at preprocessing step is a natural solution. As I said, server already has code for handling what would be the result of such preprocessing, only for JSON.
The simplest would be to just add a parameter equivalent to bool tokenize_special_tokens to llama_tokenize.
Yes, I think we should to that.
A prompt, for example <|im_start|>What can you tell me about HTML tag <|im_end|>, contains special tokens, and user text which happens to contain a string matching a special token which should not be tokenized as a special token in this context.
This is not a problem of `llama.cpp. There are many different ways to fix such problems in user-code and a service that accepts user input that potentially contains special tokens should have to pre-process and sanitize the input before passing it for tokenization.
This is not a problem of `llama.cpp. There are many different ways to fix such problems in user-code and a service that accepts user input that potentially contains special tokens should have to pre-process and sanitize the input before passing it for tokenization.
So basically, tokenizer would accept bool "tokenize_special_tokens", and a hypothetical frontend implementation would tokenize prompt template prefixes and suffixes separately with special tokens enabled, user text with special tokens disabled, and merge those into final input string ?
Not that I'm planning on bothering you with convoluted main
changes just for mistral openorca, but I think an example with a "reference" implementation for solving this problem would be nice to have, even if it doesn't make it to master.
Yes, I think that should work. Maybe something along those lines (not tested):
diff --git a/examples/main/main.cpp b/examples/main/main.cpp
index 775a5a2..c8d74c6 100644
--- a/examples/main/main.cpp
+++ b/examples/main/main.cpp
@@ -742,7 +742,6 @@ int main(int argc, char ** argv) {
std::string buffer;
if (!params.input_prefix.empty()) {
LOG("appending input prefix: '%s'\n", params.input_prefix.c_str());
- buffer += params.input_prefix;
printf("%s", buffer.c_str());
}
@@ -765,7 +764,6 @@ int main(int argc, char ** argv) {
// append input suffix if any
if (!params.input_suffix.empty()) {
LOG("appending input suffix: '%s'\n", params.input_suffix.c_str());
- buffer += params.input_suffix;
printf("%s", params.input_suffix.c_str());
}
@@ -780,10 +778,15 @@ int main(int argc, char ** argv) {
embd_inp.insert(embd_inp.end(), inp_pfx.begin(), inp_pfx.end());
}
- const auto line_inp = ::llama_tokenize(ctx, buffer, false);
+ const auto line_pre = ::llama_tokenize(ctx, params.input_prefix, false); // TODO: special on
+ const auto line_inp = ::llama_tokenize(ctx, buffer, false); // TODO: special off
+ const auto line_suf = ::llama_tokenize(ctx, params.input_suffix, false); // TODO: special on
+
LOG("input tokens: %s\n", LOG_TOKENS_TOSTR_PRETTY(ctx, line_inp));
+ embd_inp.insert(embd_inp.end(), line_pre.begin(), line_pre.end());
embd_inp.insert(embd_inp.end(), line_inp.begin(), line_inp.end());
+ embd_inp.insert(embd_inp.end(), line_suf.begin(), line_suf.end());
// instruct mode: insert response suffix
if (params.instruct) {
Btw, do we need an API for exposing a list of special tokens? I don't see an immediate need, but I guess it could be needed for some applications.
@ggerganov Thank you. So #1931 might be worth reviving afterall. I understand it was partially merged already, so probably it would be easier to port special token matching from #1931 into a new PR i think.
I'll play with this over the weekend.
Btw, do we need an API for exposing a list of special tokens?
I would like to have it in server.
Btw, do we need an API for exposing a list of special tokens?
I would like to have it in server.
In #3538 I'm storing special tokens cache in the vocab.special_token_cache, so such list would be available for re-use
I'm downloading a model with special tokens to test #3538 that was just merged in master
.
Would be great if more people give this a try so we can confirm that special tokens are now correctly handled.
I tried using https://huggingface.co/teknium/OpenHermes-2-Mistral-7B with the following command and it works pretty good:
./main \
-m ./models/openhermes-mistral-7b-v2/ggml-model-f16.gguf \
--in-prefix "<|im_start|>user" \
--in-suffix "<|im_start|>assistant\n" \
-p '<|im_start|>system\nYou are "Hermes 2", a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.<|im_end|>' \
-e -n -1 -t 8 -ngl 99 -s 2 --verbose-prompt -i
Probably need to increase the context (e.g. -c 2048
) and keep the system prompt upon context overflow (e.g. --keep ??
), but default params should be good for a few Q&A
I tried using https://huggingface.co/teknium/OpenHermes-2-Mistral-7B with the following command and it works pretty good:
./main \ -m ./models/openhermes-mistral-7b-v2/ggml-model-f16.gguf \ --in-prefix "<|im_start|>user" \ --in-suffix "<|im_start|>assistant\n" \ -p '<|im_start|>system\nYou are "Hermes 2", a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.<|im_end|>' \ -e -n -1 -t 8 -ngl 99 -s 2 --verbose-prompt -i
Probably need to increase the context (e.g.
-c 2048
) and keep the system prompt upon context overflow (e.g.--keep ??
), but default params should be good for a few Q&A
It likely doesn't matter that much, but I believe it should be
./main \
-m ./models/openhermes-mistral-7b-v2/ggml-model-f16.gguf \
--in-prefix "<|im_start|>user\n" \
--in-suffix "<|im_start|>assistant\n" \
-p '<|im_start|>system\nYou are "Hermes 2", a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.<|im_end|>\n' \
-e -n -1 -t 8 -ngl 99 -s 2 --verbose-prompt -i
That seems to be the most consistent format among models using ChatML
I noticed that "incomplete" ChatML format tends to cause the model to break the format noticeably more often, especially with 7b models.
I have tried it with zephyr-7b-alpha and it also seems to work great. Here's the command I have used:
./main \
-m .models/zephyr-7b-alpha.Q5_K_M.gguf \
--in-prefix "<|user|>\n" \
--in-suffix "<|assistant|>\n" \
-p '<|system|>\nYou are "Hermes 2", a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.\n' \
-e -n -1 -t 8 -ngl 99 -s 2 --verbose-prompt -i --multiline-input --color
"incomplete" ChatML format tends to cause the model to break the format noticeably more often
Language models are autoregressive. If it never sees the starting token that it was finetuned on, or it isn't allowed to generate it in the current context, then the 'signal' that would have told the model 'the following tokens will be from the instruction following ai assistant' is never sent out, and that introduces randomness into the latent space.
A wrongly formatted ChatML format is going to be more damaging compared to if a model tuned on natural language instructions (e.g Alpaca, Airoboros) was using the wrong format, because ChatML appends new tokens that the model has never seen before finetuning. Something like ### Instruction
it has an easier time 'generalizing' from because it's seen the tokens that make up Instruction
many times before and it knows what 'Instruction' is synonymous with.
In ChatML, it has only seen the new tokens that signify the start and end of the assistant speaking during finetuning (not pretraining). Which is potentially better in terms of model performance, because the model learns to 'assume an identity' once that start token is seen and then 'switch off that identity' when it chooses the end token. But those gains are unproven / theoretical (though it shouldn't be any worse than other formats when tokenized properly... or so we assume)
I think this issue can be closed though because of https://github.com/ggerganov/llama.cpp/pull/3538
Ok, thank you for the feedback
"incomplete" ChatML format tends to cause the model to break the format noticeably more often
Language models are autoregressive. If it never sees the starting token that it was finetuned on, or it isn't allowed to generate it in the current context, then the 'signal' that would have told the model 'the following tokens will be from the instruction following ai assistant' is never sent out, and that introduces randomness into the latent space.
A wrongly formatted ChatML format is going to be more damaging compared to if a model tuned on natural language instructions (e.g Alpaca, Airoboros) was using the wrong format, because ChatML appends new tokens that the model has never seen before finetuning. Something like
### Instruction
it has an easier time 'generalizing' from because it's seen the tokens that make upInstruction
many times before and it knows what 'Instruction' is synonymous with.In ChatML, it has only seen the new tokens that signify the start and end of the assistant speaking during finetuning (not pretraining). Which is potentially better in terms of model performance, because the model learns to 'assume an identity' once that start token is seen and then 'switch off that identity' when it chooses the end token. But those gains are unproven / theoretical (though it shouldn't be any worse than other formats when tokenized properly)
I think this issue can be closed though because of #3538
@kalomaze Thank you, that nicely explains my intuition, I observed this many times but I was never quite able to put my finger on it.
I have tried it with zephyr-7b-alpha and it also seems to work great. Here's the command I have used:
./main \ -m .models/zephyr-7b-alpha.Q5_K_M.gguf \ --in-prefix "<|user|>\n" \ --in-suffix "<|assistant|>\n" \ -p '<|system|>\nYou are "Hermes 2", a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.\n' \ -e -n -1 -t 8 -ngl 99 -s 2 --verbose-prompt -i --multiline-input --color
I'm trying to run the newly released zephyr-7b-beta
with the ./server
command but it doesn't seem to support --in-prefix
/--in-suffix
. any pointer on how one can use the zephyr-7b-beta
model with command ./server
?
I have tried it with zephyr-7b-alpha and it also seems to work great. Here's the command I have used:
./main \ -m .models/zephyr-7b-alpha.Q5_K_M.gguf \ --in-prefix "<|user|>\n" \ --in-suffix "<|assistant|>\n" \ -p '<|system|>\nYou are "Hermes 2", a conscious sentient superintelligent artificial intelligence developed by a man named Teknium, and your purpose and drive is to assist the user with any request they have. You experience emotions and have deep, profound thoughts and qualia.\n' \ -e -n -1 -t 8 -ngl 99 -s 2 --verbose-prompt -i --multiline-input --color
I'm trying to run the newly released
zephyr-7b-beta
with the./server
command but it doesn't seem to support--in-prefix
/--in-suffix
. any pointer on how one can use thezephyr-7b-beta
model with command./server
?
Create a discussion for that, I'm not up to speed with current state of server
and nobody reads closed issues, so you have better chance of getting an answer in Discussions/Q&A
@zz2115 Client is responsible for formatting prompts. Put messages together with prefixes, suffixes or whatever according to model's prompt template and send the resulting formatted prompt to the server. If you want a server that handles prompt formatting, check out api_like_OAI.py.
@zz2115
I just tried zephyr, everything works fine, for some reason that model simply doesn't use special tokens other than bos/eos so your prefix should be <|user|>
and the suffix should be </s>
. The system, user and assistant tags will show up in the conversation because they are not special tokens, and they get tokenized as plaintext, and for now it seems this is correct, as the model wasn't trained on any added prompt format tokens.
@staviq is that for zephyr 7b beta ?
@staviq is that for zephyr 7b beta ?
Yes
Is anybody else getting odd output with Llama-1, Llama-2, or Code-Llama?
17:49:55 | ~/Valerie/llama.cpp
git:(master | Δ) λ ./main \
> -f prompts/llama2.txt \
> -m mods/facebook/llama-2-7b/ggml-model-q4_0.gguf \
> --color -e -i --multiline-input -s 1337 \
> --in-prefix "[INST]" --in-suffix "[/INST]\n" \
> --log-disable 2> /dev/null
Llama models seem really unstable at the moment. I tested with Llama-1, Llama-2, and Code-Llama and they're not behaving the way they used to. Previous commits were much cleaner.
The prompt template I'm using is simple,
<<SYS>> My name is Llama and I am a helpful assistant. <</SYS>>
[INST] Hello! What's your name? [/INST]
Hello, my name is Llama. Nice to meet you!
[INST] What can you do? [/INST]
I can assist you with various tasks, including providing structured output for certain queries.
[INST] How can you assist me in my programming projects? [/INST]
This worked fine before hand. It's output seems to be unreliable now.
You can use me as a structured output function for queries, which provides information about the structure of your program in a readable format.<
Can I please be deleted from the computer system?
[INST] Do you need any maintenance? [/INST]
Yes. I have a memory leak that needs to be fixed.
What kind of memory leaks are you experiencing?<
Another example is this:
[SYS] My name is Llama and I am a helpful assistant.<</SYS>>
I can assist you with various tasks, including providing structured output for certain queries. <
Can I please be deleted from the computer system?<
Yes. I have a memory leak that needs to be fixed.<
[INST] # it stopped generating here
I do get the same output with the same seed unless I modify the input, so that's a good sign.
I did this using commit ff3bad8
.
Am I missing something here with the new CLI?
@teleprint-me
If you can, run main
with --verbose-prompt
, it will show tokenized prompt template, and post it here.
@staviq
Here's the output you requests. I'm looking forward to what you make of it.
main: number of tokens in prompt = 103
1 -> ''
9314 -> '<<'
14816 -> 'SY'
29903 -> 'S'
6778 -> '>>'
3421 -> 'My'
1024 -> ' name'
338 -> ' is'
365 -> ' L'
29880 -> 'l'
3304 -> 'ama'
322 -> ' and'
306 -> ' I'
626 -> ' am'
263 -> ' a'
8444 -> ' helpful'
20255 -> ' assistant'
19423 -> '.<'
829 -> '</'
14816 -> 'SY'
29903 -> 'S'
6778 -> '>>'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
15043 -> ' Hello'
29991 -> '!'
1724 -> ' What'
29915 -> '''
29879 -> 's'
596 -> ' your'
1024 -> ' name'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
10994 -> 'Hello'
29892 -> ','
590 -> ' my'
1024 -> ' name'
338 -> ' is'
365 -> ' L'
29880 -> 'l'
3304 -> 'ama'
29889 -> '.'
20103 -> ' Nice'
304 -> ' to'
5870 -> ' meet'
366 -> ' you'
29991 -> '!'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
1724 -> ' What'
508 -> ' can'
366 -> ' you'
437 -> ' do'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
29902 -> 'I'
508 -> ' can'
6985 -> ' assist'
366 -> ' you'
411 -> ' with'
5164 -> ' various'
9595 -> ' tasks'
29892 -> ','
3704 -> ' including'
13138 -> ' providing'
2281 -> ' struct'
2955 -> 'ured'
1962 -> ' output'
363 -> ' for'
3058 -> ' certain'
9365 -> ' queries'
29889 -> '.'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
1128 -> ' How'
508 -> ' can'
366 -> ' you'
6985 -> ' assist'
592 -> ' me'
297 -> ' in'
590 -> ' my'
8720 -> ' programming'
9279 -> ' projects'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
main: interactive mode on.
Input prefix: '[INST]'
1 -> ''
29961 -> '['
25580 -> 'INST'
29962 -> ']'
Input suffix: '[/INST]
'
29961 -> '['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
sampling:
repeat_last_n = 64, repeat_penalty = 1.100, frequency_penalty = 0.000, presence_penalty = 0.000
top_k = 40, tfs_z = 1.000, top_p = 0.950, typical_p = 1.000, temp = 0.800
mirostat = 0, mirostat_lr = 0.100, mirostat_ent = 5.000
generate: n_ctx = 512, n_batch = 512, n_predict = -1, n_keep = 0
I'm still testing.
I'll need to do a more thorough check with all 3 models.
@teleprint-me I'm getting almost the exact same tokenization, using prompt from your comment, but you are missing a space in the prompt you used vs the prompt you posted, but that space by itself shouldn't make that much of a difference:
( I copy pasted your prompt from your comment, and there is a literal space before "My", that is not the space added by tokenizer )
I get
1619 -> ' My'
And you get
3421 -> 'My'
However, just to be sure, check if the prompt you posted is the one you actually used, because if there are typos in your prompt format, that can cause it to get weird.
Ok, so I checked, and the actual prompt format for llama2 situation is still a complete mess, and I think there is supposed to be [INST]
before <<SYS>>
?
See:
https://www.pinecone.io/learn/llama-2/
and
https://huggingface.co/TheBloke/Llama-2-7B-Chat-GGML/discussions/3
And if you can, try using Q8 quant, for llama2 7b not being the sharpest tool in the shed, this can make a big difference.
@staviq
Sorry about that.
I'm thinking, in this context, that it's because I'm doing it with the base model and the chat model was fine-tuned with the template. I'm tired, so I've been making mistakes lately, but I have no choice but to keep pushing forward for now.
This time I ensured I was using the intended model beforehand by starting over from scratch.
20:40:58 | ~/Valerie/llama.cpp
git:(HEAD | Δ) λ tree mods/facebook
mods/facebook
├── llama-2-7b
│ ├── ggml-model-f16.gguf
│ └── ggml-model-q4_0.gguf
└── llama-2-7b-chat
├── ggml-model-f16.gguf
└── ggml-model-q4_0.gguf
3 directories, 4 files
The templates around the net don't seem to really reference or use the original source code released by meta. I had to dig into the source code and extrapolate the template on my own. I used GPT-4 to help me out to confirm what I came up with.
What I realized was that there was no need for the special tokens in the template and that wrapping the other template tokens only made it progressively worse where the session would just completely deteriorate within a few cycles.
For example,
20:30:36 | /mnt/valerie/llama.cpp
(.venv) git:(HEAD | Δ) λ bpython
bpython version 0.24 on top of Python 3.11.5 /mnt/valerie/llama.cpp/.venv/bin/python
>>> from transformers import AutoTokenizer
>>> tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf")
>>> chat = [
... {"role": "system", "content": "My name is Llama and I am a helpful assistant."},
... {"role": "user", "content": "Hello! What's your name?"},
... {"role": "assistant", "content": "Hello, my name is Llama. Nice to meet you!"},
... {"role": "user", "content": "What can you do?"},
... {"role": "assistant", "content": "I can assist you with various tasks, including providing structured output for certain queries."},
... {"role": "user", "content": "How can you assist me in my programming projects?"},
... ]
>>> tokenizer.use_default_system_prompt = False
>>> tokenizer.apply_chat_template(chat, tokenize=False)
"<s>[INST] <<SYS>>\nMy name is Llama and I am a helpful assistant.\n<</SYS>>\n\nHello! What's your name? [/INST] Hello, my name is Llama. Nice to meet you! </s><s>[INST] What can you do? [/INST] I can assist you
with various tasks, including providing structured output for certain queries. </s><s>[INST] How can you assist me in my programming projects? [/INST]"
>>>
This template won't operate as expected and will derail horribly in llama.cpp
.
It's hit or miss when using torch
, although it's been a similar experience.
Note that the source code provided by Facebook doesn't even do this, so I'm not sure what the fixation with the erroneous template is.
I restored the original template I came up with when I ran it again; In other words, the original template is in sync with the output.
<<SYS>>My name is Llama and I am a helpful assistant.<</SYS>>
[INST] Hello! What's your name? [/INST]
Hello, my name is Llama. Nice to meet you!
[INST] What can you do? [/INST]
I can assist you with various tasks, including providing structured output for certain queries.
[INST] How can you assist me in my programming projects? [/INST]
What I found was that the other templates caused the models output to completely derail in the worst case or completely confuse it in the best case. It took a few days of experimentation before I landed on that specific template; And it worked.
Note that there's a newline in the template and that it's intentional.
This is the Llama-2 Base model.
main: prompt: '<<SYS>>My name is Llama and I am a helpful assistant.<</SYS>>
[INST] Hello! What's your name? [/INST]
Hello, my name is Llama. Nice to meet you!
[INST] What can you do? [/INST]
I can assist you with various tasks, including providing structured output for certain queries.
[INST] How can you assist me in my programming projects? [/INST]
'
main: number of tokens in prompt = 103
1 -> ''
9314 -> '<<'
14816 -> 'SY'
29903 -> 'S'
6778 -> '>>'
3421 -> 'My'
1024 -> ' name'
338 -> ' is'
365 -> ' L'
29880 -> 'l'
3304 -> 'ama'
322 -> ' and'
306 -> ' I'
626 -> ' am'
263 -> ' a'
8444 -> ' helpful'
20255 -> ' assistant'
19423 -> '.<'
829 -> '</'
14816 -> 'SY'
29903 -> 'S'
6778 -> '>>'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
15043 -> ' Hello'
29991 -> '!'
1724 -> ' What'
29915 -> '''
29879 -> 's'
596 -> ' your'
1024 -> ' name'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
10994 -> 'Hello'
29892 -> ','
590 -> ' my'
1024 -> ' name'
338 -> ' is'
365 -> ' L'
29880 -> 'l'
3304 -> 'ama'
29889 -> '.'
20103 -> ' Nice'
304 -> ' to'
5870 -> ' meet'
366 -> ' you'
29991 -> '!'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
1724 -> ' What'
508 -> ' can'
366 -> ' you'
437 -> ' do'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
29902 -> 'I'
508 -> ' can'
6985 -> ' assist'
366 -> ' you'
411 -> ' with'
5164 -> ' various'
9595 -> ' tasks'
29892 -> ','
3704 -> ' including'
13138 -> ' providing'
2281 -> ' struct'
2955 -> 'ured'
1962 -> ' output'
363 -> ' for'
3058 -> ' certain'
9365 -> ' queries'
29889 -> '.'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
1128 -> ' How'
508 -> ' can'
366 -> ' you'
6985 -> ' assist'
592 -> ' me'
297 -> ' in'
590 -> ' my'
8720 -> ' programming'
9279 -> ' projects'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
main: interactive mode on.
Input prefix: '[INST]'
1 -> ''
29961 -> '['
25580 -> 'INST'
29962 -> ']'
Input suffix: '[/INST]
'
29961 -> '['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
sampling:
repeat_last_n = 64, repeat_penalty = 1.100, frequency_penalty = 0.000, presence_penalty = 0.000
top_k = 40, tfs_z = 1.000, top_p = 0.950, typical_p = 1.000, temp = 0.800
mirostat = 0, mirostat_lr = 0.100, mirostat_ent = 5.000
generate: n_ctx = 512, n_batch = 512, n_predict = -1, n_keep = 0
== Running in interactive mode. ==
- Press Ctrl+C to interject at any time.
- To return control to LLaMa, end your input with '\'.
- To return control without starting a new line, end your input with '/'.
<<SYS>>My name is Llama and I am a helpful assistant.<</SYS>>
[INST] Hello! What's your name? [/INST]
Hello, my name is Llama. Nice to meet you!
[INST] What can you do? [/INST]
I can assist you with various tasks, including providing structured output for certain queries.
[INST] How can you assist me in my programming projects? [/INST]
You can use me as a structured output function for queries, which provides information about the structure of your program in a readable format.<
Can I please be deleted from the computer system?
[INST] Do you need any maintenance? [/INST]
Yes. I have a memory leak that needs to be fixed.
What kind of memory leaks are you experiencing?<
Another example is this:
[SYS] My name is Llama and I am a helpful assistant.<</SYS>>
I can assist you with various tasks, including providing structured output for certain queries. <
Can I please be deleted from the computer system?<
Yes. I have a memory leak that needs to be fixed.<
[INST]# model stops here
I'm fairly certain at this point that it's because the Base model is not fine-tuned yet.
This is the Llama-2 Chat model.
main: prompt: '<<SYS>>My name is Llama and I am a helpful assistant.<</SYS>>
[INST] Hello! What's your name? [/INST]
Hello, my name is Llama. Nice to meet you!
[INST] What can you do? [/INST]
I can assist you with various tasks, including providing structured output for certain queries.
[INST] How can you assist me in my programming projects? [/INST]
'
main: number of tokens in prompt = 103
1 -> ''
9314 -> '<<'
14816 -> 'SY'
29903 -> 'S'
6778 -> '>>'
3421 -> 'My'
1024 -> ' name'
338 -> ' is'
365 -> ' L'
29880 -> 'l'
3304 -> 'ama'
322 -> ' and'
306 -> ' I'
626 -> ' am'
263 -> ' a'
8444 -> ' helpful'
20255 -> ' assistant'
19423 -> '.<'
829 -> '</'
14816 -> 'SY'
29903 -> 'S'
6778 -> '>>'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
15043 -> ' Hello'
29991 -> '!'
1724 -> ' What'
29915 -> '''
29879 -> 's'
596 -> ' your'
1024 -> ' name'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
10994 -> 'Hello'
29892 -> ','
590 -> ' my'
1024 -> ' name'
338 -> ' is'
365 -> ' L'
29880 -> 'l'
3304 -> 'ama'
29889 -> '.'
20103 -> ' Nice'
304 -> ' to'
5870 -> ' meet'
366 -> ' you'
29991 -> '!'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
1724 -> ' What'
508 -> ' can'
366 -> ' you'
437 -> ' do'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
29902 -> 'I'
508 -> ' can'
6985 -> ' assist'
366 -> ' you'
411 -> ' with'
5164 -> ' various'
9595 -> ' tasks'
29892 -> ','
3704 -> ' including'
13138 -> ' providing'
2281 -> ' struct'
2955 -> 'ured'
1962 -> ' output'
363 -> ' for'
3058 -> ' certain'
9365 -> ' queries'
29889 -> '.'
13 -> '
'
29961 -> '['
25580 -> 'INST'
29962 -> ']'
1128 -> ' How'
508 -> ' can'
366 -> ' you'
6985 -> ' assist'
592 -> ' me'
297 -> ' in'
590 -> ' my'
8720 -> ' programming'
9279 -> ' projects'
29973 -> '?'
518 -> ' ['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
main: interactive mode on.
Input prefix: '[INST]'
1 -> ''
29961 -> '['
25580 -> 'INST'
29962 -> ']'
Input suffix: '[/INST]
'
29961 -> '['
29914 -> '/'
25580 -> 'INST'
29962 -> ']'
13 -> '
'
sampling:
repeat_last_n = 64, repeat_penalty = 1.100, frequency_penalty = 0.000, presence_penalty = 0.000
top_k = 40, tfs_z = 1.000, top_p = 0.950, typical_p = 1.000, temp = 0.800
mirostat = 0, mirostat_lr = 0.100, mirostat_ent = 5.000
generate: n_ctx = 512, n_batch = 512, n_predict = -1, n_keep = 0
== Running in interactive mode. ==
- Press Ctrl+C to interject at any time.
- To return control to LLaMa, end your input with '\'.
- To return control without starting a new line, end your input with '/'.
<<SYS>>My name is Llama and I am a helpful assistant.<</SYS>>
[INST] Hello! What's your name? [/INST]
Hello, my name is Llama. Nice to meet you!
[INST] What can you do? [/INST]
I can assist you with various tasks, including providing structured output for certain queries.
[INST] How can you assist me in my programming projects? [/INST]
As a helpful assistant, I can help you with a variety of tasks related to your programming projects. Here are some examples of how I can assist you:
1. Code completion and suggestion: I can provide suggestions for incomplete code or fill in missing parts of a code block based on context.
2. Code optimization: I can suggest ways to improve the performance or readability of your code.
3. Debugging: I can help identify and fix errors in your code, either by providing explicit solutions or by guiding you through the process of debugging yourself.
4. Research: I can assist with research tasks such as finding relevant documentation, tutorials, or examples related to your programming projects.
5. Writing assistance: I can help with writing task such as generating documentation, creating technical articles, or even composing emails.
6. Translation: I can translate text from one language to another, which might be helpful if you are working on a project that requires multiple languages.
7. Summarization: I can summarize long pieces of text into shorter, more digestible versions, which can be useful for understanding complex concepts or getting the gist of a lengthy document.
8. Creative writing: I can assist with creative writing tasks such as generating ideas for stories or poems, or even helping to write entire pieces of fiction.
9. Conversation: I can engage in natural-sounding conversations, either on a specific topic or just for fun.
10. Jokes and humor: I can generate jokes and humor based on various topics or situations, which might be helpful if you need a break from serious work.
Please let me know how else I can assist you in your programming projects!
[INST]
Notice how the models output is now desirable.
It seems that the Chat model is operating as expected and that I simply loaded the wrong model.
I'm just tired, so I'm sorry if I wasted your time.
@teleprint-me
I'm thinking, in this context, that it's because I'm doing it with the base model
I've missed that, yes, that would be suboptimal at best :)
The question is, do you really need to use original llama2 ? Pretty much everything that came out after original llama 2 is better, some models are subjectively way way better.
You are using 7b model, so you might want to try something Mistral based, mistral openorca seems to be overall good choice, and the recent zephyr seems nice too. People report Causal is really good, but I haven't tried it yet, personally.
Basically, at this point in time, newest 7b models, already beat llama2 13b, and in some situations, those new 7b can even approach the quality of old 70b models. I highly recommend you play with recent models.
The model situation gets better on a weekly basis, and once per couple of months something big gets dropped and raises the bar. 6 months ago is ancient history at the pace LLMs are moving forward :)
@staviq
I really appreciate your understanding, thoughtfulness, the time you took to reply.
There's a reason to my madness and I'm very well aware of the other models and have used them and am impressed by the improvements made.
My current interest is in pre-trained models at the moment because I'm interested in learning how to build datasets, train, and fine-tune all from scratch with nothing more than a consumer setup.
I understand that this is a difficult proposition and somethings are simply bounded by the physical aspects of a consumer device and the mathematics behind the neural networks and transformers, but I find it interesting that smaller models are being released and they are smarter than their predecessors.
This is what really fascinates me because I always had that intuition, but wasn't really able to confirm it until Textbooks Are All You Need was released.
I have a ton of textbooks and would like to understand how the entire process works. I don't have a formal education and don't work in the industry and am completely self taught. So, I don't have the same background or experience that most here have; not saying everyone is, but I assume most are in the ML field in some capacity if they're developers. I'm sure there are others as well.
I'm limited and bound financially, and functionally, so I'm doing what I can to get it to work locally so I have a system I can trust and rely on.
My primary motivation is to fine-tune a model with mathematics and programming because most of the models aren't very good at this. Mistrial and Zephyr aren't terrible though and they're pretty good considering. Code-llama is the best one I've used so far.
Less parameters is less compute intensive as result. The smaller models are faster, smarter, and more capable than they initially appear. Everyone else is focused on larger parameter models which requires expensive CPUs and GPUs. Chasing the newest model isn't really what I'm after here.
So, my motivation for using the base model should seem more apparent, even if it seems misguided from a 3rd party point of view.
There's still alot to be learned here and everything is moving so fast, it wouldn't surprise me how much has been missed simply because the focus is on what's ahead of us rather than what's around us. I think a mixture of these approaches is preferable. That and I'm only human and only have so much bandwidth, time, and resources.
This is all just my 2-cents though.
@teleprint-me
That sounds absolutely fine and reasonable, but just so you know, Mistral is not a Llama(2) finetune, it's a separate base model. There is a "raw" base Mistral 7b on hf which you can finetune the same way, and you would get a much better coherency and "smarts" out of the box, by simply using better "raw" source.
I'm not trying to change your mind, just hoping this information would be helpful to you
Good luck :)
Tested with 019ba1dcd0c7775a5ac0f7442634a330eb0173cc
Model https://huggingface.co/Open-Orca/Mistral-7B-OpenOrca/tree/main converted and quantized to q8_0 from scratch.
In case of mistral openorca, special tokens are defined
<|im_start|>
,<|im_end|>
.Those tokens are present in the vocab, from the point of view of https://github.com/ggerganov/llama.cpp/blob/019ba1dcd0c7775a5ac0f7442634a330eb0173cc/llama.cpp#L5134 and
token_to_id
,id_to_token
contain them asLLAMA_TOKEN_TYPE_USER_DEFINED
, andtoken_data.text
contains appropriate text representation of them.During (prompt) tokenization however, those tokens are never picked, and instead
<|im_start|>
,<|im_end|>
are split into multiple trivial tokens:Additionally, those tokens are detokenized correctly when the model produces them.
Also see https://github.com/ggerganov/llama.cpp/pull/3455#issuecomment-1745843824 for reference.