Opera8 commited on
Commit
1844230
·
verified ·
1 Parent(s): b1926d6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -30
app.py CHANGED
@@ -1,6 +1,7 @@
1
  import os
2
  import json
3
  import random
 
4
  from fastapi import FastAPI, HTTPException
5
  from fastapi.responses import HTMLResponse, JSONResponse
6
  from pydantic import BaseModel
@@ -11,17 +12,15 @@ load_dotenv()
11
 
12
  app = FastAPI()
13
 
14
- # بارگذاری و پردازش کلیدها از متغیر محیطی
15
- # کلیدها باید با کاما (,) جدا شده باشند
16
  all_keys_str = os.getenv("ALL_GEMINI_API_KEYS", "")
17
- # حذف فاصله‌های اضافی و جدا کردن کلیدها
18
  GEMINI_KEYS = [k.strip() for k in all_keys_str.split(",") if k.strip()]
19
 
20
- # نمایش پیام در لاگ هنگام شروع برنامه
21
  if GEMINI_KEYS:
22
- print(f"تعداد {len(GEMINI_KEYS)} کلید جیمینای شناسایی شد")
23
  else:
24
- print("هیچ کلید جیمینای شناسایی نشد. لطفاً متغیر ALL_GEMINI_API_KEYS را تنظیم کنید.")
25
 
26
  class IdeaRequest(BaseModel):
27
  idea: str
@@ -36,25 +35,26 @@ async def read_root():
36
 
37
  @app.post("/api/refine")
38
  async def refine_text(request: IdeaRequest):
 
39
  if not GEMINI_KEYS:
40
- raise HTTPException(status_code=500, detail="هیچ کلید API تنظیم نشده است.")
41
 
42
- # ساخت یک لیست کپی و مخلوط کردن آن برای انتخاب تصادفی
43
- shuffled_keys = list(GEMINI_KEYS)
44
- random.shuffle(shuffled_keys)
45
-
46
- last_error = None
47
 
48
- # حلقه برای امتحان کردن کلیدها یکی پس از دیگری
49
- for api_key in shuffled_keys:
 
50
  try:
51
- # تنظیم کلید برای این تلاش
52
- genai.configure(api_key=api_key)
 
53
 
54
- # استفاده از مدل
55
  model = genai.GenerativeModel('gemini-2.5-flash')
56
 
57
- # پرامپت دقیق برای تشخیص زبان و جلوگیری از توضیحات اضافی
58
  prompt = f"""
59
  You are a professional songwriter and music producer.
60
  Task: Convert the user's input into a COMPLETE song structure and a music generation prompt.
@@ -62,7 +62,7 @@ async def refine_text(request: IdeaRequest):
62
  1. **Music Prompt (English):** Describe the mood, instruments, BPM, and style suitable for an AI music generator.
63
 
64
  2. **Lyrics (Match User's Language):**
65
- - **Language Detection:** Detect the language of the "User Input" (e.g., English, Persian, Spanish, etc.).
66
  - **Write the lyrics entirely in that detected language.**
67
  - The song MUST be long enough for **3 to 5 minutes**.
68
  - If the language is Persian/Arabic, do **NOT** use diacritics (اعراب نگذار).
@@ -73,37 +73,45 @@ async def refine_text(request: IdeaRequest):
73
  [Verse 2]
74
  [Chorus]
75
  [Bridge]
 
76
  [Chorus]
77
  [Outro]
78
 
79
  **CRITICAL RULES FOR LYRICS content:**
80
  - The "lyrics" field must contain **ONLY the words to be sung**.
81
- - **ABSOLUTELY NO** descriptive text, stage directions, or instrumental notes inside the lyrics (e.g., DO NOT write "(Instrumental)", "(Fade out)", "(Repeat 2x)", or descriptions of the solo).
82
- - For instrumental sections, if there are no words to sing, leave the content under that tag empty or just write the tag itself.
83
- - Do NOT write things like "Guitar solo starts here" inside the lyrics value.
84
 
85
  Output strictly in JSON format:
86
  {{
87
  "music_prompt": "YOUR ENGLISH PROMPT HERE",
88
- "lyrics": "YOUR FULL LYRICS HERE (ONLY SUNG WORDS IN DETECTED LANGUAGE)"
89
  }}
90
 
91
  User Input: {request.idea}
92
  """
93
 
94
- # تلاش برای تولید محتوا
95
- result = model.generate_content(prompt)
 
 
96
  clean_json = result.text.replace("```json", "").replace("```", "").strip()
97
  data = json.loads(clean_json)
98
 
99
- # اگر موفقیت‌آمیز بود، خروجی را برگردان و از حلقه خارج شو
100
  return JSONResponse(content=data)
101
 
102
  except Exception as e:
103
- # اگر کلید فعلی خطا داد (مثلاً اعتبار تمام شده)، لاگ کن و برو سراغ کلید بعدی
104
- print(f"Error with a key: {e}. Trying next key...")
105
  last_error = e
 
 
 
 
 
 
 
106
  continue
107
 
