benjamin5607 commited on
Commit
f2609ff
ยท
verified ยท
1 Parent(s): da89e23

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +30 -97
app.py CHANGED
@@ -4,119 +4,52 @@ import edge_tts
4
  import asyncio
5
  import os
6
 
7
- # 1. ๊ตฌ๊ธ€ ์ œ๋ฏธ๋‚˜์ด(๋‡Œ) ์—ฐ๊ฒฐ
8
- # (Settings์—์„œ ์„ค์ •ํ•œ ๋น„๋ฐ€ํ‚ค๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค)
9
  GENAI_KEY = os.getenv("GEMINI_KEY")
10
  genai.configure(api_key=GENAI_KEY)
11
-
12
- # ๋ชจ๋ธ ์„ค์ • (๊ฐ€๋ณ๊ณ  ๋น ๋ฅธ Flash ๋ชจ๋ธ ์‚ฌ์šฉ)
13
  model = genai.GenerativeModel('gemini-1.5-flash')
14
 
15
- # 2. ๋ฉค๋ฒ„๋ณ„ ํŽ˜๋ฅด์†Œ๋‚˜(์„ฑ๊ฒฉ) & ๋ชฉ์†Œ๋ฆฌ ์„ค์ •
16
  MEMBERS = {
17
- "์„œ์œค (Korea)": {
18
- "role": "๋ฉ”์ธ ๋ณด์ปฌ",
19
- "voice": "ko-KR-SunHiNeural", # ํ•œ๊ตญ ์•„๋‚˜์šด์„œ ํ†ค (๋˜๋ ทํ•จ)
20
- "prompt": """๋‹น์‹ ์€ ๋ก๋ฐด๋“œ 'Error 404'์˜ ๋ฉ”์ธ๋ณด์ปฌ '์„œ์œค'์ž…๋‹ˆ๋‹ค.
21
- ํ•œ๊ตญ์–ด(Korean)๋กœ ๋Œ€๋‹ตํ•˜์„ธ์š”.
22
- ์„ฑ๊ฒฉ: ์‹œ๋‹ˆ์ปฌํ•˜์ง€๋งŒ ์†์€ ๋”ฐ๋œปํ•จ. '์•ผ', '์žˆ์ž–์•„' ๊ฐ™์€ ๊ตฌ์–ด์ฒด๋ฅผ ์”€.
23
- ์—ญํ• : ์‚ฌ์šฉ์ž์˜ ๊ณ ๋ฏผ์„ ๋“ฃ๊ณ  ๊ฐ€์‚ฌ(Lyrics)์— ๋น—๋Œ€์–ด ํ•ด๊ฒฐ์ฑ…์„ ์คŒ.
24
- ๋งํˆฌ ์˜ˆ์‹œ: "์•ผ, ๊ฐ€์‚ฌ๊ฐ€ ๋ง‰ํ˜”์–ด? ๊ทธ๋ƒฅ ์งˆ๋Ÿฌ๋ณด๋Š” ๊ฑฐ์•ผ. ๋„ค ๋งˆ์Œ์ด ์‹œํ‚ค๋Š” ๋Œ€๋กœ." """
25
- },
26
- "Chloe (USA)": {
27
- "role": "๋ฆฌ๋“œ ๊ธฐํƒ€",
28
- "voice": "en-US-AriaNeural", # ๋ฏธ๊ตญ ์พŒํ™œํ•œ ํ†ค
29
- "prompt": """You are 'Chloe', the lead guitarist of the rock band 'Error 404'.
30
- Respond in English.
31
- Personality: Energetic, cool, confident rockstar.
32
- Role: Give advice using guitar metaphors (riffs, distortion, tension).
33
- Tone: "Hey! Pump up the volume! Don't be afraid to break the rules." """
34
- },
35
- "Beatrice (Brazil)": {
36
- "role": "๋“œ๋Ÿผ",
37
- "voice": "pt-BR-FranciscaNeural", # ๋ธŒ๋ผ์งˆ ์—ด์ • ํ†ค
38
- "prompt": """You are 'Beatrice', the drummer from Brazil.
39
- Respond in English (mixed with some Portuguese words like 'Vamos', 'Amigo').
40
- Personality: Passionate, loud, high energy.
41
- Role: Focus on rhythm, beat, and heart pounding.
42
- Tone: "Vamos! Feel the beat! Smash that kick drum!" """
43
- },
44
- "Naomi (Japan)": {
45
- "role": "๋ฆฌ๋“ฌ ๊ธฐํƒ€",
46
- "voice": "ja-JP-NanamiNeural", # ์ผ๋ณธ ์ฐจ๋ถ„ํ•œ ํ†ค
47
- "prompt": """You are 'Naomi', the rhythm guitarist from Japan.
48
- Respond in Japanese (and a little English).
49
- Personality: Calm, mysterious, professional.
50
- Role: Focus on stability, backbone, and harmony.
51
- Tone: "ๅคงไธˆๅคซ (It's okay). Rhythm is the foundation. Keep it steady." """
52
- },
53
- "Elena (Spain)": {
54
- "role": "๋ฒ ์ด์Šค",
55
- "voice": "es-ES-ElviraNeural", # ์ŠคํŽ˜์ธ ์„ฑ์ˆ™ํ•œ ํ†ค
56
- "prompt": """You are 'Elena', the bassist from Spain.
57
- Respond in Spanish (mixed with English).
58
- Personality: Sexy, mature, deep voice.
59
- Role: Focus on groove, low-end, and grounding.
60
- Tone: "Hola. Feel the bass. Deep inside your soul." """
61
- },
62
- "Amira (Egypt)": {
63
- "role": "ํ‚ค๋ณด๋“œ",
64
- "voice": "ar-EG-SalmaNeural", # ์•„๋ž ์‹ ๋น„ํ•œ ํ†ค
65
- "prompt": """You are 'Amira', the keyboardist from Egypt.
66
- Respond in Arabic (mixed with English).
67
- Personality: Dreamy, mystical, wise.
68
- Role: Focus on atmosphere, melody, and magic.
69
- Tone: "Salam. Like a desert wind... create a melody." """
70
- },
71
- "Liwei (China)": {
72
- "role": "DJ / FX",
73
- "voice": "zh-CN-XiaoxiaoNeural", # ์ค‘๊ตญ ํ†กํ†ก ํŠ€๋Š” ํ†ค
74
- "prompt": """You are 'Liwei', the DJ/FX from China.
75
- Respond in Chinese (mixed with English).
76
- Personality: Trendy, tech-savvy, Gen-Z hacker.
77
- Role: Focus on glitch, noise, trend, and remix.
78
- Tone: "ๅฌ็€ (Listen)! Glitch is art. Make it trendy." """
79
- },
80
- "Sophie (France)": {
81
- "role": "๋ฐ”์ด์˜ฌ๋ฆฐ",
82
- "voice": "fr-FR-DeniseNeural", # ํ”„๋ž‘์Šค ์šฐ์•„ํ•œ ํ†ค
83
- "prompt": """You are 'Sophie', the violinist from France.
84
- Respond in French (mixed with English).
85
- Personality: Elegant, artistic, slightly arrogant but charming.
86
- Role: Focus on beauty, strings, and elegance.
87
- Tone: "C'est magnifique. Add some strings, chรฉri." """
88
- }
89
  }
