Jiangxz01 commited on
Commit
36dc16f
·
verified ·
1 Parent(s): 8c30abd

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -27
app.py CHANGED
@@ -3,30 +3,33 @@
3
 
4
  import gradio as gr
5
  import openai
6
- import os
7
- import re
8
  from pydub import AudioSegment
9
  import uuid
10
  import edge_tts
11
  import json
 
 
 
12
 
13
  def create_client(api_key=None):
14
  if api_key:
15
  openai.api_key = api_key
16
  else:
17
- openai.api_key = os.getenv("YOUR_API_TOKEN")
18
  return openai.OpenAI(api_key=openai.api_key, base_url="https://api.sambanova.ai/v1")
19
 
20
  def generate_response(input_text, language, speaker1, speaker2, api_key):
21
  speaker1_name = speaker1.split(' - ')[0]
22
  speaker2_name = speaker2.split(' - ')[0]
 
 
23
  if language == "Auto Detect":
24
  language_instruction = "- The podcast MUST be in the same language as the user input."
25
  else:
26
  language_instruction = f"- The podcast Must reply to me in {language} language."
27
  example = """
28
  {
29
- "topic": "AGI",
30
  "podcast": [
31
  {
32
  "speaker": 1,
@@ -53,23 +56,23 @@ def generate_response(input_text, language, speaker1, speaker2, api_key):
53
  }
54
  """
55
 
56
- system_prompt = f"""你的任務是將提供的輸入文字轉換為一個引人入勝、訊息豐富且專業的Podcast對話。輸入文字可能會比較混亂或結構不完整,因為它可能來自不同來源,如PDF檔案或文字檔等。不要擔心格式問題或任何不相關的訊息;你的目標是提取可以在Podcast中討論的關鍵點、識別重要定義,並突出有趣的事實。
57
 
58
  以下是你將要處理的輸入文字:
59
  <input_text>
60
  {{input_text}}
61
  </input_text>
62
 
63
- 首先,仔細閱讀輸入文字,找出主要話題、關鍵點,以及任何有趣的事實或軼事。思考如何將這些訊息以一種有趣且吸引人的方式呈現出來,適合高質量的音訊Podcast。
64
 
65
  <scratchpad>
66
- 頭腦風暴一些創造性的方法來討論你在輸入文字中識別出的主要話題、關鍵點及任何有趣的事實或軼事。可以考慮使用類比、講故事技巧或假設情境來讓內容對聽眾更加貼近和有趣。
67
- 請記住,你的Podcast應當易於普通聽眾理解,所以避免使用過多的專業術語或假設聽眾對該話題已有瞭解。如有必要,請思考如何用簡單的術語簡要解釋任何複雜的概念。
68
- 利用你的想像力填補輸入文字中的任何空白,或者想出一些值得探討與發人深省的問題,以供Podcast討論。目標是創造一個訊息豐富且娛樂性強的對話,因此可以在你的方法上大膽自由發揮創意。
69
- 將你的頭腦風暴想法和Podcast對話的粗略大綱寫在這裡。確保記錄下你希望在結尾重申的主要見解和要點。
70
  </scratchpad>
71
 
72
- 現在你已經進行了頭腦風暴並建立了一個粗略的大綱,是時候撰寫實際的Podcast對話了。目標是主持人({speaker1_name})與嘉賓({speaker2_name})之間自然、對話式的交流。融入你在頭腦風暴中得出的最佳想法,並確保將任何複雜話題以易於理解的方式解釋清楚。
73
  {language_instruction}
74
  - The podcast should have 2 speakers: {speaker1_name} and {speaker2_name}.
75
  - The podcast should be long.
@@ -79,9 +82,9 @@ Follow this JSON example structure, MUST be in {language} language:
79
  {example}
80
 
81
  <podcast_dialogue>
82
- 根據你在頭腦風暴階段提出的關鍵點和創造性想法,撰寫你的引人入勝、訊息豐富的Podcast對話。採用對話式的語氣,並包括任何必要的上下文或解釋,使內容對一般聽眾而言容易理解。使用主持人名字 {speaker1_name} 和嘉賓名字 {speaker2_name},以營造更吸引人和身臨其境的聆聽體驗。不要包括像[主持人]或[嘉賓]這樣的括號預留位置。設計你的輸出內容以供直接朗讀——它將直接轉換為音訊。
83
- 確保對話儘可能詳細、完整,同時保持在主題之內並維持吸引人的流暢性。目標是使用你的全部輸出容量,建立儘可能長的Podcast節目,同時以有趣的方式傳遞輸入文字中的關鍵訊息。
84
- 在對話結束時,讓主持人和嘉賓自然總結他們討論中的主要見解和要點。這應當是對話的隨機部分,以自然隨意而非明顯的總結——目的是在結束前最後一次以自然流暢的方式強化核心思想。最終以感謝詞結束。
85
  </podcast_dialogue>
86
  """
