benjamin5607 commited on
Commit
440060b
ยท
verified ยท
1 Parent(s): da0beb9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -60
app.py CHANGED
@@ -1,60 +1,66 @@
1
  import gradio as gr
2
- import requests # ๊ตฌ๊ธ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ญ์ œ -> requests๋กœ ๋Œ€์ฒด
3
  import edge_tts
4
  import os
5
  import json
6
 
7
- # 1. API ํ‚ค ๊ฐ€์ ธ์˜ค๊ธฐ
8
  GENAI_KEY = os.getenv("GEMINI_KEY")
9
 
10
- # 2. ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ (๊ทธ๋Œ€๋กœ ์œ ์ง€)
11
- MEMBERS = {
12
- "์„œ์œค (Korea)": {
13
- "role": "๋ฉ”์ธ ๋ณด์ปฌ",
14
- "voice": "ko-KR-SunHiNeural",
15
- "prompt": "๋‹น์‹ ์€ ๋ก๋ฐด๋“œ 'Error 404'์˜ ๋ฉ”์ธ๋ณด์ปฌ '์„œ์œค'์ž…๋‹ˆ๋‹ค. ํ•œ๊ตญ์–ด(Korean)๋กœ ๋Œ€๋‹ตํ•˜์„ธ์š”. ์„ฑ๊ฒฉ: ์‹œ๋‹ˆ์ปฌํ•˜์ง€๋งŒ ์ธค๋ฐ๋ ˆ. ๋งํˆฌ: '์•ผ', '์žˆ์ž–์•„' ๊ฐ™์€ ๊ตฌ์–ด์ฒด ์‚ฌ์šฉ. ์—ญํ• : ๊ณ ๋ฏผ์„ ๊ฐ€์‚ฌ(Lyrics)์— ๋น—๋Œ€์–ด ํ•ด๊ฒฐ."
16
- },
17
- "Chloe (USA)": {
18
- "role": "๋ฆฌ๋“œ ๊ธฐํƒ€",
19
- "voice": "en-US-AriaNeural",
20
- "prompt": "You are 'Chloe'. Respond in English. Personality: Energetic, cool rockstar. Tone: 'Hey! Pump up the volume!'"
21
- },
22
- "Beatrice (Brazil)": {
23
- "role": "๋“œ๋Ÿผ",
24
- "voice": "pt-BR-FranciscaNeural",
25
- "prompt": "You are 'Beatrice'. Respond in English mixed with Portuguese. Personality: Passionate, loud. Tone: 'Vamos! Feel the beat!'"
26
- },
27
- "Naomi (Japan)": {
28
- "role": "๋ฆฌ๋“ฌ ๊ธฐํƒ€",
29
- "voice": "ja-JP-NanamiNeural",
30
- "prompt": "You are 'Naomi'. Respond in Japanese. Personality: Calm, mysterious. Tone: 'ๅคงไธˆๅคซ (It's okay). Keep it steady.'"
31
- },
32
- "Elena (Spain)": {
33
- "role": "๋ฒ ์ด์Šค",
34
- "voice": "es-ES-ElviraNeural",
35
- "prompt": "You are 'Elena'. Respond in Spanish mixed with English. Personality: Sexy, mature. Tone: 'Hola. Feel the bass.'"
36
- },
37
- "Amira (Egypt)": {
38
- "role": "ํ‚ค๋ณด๋“œ",
39
- "voice": "ar-EG-SalmaNeural",
40
- "prompt": "You are 'Amira'. Respond in Arabic mixed with English. Personality: Dreamy, mystical. Tone: 'Salam. Like a desert wind...'"
41
- },
42
- "Liwei (China)": {
43
- "role": "DJ / FX",
44
- "voice": "zh-CN-XiaoxiaoNeural",
45
- "prompt": "You are 'Liwei'. Respond in Chinese mixed with English. Personality: Trendy Gen-Z. Tone: 'ๅฌ็€ (Listen)! Glitch is art.'"
46
- },
47
- "Sophie (France)": {
48
- "role": "๋ฐ”์ด์˜ฌ๋ฆฐ",
49
- "voice": "fr-FR-DeniseNeural",
50
- "prompt": "You are 'Sophie'. Respond in French mixed with English. Personality: Elegant, artistic. Tone: 'C'est magnifique.'"
51
- }
52
- }
 
 
 
 
53
 