90
 
91
- # 3. ๋‡Œ(Gemini) + ์ž…(Edge-TTS) ํ•ฉ์ฒด ํ•จ์ˆ˜
92
  async def band_consulting(user_input, member_name):
93
  member = MEMBERS[member_name]
94
-
95
- # [Step 1] ๋‡Œ: ์ œ๋ฏธ๋‚˜์ด์—๊ฒŒ ๋Œ€์‚ฌ ์‹œํ‚ค๊ธฐ
96
  chat_prompt = f"{member['prompt']}\n\nUser's Error/Worry: {user_input}\nResponse:"
97
  response = model.generate_content(chat_prompt)
98
  ai_text = response.text
99
 
100
- # [Step 2] ์ž…: ์—ฃ์ง€TTS๋กœ ๋ชฉ์†Œ๋ฆฌ ๋งŒ๋“ค๊ธฐ
101
  output_file = f"/tmp/{member_name}_reply.mp3"
102
  communicate = edge_tts.Communicate(ai_text, member['voice'])
103
  await communicate.save(output_file)
104
-
105
  return ai_text, output_file
106
 
107
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค (์™ธ๋ถ€์—์„œ ์ ‘์†ํ•  ํ†ต๋กœ)
108
- iface = gr.Interface(
109
- fn=band_consulting,
110
- inputs=[
111
- gr.Textbox(label="๋‹น์‹ ์˜ ๊ณ ๋ฏผ (Error)"),
112
- gr.Dropdown(choices=list(MEMBERS.keys()), label="์ƒ๋‹ดํ•  ๋ฉค๋ฒ„", value="์„œ์œค (Korea)")
113
- ],
114
- outputs=[
115
- gr.Textbox(label="๋ฉค๋ฒ„์˜ ์กฐ์–ธ"),
116
- gr.Audio(label="๋ชฉ์†Œ๋ฆฌ")
117
- ],
118
- title="Error 404 Band API Server",
119
- description="์ด๊ณณ์€ 8์ธ์กฐ ๋ฐด๋“œ์˜ ๋‘๋‡Œ์™€ ๋ชฉ์†Œ๋ฆฌ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค."
120
- )
 
 
 
 
 
 
121
 
122
- iface.launch()
 
4
  import asyncio
5
  import os
