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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -68
app.py CHANGED
@@ -2,6 +2,7 @@ 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
@@ -22,6 +23,9 @@ if GEMINI_KEYS:
22
  else:
23
  print("هشدار: هیچ کلید جیمینای یافت نشد.")
24
 
 
 
 
25
  class IdeaRequest(BaseModel):
26
  idea: str
27
 
@@ -33,85 +37,85 @@ async def read_root():
33
  except FileNotFoundError:
34
  return "<h1>Error: index.html not found</h1>"
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.
61
-
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 (اعراب نگذار).
69
- - You MUST use the following structure tags exactly:
70
- [Verse 1]
71
- [Pre-Chorus]
72
- [Chorus]
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)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  import json
3
  import random
4
  import asyncio
5
+ from concurrent.futures import ThreadPoolExecutor
6
  from fastapi import FastAPI, HTTPException
7
  from fastapi.responses import HTMLResponse, JSONResponse
8
  from pydantic import BaseModel
 
23
  else:
24
  print("هشدار: هیچ کلید جیمینای یافت نشد.")
25
 
26
+ # 2. ایجاد ThreadPool برای اجرای موازی درخواست‌ها (دست‌های زیاد)
27
+ executor = ThreadPoolExecutor(max_workers=10)
28
+
29
  class IdeaRequest(BaseModel):
30
  idea: str
31
 
 
37
  except FileNotFoundError:
38
  return "<h1>Error: index.html not found</h1>"
39
 
40
+ def sync_generate_content(prompt):
41
+ """
42
+ این تابع همگام است و در یک ترد جداگانه اجرا می‌شود تا سرور اصلی را قفل نکند.
43
+ تلاش می‌کند تا 100 بار با کلیدهای مختلف محتوا تولید کند.
44
+ """
45
+ max_retries = 100 # درخواست شما: 100 بار تلاش تصادفی
 
 
 
 
46
 
47
+ for _ in range(max_retries):
 
 
48
  try:
49
+ # انتخاب کاملاً تصادفی یک کلید در هر بار تلاش
 
50
  current_key = random.choice(GEMINI_KEYS)
51
 
52
  genai.configure(api_key=current_key)
53
  model = genai.GenerativeModel('gemini-2.5-flash')
 
 
 
 
 
 
54
 
55
+ # تولید محتوا (این عملیات ممکن است طول بکشد)
56
+ response = model.generate_content(prompt)
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
+ clean_json = response.text.replace("```json", "").replace("```", "").strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  data = json.loads(clean_json)
60
 
61
+ return data # موفقیت! خروجی را برگردان
 
62
 
63
  except Exception as e:
64
+ # خطا را نادیده بگیر و دوباره تلاش کن (حلقه بعدی)
65
+ # print(f"Key failed: {str(e)[:50]}...")
 
 
 
 
 
 
66
  continue
67
+
68
+ # اگر بعد از 100 تلاش نشد
69
+ return None
70
+
71
+ @app.post("/api/refine")
72
+ async def refine_text(request: IdeaRequest):
73
+ if not GEMINI_KEYS:
74
+ raise HTTPException(status_code=500, detail="کلید API تنظیم نشده است.")
75
+
76
+ prompt = f"""
77
+ You are a professional songwriter and music producer.
78
+ Task: Convert the user's input into a COMPLETE song structure and a music generation prompt.
79
 
80
+ 1. **Music Prompt (English):** Describe the mood, instruments, BPM, and style suitable for an AI music generator.
81
+
82
+ 2. **Lyrics (Match User's Language):**
83
+ - **Language Detection:** Detect the language of the "User Input".
84
+ - **Write the lyrics entirely in that detected language.**
85
+ - The song MUST be long enough for **3 to 5 minutes**.
86
+ - If the language is Persian/Arabic, do **NOT** use diacritics (اعراب نگذار).
87
+ - You MUST use the following structure tags exactly:
88
+ [Verse 1]
89
+ [Pre-Chorus]
90
+ [Chorus]
91
+ [Verse 2]
92
+ [Chorus]
93
+ [Bridge]
94
+ [Guitar Solo]
95
+ [Chorus]
96
+ [Outro]
97
+
98
+ **CRITICAL RULES FOR LYRICS content:**
99
+ - The "lyrics" field must contain **ONLY the words to be sung**.
100
+ - **ABSOLUTELY NO** descriptive text inside the lyrics.
101
+ - For instrumental sections, leave the content empty.
102
+
103
+ Output strictly in JSON format:
104
+ {{
105
+ "music_prompt": "YOUR ENGLISH PROMPT HERE",
106
+ "lyrics": "YOUR FULL LYRICS HERE"
107
+ }}
108
+
109
+ User Input: {request.idea}
110
+ """
111
+
112
+ # 3. اجرای درخواست سنگین در پس‌زمینه (Non-blocking)
113
+ # این باعث می‌شود سرور اصلی آزاد باشد و بتواند درخواست‌های جدید بگیرد
114
+ loop = asyncio.get_running_loop()
115
+ result = await loop.run_in_executor(executor, sync_generate_content, prompt)
116
+
117
+ if result:
118
+ return JSONResponse(content=result)
119
+ else:
120
+ # اگر بعد از 100 تلاش هیچ کلیدی کار نکرد
121
+ return JSONResponse(content={"error": "Server busy (100 retries failed). Please try again later."}, status_code=503)