🚨 🚨 Allow saving and loading multiple "raw" chat template files (#36588)
* Add saving in the new format (but no loading yet!) * Add saving in the new format (but no loading yet!) * A new approach to template files! * make fixup * make fixup, set correct dir * Some progress but need to rework for cached_file * Rework loading handling again * Small fixes * Looks like it's working now! * make fixup * Working! * make fixup * make fixup * Add TODO so I don't miss it * Cleaner control flow with one less indent * Copy the new logic to processing_utils as well * Proper support for dicts of templates * make fixup * define the file/dir names in a single place * Update the processor chat template reload test as well * Add processor loading of multiple templates * Flatten correctly to match tokenizers * Better support when files are empty sometimes * Stop creating those empty templates * Revert changes now we don't have empty templates * Revert changes now we don't have empty templates * Don't support separate template files on the legacy path * Rework/simplify loading code * Make sure it's always a chat_template key in chat_template.json * Update processor handling of multiple templates * Add a full save-loading test to the tokenizer tests as well * Correct un-flattening * New test was incorrect * Correct error/offline handling * Better exception handling * More error handling cleanup * Add skips for test failing on main * Reorder to fix errors * make fixup * clarify legacy processor file docs and location * Update src/transformers/processing_utils.py Co-authored-by: Lucain <lucainp@gmail.com> * Update src/transformers/processing_utils.py Co-authored-by: Lucain <lucainp@gmail.com> * Update src/transformers/processing_utils.py Co-authored-by: Lucain <lucainp@gmail.com> * Update src/transformers/processing_utils.py Co-authored-by: Lucain <lucainp@gmail.com> * Rename to _jinja and _legacy * Stop saving multiple templates in the legacy format * Cleanup the processing code * Cleanup the processing code more * make fixup * make fixup * correct reformatting * Use correct dir name * Fix import location * Use save_jinja_files instead of save_raw_chat_template_files * Correct the test for saving multiple processor templates * Fix type hint * Update src/transformers/utils/hub.py Co-authored-by: Julien Chaumond <julien@huggingface.co> * Patch llava_onevision test * Update src/transformers/processing_utils.py Co-authored-by: Julien Chaumond <julien@huggingface.co> * Update src/transformers/tokenization_utils_base.py Co-authored-by: Julien Chaumond <julien@huggingface.co> * Refactor chat template saving out into a separate function * Update tests for the new default * Don't do chat template saving logic when chat template isn't there * Ensure save_jinja_files is propagated to tokenizer correctly * Trigger tests * Update more tests to new default * Trigger tests --------- Co-authored-by: Lucain <lucainp@gmail.com> Co-authored-by: Julien Chaumond <julien@huggingface.co>
This commit is contained in:
@@ -767,7 +767,7 @@ class ProcessorTesterMixin:
|
||||
existing_tokenizer_template = getattr(processor.tokenizer, "chat_template", None)
|
||||
processor.chat_template = "test template"
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
processor.save_pretrained(tmpdirname)
|
||||
processor.save_pretrained(tmpdirname, save_jinja_files=False)
|
||||
self.assertTrue(Path(tmpdirname, "chat_template.json").is_file())
|
||||
self.assertFalse(Path(tmpdirname, "chat_template.jinja").is_file())
|
||||
reloaded_processor = self.processor_class.from_pretrained(tmpdirname)
|
||||
@@ -777,15 +777,34 @@ class ProcessorTesterMixin:
|
||||
self.assertEqual(getattr(reloaded_processor.tokenizer, "chat_template", None), existing_tokenizer_template)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
processor.save_pretrained(tmpdirname, save_raw_chat_template=True)
|
||||
processor.save_pretrained(tmpdirname)
|
||||
self.assertTrue(Path(tmpdirname, "chat_template.jinja").is_file())
|
||||
self.assertFalse(Path(tmpdirname, "chat_template.json").is_file())
|
||||
self.assertFalse(Path(tmpdirname, "additional_chat_templates").is_dir())
|
||||
reloaded_processor = self.processor_class.from_pretrained(tmpdirname)
|
||||
self.assertEqual(processor.chat_template, reloaded_processor.chat_template)
|
||||
# When we save as single files, tokenizers and processors share a chat template, which means
|
||||
# the reloaded tokenizer should get the chat template as well
|
||||
self.assertEqual(reloaded_processor.chat_template, reloaded_processor.tokenizer.chat_template)
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
processor.chat_template = {"default": "a", "secondary": "b"}
|
||||
processor.save_pretrained(tmpdirname)
|
||||
self.assertTrue(Path(tmpdirname, "chat_template.jinja").is_file())
|
||||
self.assertFalse(Path(tmpdirname, "chat_template.json").is_file())
|
||||
self.assertTrue(Path(tmpdirname, "additional_chat_templates").is_dir())
|
||||
reloaded_processor = self.processor_class.from_pretrained(tmpdirname)
|
||||
self.assertEqual(processor.chat_template, reloaded_processor.chat_template)
|
||||
# When we save as single files, tokenizers and processors share a chat template, which means
|
||||
# the reloaded tokenizer should get the chat template as well
|
||||
self.assertEqual(reloaded_processor.chat_template, reloaded_processor.tokenizer.chat_template)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
# Saving multiple templates in the legacy format is not permitted
|
||||
with tempfile.TemporaryDirectory() as tmpdirname:
|
||||
processor.chat_template = {"default": "a", "secondary": "b"}
|
||||
processor.save_pretrained(tmpdirname, save_jinja_files=False)
|
||||
|
||||
@require_torch
|
||||
def _test_apply_chat_template(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user