Spaces:
Sleeping
Sleeping
Julian-Hans
commited on
Commit
•
fa554aa
1
Parent(s):
a15bc9b
implemented option to use inference endpoints, implemented parameter selection, updated UI, cleaned up return formats of models
Browse files- app.py +50 -9
- blip_image_caption_large.py +15 -2
- config.py +14 -1
- musicgen_small.py +33 -1
- phi3_mini_4k_instruct.py +18 -3
app.py
CHANGED
@@ -16,7 +16,12 @@ log.basicConfig(level=log.INFO)
|
|
16 |
|
17 |
|
18 |
class Image_To_Music:
|
19 |
-
def __init__(self):
|
|
|
|
|
|
|
|
|
|
|
20 |
self.image_path = None
|
21 |
self.generated_caption = None
|
22 |
self.generated_description = None
|
@@ -44,14 +49,14 @@ class Image_To_Music:
|
|
44 |
self.image_caption_model = Blip_Image_Caption_Large()
|
45 |
|
46 |
self.image_path = image_path
|
47 |
-
self.generated_caption = self.image_caption_model.
|
48 |
|
49 |
# delete model to free up ram
|
50 |
del self.image_caption_model
|
51 |
gc.collect()
|
52 |
|
53 |
self.caption_generation_duration = time.time() - caption_start_time
|
54 |
-
log.info(f"Captioning Complete in {self.caption_generation_duration:.2f} seconds: {self.generated_caption}")
|
55 |
return self.generated_caption
|
56 |
|
57 |
def generate_description(self):
|
@@ -65,14 +70,14 @@ class Image_To_Music:
|
|
65 |
{"role": "system", "content": "You are an image caption to song description converter with a deep understanding of Music and Art. You are given the caption of an image. Your task is to generate a textual description of a musical piece that fits the caption. The description should be detailed and vivid, and should include the genre, mood, instruments, tempo, and other relevant information about the music. You should also use your knowledge of art and visual aesthetics to create a musical piece that complements the image. Only output the description of the music, without any explanation or introduction. Be concise."},
|
66 |
{"role": "user", "content": self.generated_caption},
|
67 |
]
|
68 |
-
self.generated_description = self.text_generation_model.
|
69 |
|
70 |
# delete model to free up ram
|
71 |
del self.text_generation_model
|
72 |
gc.collect()
|
73 |
|
74 |
self.description_generation_duration = time.time() - description_start_time
|
75 |
-
log.info(f"Description Generation Complete in {self.description_generation_duration:.2f} seconds: {self.generated_description}")
|
76 |
return self.generated_description
|
77 |
|
78 |
def generate_music(self):
|
@@ -82,14 +87,14 @@ class Image_To_Music:
|
|
82 |
# load model
|
83 |
self.music_generation_model = Musicgen_Small()
|
84 |
|
85 |
-
self.music_generation_model.
|
86 |
|
87 |
# delete model to free up ram
|
88 |
del self.music_generation_model
|
89 |
gc.collect()
|
90 |
|
91 |
self.music_generation_duration = time.time() - music_start_time
|
92 |
-
log.info(f"Music Generation Complete in {self.music_generation_duration:.2f} seconds: {self.audio_path}")
|
93 |
return self.audio_path
|
94 |
|
95 |
def get_durations(self):
|
@@ -112,12 +117,49 @@ class Image_To_Music:
|
|
112 |
return [self.generated_caption, self.generated_description, self.audio_path, self.get_durations()]
|
113 |
|
114 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
# Gradio UI
|
116 |
def gradio():
|
117 |
# Define Gradio Interface, information from (https://www.gradio.app/docs/chatinterface)
|
118 |
with gr.Blocks() as demo:
|
119 |
gr.Markdown("<h1 style='text-align: center;'> ⛺ Image to Music Generator 🎼</h1>")
|
120 |
image_input = gr.Image(type="filepath", label="Upload Image")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
with gr.Row():
|
122 |
caption_output = gr.Textbox(label="Image Caption")
|
123 |
music_description_output = gr.Textbox(label="Music Description")
|
@@ -126,8 +168,7 @@ def gradio():
|
|
126 |
music_output = gr.Audio(label="Generated Music")
|
127 |
# Button to trigger the process
|
128 |
generate_button = gr.Button("Generate Music")
|
129 |
-
|
130 |
-
generate_button.click(fn=itm.run, inputs=image_input, outputs=[caption_output, music_description_output, music_output, durations])
|
131 |
# Launch Gradio app
|
132 |
demo.launch()
|
133 |
|
|
|
16 |
|
17 |
|
18 |
class Image_To_Music:
|
19 |
+
def __init__(self, use_local_caption=False, use_local_llm=False, use_local_musicgen=False):
|
20 |
+
|
21 |
+
self.use_local_llm = use_local_llm
|
22 |
+
self.use_local_caption = use_local_caption
|
23 |
+
self.use_local_musicgen = use_local_musicgen
|
24 |
+
|
25 |
self.image_path = None
|
26 |
self.generated_caption = None
|
27 |
self.generated_description = None
|
|
|
49 |
self.image_caption_model = Blip_Image_Caption_Large()
|
50 |
|
51 |
self.image_path = image_path
|
52 |
+
self.generated_caption = self.image_caption_model.caption_image(self.image_path, self.use_local_caption)
|
53 |
|
54 |
# delete model to free up ram
|
55 |
del self.image_caption_model
|
56 |
gc.collect()
|
57 |
|
58 |
self.caption_generation_duration = time.time() - caption_start_time
|
59 |
+
log.info(f"Captioning Complete in {self.caption_generation_duration:.2f} seconds: {self.generated_caption} - used local model: {self.use_local_caption}")
|
60 |
return self.generated_caption
|
61 |
|
62 |
def generate_description(self):
|
|
|
70 |
{"role": "system", "content": "You are an image caption to song description converter with a deep understanding of Music and Art. You are given the caption of an image. Your task is to generate a textual description of a musical piece that fits the caption. The description should be detailed and vivid, and should include the genre, mood, instruments, tempo, and other relevant information about the music. You should also use your knowledge of art and visual aesthetics to create a musical piece that complements the image. Only output the description of the music, without any explanation or introduction. Be concise."},
|
71 |
{"role": "user", "content": self.generated_caption},
|
72 |
]
|
73 |
+
self.generated_description = self.text_generation_model.generate_text(messages, self.use_local_llm)
|
74 |
|
75 |
# delete model to free up ram
|
76 |
del self.text_generation_model
|
77 |
gc.collect()
|
78 |
|
79 |
self.description_generation_duration = time.time() - description_start_time
|
80 |
+
log.info(f"Description Generation Complete in {self.description_generation_duration:.2f} seconds: {self.generated_description} - used local model: {self.use_local_llm}")
|
81 |
return self.generated_description
|
82 |
|
83 |
def generate_music(self):
|
|
|
87 |
# load model
|
88 |
self.music_generation_model = Musicgen_Small()
|
89 |
|
90 |
+
self.music_generation_model.generate_music(self.generated_description, self.audio_path, self.use_local_musicgen)
|
91 |
|
92 |
# delete model to free up ram
|
93 |
del self.music_generation_model
|
94 |
gc.collect()
|
95 |
|
96 |
self.music_generation_duration = time.time() - music_start_time
|
97 |
+
log.info(f"Music Generation Complete in {self.music_generation_duration:.2f} seconds: {self.audio_path} - used local model: {self.use_local_musicgen}")
|
98 |
return self.audio_path
|
99 |
|
100 |
def get_durations(self):
|
|
|
117 |
return [self.generated_caption, self.generated_description, self.audio_path, self.get_durations()]
|
118 |
|
119 |
|
120 |
+
def run_image_to_music(image_path, llm_max_new_tokens, llm_temperature, llm_top_p, musicgen_max_seconds, use_local_caption, use_local_llm, use_local_musicgen):
|
121 |
+
config.LLM_MAX_NEW_TOKENS = llm_max_new_tokens
|
122 |
+
config.LLM_TEMPERATURE = llm_temperature
|
123 |
+
config.LLM_TOP_P = llm_top_p
|
124 |
+
config.MUSICGEN_MAX_NEW_TOKENS = musicgen_max_seconds * 51
|
125 |
+
itm = Image_To_Music(use_local_caption=use_local_caption, use_local_llm=use_local_llm, use_local_musicgen=use_local_musicgen)
|
126 |
+
return itm.run(image_path)
|
127 |
+
|
128 |
# Gradio UI
|
129 |
def gradio():
|
130 |
# Define Gradio Interface, information from (https://www.gradio.app/docs/chatinterface)
|
131 |
with gr.Blocks() as demo:
|
132 |
gr.Markdown("<h1 style='text-align: center;'> ⛺ Image to Music Generator 🎼</h1>")
|
133 |
image_input = gr.Image(type="filepath", label="Upload Image")
|
134 |
+
|
135 |
+
|
136 |
+
# ----ATTRIBUTION-START----
|
137 |
+
# LLM: ChatGPT4o
|
138 |
+
# PROMPT: i need 3 checkbox fields that pass booleans to the run_image_to_music function. it should be "Use local Image Captioning" "Use local LLM" "Use local Music Generation". please make it a nice parameter selector
|
139 |
+
# EDITS: /
|
140 |
+
|
141 |
+
# Checkbox parameters
|
142 |
+
with gr.Row():
|
143 |
+
local_captioning = gr.Checkbox(label="Use local Image Captioning", value=False)
|
144 |
+
local_llm = gr.Checkbox(label="Use local LLM", value=False)
|
145 |
+
local_music_gen = gr.Checkbox(label="Use local Music Generation", value=False)
|
146 |
+
# -----ATTRIBUTION-END-----
|
147 |
+
|
148 |
+
# ----ATTRIBUTION-START----
|
149 |
+
# LLM: ChatGPT4o
|
150 |
+
# PROMPT: now, i need sliders for the different models that are used in the product:\n LLM_MAX_NEW_TOKENS = 50\nLLM_TEMPERATURE = 0.7\nLLM_TOP_P = 0.95\nMUSICGEN_MAX_NEW_TOKENS = 256 # 256 = 5 seconds of audio\n they should be in a hidden menu that opens when i click on "advanced options"\nplease label them for the end user and fit them nicely in the following ui: <code>
|
151 |
+
# EDITS: added interactive flags
|
152 |
+
# Advanced options with sliders
|
153 |
+
with gr.Accordion("Advanced Options", open=False):
|
154 |
+
gr.Markdown("<h3>LLM Settings</h3>")
|
155 |
+
llm_max_new_tokens = gr.Slider(1, 200, value=50, step=1, label="LLM Max Tokens", interactive=True)
|
156 |
+
llm_temperature = gr.Slider(0.0, 1.0, value=0.7, step=0.01, label="LLM Temperature", interactive=True)
|
157 |
+
llm_top_p = gr.Slider(0.01, 0.99, value=0.95, step=0.01, label="LLM Top P", interactive=True)
|
158 |
+
|
159 |
+
gr.Markdown("<h3>Music Generation Settings</h3>")
|
160 |
+
musicgen_max_seconds = gr.Slider(1, 30, value=5, step=1, label="MusicGen Duration in Seconds (local model only)", interactive=True)
|
161 |
+
# -----ATTRIBUTION-END-----
|
162 |
+
|
163 |
with gr.Row():
|
164 |
caption_output = gr.Textbox(label="Image Caption")
|
165 |
music_description_output = gr.Textbox(label="Music Description")
|
|
|
168 |
music_output = gr.Audio(label="Generated Music")
|
169 |
# Button to trigger the process
|
170 |
generate_button = gr.Button("Generate Music")
|
171 |
+
generate_button.click(fn=run_image_to_music, inputs=[image_input, llm_max_new_tokens, llm_temperature, llm_top_p, musicgen_max_seconds, local_captioning, local_llm, local_music_gen], outputs=[caption_output, music_description_output, music_output, durations])
|
|
|
172 |
# Launch Gradio app
|
173 |
demo.launch()
|
174 |
|
blip_image_caption_large.py
CHANGED
@@ -1,13 +1,26 @@
|
|
1 |
# external imports
|
2 |
from transformers import pipeline
|
|
|
3 |
|
4 |
# local imports
|
5 |
import config
|
6 |
|
7 |
class Blip_Image_Caption_Large:
|
8 |
def __init__(self):
|
9 |
-
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
def caption_image_local_pipeline(self, image_path):
|
12 |
-
|
|
|
13 |
return result
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# external imports
|
2 |
from transformers import pipeline
|
3 |
+
from huggingface_hub import InferenceClient
|
4 |
|
5 |
# local imports
|
6 |
import config
|
7 |
|
8 |
class Blip_Image_Caption_Large:
|
9 |
def __init__(self):
|
10 |
+
pass
|
11 |
|
12 |
+
def caption_image(self, image_path, use_local_caption):
|
13 |
+
if use_local_caption:
|
14 |
+
return self.caption_image_local_pipeline(image_path)
|
15 |
+
else:
|
16 |
+
return self.caption_image_api(image_path)
|
17 |
+
|
18 |
def caption_image_local_pipeline(self, image_path):
|
19 |
+
self.local_pipeline = pipeline("image-to-text", model=config.IMAGE_CAPTION_MODEL)
|
20 |
+
result = self.local_pipeline(image_path)[0]['generated_text']
|
21 |
return result
|
22 |
+
|
23 |
+
def caption_image_api(self, image_path):
|
24 |
+
client = InferenceClient(config.IMAGE_CAPTION_MODEL, token=config.HF_API_TOKEN)
|
25 |
+
result = client.image_to_text(image_path).generated_text
|
26 |
+
return result
|
config.py
CHANGED
@@ -1,10 +1,23 @@
|
|
|
|
|
|
|
|
|
|
1 |
IMAGE_CAPTION_MODEL = "Salesforce/blip-image-captioning-large"
|
2 |
|
3 |
LLM_MODEL = "microsoft/Phi-3-mini-4k-instruct"
|
4 |
LLM_MAX_LENGTH = 50
|
5 |
LLM_MAX_NEW_TOKENS = 50
|
|
|
|
|
6 |
|
7 |
MUSICGEN_MODEL = "facebook/musicgen-small"
|
|
|
8 |
MUSICGEN_MAX_NEW_TOKENS = 256 # 5 seconds of audio
|
9 |
|
10 |
-
AUDIO_DIR = "Case-Study-1/data/"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import logging as log
|
3 |
+
log.basicConfig(level=log.INFO)
|
4 |
+
|
5 |
IMAGE_CAPTION_MODEL = "Salesforce/blip-image-captioning-large"
|
6 |
|
7 |
LLM_MODEL = "microsoft/Phi-3-mini-4k-instruct"
|
8 |
LLM_MAX_LENGTH = 50
|
9 |
LLM_MAX_NEW_TOKENS = 50
|
10 |
+
LLM_TEMPERATURE = 0.7
|
11 |
+
LLM_TOP_P = 0.95
|
12 |
|
13 |
MUSICGEN_MODEL = "facebook/musicgen-small"
|
14 |
+
MUSICGEN_MODEL_API_URL = f"https://api-inference.huggingface.co/models/{MUSICGEN_MODEL}"
|
15 |
MUSICGEN_MAX_NEW_TOKENS = 256 # 5 seconds of audio
|
16 |
|
17 |
+
AUDIO_DIR = "Case-Study-1/data/"
|
18 |
+
|
19 |
+
HF_API_TOKEN = os.getenv("HF_API_TOKEN")
|
20 |
+
if HF_API_TOKEN:
|
21 |
+
log.info(f"Read HF_API_TOKEN: {HF_API_TOKEN[0:4]}...")
|
22 |
+
else:
|
23 |
+
print("HF_API_TOKEN not found in environment variables.")
|
musicgen_small.py
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
# external imports
|
2 |
from transformers import pipeline
|
|
|
|
|
3 |
import scipy
|
4 |
|
5 |
# local imports
|
@@ -7,8 +9,38 @@ import config
|
|
7 |
|
8 |
class Musicgen_Small:
|
9 |
def __init__(self):
|
10 |
-
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
def generate_music_local_pipeline(self, prompt, audio_path):
|
|
|
13 |
music = self.local_pipeline(prompt, forward_params={"do_sample": True, "max_new_tokens": config.MUSICGEN_MAX_NEW_TOKENS})
|
14 |
scipy.io.wavfile.write(audio_path, rate=music["sampling_rate"], data=music["audio"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# external imports
|
2 |
from transformers import pipeline
|
3 |
+
from io import BytesIO
|
4 |
+
import requests
|
5 |
import scipy
|
6 |
|
7 |
# local imports
|
|
|
9 |
|
10 |
class Musicgen_Small:
|
11 |
def __init__(self):
|
12 |
+
pass
|
13 |
|
14 |
+
def generate_music(self, prompt, audio_path, use_local_musicgen):
|
15 |
+
if use_local_musicgen:
|
16 |
+
self.generate_music_local_pipeline(prompt, audio_path)
|
17 |
+
else:
|
18 |
+
self.generate_music_api(prompt, audio_path)
|
19 |
+
|
20 |
def generate_music_local_pipeline(self, prompt, audio_path):
|
21 |
+
self.local_pipeline = pipeline("text-to-audio", model=config.MUSICGEN_MODEL)
|
22 |
music = self.local_pipeline(prompt, forward_params={"do_sample": True, "max_new_tokens": config.MUSICGEN_MAX_NEW_TOKENS})
|
23 |
scipy.io.wavfile.write(audio_path, rate=music["sampling_rate"], data=music["audio"])
|
24 |
+
|
25 |
+
def generate_music_api(self, prompt, audio_path):
|
26 |
+
headers = {"Authorization": f"Bearer {config.HF_API_TOKEN}"}
|
27 |
+
payload = {
|
28 |
+
"inputs": prompt
|
29 |
+
}
|
30 |
+
|
31 |
+
response = requests.post(config.MUSICGEN_MODEL_API_URL, headers=headers, json=payload)
|
32 |
+
|
33 |
+
# ----ATTRIBUTION-START----
|
34 |
+
# LLM: ChatGPT4o
|
35 |
+
# PROMPT: please save the audio to a .wav file
|
36 |
+
# EDITS: changed variables to match the code
|
37 |
+
|
38 |
+
# Convert the byte content into an audio array
|
39 |
+
audio_buffer = BytesIO(response.content)
|
40 |
+
|
41 |
+
# Use scipy to save the audio, assuming it's a WAV format audio stream
|
42 |
+
# If it's raw PCM audio, you would need to decode it first.
|
43 |
+
with open(audio_path, "wb") as f:
|
44 |
+
f.write(audio_buffer.read())
|
45 |
+
# -----ATTRIBUTION-END-----
|
46 |
+
|
phi3_mini_4k_instruct.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
# external imports
|
2 |
from transformers import pipeline
|
|
|
3 |
|
4 |
# local imports
|
5 |
import config
|
@@ -7,10 +8,24 @@ import config
|
|
7 |
|
8 |
class Phi3_Mini_4k_Instruct:
|
9 |
def __init__(self):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
self.local_pipeline = pipeline("text-generation", model=config.LLM_MODEL, trust_remote_code=True)
|
11 |
self.local_pipeline.model.config.max_length = config.LLM_MAX_LENGTH
|
12 |
self.local_pipeline.model.config.max_new_tokens = config.LLM_MAX_NEW_TOKENS
|
13 |
-
|
14 |
-
|
15 |
-
result = self.local_pipeline(messages)
|
16 |
return result
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# external imports
|
2 |
from transformers import pipeline
|
3 |
+
from huggingface_hub import InferenceClient
|
4 |
|
5 |
# local imports
|
6 |
import config
|
|
|
8 |
|
9 |
class Phi3_Mini_4k_Instruct:
|
10 |
def __init__(self):
|
11 |
+
pass
|
12 |
+
|
13 |
+
def generate_text(self, messages, use_local_llm):
|
14 |
+
if use_local_llm:
|
15 |
+
return self.generate_text_local_pipeline(messages)
|
16 |
+
else:
|
17 |
+
return self.generate_text_api(messages)
|
18 |
+
|
19 |
+
def generate_text_local_pipeline(self, messages):
|
20 |
self.local_pipeline = pipeline("text-generation", model=config.LLM_MODEL, trust_remote_code=True)
|
21 |
self.local_pipeline.model.config.max_length = config.LLM_MAX_LENGTH
|
22 |
self.local_pipeline.model.config.max_new_tokens = config.LLM_MAX_NEW_TOKENS
|
23 |
+
self.local_pipeline.model.config.temperature = config.LLM_TEMPERATURE
|
24 |
+
self.local_pipeline.model.config.top_p = config.LLM_TOP_P
|
25 |
+
result = self.local_pipeline(messages)[-1]['generated_text'][-1]['content']
|
26 |
return result
|
27 |
+
|
28 |
+
def generate_text_api(self, messages):
|
29 |
+
client = InferenceClient(config.LLM_MODEL, token=config.HF_API_TOKEN)
|
30 |
+
result = client.chat_completion(messages, max_tokens=config.LLM_MAX_NEW_TOKENS, temperature=config.LLM_TEMPERATURE, top_p=config.LLM_TOP_P).choices[0].message.content
|
31 |
+
return result
|