108
- # اگر تمام کلیدها تست شدند و همه خطا دادند
109
- return JSONResponse(content={"error": f"All keys failed. Last error: {str(last_error)}"}, status_code=500)
 
 
1
  import os
2
  import json
3
  import random
4
+ import asyncio
5
  from fastapi import FastAPI, HTTPException
6
  from fastapi.responses import HTMLResponse, JSONResponse
7
  from pydantic import BaseModel
 
12
 
13
  app = FastAPI()
14
 
15
+ # 1. بارگذاری تمام کلیدها در حافظه
 
16
  all_keys_str = os.getenv("ALL_GEMINI_API_KEYS", "")
17
+ # تمیز کردن لیست کلیدها
18
  GEMINI_KEYS = [k.strip() for k in all_keys_str.split(",") if k.strip()]
19
 
 
20
  if GEMINI_KEYS:
21
+ print(f"تعداد {len(GEMINI_KEYS)} کلید جیمینای بارگذاری شد.")
22
  else:
23
+ print("هشدار: هیچ کلید جیمینای یافت نشد.")
24
 
25
  class IdeaRequest(BaseModel):
26
  idea: str
 
35
 
36
  @app.post("/api/refine")
37
  async def refine_text(request: IdeaRequest):
38
+ # اگر کلاً کلیدی وجود ندارد، خطا بده
39
  if not GEMINI_KEYS:
40
+ raise HTTPException(status_code=500, detail="کلید API تنظیم نشده است.")
41
 
42
+ # 2. تنظیمات تلاش مجدد
43
+ # ما حداکثر 60 بار تلاش می‌کنیم (حدود 1 دقیقه در بدترین حالت)
44
+ # این کار باعث می‌شود اگر اکثر کلیدها 429 بودند، سرور بی‌نهایت درگیر نماند
45
+ max_retries = 60
 
46
 
47
+ last_error = None
48
+
49
+ for attempt in range(max_retries):
50
  try:
51
+ # 3. انتخاب کاملاً تصادفی یک کلید در هر بار تلاش
52
+ # کلید از لیست حذف نمی‌شود، فقط خوانده می‌شود
53
+ current_key = random.choice(GEMINI_KEYS)
54
 
55
+ genai.configure(api_key=current_key)
56
  model = genai.GenerativeModel('gemini-2.5-flash')
57
 
 
58
  prompt = f"""
59
  You are a professional songwriter and music producer.
60
  Task: Convert the user's input into a COMPLETE song structure and a music generation prompt.
 
62
  1. **Music Prompt (English):** Describe the mood, instruments, BPM, and style suitable for an AI music generator.
63
 
64
  2. **Lyrics (Match User's Language):**
65
+ - **Language Detection:** Detect the language of the "User Input".
66
  - **Write the lyrics entirely in that detected language.**
67
  - The song MUST be long enough for **3 to 5 minutes**.
68
  - If the language is Persian/Arabic, do **NOT** use diacritics (اعراب نگذار).
 
73
  [Verse 2]
74
  [Chorus]
75
  [Bridge]
76
+ [Guitar Solo]
77
  [Chorus]
78
  [Outro]
79
 
80
  **CRITICAL RULES FOR LYRICS content:**
81
  - The "lyrics" field must contain **ONLY the words to be sung**.
82
+ - **ABSOLUTELY NO** descriptive text inside the lyrics.
83
+ - For instrumental sections, leave the content empty.
 
84
 
85
  Output strictly in JSON format:
86
  {{
87
  "music_prompt": "YOUR ENGLISH PROMPT HERE",
88
+ "lyrics": "YOUR FULL LYRICS HERE"
89
  }}
90
 
91
  User Input: {request.idea}
92
  """
93
 
94
+ # 4. استفاده از متد Async (دست‌های زیاد)
95
+ # این خط کلیدی است: باعث می‌شود سرور منتظر نماند و همزمان درخواست بقیه را بگیرد
96
+ result = await model.generate_content_async(prompt)
97
+
98
  clean_json = result.text.replace("```json", "").replace("```", "").strip()
99
  data = json.loads(clean_json)
100
 
101
+ # اگر موفق شد، نتیجه را برگردان و تمام
102
  return JSONResponse(content=data)
103
 
104
  except Exception as e:
 
 
105
  last_error = e
106
+ # خطای کوتاه در لاگ (برای جلوگیری از شلوغی)
107
+ # print(f"Attempt {attempt+1} failed with key ...{current_key[-4:]}: {str(e)[:50]}...")
108
+
109
+ # 5. وقفه کوتاه بسیار مهم
110
+ # این وقفه (0.05 ثانیه) باعث می‌شود CPU درگیر حلقه‌های تند نشود
111
+ # و به "دست‌های دیگر" فرصت کار می‌دهد
112
+ await asyncio.sleep(0.05)
113
  continue
114
 
115
+ # اگر بعد از 60 تلاش شانسی موفق نشدیم
116
+ print("تمام تلاش‌ها ناموفق بود. ترافیک بالا یا اعتبار تمام .")
117
+ return JSONResponse(content={"error": "Server is busy, please try again."}, status_code=503)