ILRDF-Lowking commited on
Commit
df8dadb
·
verified ·
1 Parent(s): 40ed9bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +16 -45
app.py CHANGED
@@ -1,13 +1,12 @@
1
  import os
2
  import shutil
3
  import hashlib
4
- from fastapi import FastAPI, UploadFile, File, Form
5
  from fastapi.middleware.cors import CORSMiddleware
6
  from fastapi.staticfiles import StaticFiles
7
  from fastapi.responses import JSONResponse
8
- from pydub import AudioSegment
9
  import google.generativeai as genai
10
- from gradio_client import Client, handle_file # 👈 迎回完全正常的 handle_file
11
  import uvicorn
12
 
13
  app = FastAPI()
@@ -26,27 +25,21 @@ if not os.path.exists("static"):
26
  os.makedirs("static")
27
  app.mount("/static", StaticFiles(directory="static"), name="static")
28
 
29
- # 💡 3. API Keys & Models 初始化 (對接 2026 最新 Gemini 3.5 Flash)
30
  GOOGLE_API_KEY = os.getenv('GEMINI_KEY', '請填入您的GEMINI_KEY')
31
  genai.configure(api_key=GOOGLE_API_KEY)
32
  MODEL_NAME = 'gemini-3.5-flash'
33
  model = genai.GenerativeModel(MODEL_NAME)
34
 
35
- # 💡 4. 【完全複製你最原始、完全不加額外參數的初始化寫法】
36
- asr_client = Client("https://ai-labs.ilrdf.org.tw/sapolita-kaldi/")
37
  tts_client = Client("https://ai-labs.ilrdf.org.tw/hnang-kari-ai-asi-sluhay/")
38
  mt_client = Client("https://ai-labs.ilrdf.org.tw/kari-seejiq-tnpusu-ai-hmjil/")
39
 
40
- # 【完全複製你原本的族語配置】
41
  TRIBE_CONFIG = {
42
- "阿美": {"asr": "formosan_ami", "mt": "阿美"}, "泰雅": {"asr": "formosan_tay", "mt": "泰雅"},
43
- "排灣": {"asr": "formosan_pwn", "mt": "排灣"}, "布農": {"asr": "formosan_bnn", "mt": "布農"},
44
- "卑南": {"asr": "formosan_pyu", "mt": "卑南"}, "魯凱": {"asr": "formosan_dru", "mt": "魯"},
45
- "": {"asr": "formosan_tsu", "mt": ""}, "賽夏": {"asr": "formosan_xsy", "mt": "賽夏"},
46
- "雅美": {"asr": "formosan_tao", "mt": "雅美"}, "邵": {"asr": "formosan_ssf", "mt": "邵"},
47
- "噶瑪蘭": {"asr": "formosan_ckv", "mt": "噶瑪蘭"}, "太魯閣": {"asr": "formosan_trv", "mt": "太魯閣"},
48
- "撒奇萊雅": {"asr": "formosan_szy", "mt": "撒奇萊雅"}, "賽德克": {"asr": "formosan_sdq", "mt": "賽德克"},
49
- "拉阿魯哇": {"asr": "formosan_sxr", "mt": "拉阿魯哇"}, "卡那卡那富": {"asr": "formosan_xnb", "mt": "卡那卡那富"}
50
  }
51
 
52
  def get_clean_value(res):
@@ -62,50 +55,31 @@ def format_native_text(text, tribe):
62
 
63
  @app.get("/")
64
  def read_root():
65
- return {"status": "ILRDF Avatar Backend is Running Successfully!", "model_in_use": MODEL_NAME}
66
 
67
  @app.post("/api/chat")
68
  async def avatar_chat(
69
  tribe: str = Form(...),
70
- audio: UploadFile = File(...)
71
  ):
72
  try:
73
  config = TRIBE_CONFIG.get(tribe)
74
  if not config:
75
  return JSONResponse({"error": f"不支援的族語: {tribe}"}, status_code=400)
76
 