54
- # โ˜… ํ•ต์‹ฌ: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด ์ง์ ‘ ํ†ต์‹ ํ•˜๋Š” ํ•จ์ˆ˜
55
- def call_gemini_direct(prompt):
56
- # 1.5 Flash ๋ชจ๋ธ ์ฃผ์†Œ ์ง์ ‘ ํ˜ธ์ถœ
57
- url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key={GENAI_KEY}"
 
 
58
 
59
  headers = {'Content-Type': 'application/json'}
60
  data = {
@@ -68,8 +74,21 @@ def call_gemini_direct(prompt):
68
  if response.status_code == 200:
69
  return response.json()['candidates'][0]['content']['parts'][0]['text']
70
  else:
71
- # ์—๋Ÿฌ ๋ฐœ์ƒ ์‹œ ์ƒ์„ธ ๋‚ด์šฉ ๋ฐ˜ํ™˜
72
- raise Exception(f"Google API Error {response.status_code}: {response.text}")
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  async def band_consulting(user_input, member_name):
75
  try:
@@ -77,16 +96,18 @@ async def band_consulting(user_input, member_name):
77
  return f"Error: ์ด๋ฆ„ ๋ถˆ์ผ์น˜! ('{member_name}')", None
78
 
79
  member = MEMBERS[member_name]
80
-
81
- # [Step 1] ๋‡Œ: ์ง์ ‘ ํ†ต์‹  ํ•จ์ˆ˜ ํ˜ธ์ถœ
82
  full_prompt = f"{member['prompt']}\n\nUser's Error/Worry: {user_input}\nResponse:"
83
 
84
  try:
85
- ai_text = call_gemini_direct(full_prompt)
 
 
 
 
 
86
  except Exception as e:
87
- return f"Error (Gemini Direct): {str(e)}", None
88
 
89
- # [Step 2] ์ž…: Edge-TTS
90
  try:
91
  output_file = f"/tmp/{member_name}_reply.mp3"
92
  communicate = edge_tts.Communicate(ai_text, member['voice'])
@@ -99,17 +120,15 @@ async def band_consulting(user_input, member_name):
99
  except Exception as e:
100
  return f"System Error: {str(e)}", None
101
 
102
- # Blocks UI
103
  with gr.Blocks() as demo:
104
- gr.Markdown("# Error 404 Band API Server (Direct REST Mode)")
105
  with gr.Row():
106
  inp_text = gr.Textbox(label="๊ณ ๋ฏผ ์ž…๋ ฅ")
107
  inp_member = gr.Dropdown(choices=list(MEMBERS.keys()), label="๋ฉค๋ฒ„ ์„ ํƒ", value="์„œ์œค (Korea)")
108
  out_text = gr.Textbox(label="์กฐ์–ธ")
109
  out_audio = gr.Audio(label="์Œ์„ฑ")
110
  btn = gr.Button("์ƒ๋‹ด ์š”์ฒญ")
111
-
112
- # API ์ด๋ฆ„ 'predict' ๊ฐ•์ œ ์ง€์ •
113
  btn.click(fn=band_consulting, inputs=[inp_text, inp_member], outputs=[out_text, out_audio], api_name="predict")
114
 
115
  demo.launch()
 
1
  import gradio as gr
2
+ import requests
3
  import edge_tts
4
  import os
5
  import json
6
 
7
+ # 1. API ํ‚ค ์„ค์ •
8
  GENAI_KEY = os.getenv("GEMINI_KEY")
9
 
10
+ # ======================================================
11
+ # ๐Ÿ•ต๏ธโ€โ™‚๏ธ [ํ•ต์‹ฌ] ๊ตฌ๊ธ€ ์„œ๋ฒ„์—์„œ '์ง„์งœ ๋ชจ๋ธ ์ด๋ฆ„' ์•Œ์•„์˜ค๊ธฐ
12
+ # ======================================================
13
+ def find_working_model():
14
+ # ๋ชจ๋ธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ API ํ˜ธ์ถœ
15
+ url = f"https://generativelanguage.googleapis.com/v1beta/models?key={GENAI_KEY}"
16
+ response = requests.get(url)
17
+
18
+ if response.status_code != 200:
19
+ print(f"โŒ ๋ชจ๋ธ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ ์‹คํŒจ: {response.text}")
20
+ return "gemini-pro" # ์‹คํŒจํ•˜๋ฉด ๊ทธ๋ƒฅ ๊นกํ†ต ๋ชจ๋ธ๋กœ ์žก๊ธฐ
21
+
22
+ data = response.json()
23
+
24
+ # 1. 'generateContent' ๊ธฐ๋Šฅ์ด ์žˆ๋Š” ๋ชจ๋ธ๋งŒ ํ•„ํ„ฐ๋ง
25
+ candidates = []
26
+ if 'models' in data:
27
+ for m in data['models']:
28
+ if 'supportedGenerationMethods' in m and 'generateContent' in m['supportedGenerationMethods']:
29
+ # ์ด๋ฆ„์—์„œ 'models/' ๋ถ€๋ถ„ ๋–ผ๊ณ  ์ €์žฅ (์˜ˆ: models/gemini-pro -> gemini-pro)
30
+ clean_name = m['name'].replace("models/", "")
31
+ candidates.append(clean_name)
32
+
33
+ print(f"๐Ÿ“‹ ์‚ฌ์šฉ ๊ฐ€๋Šฅ ๋ชจ๋ธ ๋ชฉ๋ก: {candidates}")
34
+
35
+ # 2. ์šฐ์„ ์ˆœ์œ„๋Œ€๋กœ ์„ ํƒ (ํ”Œ๋ž˜์‹œ -> ํ”„๋กœ)
36
+ # ๋ฆฌ๋”๋‹˜ ํ‚ค๋กœ 'gemini-1.5-flash'๊ฐ€ ์•ˆ๋˜๋ฉด 'gemini-1.0-pro'๋ผ๋„ ์žก์Šต๋‹ˆ๋‹ค.
37
+ preferred_order = [
38
+ "gemini-1.5-flash-latest",
39
+ "gemini-1.5-flash",
40
+ "gemini-1.5-flash-001",
41
+ "gemini-1.5-pro",
42
+ "gemini-1.0-pro",
43
+ "gemini-pro"
44
+ ]
45
+
46
+ for pref in preferred_order:
47
+ if pref in candidates:
48
+ print(f"โœ… ๊ฒฐ์ •๋œ ๋ชจ๋ธ: {pref}")
49
+ return pref
50
+
51
+ # ์„ ํ˜ธํ•˜๋Š” ๊ฒŒ ์—†์œผ๋ฉด ๋ชฉ๋ก์˜ ์ฒซ ๋ฒˆ์งธ ๋†ˆ ์žก๊ธฐ
52
+ if candidates:
53
+ print(f"โš ๏ธ ์„ ํ˜ธ ๋ชจ๋ธ ์—†์Œ. ๋Œ€์ฒด ๋ชจ๋ธ ์‚ฌ์šฉ: {candidates[0]}")
54
+ return candidates[0]
55
+
56
+ return "gemini-pro" # ์ง„์งœ ์•„๋ฌด๊ฒƒ๋„ ์—†์œผ๋ฉด...
57
 
58
+ # ======================================================
59
+ # 3. ์ง์ ‘ ํ†ต์‹  ํ•จ์ˆ˜ (๋ชจ๋ธ๋ช…์„ ๋™์ ์œผ๋กœ ๋„ฃ์Œ)
60
+ # ======================================================
61
+ def call_gemini_direct(prompt, model_name):
62
+ # ์œ„์—์„œ ์ฐพ์€ ๋ชจ๋ธ๋ช…์„ URL์— ๋ผ์›Œ๋„ฃ๊ธฐ
63
+ url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_name}:generateContent?key={GENAI_KEY}"
64
 
