2121
2222class TemplateCodeGenerator (BaseCodeGenerator ):
2323 """Code generator using Jinja2 template"""
24-
24+
2525 def __init__ (self , template_path : Optional [str ] = None ):
2626 """
2727 Args:
2828 template_path: Path to Jinja2 template file (optional)
2929 """
3030 self .template_path = template_path
3131 self ._template = None
32-
32+
3333 def generate (
3434 self ,
3535 model_dir : Path ,
@@ -38,37 +38,37 @@ def generate(
3838 ) -> Path :
3939 """
4040 Generate run_model.py extraction script using template
41-
41+
4242 Args:
4343 model_dir: Path to model directory
4444 model_metadata: Model metadata extracted from configuration
4545 output_dir: Output directory for generated script
46-
46+
4747 Returns:
4848 Path to generated script file
4949 """
5050 try :
5151 output_dir .mkdir (parents = True , exist_ok = True )
5252 code = self ._generate_code (model_dir , model_metadata )
53-
53+
5454 script_path = output_dir / "run_model.py"
55- with open (script_path , 'w' , encoding = ' utf-8' ) as f :
55+ with open (script_path , "w" , encoding = " utf-8" ) as f :
5656 f .write (code )
57-
57+
5858 return script_path
5959 except Exception as e :
6060 raise CodeGenError (f"Failed to generate code: { e } " ) from e
61-
61+
6262 def _generate_code (self , model_dir : Path , model_metadata : ModelMetadata ) -> str :
6363 """Generate complete extraction script code string"""
6464 # Generate model loading code
6565 load_code = self ._generate_model_loader (model_dir , model_metadata )
66-
66+
6767 # Generate input construction code
6868 input_code = self ._generate_input_code (model_metadata )
69-
69+
7070 # Generate main code
71- code = f''' import torch
71+ code = f""" import torch
7272try:
7373 from transformers import AutoModel
7474except ImportError:
@@ -97,41 +97,49 @@ def main():
9797
9898if __name__ == "__main__":
9999 main()
100- '''
100+ """
101101 return code
102-
103- def _generate_model_loader (self , model_dir : Path , model_metadata : ModelMetadata ) -> str :
102+
103+ def _generate_model_loader (
104+ self , model_dir : Path , model_metadata : ModelMetadata
105+ ) -> str :
104106 """Generate model loading code based on model type"""
105107 model_path = str (model_dir ).replace ("\\ " , "/" )
106-
107- if model_metadata .model_type in [' bert' , ' gpt' , 't5' , ' roberta' ]:
108+
109+ if model_metadata .model_type in [" bert" , " gpt" , "t5" , " roberta" ]:
108110 return f'model = AutoModel.from_pretrained("{ model_path } ")'
109- elif model_metadata .model_type in [' resnet' , ' vgg' , ' densenet' ]:
110- return f' model = torchvision.models.{ model_metadata .model_type } (pretrained=True)'
111+ elif model_metadata .model_type in [" resnet" , " vgg" , " densenet" ]:
112+ return f" model = torchvision.models.{ model_metadata .model_type } (pretrained=True)"
111113 else :
112114 # Generic loading
113115 return f'model = AutoModel.from_pretrained("{ model_path } ")'
114-
116+
115117 def _generate_input_code (self , model_metadata : ModelMetadata ) -> str :
116118 """Generate input tensor construction code based on model metadata"""
117- lines = [' inputs = {}' ]
118-
119+ lines = [" inputs = {}" ]
120+
119121 for name , shape in model_metadata .input_shapes .items ():
120122 dtype = model_metadata .input_dtypes .get (name , "int64" )
121123 torch_dtype = self ._get_torch_dtype (dtype )
122124 shape_tuple = f"({ ', ' .join (map (str , shape ))} )"
123-
125+
124126 if dtype == "int64" :
125127 if "input_ids" in name .lower ():
126128 safe_vocab_size = self ._calculate_safe_vocab_size (model_metadata )
127- lines .append (f'inputs["{ name } "] = torch.randint(0, { safe_vocab_size } , { shape_tuple } , dtype={ torch_dtype } )' )
129+ lines .append (
130+ f'inputs["{ name } "] = torch.randint(0, { safe_vocab_size } , { shape_tuple } , dtype={ torch_dtype } )'
131+ )
128132 else :
129- lines .append (f'inputs["{ name } "] = torch.ones({ shape_tuple } , dtype={ torch_dtype } )' )
133+ lines .append (
134+ f'inputs["{ name } "] = torch.ones({ shape_tuple } , dtype={ torch_dtype } )'
135+ )
130136 else :
131- lines .append (f'inputs["{ name } "] = torch.randn({ shape_tuple } , dtype={ torch_dtype } )' )
132-
137+ lines .append (
138+ f'inputs["{ name } "] = torch.randn({ shape_tuple } , dtype={ torch_dtype } )'
139+ )
140+
133141 return "\n " .join (lines )
134-
142+
135143 def _get_torch_dtype (self , dtype : str ) -> str :
136144 """Convert dtype string to torch dtype"""
137145 if dtype == "int64" :
@@ -140,19 +148,19 @@ def _get_torch_dtype(self, dtype: str) -> str:
140148 return "torch.float32"
141149 else :
142150 return f"torch.{ dtype } "
143-
151+
144152 def _calculate_safe_vocab_size (self , model_metadata : ModelMetadata ) -> int :
145153 """Calculate safe vocabulary size for input generation"""
146154 if model_metadata .embedding_size :
147155 return max (MIN_SAFE_VOCAB_SIZE , model_metadata .embedding_size - 1 )
148-
156+
149157 vocab_size = model_metadata .vocab_size or DEFAULT_VOCAB_SIZE
150158 model_type = (model_metadata .model_type or "" ).lower ()
151-
159+
152160 # Model-type-specific limits
153161 if self ._is_large_vocab_model_type (model_type ):
154162 return FIXED_SAFE_LIMIT
155-
163+
156164 # Size-based strategy
157165 if vocab_size > LARGE_VOCAB_THRESHOLD :
158166 return FIXED_SAFE_LIMIT
@@ -162,11 +170,15 @@ def _calculate_safe_vocab_size(self, model_metadata: ModelMetadata) -> int:
162170 return max (MIN_SAFE_VOCAB_SIZE , int (vocab_size * MEDIUM_VOCAB_RATIO ))
163171 else :
164172 return max (MIN_SAFE_VOCAB_SIZE , int (vocab_size * SMALL_VOCAB_RATIO ))
165-
173+
166174 def _is_large_vocab_model_type (self , model_type : str ) -> bool :
167175 """Check if model type typically has large vocabulary but small embedding"""
168- return "xlm-roberta" in model_type or "xlm_roberta" in model_type or "roberta" in model_type
169-
176+ return (
177+ "xlm-roberta" in model_type
178+ or "xlm_roberta" in model_type
179+ or "roberta" in model_type
180+ )
181+
170182 def _indent (self , text : str , spaces : int ) -> str :
171183 """Indent text by specified spaces"""
172184 indent = " " * spaces
0 commit comments