77
- # --- 步驟 A: 處理網頁傳來的錄音檔 ---
78
- temp_in = f"static/in_{audio.filename}"
79
- with open(temp_in, "wb") as buffer:
80
- shutil.copyfileobj(audio.file, buffer)
81
 
82
- wav_path = f"static/in_converted.wav"
83
- audio_segment = AudioSegment.from_file(temp_in)
84
- audio_segment.export(wav_path, format="wav")
85
-
86
- # --- 步驟 B: 【100% 複製你 handle_audio 裡的 ASR 程式碼】 ---
87
- native_in = asr_client.predict(
88
- dialect_id=config["asr"],
89
- audio_data=handle_file(wav_path),
90
- api_name="/automatic_speech_recognition"
91
- )
92
-
93
- # --- 步驟 C: 【100% 複製你 handle_audio 裡的 中文翻譯 程式碼】 ---
94
- go_code = get_clean_value(mt_client.predict(ethnicity=config["mt"], api_name="/lambda"))
95
- zh_in = get_clean_value(mt_client.predict(text=native_in, src_lang=go_code, tgt_lang="zho_Hant", api_name="/translate"))
96
- native_in = format_native_text(native_in, tribe)
97
-
98
- # --- 步驟 D: AI 大腦生成對話 (Gemini 3.5 Flash) ---
99
  prompt = f"你現在是與我對話的{tribe}族朋友。請用中文聊天。回覆規則:1.口吻生活化親切。2.不要說教解釋。3.字數一定要少(15字內),限一個短句。\n\n使用者說:{zh_in}"
100
  response = model.generate_content(prompt)
101
  ai_zh = response.text.strip()
102
 
103
- # --- 步驟 E: 【100% 複製你一般聊天模式裡的 族語翻譯 程式碼】 ---
104
  back_code = get_clean_value(mt_client.predict(ethnicity=config["mt"], api_name="/lambda_1"))
105
  ai_native = get_clean_value(mt_client.predict(text=ai_zh, src_lang="zho_Hant", tgt_lang=back_code, api_name="/translate_1"))
106
  ai_native = format_native_text(ai_native, tribe)
107
 
108
- # --- 步驟 F: 【100% 複製你 handle_text 裡的 TTS 語音合成與路徑搬移程式碼】 ---
109
  speaker = get_clean_value(tts_client.predict(ethnicity=config["mt"], api_name="/lambda"))
110
  if tribe == "阿美": speaker = "阿美_秀姑巒_女聲1"
111
  temp_tts = tts_client.predict(ref=speaker, gen_text_input=ai_native, api_name="/default_speaker_tts")
