char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
c0c7e147e
char/aliceai-t5-moe
1#!/usr/bin/env python3 2 3import argparse 4import os 5import sys 6import importlib 7 8from transformers import AutoTokenizer ,AutoConfig ,AutoModel 9import torch 10 11# Add parent directory to path for imports 12sys .path .insert (0 ,os .path .join (os .path .dirname (__file__ ),'..' )) 13from utils .common import save_output_data 14 15 16def parse_arguments (): 17parser = argparse .ArgumentParser (description = 'Run original embedding model' ) 18parser .add_argument ( 19'--model-path' , 20'-m' , 21help = 'Path to the model' 22 ) 23parser .add_argument ( 24'--prompts-file' , 25'-p' , 26help = 'Path to file containing prompts (one per line)' 27 ) 28parser .add_argument ( 29'--use-sentence-transformers' , 30action = 'store_true' , 31help = ('Use SentenceTransformer to apply all numbered layers ' 32'(01_Pooling, 02_Dense, 03_Dense, 04_Normalize)' ) 33 ) 34parser .add_argument ( 35'--device' , 36'-d' , 37help = 'Device to use (cpu, cuda, mps, auto)' , 38default = 'auto' 39 ) 40return parser .parse_args () 41 42 43def load_model_and_tokenizer (model_path ,use_sentence_transformers = False ,device = "auto" ): 44if device == "cpu" : 45device_map = {"" :"cpu" } 46"Forcing CPU usage" ) 47elif device == "auto" : 48# On Mac, "auto" device_map can cause issues with accelerate 49# So we detect the best device manually 50if torch .cuda .is_available (): 51device_map = {"" :"cuda" } 52"Using CUDA" ) 53elif torch .backends .mps .is_available (): 54device_map = {"" :"mps" } 55"Using MPS (Apple Metal)" ) 56else : 57device_map = {"" :"cpu" } 58"Using CPU" ) 59else : 60device_map = {"" :device } 61 62if use_sentence_transformers : 63from sentence_transformers import SentenceTransformer 64"Using SentenceTransformer to apply all numbered layers" ) 65model = SentenceTransformer (model_path ) 66tokenizer = model .tokenizer 67config = model [0 ].auto_model .config # ty: ignore[unresolved-attribute] 68else : 69tokenizer = AutoTokenizer .from_pretrained (model_path ) 70config = AutoConfig .from_pretrained (model_path ,trust_remote_code = True ) 71 72# This can be used to override the sliding window size for manual testing. This 73# can be useful to verify the sliding window attention mask in the original model 74# and compare it with the converted .gguf model. 75if hasattr (config ,'sliding_window' ): 76original_sliding_window = config .sliding_window 77f"Modified sliding window: { original_sliding_window } -> { config . sliding_window } " ) 78 79unreleased_model_name = os .getenv ('UNRELEASED_MODEL_NAME' ) 80f"Using unreleased model: { unreleased_model_name } " ) 81if unreleased_model_name : 82model_name_lower = unreleased_model_name .lower () 83unreleased_module_path = f"transformers.models. { model_name_lower } .modular_ { model_name_lower } " 84class_name = f" { unreleased_model_name } Model" 85f"Importing unreleased model module: { unreleased_module_path } " ) 86 87try : 88model_class = getattr (importlib .import_module (unreleased_module_path ),class_name ) 89model = model_class .from_pretrained ( 90model_path , 91device_map = device_map , 92offload_folder = "offload" , 93trust_remote_code = True , 94config = config 95 ) 96except (ImportError ,AttributeError )as e : 97f"Failed to import or load model: { e } " ) 98sys .exit (1 ) 99else : 100model = AutoModel .from_pretrained ( 101model_path , 102device_map = device_map , 103offload_folder = "offload" , 104trust_remote_code = True , 105config = config 106 ) 107f"Model class: { type ( model ) } " ) 108f"Model file: { type ( model ). __module__ } " ) 109 110# Verify the model is using the correct sliding window 111if hasattr (model .config ,'sliding_window' ): 112f"Model's sliding_window: { model . config . sliding_window } " ) 113else : 114"Model config does not have sliding_window attribute" ) 115 116return model ,tokenizer ,config 117 118 119def get_prompt (args ): 120if args .prompts_file : 121try : 122with open (args .prompts_file ,'r' ,encoding = 'utf-8' )as f : 123return f .read ().strip () 124except FileNotFoundError : 125f"Error: Prompts file ' { args . prompts_file } ' not found" ) 126sys .exit (1 ) 127except Exception as e : 128f"Error reading prompts file: { e } " ) 129sys .exit (1 ) 130else : 131return "Hello world today" 132 133 134def main (): 135args = parse_arguments () 136 137model_path = os .environ .get ('EMBEDDING_MODEL_PATH' ,args .model_path ) 138if model_path is None : 139"Error: Model path must be specified either via --model-path argument " 140"or EMBEDDING_MODEL_PATH environment variable" ) 141sys .exit (1 ) 142 143# Determine if we should use SentenceTransformer 144use_st = ( 145args .use_sentence_transformers or os .environ .get ('USE_SENTENCE_TRANSFORMERS' ,'' ).lower ()in ('1' ,'true' ,'yes' ) 146 ) 147 148model ,tokenizer ,config = load_model_and_tokenizer (model_path ,use_st ,args .device ) 149 150# Get the device the model is on 151if not use_st : 152device = next (model .parameters ()).device 153else : 154# For SentenceTransformer, get device from the underlying model 155device = next (model [0 ].auto_model .parameters ()).device 156 157model_name = os .path .basename (model_path ) 158 159prompt_text = get_prompt (args ) 160texts = [prompt_text ] 161 162with torch .no_grad (): 163if use_st : 164embeddings = model .encode (texts ,convert_to_numpy = True ) 165all_embeddings = embeddings # Shape: [batch_size, hidden_size] 166 167encoded = tokenizer ( 168texts , 169padding = True , 170truncation = True , 171return_tensors = "pt" 172 ) 173tokens = encoded ['input_ids' ][0 ] 174token_ids = tokens .cpu ().tolist () 175token_strings = tokenizer .convert_ids_to_tokens (tokens ) 176for i , (token_id ,token_str )in enumerate (zip (tokens ,token_strings )): 177f" { token_id :6d } -> ' { token_str } '" ) 178 179f"Embeddings shape (after all SentenceTransformer layers): { all_embeddings . shape } " ) 180f"Embedding dimension: { all_embeddings . shape [ 1 ] if len ( all_embeddings . shape ) > 1 else all_embeddings . shape [ 0 ] } " ) 181else : 182# Standard approach: use base model output only 183encoded = tokenizer ( 184texts , 185padding = True , 186truncation = True , 187return_tensors = "pt" 188 ) 189 190tokens = encoded ['input_ids' ][0 ] 191token_ids = tokens .cpu ().tolist () 192token_strings = tokenizer .convert_ids_to_tokens (tokens ) 193for i , (token_id ,token_str )in enumerate (zip (tokens ,token_strings )): 194f" { token_id :6d } -> ' { token_str } '" ) 195 196# Move inputs to the same device as the model 197encoded = {k :v .to (device )for k ,v in encoded .items ()} 198outputs = model (** encoded ) 199hidden_states = outputs .last_hidden_state # Shape: [batch_size, seq_len, hidden_size] 200 201all_embeddings = hidden_states [0 ].float ().cpu ().numpy ()# Shape: [seq_len, hidden_size] 202 203f"Hidden states shape: { hidden_states . shape } " ) 204f"All embeddings shape: { all_embeddings . shape } " ) 205f"Embedding dimension: { all_embeddings . shape [ 1 ] } " ) 206 207if len (all_embeddings .shape )== 1 : 208n_embd = all_embeddings .shape [0 ] 209n_embd_count = 1 210all_embeddings = all_embeddings .reshape (1 ,- 1 ) 211else : 212n_embd = all_embeddings .shape [1 ] 213n_embd_count = all_embeddings .shape [0 ] 214 215for j in range (n_embd_count ): 218embedding = all_embeddings [j ] 219f"embedding { j } : " ,end = "" ) 220 221# Print first 3 values 222for i in range (min (3 ,n_embd )): 223f" { embedding [ i ]:9.6f } " ,end = "" ) 224 225" ... " ,end = "" ) 226 227# Print last 3 values 228for i in range (n_embd - 3 ,n_embd ): 229f" { embedding [ i ]:9.6f } " ,end = "" ) 230 231# New line 232 233flattened_embeddings = all_embeddings .flatten () 236f"Total values: { len ( flattened_embeddings ) } ( { n_embd_count } embeddings × { n_embd } dimensions)" ) 237"" ) 238 239save_output_data (flattened_embeddings ,token_ids ,prompt_text ,model_name ,type_suffix = "-embeddings" ) 240 241 242if __name__ == "__main__" : 243main ()