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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +67 -79
app.py CHANGED
@@ -1,8 +1,6 @@
1
  import os
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
@@ -13,18 +11,17 @@ load_dotenv()
13
 
14
  app = FastAPI()
15
 
16
- # 1. بارگذاری تمام کلیدها در حافظه
 
17
  all_keys_str = os.getenv("ALL_GEMINI_API_KEYS", "")
18
- # تمیز کردن لیست کلیدها
19
  GEMINI_KEYS = [k.strip() for k in all_keys_str.split(",") if k.strip()]
20
 
 
21
  if GEMINI_KEYS:
22
- print(f"تعداد {len(GEMINI_KEYS)} کلید جیمینای بارگذاری شد.")
23
  else:
24
- print("هشدار: هیچ کلید جیمینای یافت نشد.")
25
-
26
- # 2. ایجاد ThreadPool برای اجرای موازی درخواست‌ها (دست‌های زیاد)
27
- executor = ThreadPoolExecutor(max_workers=10)
28
 
29
  class IdeaRequest(BaseModel):
30
  idea: str
@@ -37,85 +34,76 @@ async def read_root():
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)
 
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
 
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
 
34
  except FileNotFoundError:
35
  return "<h1>Error: index.html not found</h1>"
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.
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" (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 (اعراب نگذار).
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
+ [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)