optimum/exporters/executorch/utils.py (60 lines of code) (raw):

# Copyright 2025 The HuggingFace Team. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from typing import List, Optional, Set import torch from transformers import GenerationConfig, PretrainedConfig def save_config_to_constant_methods( config: PretrainedConfig, generation_config: Optional[GenerationConfig] = None, **kwargs, ): # Initialize metadata with values from model config head_dim = None if ( hasattr(config, "hidden_size") and hasattr(config, "num_attention_heads") and isinstance(config.num_attention_heads, int) ): head_dim = config.hidden_size / config.num_attention_heads metadata = { "get_dtype": 5 if config.torch_dtype == torch.float16 else 6, "get_bos_id": getattr(config, "bos_token_id", None), "get_eos_id": getattr(config, "eos_token_id", None), "get_head_dim": head_dim, "get_n_kv_heads": getattr(config, "num_key_value_heads", None), "get_n_layers": getattr(config, "num_hidden_layers", None), "get_vocab_size": getattr(config, "vocab_size", None), "get_max_batch_size": 1, "get_max_seq_len": getattr(config, "max_position_embeddings", None), "use_kv_cache": getattr(generation_config, "use_cache", None), "sliding_window": getattr(config, "sliding_window", None), "decoder_start_token_id": getattr(config, "decoder_start_token_id", None), "use_sdpa_with_kv_cache": "custom_sdpa" in config._attn_implementation, } # Safely access fields from generation_config if it exists if generation_config is not None: # Check for cache_config and its attributes cache_config = getattr(generation_config, "cache_config", None) if cache_config is not None: max_batch_size = getattr(cache_config, "batch_size", None) max_seq_len = getattr(cache_config, "max_cache_len", None) if max_batch_size is not None: metadata["get_max_batch_size"] = max_batch_size if max_seq_len is not None: metadata["get_max_seq_len"] = max_seq_len # Combine with any additional kwargs and filter out None values return {k: v for k, v in {**metadata, **kwargs}.items() if v is not None} def verify_eos_tokens_in_tokenizer(model_eos_ids: List[int], tokenizer) -> bool: """ Verifies that the model's EOS token IDs are present in the tokenizer's set of potential end-of-sequence tokens. Args: model_eos_ids: A list of EOS token IDs recorded int the PTE file (the source of truth). tokenizer: The Hugging Face tokenizer instance to check. Returns: True if at least one model EOS ID is found among the tokenizer's potential EOS tokens, False otherwise. """ if not model_eos_ids: print("Warning: model_eos_ids list is empty. No verification can be performed.") return True candidate_eos_ids: Set[int] = set() # 1. Check primary eos_token and pad_token attributes if tokenizer.eos_token_id is not None: candidate_eos_ids.add(tokenizer.eos_token_id) if tokenizer.pad_token_id is not None: candidate_eos_ids.add(tokenizer.pad_token_id) # 2. Check all tokens listed in the special_tokens_map for token_string in tokenizer.special_tokens_map.values(): if token_string: # Use convert_tokens_to_ids for robustness token_id = tokenizer.convert_tokens_to_ids(token_string) if isinstance(token_id, int): candidate_eos_ids.add(token_id) # 3. Check added tokens for "end-of-X" patterns for token_id, added_token in tokenizer.added_tokens_decoder.items(): token_str = added_token.content.lower() # Heuristic to find tokens that signify an end if "end" in token_str or token_str.startswith("</"): candidate_eos_ids.add(token_id) # The check: is any "true" ID present in the candidate set? is_valid = any(model_id in candidate_eos_ids for model_id in model_eos_ids) return is_valid