Universal Assisted Generation: Assisted generation with any assistant model (by Intel Labs) - #33383
Conversation
|
Note: sd_config = SpeculativeConfig(model_name_or_path=model_name_or_path, assistant_name_or_path=assistant_name_or_path)
out = model.generate(input_ids, do_sample=False, max_new_tokens=max_new_tokens, sd_config=sd_config) |
…-basic-1 added any tokenizer generation correctness test
|
Hi @gante |
|
We even got a significant speedup using a 9 billion target model (
|
|
@danielkorat @jmamou apologies for the delayed review, bugfixes in the pipeline 👼 I had a quick look at the PR and it looks really really cool, thank you for proposing this technique and opening the PR 💛 My immediate comment goes in the same direction as a comment added above, about having a
Let me know if I can help in any way beyond reviewing. I've placed this PR on my top priorities :) |
|
I think I will have to work next on |
| new_cur_len = assistant_input_ids.shape[-1] | ||
| else: | ||
| # input_ids contains all target prompt input ids and some new target input ids | ||
| if self.prev_target_ids.shape[1] > self.target_lookbehind: |
There was a problem hiding this comment.
❗ ❗
Sanity check: you have confirmed that the runtime with this logic is faster than simply re-encoding the whole input_ids?
If it is just a tiny bit faster, like 5%, then I'd prefer having the simpler reencoding code path exclusively -- it's much simpler to maintain and document
(I'll likely have a few comments to make this section more beginner-friendly, but I'm holding them until we confirm this part :D)
There was a problem hiding this comment.
Yes, we have tested both options and this one is significantly faster.
Natuarlly, as the number of new tokens increases it becomes even more significant.
There was a problem hiding this comment.
In one test we did, it was 15% faster. And that test used cnn_dailymail which does not even have long prompts.
Re-encoding (decode+encode) the whole input_ids (which increase in size at at each step) at every assistant generation step incurs a significant overhead.
There was a problem hiding this comment.
awesome, thank you for confirming
(going to leave this comment unresolved for future reference)
|
@gante The line above is super slow since it deep-copies two Tokenizer objects living inside A proper solution could be implementing something like this for from copy import deepcopy
class Foo:
def __init__(self, content, linked_to):
self.content = content
self.linked_to = linked_to
def __deepcopy__(self, memo):
# create a copy with self.linked_to *not copied*, just referenced.
return Foo(deepcopy(self.content, memo), self.linked_to)where |
|
Hi @danielkorat 👋 I got it right from the comments above, passing the assistant tokenizer separately (like we pass the assistant model) is an option -- let's go with it :) The deep copy is a hard requirement, to prevent side-effects -- we want to make adjustments to the object inside |
gante
left a comment
There was a problem hiding this comment.
Aside from the tokenizer placement in the generation config, LGTM 🤗
|
Thanks @gante, applied your suggestions 😃 Ready to merge (failing tests are unrelated to this PR) |
gante
left a comment
There was a problem hiding this comment.
Perfect! Thank you for iterating 🤗
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
|
(the broken CI should be fixed by #33950 , let's wait for it to be merged to then rebase :) ) |
ArthurZucker
left a comment
There was a problem hiding this comment.
Very nice addition! Needs a tad bit more documentation!
|
hi @gante @ArthurZucker |
|
Sorry for the delay, merging! Great work, congrats 🔥 |
… model (by Intel Labs) (huggingface#33383) * Update candidate_generator.py * Update utils.py * add lookbehind params to _get_candidate_generator * make fixup * add unit tests * fix failing tests * add docstrings * fix docstrings; remove non-optimized AnyTokenizer * added any tokenizer generation correctness test * make fixup * fix assertion syntax * PR review fixes * address additional PR comments * fix tests * remove stropping criteria arg * make fixup * add AssistantConfig * fix prev_tokens branching * pass tokenizers through `generate()`kwargs * fix lookbehind values; tokenizer params WIP * fixup * AssistantConfig * remove AssistantConfig; apply PR suggestions * restructure tests * fixup * fix assistant_tokenizer arg validation * fixup * fix tests in TestAssistedCandidateGeneratorDifferentTokenizers * fix class docstring * PR suggestions * doc * doc update and improvements to `_validate_assistant()` --------- Co-authored-by: mosheber <moshe.berchansky@intel.com>
What does this PR do?
Co-Authors: @mosheber, @jmamou, @orenpereg
Assisted Generation (AG; i.e. Speculative Decoding) can accelerate inference speed by using a small assistant model in tandem with the original (target) model. However, it only supports assistant models that use the same tokenizer as the target model. This significantly limits the usability of AG, as only few models have such corresponding assistant models.
This PR alleviates that requirement, allowing AG execution with any assistant model regardless of its tokenizer.
Thus, AG can support any target model (!), allowing acceleration of a wide range of models that was not possible until now.
For example, our initial experiments show the following speedups:
codellama/CodeLlama-13b-Instruct-hfbigcode/tiny_starcoder_pyopenai/humanevalmicrosoft/Phi-3-medium-128k-instructQwen/Qwen2-0.5B-Instructtau/scrollsgoogle/gemma-2-9bdouble7/vicuna-68mcnn_dailymailOur method works by decoding the speculated tokens and re-encoding them using the target tokenizer, and then performing an alignment procedure, to account for inter-tokenizer discrepancies.
Usage example:
where
target_tokenizerandassistant_tokenizerare the respective tokenizers;target_lookbehindandassistant_lookbehindare optional parameters which define the window size to consider for solving inter-tokenizer discrepancies after every generation step of the assistant model.Experimental setup:
1 x A6000 GPU
100 examples per dataset
@gante
CC @lewtun
Before submitting
This PR fixes a typo or improves the docs (you can dismiss the other checks if that's the case).Pull Request section?
Was this discussed/approved via a Github issue or the forum? Please add a link to it if that's the case.documentation guidelines, and
here are tips on formatting docstrings.