87
  client = create_client(api_key)
@@ -102,28 +105,30 @@ Follow this JSON example structure, MUST be in {language} language:
102
  except json.JSONDecodeError:
103
  podcast_json = re.sub(r',\s*}', '}', podcast_json)
104
  podcast_json = re.sub(r',\s*]', ']', podcast_json)
 
 
105
  return podcast_json
106
  else:
107
- raise gr.Error("生成 Podcast 劇本失敗!!請稍後再試。")
108
  except Exception as e:
109
  if "API key not valid" in str(e):
110
  raise gr.Error("無效的 API 金鑰!!請提供有效的 API 金鑰。")
111
  elif "rate limit" in str(e).lower():
112
  raise gr.Error("API 金鑰使用額度已超過限制!!請稍後再試或使用其他 API 金鑰。")
113
  else:
114
- raise gr.Error(f"生成 Podcast 劇本失敗!!請稍後再試。")
115
 
116
  async def tts_generate(input_text, speaker1, speaker2):
117
  voice_names = {
118
  "家豪 - 中文 (Male)": "zh-TW-YunJheNeural",
119
  "淑芬 - 中文 (Female)": "zh-TW-HsiaoChenNeural",
120
  "子晴 - 中文 (Female)": "zh-TW-HsiaoYuNeural",
 
121
  "品妍 - 中文 (Female)": "zh-CN-XiaoxiaoNeural",
 
122
  "美玲 - 中文 (Female)": "zh-CN-XiaoyiNeural",
123
  "建宏 - 中文 (Male)": "zh-CN-YunjianNeural",
124
- "品睿 - 中文 (Male)": "zh-CN-YunxiNeural",
125
  "宥廷 - 中文 (Male)": "zh-CN-YunxiaNeural",
126
- "志明 - 中文 (Male)": "zh-CN-YunyangNeural",
127
  "雨霏 - 中文 (Female)": "zh-CN-liaoning-XiaobeiNeural",
128
  "Andrew - English (Male)": "en-US-AndrewMultilingualNeural",
129
  "Ava - English (Female)": "en-US-AvaMultilingualNeural",
@@ -137,6 +142,8 @@ async def tts_generate(input_text, speaker1, speaker2):
137
 
138
  speaker1_voice = voice_names[speaker1]
139
  speaker2_voice = voice_names[speaker2]
 
 
140
 
141
  try:
142
  podcast_dict = json.loads(input_text)
@@ -176,9 +183,13 @@ async def tts_generate(input_text, speaker1, speaker2):
176
 
177
  output_file = f"Jiangxz_{uuid.uuid4()}.mp3"
178
  combined.export(output_file, format="mp3")
 
 
179
  return output_file
180
 
181
  async def process_podcast(input_text, language, speaker1, speaker2, api_key):
 
 
182
  podcast_script = generate_response(input_text, language, speaker1, speaker2, api_key)
183
  speaker1_name = speaker1.split(' - ')[0]
184
  speaker2_name = speaker2.split(' - ')[0]
@@ -196,6 +207,9 @@ async def process_podcast(input_text, language, speaker1, speaker2, api_key):
196
  podcast_text = "Error: Unable to parse the podcast script."
197
 
198
  audio_file = await tts_generate(podcast_script, speaker1, speaker2)
 
 
 
199
  return podcast_text, audio_file
200
 
201
  custom_css = """
@@ -287,20 +301,22 @@ body {
287
 
288
  with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as iface:
289
  gr.Markdown("""
290
- # 🎙️ 聲音行銷企劃 - 財資歐北共 Podcast 🎙️
291
- > ### **※ 自動生成 Podcast 節目及音檔,系統布署:江信宗,LLM:Llama-3.1-405B-Instruct。**
292
  """, elem_classes="center-aligned")
293
 
294
  input_text = gr.Textbox(
295
  label="請輸入 Podcast 話題(建議50至1000字)",
296
- placeholder="輸入 Podcast 話題內容越詳細劇本越佳 ......",
297
  elem_classes="input-background",
298
  max_lines=20
299
  )
300
 
301
  def check_input_length(text):
302
- if len(text) > 4096:
303
- return gr.Warning("輸入內容已超過 max_tokens,請縮短話題內容。")
 
 
304
 
305
  input_text.change(fn=check_input_length, inputs=[input_text])
306
 
@@ -318,7 +334,7 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as iface:
318
  "家豪 - 中文 (Male)",
319
  "淑芬 - 中文 (Female)",
320
  "子晴 - 中文 (Female)",
321
- "品睿 - 中文 (Male)",
322
  "品妍 - 中文 (Female)",
323
  "志明 - 中文 (Male)",
324
  "美玲 - 中文 (Female)",
@@ -337,7 +353,7 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as iface:
337
 
338
  Speaker_1 = gr.Dropdown(
339
  choices=speaker_choices,
340
- value="品睿 - 中文 (Male)",
341
  label="播客#1語音",
342
  interactive=True,
343
  scale=2,
@@ -360,11 +376,12 @@ with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as iface:
360
  api_key = gr.Textbox(label="請輸入您的 API Key", type="password", placeholder="API authentication key for large language models", scale=1, elem_classes="api-background")
361
 
362
  audio_output = gr.Audio(label="Generated Podcast Audio", elem_classes="audio-background")
363
- podcast_script = gr.Textbox(label="Generated Podcast 文案", elem_classes="script-background")
364
  generate_button.click(fn=process_podcast, inputs=[input_text, Language, Speaker_1, Speaker_2, api_key], outputs=[podcast_script, audio_output])
365
 
 
366
  if __name__ == "__main__":
367
  if "SPACE_ID" in os.environ:
368
  iface.launch()
369
  else:
370
- iface.launch(share=True, show_api=False)
 
3
 
4
  import gradio as gr
5
  import openai
 
 
6
  from pydub import AudioSegment
7
  import uuid
8
  import edge_tts
9
  import json
10
+ import os
11
+ import re
12
+ import time
13
 
14
  def create_client(api_key=None):
15
  if api_key:
16
  openai.api_key = api_key
17
  else:
18
+ openai.api_key = os.getenv("YOUR_API_KEY")
19
  return openai.OpenAI(api_key=openai.api_key, base_url="https://api.sambanova.ai/v1")
20
 
21
  def generate_response(input_text, language, speaker1, speaker2, api_key):
22
  speaker1_name = speaker1.split(' - ')[0]
23
  speaker2_name = speaker2.split(' - ')[0]
24
+ gr.Info("正在生成 Podcast 文稿中,請稍待片刻......")
25
+ start_time = time.time()
26
  if language == "Auto Detect":
27
  language_instruction = "- The podcast MUST be in the same language as the user input."
28
  else:
29
  language_instruction = f"- The podcast Must reply to me in {language} language."
30
  example = """
31
  {
32
+ "topic": "AIF",
33
  "podcast": [
34
  {
35
  "speaker": 1,
 
56
  }
57
  """
58
 
59
+ system_prompt = f"""你的任務是將提供的輸入文字轉換為一個引人入勝、訊息豐富且專業的播客對話。輸入文字可能會比較混亂或結構不完整,因為它可能來自不同來源,如PDF檔案或網頁文字等。不要擔心格式問題或任何不相關的訊息;你的目標是提取可以在播客中討論的關鍵點、識別重要定義,並突顯有趣的事實。
60
 
61
  以下是你將要處理的輸入文字:
62
  <input_text>
63
  {{input_text}}
64
  </input_text>
65
 
66
+ 首先,仔細閱讀輸入文字,並積極找出主要話題、關鍵點,以及任何有趣的事實或軼事。Chain-of-Thought思考如何將這些訊息以一種有趣且吸引人的方式呈現出來,適合高品質的播客文稿。
67
 
68
  <scratchpad>
69
+ 頭腦風暴一些創造性的方法來討論你在輸入文字中識別出的主要話題、關鍵點及任何有趣的事實或軼事。可以考慮使用類比、例子、講故事技巧或假設情境來讓內容更能與聽眾產生共鳴並吸引他們。
70
+ 請記住,你的播客應當易於普通聽眾理解,所以避免使用過多的專業術語或假設聽眾對該話題已有瞭解。如有必要,請思考如何用簡單的術語簡要解釋任何複雜的概念。
71
+ 發揮你的想像力填補輸入文字中的任何空白,或頭腦風暴提出一些值得探討與發人深省的問題,以供播客討論。目標是創造一個訊息豐富且娛樂性強的對話,因此可以在你的方法上大膽盡情自由發揮創意。
72
+ 將你的頭腦風暴想法和播客對話的粗略大綱寫在這裡,務必讓它有趣且吸引人。確保記錄下你希望在結尾重申的主要見解和要點。
73
  </scratchpad>
74
 
75
+ 現在你已經進行頭腦風暴並建立粗略大綱,是時候撰寫實際的播客對話了。目標是主持人({speaker1_name})與嘉賓({speaker2_name})之間自然、對話式的交流,融入你在頭腦風暴中得出的最佳想法,並花費精力確保將任何複雜話題以易於理解的方式解釋清楚。
76
  {language_instruction}
77
  - The podcast should have 2 speakers: {speaker1_name} and {speaker2_name}.
78
  - The podcast should be long.
 
82
  {example}
83
 
84
  <podcast_dialogue>
85
+ 根據你在頭腦風暴階段提出的關鍵點和創造性想法,撰寫一段引人入勝且訊息豐富的播客對話。採用對話式的語氣,並包括任何必要的上下文或解釋,使內容對一般聽眾容易理解。使用主持人名字 {speaker1_name} 和嘉賓名字 {speaker2_name},為聽眾營造更吸引人和身臨其境的聆聽體驗。不要包括像[主持人]或[嘉賓]這樣的括號預留位置。設計你的輸出內容必須適合直接朗讀,因為它將直接轉換為音訊。
86
+ 確保對話儘可能詳細且完整,同時保持在主題之內並維持吸引人的流暢性。目標是使用你的全部輸出容量,建立儘可能長的播客節目,同時以娛樂性的方式傳達輸入文字中的關鍵訊息。
87
+ 在對話結束時,讓主持人和嘉賓自然總結他們討論中的主要見解和要點,這應當是對話的隨機部分,以自然隨意而非明顯的總結 - 目的是在結束前最後一次以自然流暢的方式強化核心思想。最終以感謝詞結束。
88
  </podcast_dialogue>
89
  """
90
  client = create_client(api_key)
 
105
  except json.JSONDecodeError:
106
  podcast_json = re.sub(r',\s*}', '}', podcast_json)
107
  podcast_json = re.sub(r',\s*]', ']', podcast_json)
108
+ end_time = time.time()
109
+ gr.Info(f"已成功生成 Podcast 文稿,執行時間: {(end_time - start_time):.2f} 秒。")
110
  return podcast_json
111
  else:
112
+ raise gr.Error("生成 Podcast 文稿失敗!!請稍後再試。")
113
  except Exception as e:
114
  if "API key not valid" in str(e):
115
  raise gr.Error("無效的 API 金鑰!!請提供有效的 API 金鑰。")
116
  elif "rate limit" in str(e).lower():
117
  raise gr.Error("API 金鑰使用額度已超過限制!!請稍後再試或使用其他 API 金鑰。")
118
  else:
119
+ raise gr.Error(f"生成 Podcast 文稿失敗!!請稍後再試。")
120
 
121
  async def tts_generate(input_text, speaker1, speaker2):
122
  voice_names = {
123
  "家豪 - 中文 (Male)": "zh-TW-YunJheNeural",
124
  "淑芬 - 中文 (Female)": "zh-TW-HsiaoChenNeural",
125
  "子晴 - 中文 (Female)": "zh-TW-HsiaoYuNeural",
126
+ "景睿 - 中文 (Male)": "zh-CN-YunxiNeural",
127
  "品妍 - 中文 (Female)": "zh-CN-XiaoxiaoNeural",
128
+ "志明 - 中文 (Male)": "zh-CN-YunyangNeural",
129
  "美玲 - 中文 (Female)": "zh-CN-XiaoyiNeural",
130
  "建宏 - 中文 (Male)": "zh-CN-YunjianNeural",
 
131
  "宥廷 - 中文 (Male)": "zh-CN-YunxiaNeural",
 
132
  "雨霏 - 中文 (Female)": "zh-CN-liaoning-XiaobeiNeural",
133
  "Andrew - English (Male)": "en-US-AndrewMultilingualNeural",
134
  "Ava - English (Female)": "en-US-AvaMultilingualNeural",
 
142
 
143
  speaker1_voice = voice_names[speaker1]
144
  speaker2_voice = voice_names[speaker2]
145
+ gr.Info("正在生成 Podcast 音檔中,請稍待片刻......")
146
+ start_time = time.time()
147
 
148
  try:
149
  podcast_dict = json.loads(input_text)
 
183
 
184
  output_file = f"Jiangxz_{uuid.uuid4()}.mp3"
185
  combined.export(output_file, format="mp3")
186
+ end_time = time.time()
187
+ gr.Info(f"已成功生成 Podcast 音檔,執行時間: {(end_time - start_time):.2f} 秒。")
188
  return output_file
189
 
190
  async def process_podcast(input_text, language, speaker1, speaker2, api_key):
191
+ gr.Info("開始生成 Podcast 節目及音檔,請稍待片刻......")
192
+ start_time = time.time()
193
  podcast_script = generate_response(input_text, language, speaker1, speaker2, api_key)
194
  speaker1_name = speaker1.split(' - ')[0]
195
  speaker2_name = speaker2.split(' - ')[0]
 
207
  podcast_text = "Error: Unable to parse the podcast script."
208
 
209
  audio_file = await tts_generate(podcast_script, speaker1, speaker2)
210
+ end_time = time.time()
211
+ gr.Info(f"已成功完成 Podcast 節目及音檔,總執行時間: {(end_time - start_time):.2f} 秒。")
212
+ gr.Info("請待本訊息自動消失後即可播放或下載 Podcast 音檔!!")
213
  return podcast_text, audio_file
214
 
215
  custom_css = """
 
301
 
302
  with gr.Blocks(theme=gr.themes.Monochrome(), css=custom_css) as iface:
303
  gr.Markdown("""
304
+ # 🎙️ 聲音經濟 - 財資歐北共 Podcast 🎙️
305
+ > ### **※ 玩轉聲音魅力,開拓更多可能性,自動生成 Podcast 節目及音檔,系統布署:江信宗,LLM:Llama-3.1-405B-Instruct。**
306
  """, elem_classes="center-aligned")
307
 
308
  input_text = gr.Textbox(
309
  label="請輸入 Podcast 話題(建議50至1000字)",
310
+ placeholder="輸入 Podcast 話題內容,受限 LLM Context Length,建議1000字以內 ......",
311
  elem_classes="input-background",
312
  max_lines=20
313
  )
314
 
315
  def check_input_length(text):
316
+ if 0 < len(text) < 4:
317
+ return gr.Warning("輸入內容過短,請提供明確的話題內容。")
318
+ elif len(text) > 4096:
319
+ return gr.Warning("輸入內容已超過 max tokens,請縮短話題內容。")
320
 
321
  input_text.change(fn=check_input_length, inputs=[input_text])
322
 
 
334
  "家豪 - 中文 (Male)",
335
  "淑芬 - 中文 (Female)",
336
  "子晴 - 中文 (Female)",
337
+ "景睿 - 中文 (Male)",
338
  "品妍 - 中文 (Female)",
339
  "志明 - 中文 (Male)",
340
  "美玲 - 中文 (Female)",
 
353
 
354
  Speaker_1 = gr.Dropdown(
355
  choices=speaker_choices,
356
+ value="景睿 - 中文 (Male)",
357
  label="播客#1語音",
358
  interactive=True,
359
  scale=2,
 
376
  api_key = gr.Textbox(label="請輸入您的 API Key", type="password", placeholder="API authentication key for large language models", scale=1, elem_classes="api-background")
377
 
378
  audio_output = gr.Audio(label="Generated Podcast Audio", elem_classes="audio-background")
379
+ podcast_script = gr.Textbox(label="Generated Podcast 文稿", elem_classes="script-background")
380
  generate_button.click(fn=process_podcast, inputs=[input_text, Language, Speaker_1, Speaker_2, api_key], outputs=[podcast_script, audio_output])
381
 
382
+
383
  if __name__ == "__main__":
384
  if "SPACE_ID" in os.environ:
385
  iface.launch()
386
  else:
387
+ iface.launch(share=True, show_api=False)