benjamin5607 commited on
Commit
5884655
ยท
verified ยท
1 Parent(s): 102cca0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -73
app.py CHANGED
@@ -1,90 +1,118 @@
1
  import os
2
  import re
3
- import requests
4
  import uuid
5
- import scipy.io.wavfile
6
- import numpy as np
7
  import torch
8
- from transformers import pipeline
 
 
 
 
9
 
10
- # Hugging Face ํ† ํฐ ๋ฐ ๋ชจ๋ธ ์„ค์ •
11
- HF_TOKEN = os.getenv("HF_TOKEN")
12
- MODEL_ID = "Qwen/Qwen2.5-7B-Instruct"
 
 
13
 
14
- # ์Œ์•… ๋ชจ๋ธ ๋กœ๋“œ (๊ธฐ์กด ์œ ์ง€)
15
- try:
16
- music_synthesiser = pipeline("text-to-audio", "facebook/musicgen-small")
17
- except Exception as e:
18
- print(f"Music Model Load Error: {e}")
19
- music_synthesiser = None
 
 
 
 
 
 
 
 
20
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  async def band_consulting(user_input, member_name, lang_code):
22
  req_id = str(uuid.uuid4())[:8]
23
- voice_path = f"/tmp/v_{req_id}.mp3"
24
  music_path = f"/tmp/m_{req_id}.wav"
25
 
26
- # 1. Qwen์šฉ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ๊ตฌ์„ฑ (Gemini๋ณด๋‹ค ๋” ๊ฐ•๋ ฅํ•˜๊ฒŒ ์ง€์‹œ)
27
- system_instruction = f"""
28
- You are '{member_name}', a professional rock band member.
29
- [Language Rules] Respond ONLY in {lang_code}.
30
- [Output Format]
31
- 1. Short advice (under 5 lines).
32
- 2. Detailed sheet music/advice inside [TAB] tags.
33
- 3. Music generation prompt inside [MUSIC: English Prompt] tags.
34
- """
35
-
36
- try:
37
- # 2. Hugging Face Inference API ํ˜ธ์ถœ
38
- api_url = f"https://api-inference.huggingface.co/models/{MODEL_ID}"
39
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
40
-
41
- prompt = f"<|im_start|>system\n{system_instruction}<|im_end|>\n<|im_start|>user\n{user_input}<|im_end|>\n<|im_start|>assistant\n"
42
-
43
- payload = {
44
- "inputs": prompt,
45
- "parameters": {"max_new_tokens": 1024, "temperature": 0.7, "top_p": 0.9}
46
- }
47
 
48
- response = requests.post(api_url, headers=headers, json=payload, timeout=20)
49
- res_json = response.json()
 
 
 
 
 
 
 
 
 
 
 
50
 
51
- # ์‘๋‹ต์ด ๋น„์–ด์žˆ๊ฑฐ๋‚˜ ์—๋Ÿฌ์ผ ๊ฒฝ์šฐ 'Improv Mode' ๋ฐœ๋™
52
- if not res_json or 'error' in res_json:
53
- ai_text_raw = "์ด๋ด ๋ฆฌ๋”, ์ง€๊ธˆ์€ ๋ง๋ณด๋‹ค ์—ฐ์ฃผ๊ฐ€ ํ•„์š”ํ•œ ์ˆœ๊ฐ„์ด์•ผ! ๋‚ด ์ฆ‰ํฅ ์—ฐ์ฃผ๋ฅผ ๋“ค์–ด๋ด. [TAB] ์ฆ‰ํฅ ์—ฐ์ฃผ ๋ชจ๋“œ ๊ฐ€๋™ [MUSIC: aggressive hard rock guitar solo]"
54
- else:
55
- # Qwen์€ ์ž…๋ ฅ ํ”„๋กฌํ”„ํŠธ๋ฅผ ํฌํ•จํ•ด์„œ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ assistant ์‘๋‹ต๋งŒ ์ถ”์ถœ
56
- full_text = res_json[0]['generated_text']
57
- ai_text_raw = full_text.split("assistant\n")[-1].strip()
 
58
 
59
- # 3. ํŒŒ์‹ฑ ๋กœ์ง (Regex ๊ฐ•ํ™”)
60
- tab_match = re.search(r'\[TAB\](.*?)(\[|$)', ai_text_raw, re.DOTALL | re.IGNORECASE)
61
- music_match = re.search(r'\[MUSIC:(.*?)\]', ai_text_raw, re.IGNORECASE)
62
-
63
- tab_display = tab_match.group(1).strip() if tab_match else "์˜ค๋Š˜์˜ ์ฆ‰ํฅ ์กฐ์–ธ: ๋А๋‚Œ๋Œ€๋กœ ์ณ๋ด!"
64
- clean_text = re.sub(r'\[TAB\].*?(\[|$)', '', ai_text_raw, flags=re.DOTALL | re.IGNORECASE)
65
- clean_text = re.sub(r'\[MUSIC:.*?\]', '', clean_text, flags=re.IGNORECASE).strip()
66
-
67
- # ํ…์ŠคํŠธ๊ฐ€ ๋น„์–ด์žˆ์œผ๋ฉด Fallback
68
- if len(clean_text) < 5:
69
- clean_text = "๋ง์ด ํ•„์š” ์—†๋Š” ๋๋‚ด์ฃผ๋Š” ๋ผ์ธ์ด ์ƒ๊ฐ๋‚ฌ์–ด. ๋ฐ”๋กœ ๋“ค์–ด๋ณด์ž๊ณ !"
70
 