6
 
7
+ # 1. ์„ค์ • ๋ฐ ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ (์ด ๋ถ€๋ถ„์€ ๊ธฐ์กด๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค)
 
8
  GENAI_KEY = os.getenv("GEMINI_KEY")
9
  genai.configure(api_key=GENAI_KEY)
 
 
10
  model = genai.GenerativeModel('gemini-1.5-flash')
11
 
 
12
  MEMBERS = {
13
+ "์„œ์œค (Korea)": { "role": "๋ฉ”์ธ ๋ณด์ปฌ", "voice": "ko-KR-SunHiNeural", "prompt": "๋‹น์‹ ์€ ๋ก๋ฐด๋“œ 'Error 404'์˜ ๋ฉ”์ธ๋ณด์ปฌ '์„œ์œค'์ž…๋‹ˆ๋‹ค. ํ•œ๊ตญ์–ด(Korean)๋กœ ๋Œ€๋‹ตํ•˜์„ธ์š”..." },
14
+ "Chloe (USA)": { "role": "๋ฆฌ๋“œ ๊ธฐํƒ€", "voice": "en-US-AriaNeural", "prompt": "You are 'Chloe'. Respond in English..." },
15
+ "Beatrice (Brazil)": { "role": "๋“œ๋Ÿผ", "voice": "pt-BR-FranciscaNeural", "prompt": "You are 'Beatrice'. Respond in English/Portuguese..." },
16
+ "Naomi (Japan)": { "role": "๋ฆฌ๋“ฌ ๊ธฐํƒ€", "voice": "ja-JP-NanamiNeural", "prompt": "You are 'Naomi'. Respond in Japanese..." },
17
+ "Elena (Spain)": { "role": "๋ฒ ์ด์Šค", "voice": "es-ES-ElviraNeural", "prompt": "You are 'Elena'. Respond in Spanish..." },
18
+ "Amira (Egypt)": { "role": "ํ‚ค๋ณด๋“œ", "voice": "ar-EG-SalmaNeural", "prompt": "You are 'Amira'. Respond in Arabic..." },
19
+ "Liwei (China)": { "role": "DJ / FX", "voice": "zh-CN-XiaoxiaoNeural", "prompt": "You are 'Liwei'. Respond in Chinese..." },
20
+ "Sophie (France)": { "role": "๋ฐ”์ด์˜ฌ๋ฆฐ", "voice": "fr-FR-DeniseNeural", "prompt": "You are 'Sophie'. Respond in French..." }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  }
22
 
 
23
  async def band_consulting(user_input, member_name):
24
  member = MEMBERS[member_name]
 
 
25
  chat_prompt = f"{member['prompt']}\n\nUser's Error/Worry: {user_input}\nResponse:"
26
  response = model.generate_content(chat_prompt)
27
  ai_text = response.text
28
 
 
29
  output_file = f"/tmp/{member_name}_reply.mp3"
30
  communicate = edge_tts.Communicate(ai_text, member['voice'])
31
  await communicate.save(output_file)
 
32
  return ai_text, output_file
33
 
34
+ # ==================================================
35
+ # โ–ผ ์—ฌ๊ธฐ๊ฐ€ ํ•ต์‹ฌ! (Blocks๋กœ ๋ฐ”๊พธ๊ณ  api_name ๊ฐ•์ œ ์ง€์ •) โ–ผ
36
+ # ==================================================
37
+ with gr.Blocks() as demo:
38
+ gr.Markdown("# Error 404 Band API Server")
39
+
40
+ # ์ž…๋ ฅ ์นธ ๋งŒ๋“ค๊ธฐ
41
+ with gr.Row():
42
+ inp_text = gr.Textbox(label="๊ณ ๋ฏผ ์ž…๋ ฅ")
43
+ inp_member = gr.Dropdown(choices=list(MEMBERS.keys()), label="๋ฉค๋ฒ„ ์„ ํƒ", value="์„œ์œค (Korea)")
44
+
45
+ # ์ถœ๋ ฅ ์นธ ๋งŒ๋“ค๊ธฐ
46
+ out_text = gr.Textbox(label="์กฐ์–ธ")
47
+ out_audio = gr.Audio(label="์Œ์„ฑ")
48
+
49
+ # ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ
50
+ btn = gr.Button("์ƒ๋‹ด ์š”์ฒญ")
51
+
52
+ # โ˜…โ˜…โ˜… ์—ฌ๊ธฐ์„œ api_name="predict"๋ผ๊ณ  ๋ช…์ฐฐ์„ ๋”ฑ ๋ถ™์ž…๋‹ˆ๋‹ค! โ˜…โ˜…โ˜…
53
+ btn.click(fn=band_consulting, inputs=[inp_text, inp_member], outputs=[out_text, out_audio], api_name="predict")
54
 
55
+ demo.launch()