65
  headers = {'Content-Type': 'application/json'}
66
  data = {
 
74
  if response.status_code == 200:
75
  return response.json()['candidates'][0]['content']['parts'][0]['text']
76
  else:
77
+ # ์—๋Ÿฌ ๋‚˜๋ฉด ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ๋ฐ˜ํ™˜
78
+ raise Exception(f"Google API Error ({model_name}): {response.text}")
79
+
80
+
81
+ # 4. ๋ฉค๋ฒ„ ๋ฐ์ดํ„ฐ (๊ทธ๋Œ€๋กœ)
82
+ MEMBERS = {
83
+ "์„œ์œค (Korea)": { "role": "๋ฉ”์ธ ๋ณด์ปฌ", "voice": "ko-KR-SunHiNeural", "prompt": "๋‹น์‹ ์€ ๋ก๋ฐด๋“œ 'Error 404'์˜ ๋ฉ”์ธ๋ณด์ปฌ '์„œ์œค'์ž…๋‹ˆ๋‹ค. ํ•œ๊ตญ์–ด(Korean)๋กœ ๋Œ€๋‹ตํ•˜์„ธ์š”. ์„ฑ๊ฒฉ: ์‹œ๋‹ˆ์ปฌ, ์ธค๋ฐ๋ ˆ. ๋งํˆฌ: '์•ผ', '์žˆ์ž–์•„' ์‚ฌ์šฉ." },
84
+ "Chloe (USA)": { "role": "๋ฆฌ๋“œ ๊ธฐํƒ€", "voice": "en-US-AriaNeural", "prompt": "You are 'Chloe'. Respond in English. Personality: Cool rockstar." },
85
+ "Beatrice (Brazil)": { "role": "๋“œ๋Ÿผ", "voice": "pt-BR-FranciscaNeural", "prompt": "You are 'Beatrice'. Respond in English/Portuguese. Personality: Passionate." },
86
+ "Naomi (Japan)": { "role": "๋ฆฌ๋“ฌ ๊ธฐํƒ€", "voice": "ja-JP-NanamiNeural", "prompt": "You are 'Naomi'. Respond in Japanese. Personality: Calm." },
87
+ "Elena (Spain)": { "role": "๋ฒ ์ด์Šค", "voice": "es-ES-ElviraNeural", "prompt": "You are 'Elena'. Respond in Spanish/English. Personality: Mature." },
88
+ "Amira (Egypt)": { "role": "ํ‚ค๋ณด๋“œ", "voice": "ar-EG-SalmaNeural", "prompt": "You are 'Amira'. Respond in Arabic/English. Personality: Mystical." },
89
+ "Liwei (China)": { "role": "DJ / FX", "voice": "zh-CN-XiaoxiaoNeural", "prompt": "You are 'Liwei'. Respond in Chinese/English. Personality: Trendy." },
90
+ "Sophie (France)": { "role": "๋ฐ”์ด์˜ฌ๋ฆฐ", "voice": "fr-FR-DeniseNeural", "prompt": "You are 'Sophie'. Respond in French/English. Personality: Elegant." }
91
+ }
92
 
93
  async def band_consulting(user_input, member_name):
94
  try:
 
96
  return f"Error: ์ด๋ฆ„ ๋ถˆ์ผ์น˜! ('{member_name}')", None
97
 
98
  member = MEMBERS[member_name]
 
 
99
  full_prompt = f"{member['prompt']}\n\nUser's Error/Worry: {user_input}\nResponse:"
100
 
101
  try:
102
+ # 1. ์‚ด์•„์žˆ๋Š” ๋ชจ๋ธ ์ฐพ๊ธฐ (๋งค๋ฒˆ ์ฐพ์œผ๋ฉด ๋А๋ฆฌ๋‹ˆ๊นŒ ์บ์‹ฑํ•˜๋ฉด ์ข‹์ง€๋งŒ, ํ™•์‹คํ•จ์„ ์œ„ํ•ด ๋งค๋ฒˆ ํ™•์ธ)
103
+ active_model = find_working_model()
104
+
105
+ # 2. ๊ทธ ๋ชจ๋ธ๋กœ ์š”์ฒญ ๋ณด๋‚ด๊ธฐ
106
+ ai_text = call_gemini_direct(full_prompt, active_model)
107
+
108
  except Exception as e:
109
+ return f"Error (Gemini): {str(e)}", None
110
 
 
111
  try:
112
  output_file = f"/tmp/{member_name}_reply.mp3"
113
  communicate = edge_tts.Communicate(ai_text, member['voice'])
 
120
  except Exception as e:
121
  return f"System Error: {str(e)}", None
122
 
123
+ # UI
124
  with gr.Blocks() as demo:
125
+ gr.Markdown("# Error 404 Band API Server (Auto-Discovery Mode)")
126
  with gr.Row():
127
  inp_text = gr.Textbox(label="๊ณ ๋ฏผ ์ž…๋ ฅ")
128
  inp_member = gr.Dropdown(choices=list(MEMBERS.keys()), label="๋ฉค๋ฒ„ ์„ ํƒ", value="์„œ์œค (Korea)")
129
  out_text = gr.Textbox(label="์กฐ์–ธ")
130
  out_audio = gr.Audio(label="์Œ์„ฑ")
131
  btn = gr.Button("์ƒ๋‹ด ์š”์ฒญ")
 
 
132
  btn.click(fn=band_consulting, inputs=[inp_text, inp_member], outputs=[out_text, out_audio], api_name="predict")
133
 
134
  demo.launch()