71
- # 4. ์Œ์•… ์ƒ์„ฑ (MusicGen ์—ฐ๋™)
72
- music_p = music_match.group(1).strip() if music_match else "energetic rock riff"
73
-
74
- if music_synthesiser:
75
- # ์•ˆ์ „ ํ•„ํ„ฐ ๋‹จ์–ด ์šฐํšŒ (Vocal ๋“ฑ ์ฐจ๋‹จ ๋ฐฉ์ง€)
76
- safe_p = re.sub(r'(laugh|vocal|voice|human)', 'rock guitar', music_p.lower())
77
- music_output = music_synthesiser(safe_p, forward_params={"max_new_tokens": 512})
78
-
79
- # ์˜ค๋””์˜ค ์ฒ˜๋ฆฌ (Float32 -> Int16)
80
- audio_data = np.squeeze(music_output["audio"])
81
- audio_int16 = (audio_data * 32767).astype(np.int16)
82
- scipy.io.wavfile.write(music_path, music_output["sampling_rate"], audio_int16)
83
- else:
84
- music_path = None
85
 
86
- return clean_text, None, music_path, tab_display # voice_path๋Š” ํ•„์š”์‹œ edge_tts ์ถ”๊ฐ€
 
 
 
 
 
 
87
 
88
- except Exception as e:
89
- print(f"Critical System Error: {e}")
90
- return "์‹œ์Šคํ…œ ๊ณผ๋ถ€ํ•˜์ธ๊ฐ€? ํ•˜์ง€๋งŒ ๋ฝ์€ ๋ฉˆ์ถ”์ง€ ์•Š์•„! [MUSIC: basic rock drum beat]", None, None, "Retry Mode"
 
1
  import os
2
  import re
 
3
  import uuid
 
 
4
  import torch
5
+ import numpy as np
6
+ import scipy.io.wavfile
7
+ import gradio as gr
8
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
9
+ from groq import Groq # pip install groq
10
 
11
+ # 1. ๋ชจ๋ธ ์‹ฑ๊ธ€ํ†ค ๊ด€๋ฆฌ ํด๋ž˜์Šค (๋ฉ”๋ชจ๋ฆฌ ํšจ์œจํ™”)
12
+ class ModelManager:
13
+ _llm_pipeline = None
14
+ _music_pipeline = None
15
+ _groq_client = None
16
 
17
+ @classmethod
18
+ def get_qwen(cls):
19
+ if cls._llm_pipeline is None:
20
+ model_id = "Qwen/Qwen2.5-0.5B-Instruct"
21
+ tokenizer = AutoTokenizer.from_pretrained(model_id)
22
+ # CPU ํ™˜๊ฒฝ ์ตœ์ ํ™” ๋กœ๋”ฉ
23
+ model = AutoModelForCausalLM.from_pretrained(
24
+ model_id,
25
+ device_map="cpu",
26
+ torch_dtype=torch.float32,
27
+ low_cpu_mem_usage=True
28
+ )
29
+ cls._llm_pipeline = pipeline("text-generation", model=model, tokenizer=tokenizer)
30
+ return cls._llm_pipeline
31
 
32
+ @classmethod
33
+ def get_groq(cls):
34
+ api_key = os.getenv("GROQ_API_KEY")
35
+ if cls._groq_client is None and api_key:
36
+ cls._groq_client = Groq(api_key=api_key)
37
+ return cls._groq_client
38
+
39
+ @classmethod
40
+ def get_music(cls):
41
+ if cls._music_pipeline is None:
42
+ # CPU์—์„œ ๊ฐ€์žฅ ๊ฐ€๋ฒผ์šด ์Œ์•… ๋ชจ๋ธ ์œ ์ง€
43
+ cls._music_pipeline = pipeline("text-to-audio", "facebook/musicgen-small", device="cpu")
44
+ return cls._music_pipeline
45
+
46
+ # 2. ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง
47
  async def band_consulting(user_input, member_name, lang_code):
48
  req_id = str(uuid.uuid4())[:8]
 
49
  music_path = f"/tmp/m_{req_id}.wav"
50
 
