Views
No views yet
1import torch
2from transformers import AutoProcessor, AutoModelForSpeechSeq2Seq, AutoTokenizer, AutoModelForCausalLM
3import soundfile as sf
4from model import create_asr_model, modify_llama_blocks, decode_asr_output
5import gc
6import librosa
7import numpy as np
8import os
9from datasets import load_dataset
10
11
12def load_trained_model(model_path):
13 gc.collect()
14 torch.cuda.empty_cache()
15
16 try:
17 if torch.cuda.is_available():
18 torch.cuda.set_per_process_memory_fraction(0.5)
19
20 print("Loading Whisper encoder...")
21 whisper = AutoModelForSpeechSeq2Seq.from_pretrained(
22 "openai/whisper-large-v2",
23 torch_dtype=torch.float16,
24 low_cpu_mem_usage=True,
25 device_map="auto" # 자동으로 메모리 관리
26 )
27 whisper_encoder = whisper.get_encoder()
28
29 print("Loading Llama...")
30 tokenizer = AutoTokenizer.from_pretrained(
31 "meta-llama/Llama-3.2-1B",
32 use_fast=True
33 )
34
35 # 토크나이저 설정
36 tokenizer.pad_token = tokenizer.eos_token
37 tokenizer.padding_side = "left"
38
39 # Llama 모델 설정
40 llama = AutoModelForCausalLM.from_pretrained(
41 "meta-llama/Llama-3.2-1B",
42 torch_dtype=torch.float16,
43 low_cpu_mem_usage=True,
44 device_map="auto" # 자동으로 메모리 관리
45 )
46 llama.config.pad_token_id = tokenizer.pad_token_id
47 llama.resize_token_embeddings(len(tokenizer))
48
49 modified_llama = modify_llama_blocks(llama, num_blocks_to_keep=2)
50 del llama
51 gc.collect()
52
53 print("Creating model...")
54 model = create_asr_model(whisper_encoder, modified_llama)
55 model = model.half()
56
57 print("Loading weights...")
58 state_dict = torch.load(model_path, map_location='cpu')
59
60 # 디버깅 정보 출력
61 print(f"\nModel vocab size: {model.decoder.model.embed_tokens.weight.shape[0]}")
62 print(f"Tokenizer vocab size: {len(tokenizer)}")
63 print(f"BOS token id: {tokenizer.bos_token_id}")
64 print(f"EOS token id: {tokenizer.eos_token_id}")
65 print(f"PAD token id: {tokenizer.pad_token_id}")
66
67 missing, unexpected = model.load_state_dict(
68 {k: v.half() for k, v in state_dict.items()},
69 strict=False
70 )
71
72 print(f"\nMissing keys: {len(missing)}")
73 print(f"Unexpected keys: {len(unexpected)}")
74 processor = AutoProcessor.from_pretrained("openai/whisper-large-v2")
75
76 model.eval()
77
78 return model, processor, tokenizer
79
80 except Exception as e:
81 print(f"Error during model loading: {e}")
82 gc.collect()
83 torch.cuda.empty_cache()
84 raise
85
86def process_audio(audio_path, processor):
87 try:
88 print(f"Loading audio from {audio_path}...")
89 # librosa를 사용하여 자동 리샘플링
90 audio, orig_sr = librosa.load(audio_path)
91
92 # 16kHz로 리샘플링
93 if orig_sr != 16000:
94 print(f"Resampling from {orig_sr}Hz to 16000Hz")
95 audio = librosa.resample(audio, orig_sr=orig_sr, target_sr=16000)
96
97 # 오디오 정규화
98 audio = audio / np.abs(audio).max()
99
100 input_features = processor(
101 audio,
102 sampling_rate=16000,
103 return_tensors="pt"
104 ).input_features.half()
105
106 return input_features
107
108 except Exception as e:
109 print(f"Error processing audio: {e}")
110 raise
111
112def run_inference(model, input_features, tokenizer, max_length=200):
113 try:
114 device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
115 print(f"\nUsing device: {device}")
116
117 with torch.cuda.amp.autocast():
118 with torch.no_grad():
119 if torch.cuda.is_available():
120 model = model.to(device)
121 input_features = input_features.to(device)
122
123 print("\nInput features shape:", input_features.shape)
124
125 # 시작 토큰 설정
126 start_token = tokenizer.bos_token_id
127 print(f"Using start token: {start_token} ({tokenizer.decode([start_token])})")
128
129 decoder_input_ids = torch.tensor([[start_token]],
130 device=device,
131 dtype=torch.long)
132
133 # Greedy decoding
134 max_length = 100
135 generated_ids = []
136
137 for _ in range(max_length):
138 outputs = model(
139 input_features=input_features,
140 decoder_input_ids=decoder_input_ids
141 )
142
143 next_token_logits = outputs.logits[:, -1, :]
144 next_token_id = torch.argmax(next_token_logits, dim=-1).item()
145
146 # Top 5 토큰 출력
147 top_tokens = torch.topk(next_token_logits[0], 5)
148 print("\nTop 5 tokens for position", len(generated_ids))
149 for token_id, logit in zip(top_tokens.indices, top_tokens.values):
150 token = tokenizer.decode([token_id])
151 prob = torch.softmax(top_tokens.values, dim=-1)[0].item()
152 print(f"Token: {token}, Probability: {prob:.4f}")
153
154 generated_ids.append(next_token_id)
155
156 if next_token_id == tokenizer.eos_token_id:
157 break
158
159 decoder_input_ids = torch.cat([
160 decoder_input_ids,
161 torch.tensor([[next_token_id]], device=device)
162 ], dim=-1)
163
164 # 전체 시퀀스 디코딩
165 text = tokenizer.decode(generated_ids, skip_special_tokens=True)
166
167 if torch.cuda.is_available():
168 model = model.cpu()
169 torch.cuda.empty_cache()
170
171 return text
172
173 except Exception as e:
174 print(f"Error during inference: {e}")
175 torch.cuda.empty_cache()
176 raise
177 finally:
178 gc.collect()
179 torch.cuda.empty_cache()
180
181
182def main():
183 try:
184 model_path = "/home/elicer/.cache/huggingface/hub/models--Kyudan--whisperllama/snapshots/3269c93814c84e38f2d1a46935851f4923d73659/best_model_epoch_0.pt"
185
186 # LibriSpeech 테스트 셋 로드 (10개 샘플)
187 print("Loading LibriSpeech test samples...")
188 dataset = load_dataset("librispeech_asr", "clean", split="test", streaming=True)
189 samples = list(dataset.take(10)) # 10개 샘플만 가져오기
190
191 print("Loading model...")
192 model, processor, tokenizer = load_trained_model(model_path)
193
194 # 각 샘플에 대해 추론 실행
195 for idx, sample in enumerate(samples, 1):
196 print(f"\nProcessing sample {idx}/10...")
197 print(f"Speaker ID: {sample['speaker_id']}")
198 print(f"Chapter ID: {sample['chapter_id']}")
199 print(f"Reference text: {sample['text']}")
200
201 # 오디오 처리
202 input_features = processor(
203 sample['audio']['array'],
204 sampling_rate=16000,
205 return_tensors="pt"
206 ).input_features.half()
207
208 # 추론 실행
209 print("Running inference...")
210 transcribed_text = run_inference(model, input_features, tokenizer)
211
212 print("\nTranscription Results:")
213 print("-" * 50)
214 print(f"Model output: {transcribed_text}")
215 print(f"Reference : {sample['text']}")
216 print("-" * 50)
217
218 except Exception as e:
219 print(f"Error in main: {e}")
220 finally:
221 gc.collect()
222 torch.cuda.empty_cache()
223
224if __name__ == "__main__":
225 main()