Views
No views yet
1import io
2import os
3from urllib.request import urlopen
4
5import torch
6
7import requests
8import soundfile as sf
9from PIL import Image
10from transformers import AutoModelForCausalLM, AutoProcessor, GenerationConfig
11
12# Define model path
13model_id = "tiny-random/phi-4-multimodal"
14
15# Load model and processor
16processor = AutoProcessor.from_pretrained(model_id, trust_remote_code=True)
17model = AutoModelForCausalLM.from_pretrained(
18 model_id,
19 device_map="cuda",
20 torch_dtype="auto",
21 trust_remote_code=True,
22 attn_implementation='flash_attention_2',
23).cuda()
24
25# Load generation config
26generation_config = GenerationConfig.from_pretrained(model_id)
27
28# Define prompt structure
29user_prompt = '<|user|>'
30assistant_prompt = '<|assistant|>'
31prompt_suffix = '<|end|>'
32
33# Part 1: Image Processing
34print("\n--- IMAGE PROCESSING ---")
35image_url = 'https://www.ilankelman.org/stopsigns/australia.jpg'
36prompt = f'{user_prompt}<|image_1|>What is shown in this image?{prompt_suffix}{assistant_prompt}'
37print(f'>>> Prompt\n{prompt}')
38
39# Download and open image
40image = Image.open(requests.get(image_url, stream=True).raw)
41inputs = processor(text=prompt, images=image, return_tensors='pt').to('cuda:0')
42
43# Generate response
44generate_ids = model.generate(
45 **inputs,
46 max_new_tokens=8,
47 generation_config=generation_config,
48)
49generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
50response = processor.batch_decode(
51 generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False
52)[0]
53print(f'>>> Response\n{response}')
54
55# Part 2: Audio Processing
56print("\n--- AUDIO PROCESSING ---")
57audio_url = "https://upload.wikimedia.org/wikipedia/commons/b/b0/Barbara_Sahakian_BBC_Radio4_The_Life_Scientific_29_May_2012_b01j5j24.flac"
58speech_prompt = "Transcribe the audio to text, and then translate the audio to French. Use <sep> as a separator between the original transcript and the translation."
59prompt = f'{user_prompt}<|audio_1|>{speech_prompt}{prompt_suffix}{assistant_prompt}'
60print(f'>>> Prompt\n{prompt}')
61
62# Downlowd and open audio file
63audio, samplerate = sf.read(io.BytesIO(urlopen(audio_url).read()))
64
65# Process with the model
66inputs = processor(text=prompt, audios=[(audio, samplerate)], return_tensors='pt').to('cuda:0')
67
68generate_ids = model.generate(
69 **inputs,
70 max_new_tokens=8,
71 generation_config=generation_config,
72)
73generate_ids = generate_ids[:, inputs['input_ids'].shape[1]:]
74response = processor.batch_decode(
75 generate_ids, skip_special_tokens=True, clean_up_tokenization_spaces=False
76)[0]
77print(f'>>> Response\n{response}')1import json
2import shutil
3import sys
4from pathlib import Path
5
6import torch
7
8from huggingface_hub import hf_hub_download
9from transformers import (
10 AutoConfig,
11 AutoModelForCausalLM,
12 AutoProcessor,
13 AutoTokenizer,
14 GenerationConfig,
15 pipeline,
16 set_seed,
17)
18
19source_model_id = "microsoft/Phi-4-multimodal-instruct"
20save_folder = "/tmp/tiny-random/phi-4-multimodal"
21Path(save_folder).mkdir(exist_ok=True)
22AutoTokenizer.from_pretrained(source_model_id).save_pretrained(save_folder)
23
24# preprocessor config
25for json_file in ['preprocessor_config.json', 'processor_config.json', 'config.json']:
26 with open(hf_hub_download(source_model_id, json_file), 'r') as f:
27 config = json.load(f)
28 auto_map = config.get('auto_map', {})
29 for key, value in auto_map.items():
30 if '.' in value:
31 auto_map[key] = f'{source_model_id}--{value}'
32 with open(f'{save_folder}/{json_file}', 'w') as f:
33 json.dump(config, f, indent=2)
34
35# model config
36with open(f'{save_folder}/config.json', 'r') as f:
37 config = json.load(f)
38
39config['hidden_size'] = 16
40config['intermediate_size'] = 32
41config['num_attention_heads'] = 2
42config['num_hidden_layers'] = 2
43config['num_key_value_heads'] = 1
44
45config['audio_processor']['config']['num_blocks'] = 2
46config['audio_processor']['config']['attention_dim'] = 16
47config['audio_processor']['config']['attention_heads'] = 2
48config['audio_processor']['config']['nemo_conv_settings']['conv_channels'] = 16
49config['audio_processor']['config']['depthwise_seperable_out_channel'] = 16
50config['audio_processor']['config']['ext_pw_out_channel'] = 16
51config['audio_processor']['config']['linear_units'] = 24
52
53config['vision_lora']['r'] = 8
54config['vision_lora']['lora_alpha'] = 16
55config['speech_lora']['r'] = 8
56config['speech_lora']['lora_alpha'] = 16
57
58config['rope_scaling']['long_factor'] = [1.0] * 3
59config['rope_scaling']['short_factor'] = [1.0] * 3
60
61with open(f'{save_folder}/config.json', 'w') as f:
62 json.dump(config, f, indent=2)
63
64config = AutoConfig.from_pretrained(
65 save_folder,
66 trust_remote_code=True,
67)
68
69Path(save_folder, 'phi4mm').mkdir(exist_ok=True)
70for python_files in ['modeling_phi4mm.py', 'configuration_phi4mm.py', 'speech_conformer_encoder.py', 'vision_siglip_navit.py', 'processing_phi4mm.py']:
71 with open(hf_hub_download(source_model_id, python_files), 'r') as f:
72 codes = f.read()
73 with open(f'{save_folder}/phi4mm/{python_files}', 'w') as f:
74 f.write(codes)
75with open(Path(save_folder, 'phi4mm/vision_siglip_navit.py'), 'r') as f:
76 codes = f.read()
77codes = codes.replace('def get_siglip_vision_model', '# modified for tiny-random\ndef get_siglip_vision_model')
78codes = codes.replace('"hidden_size": 1152,', '"hidden_size": 16,')
79codes = codes.replace('"intermediate_size": 4304,', '"intermediate_size": 32,')
80codes = codes.replace('"num_attention_heads": 16,', '"num_attention_heads": 2,')
81codes = codes.replace('"num_hidden_layers": 27,', '"num_hidden_layers": 2,')
82with open(Path(save_folder, 'phi4mm/vision_siglip_navit.py'), 'w') as f:
83 f.write(codes)
84
85sys.path.append(str(Path(save_folder)))
86from phi4mm.modeling_phi4mm import Phi4MMForCausalLM
87print(Phi4MMForCausalLM) # ensure imported
88model = Phi4MMForCausalLM(config).to(torch.bfloat16)
89
90set_seed(42)
91with torch.no_grad():
92 for name, p in sorted(model.named_parameters()):
93 torch.nn.init.normal_(p, 0, 0.5)
94 print(name, p.shape)
95
96model.save_pretrained(Path(save_folder))
97shutil.rmtree(Path(save_folder, 'phi4mm'))
98generation_config = GenerationConfig.from_pretrained(
99 source_model_id, trust_remote_code=True,
100)
101generation_config.save_pretrained(save_folder)