51
+ # ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ์„ค์ •
52
+ system_prompt = f"You are {member_name}, a rock star. Talk in {lang_code}. Format: 5 lines max + [TAB] details + [MUSIC: prompt]."
53
+
54
+ ai_text_raw = ""
55
+
56
+ # ์—”์ง„ ์„ ํƒ (Groq ์šฐ์„  -> ์‹คํŒจ ์‹œ ๋กœ์ปฌ Qwen)
57
+ groq_client = ModelManager.get_groq()
58
+ if groq_client:
59
+ try:
60
+ chat_completion = groq_client.chat.completions.create(
61
+ messages=[
62
+ {"role": "system", "content": system_prompt},
63
+ {"role": "user", "content": user_input}
64
+ ],
65
+ model="llama-3.3-70b-versatile",
66
+ )
67
+ ai_text_raw = chat_completion.choices[0].message.content
68
+ except Exception as e:
69
+ print(f"Groq Error, switching to Qwen: {e}")
 
 
70
 
71
+ # Groq ์‹คํŒจ ์‹œ ํ˜น์€ ๋ฏธ์„ค์ • ์‹œ ๋กœ์ปฌ Qwen ์‚ฌ์šฉ
72
+ if not ai_text_raw:
73
+ try:
74
+ qwen = ModelManager.get_qwen()
75
+ messages = [
76
+ {"role": "system", "content": system_prompt},
77
+ {"role": "user", "content": user_input}
78
+ ]
79
+ text = qwen.tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
80
+ output = qwen(text, max_new_tokens=512, do_sample=True, temperature=0.7)
81
+ ai_text_raw = output[0]['generated_text'].split("assistant\n")[-1]
82
+ except Exception as e:
83
+ ai_text_raw = "์ด๋ด ๋ฆฌ๋”, ์ง€๊ธˆ์€ ๋ง๋ณด๋‹ค ์—ฐ์ฃผ์•ผ! [TAB] ์ฆ‰ํฅ ์—ฐ์ฃผ ๊ฐ€๋™ [MUSIC: heavy rock guitar riff]"
84
 
85
+ # 3. ํŒŒ์‹ฑ ๋ฐ ์Œ์•… ์ƒ์„ฑ
86
+ tab_match = re.search(r'\[TAB\](.*?)(\[|$)', ai_text_raw, re.DOTALL | re.IGNORECASE)
87
+ music_match = re.search(r'\[MUSIC:(.*?)\]', ai_text_raw, re.IGNORECASE)
88
+
89
+ tab_display = tab_match.group(1).strip() if tab_match else "์ƒ์„ธ ์•…๋ณด ์ค€๋น„ ์ค‘..."
90
+ clean_text = re.sub(r'\[TAB\].*?(\[|$)', '', ai_text_raw, flags=re.DOTALL | re.IGNORECASE)
91
+ clean_text = re.sub(r'\[MUSIC:.*?\]', '', clean_text, flags=re.IGNORECASE).strip()
92
+ music_p = music_match.group(1).strip() if music_match else "rock music"
93
 
94
+ # ์Œ์•… ์ƒ์„ฑ ํŒŒ์ดํ”„๋ผ์ธ
95
+ music_gen = ModelManager.get_music()
96
+ try:
97
+ # CPU ํ™˜๊ฒฝ์„ ์œ„ํ•ด ํ† ํฐ ์ˆ˜๋ฅผ ์ค„์—ฌ ํƒ€์ž„์•„์›ƒ ๋ฐฉ์ง€
98
+ music_output = music_gen(music_p, forward_params={"max_new_tokens": 256})
99
+ audio_data = np.squeeze(music_output["audio"])
100
+ audio_int16 = (audio_data * 32767).astype(np.int16)
101
+ scipy.io.wavfile.write(music_path, music_output["sampling_rate"], audio_int16)
102
+ except:
103
+ music_path = None
 
104
 
105
+ # TTS์šฉ ํ…์ŠคํŠธ (๊ธฐ์กด ๊ตฌ์กฐ ์œ ์ง€)
106
+ tts_text = "\n".join(clean_text.split('\n')[:5])
107
+
108
+ return tts_text, None, music_path, tab_display # voice_path๋Š” edge_tts ๋“ฑ์—์„œ ์ฒ˜๋ฆฌ
 
 
 
 
 
 
 
 
 
 
109
 
110
+ # 3. Gradio ์ธํ„ฐํŽ˜์ด์Šค (Minimal)
111
+ with gr.Blocks() as demo:
112
+ i1 = gr.Textbox(visible=False); i2 = gr.Textbox(visible=False); i3 = gr.Textbox(visible=False)
113
+ o1 = gr.Textbox(visible=False); o2 = gr.Audio(visible=False); o3 = gr.Audio(visible=False); o4 = gr.Textbox(visible=False)
114
+
115
+ btn = gr.Button("GO", visible=False)
116
+ btn.click(band_consulting, [i1, i2, i3], [o1, o2, o3, o4], api_name="predict")
117
 
118
+ demo.queue().launch()