@@ -114,7 +88,7 @@ async def avatar_chat(
114
  out_filepath = f"static/{unique_str}"
115
  shutil.move(temp_tts, out_filepath)
116
 
117
- # --- 步驟 G: 組合網址與清理環境 ---
118
  base_url = os.getenv('SPACE_HOST', '')
119
  if base_url:
120
  base_url = f"https://{base_url}"
@@ -123,11 +97,8 @@ async def avatar_chat(
123
 
124
  audio_url = f"{base_url}/{out_filepath}"
125
 
126
- os.remove(temp_in)
127
- os.remove(wav_path)
128
-
129
  return {
130
- "user_native_text": native_in,
131
  "ai_zh_text": ai_zh,
132
  "ai_native_text": ai_native,
133
  "audio_url": audio_url
 
1
  import os
2
  import shutil
3
  import hashlib
4
+ from fastapi import FastAPI, Form
5
  from fastapi.middleware.cors import CORSMiddleware
6
  from fastapi.staticfiles import StaticFiles
7
  from fastapi.responses import JSONResponse
 
8
  import google.generativeai as genai
9
+ from gradio_client import Client
10
  import uvicorn
11
 
12
  app = FastAPI()
 
25
  os.makedirs("static")
26
  app.mount("/static", StaticFiles(directory="static"), name="static")
27
 
28
+ # 💡 3. API Keys & Models 初始化 (對接 2026 最新 Gemini 3.5 Flash)
29
  GOOGLE_API_KEY = os.getenv('GEMINI_KEY', '請填入您的GEMINI_KEY')
30
  genai.configure(api_key=GOOGLE_API_KEY)
31
  MODEL_NAME = 'gemini-3.5-flash'
32
  model = genai.GenerativeModel(MODEL_NAME)
33
 
34
+ # 💡 4. 初始化原語會的翻譯與 TTS 伺服器
 
35
  tts_client = Client("https://ai-labs.ilrdf.org.tw/hnang-kari-ai-asi-sluhay/")
36
  mt_client = Client("https://ai-labs.ilrdf.org.tw/kari-seejiq-tnpusu-ai-hmjil/")
37
 
 
38
  TRIBE_CONFIG = {
39
+ "阿美": {"mt": "阿美"}, "泰雅": {"mt": "泰雅"}, "排灣": {"mt": "排灣"}, "布農": {"mt": "布農"},
40
+ "卑南": {"mt": "卑南"}, "魯凱": {"mt": "魯凱"}, "": {"mt": ""}, "賽夏": {"mt": "賽夏"},
41
+ "雅美": {"mt": "雅美"}, "邵": {"mt": ""}, "噶瑪蘭": {"mt": "噶瑪蘭"}, "太魯閣": {"mt": ""},
42
+ "撒奇萊雅": {"mt": "撒奇萊雅"}, "賽德克": {"mt": "賽德克"}, "拉阿魯哇": {"mt": "拉阿魯哇"}, "卡那卡那富": {"mt": "卡那卡那富"}
 
 
 
 
43
  }
44
 
45
  def get_clean_value(res):
 
55
 
56
  @app.get("/")
57
  def read_root():
58
+ return {"status": "ILRDF Avatar Text Brain is Running Successfully!", "model": MODEL_NAME}
59
 
60
  @app.post("/api/chat")
61
  async def avatar_chat(
62
  tribe: str = Form(...),
63
+ text: str = Form(...) # 👈 接收前端秒傳過來的中文文字
64
  ):
65
  try:
66
  config = TRIBE_CONFIG.get(tribe)
67
  if not config:
68
  return JSONResponse({"error": f"不支援的族語: {tribe}"}, status_code=400)
69
 
70
+ zh_in = text.strip()
 
 
 
71
 
72
+ # --- 步驟 A: AI 大腦生成對話 (Gemini 3.5 Flash) ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  prompt = f"你現在是與我對話的{tribe}族朋友。請用中文聊天。回覆規則:1.口吻生活化親切。2.不要說教解釋。3.字數一定要少(15字內),限一個短句。\n\n使用者說:{zh_in}"
74
  response = model.generate_content(prompt)
75
  ai_zh = response.text.strip()
76
 
77
+ # --- 步驟 B: 翻譯回族語 ---
78
  back_code = get_clean_value(mt_client.predict(ethnicity=config["mt"], api_name="/lambda_1"))
79
  ai_native = get_clean_value(mt_client.predict(text=ai_zh, src_lang="zho_Hant", tgt_lang=back_code, api_name="/translate_1"))
80
  ai_native = format_native_text(ai_native, tribe)
81
 
82
+ # --- 步驟 C: 語音合成 (TTS) ---
83
  speaker = get_clean_value(tts_client.predict(ethnicity=config["mt"], api_name="/lambda"))
84
  if tribe == "阿美": speaker = "阿美_秀姑巒_女聲1"
85
  temp_tts = tts_client.predict(ref=speaker, gen_text_input=ai_native, api_name="/default_speaker_tts")
 
88
  out_filepath = f"static/{unique_str}"
89
  shutil.move(temp_tts, out_filepath)
90
 
91
+ # --- 步驟 D: 組合完整語音網址 ---
92
  base_url = os.getenv('SPACE_HOST', '')
93
  if base_url:
94
  base_url = f"https://{base_url}"
 
97
 
98
  audio_url = f"{base_url}/{out_filepath}"
99
 
 
 
 
100
  return {
101
+ "user_zh_text": zh_in,
102
  "ai_zh_text": ai_zh,
103
  "ai_native_text": ai_native,
104
  "audio_url": audio_url