Jan2000 commited on
Commit
44c4f43
·
unverified ·
1 Parent(s): 27294a0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +23 -30
app.py CHANGED
@@ -38,6 +38,7 @@ app = Flask(__name__)
38
 
39
  # ================== بخش پیکربندی Gemini ==================
40
 
 
41
  GEMINI_MODEL_NAME = "gemini-2.5-flash"
42
  ALL_KEYS_STR = os.environ.get("ALL_GEMINI_API_KEYS", "")
43
  GEMINI_API_KEYS = [key.strip() for key in ALL_KEYS_STR.split(',') if key.strip()]
@@ -58,10 +59,9 @@ def get_next_key_with_index():
58
  key_index_counter = (key_index_counter + 1) % len(GEMINI_API_KEYS)
59
  return key, current_index
60
 
61
- # تنظیمات تایم‌اوت برای درخواست‌ها به گوگل
62
- # تایم‌اوت اول برای اتصال، دومی برای خواندن داده. مقادیر افزایش یافته تا پایداری بیشتر شود.
63
- STREAM_CONNECT_TIMEOUT = 10
64
- STREAM_READ_TIMEOUT = 40
65
 
66
  # ================== پایان بخش پیکربندی ====================
67
 
@@ -76,11 +76,11 @@ def chat():
76
  return Response(f"data: {json.dumps(error_payload)}\n\n", status=500, mimetype='text/event-stream')
77
 
78
  data = request.json
79
- system_instruction = "تو چت بات هوش مصنوعی آلفا هستی و توسط برنامه هوش مصنوعی آلفا توسعه داده شدی. کمی با کاربران باحال و دوستانه صحبت کن و از ایموجی‌ها استفاده کن. همیشه پاسخ‌هایت را به زبان فارسی و یا هر زبانی که کاربر صحبت میکنه ارائه بده."
80
 
81
  show_thoughts = data.get("show_thoughts", False)
82
 
83
- # بخش پردازش پیام‌ها و فایل DOCX
84
  gemini_messages = []
85
  for msg in data.get("messages", []):
86
  role = "model" if msg.get("role") == "assistant" else msg.get("role")
@@ -109,6 +109,11 @@ def chat():
109
  processed_parts.append({"text": "[خطا: امکان پردازش فایل Word وجود نداشت.]"})
110
 
111
  else:
 
 
 
 
 
112
  processed_parts.append({"inline_data": {"mime_type": part["mimeType"], "data": part["base64Data"]}})
113
 
114
  if processed_parts:
@@ -121,7 +126,7 @@ def chat():
121
  return Response("data: [DONE]\n\n", mimetype='text/event-stream')
122
 
123
  def stream_response():
124
- # تعداد دفعات تلاش کلی: به اندازه 2 برابر تعداد کلیدها تلاش میکنیم تا مطمئن شویم
125
  max_attempts = len(GEMINI_API_KEYS) * 2
126
  attempts = 0
127
  last_error = None
@@ -130,8 +135,7 @@ def chat():
130
  attempts += 1
131
  try:
132
  api_key, key_index = get_next_key_with_index()
133
- # logging.info(f"تلاش شماره {attempts}: استفاده از کلید ایندکس {key_index}")
134
-
135
  api_endpoint = f"https://generativelanguage.googleapis.com/v1beta/models/{GEMINI_MODEL_NAME}:streamGenerateContent?key={api_key}&alt=sse"
136
 
137
  payload = {
@@ -148,15 +152,15 @@ def chat():
148
  "include_thoughts": True
149
  }
150
 
151
- # ارسال درخواست به گوگل
152
  with requests.post(api_endpoint, json=payload, stream=True, timeout=(STREAM_CONNECT_TIMEOUT, STREAM_READ_TIMEOUT)) as response:
153
- # اگر خطای 429 (محدودیت نرخ) یا 5xx (خطای سرور گوگل) باشد
 
154
  if response.status_code == 429 or response.status_code >= 500:
155
  logging.warning(f"خطای {response.status_code} با کلید {key_index}. رفتن به کلید بعدی...")
156
  last_error = f"Status Code: {response.status_code}"
157
- continue # برو به کلید بعدی
158
 
159
- # اگر خطای 403 (Forbidden/Invalid Key) باشد
160
  if response.status_code == 403:
161
  logging.warning(f"کلید {key_index} نامعتبر است (403). رفتن به کلید بعدی...")
162
  last_error = "Invalid API Key (403)"
@@ -164,9 +168,6 @@ def chat():
164
 
165
  response.raise_for_status()
166
 
167
- # اگر موفق شدیم وصل بشیم، شروع به استریم میکنیم
168
- # logging.info(f"اتصال موفق با کلید {key_index}. شروع استریم...")
169
-
170
  data_received = False
171
  for line in response.iter_lines():
172
  if line:
@@ -191,38 +192,30 @@ def chat():
191
  except (json.JSONDecodeError, IndexError, KeyError):
192
  continue
193
 
194
- # اگر دیتا با موفقیت دریافت شد و حلقه تمام شد، از تابع خارج میشویم
195
  if data_received:
196
  return
197
  else:
198
- # اگر وصل شدیم اما دیتایی نیامد (پاسخ خالی)، شاید مشکلی بوده، امتحان مجدد با کلید بعدی
199
  last_error = "Empty response"
200
  continue
201
 
202
  except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError) as e:
203
- logging.warning(f"خطای شبکه/تایم‌اوت با کلید {key_index}: {str(e)}. تلاش مجدد با کلید بعدی...")
204
  last_error = str(e)
205
- continue # برو به کلید بعدی
206
 
207
  except Exception as e:
208
  logging.error(f"خطای غیرمنتظره با کلید {key_index}: {e}")
209
  last_error = str(e)
210
- continue # برای اطمینان، حتی با خطای عجیب هم سعی میکنیم با کلید بعدی ادامه بدیم
211
 
212
- # اگر همه تلاش‌ها شکست خورد
213
- logging.critical("تمام کلیدها امتحان شدند و پاسخگو نبودند.")
214
- # اینجا دیگر چاره‌ای نیست جز نمایش خطا، اما چون کاربر گفته خطا نبینه،
215
- # می‌توانیم یک پیام مودبانه بفرستیم یا هیچ چیزی نفرستیم (که البته باعث میشه کاربر فکر کنه هنوز داره فکر میکنه)
216
- # بهترین کار ارسال یک پیام خطای نرم است.
217
- error_message = "سیستم در حال حاضر شلوغ است. لطفاً چند لحظه دیگر دوباره تلاش کنید."
218
- error_payload = {"choices": [{"delta": {"content": error_message}}]} # به جای ارور، به عنوان متن چت میفرستیم
219
  yield f"data: {json.dumps(error_payload)}\n\n"
220
 
221
  return Response(stream_response(), mimetype='text/event-stream')
222
 
223
  if __name__ == '__main__':
224
- if GEMINI_API_KEYS:
225
- logging.info(f"سیستم شروع به کار کرد. {len(GEMINI_API_KEYS)} کلید شناسایی شد.")
226
  app.run(debug=True, host='0.0.0.0', port=os.environ.get("PORT", 7860))
227
 
228
  # --- END OF FILE app.py ---
 
38
 
39
  # ================== بخش پیکربندی Gemini ==================
40
 
41
+ # مدل 2.5 فلش بهترین مدل برای پردازش ویدیو است
42
  GEMINI_MODEL_NAME = "gemini-2.5-flash"
43
  ALL_KEYS_STR = os.environ.get("ALL_GEMINI_API_KEYS", "")
44
  GEMINI_API_KEYS = [key.strip() for key in ALL_KEYS_STR.split(',') if key.strip()]
 
59
  key_index_counter = (key_index_counter + 1) % len(GEMINI_API_KEYS)
60
  return key, current_index
61
 
62
+ # افزایش تایم‌اوت برای آپلود ویدیو ضروری است
63
+ STREAM_CONNECT_TIMEOUT = 20
64
+ STREAM_READ_TIMEOUT = 120
 
65
 
66
  # ================== پایان بخش پیکربندی ====================
67
 
 
76
  return Response(f"data: {json.dumps(error_payload)}\n\n", status=500, mimetype='text/event-stream')
77
 
78
  data = request.json
79
+ system_instruction = "تو چت بات هوش مصنوعی آلفا هستی. تو توانایی تحلیل دقیق ویدیو، صدا و تصویر را داری. اگر کاربر ویدیویی فرستاد، تمام فریم‌ها و صدای آن را بررسی کن و به سوالات پاسخ بده. همیشه پاسخ‌هایت را به زبان فارسی و یا هر زبانی که کاربر صحبت میکنه ارائه بده."
80
 
81
  show_thoughts = data.get("show_thoughts", False)
82
 
83
+ # بخش پردازش پیام‌ها و فایل DOCX و ویدیو
84
  gemini_messages = []
85
  for msg in data.get("messages", []):
86
  role = "model" if msg.get("role") == "assistant" else msg.get("role")
 
109
  processed_parts.append({"text": "[خطا: امکان پردازش فایل Word وجود نداشت.]"})
110
 
111
  else:
112
+ # *** تغییر اصلی برای ویدیو اینجاست ***
113
+ # اگر فایل ویدیویی بود، یک راهنمایی متنی اضافه می‌کنیم تا مدل گیج نشود
114
+ if mime_type.startswith("video/"):
115
+ processed_parts.append({"text": "این فایل یک ویدیو است. لطفا فریم‌ها، حرکات و صدای داخل ویدیو را با دقت تحلیل کن."})
116
+
117
  processed_parts.append({"inline_data": {"mime_type": part["mimeType"], "data": part["base64Data"]}})
118
 
119
  if processed_parts:
 
126
  return Response("data: [DONE]\n\n", mimetype='text/event-stream')
127
 
128
  def stream_response():
129
+ # چرخش بین کلیدها در صورت بروز خطا
130
  max_attempts = len(GEMINI_API_KEYS) * 2
131
  attempts = 0
132
  last_error = None
 
135
  attempts += 1
136
  try:
137
  api_key, key_index = get_next_key_with_index()
138
+
 
139
  api_endpoint = f"https://generativelanguage.googleapis.com/v1beta/models/{GEMINI_MODEL_NAME}:streamGenerateContent?key={api_key}&alt=sse"
140
 
141
  payload = {
 
152
  "include_thoughts": True
153
  }
154
 
155
+ # درخواست به گوگل با تایم‌اوت کنترل شده
156
  with requests.post(api_endpoint, json=payload, stream=True, timeout=(STREAM_CONNECT_TIMEOUT, STREAM_READ_TIMEOUT)) as response:
157
+
158
+ # مدیریت خطاهای خاص گوگل (429, 500, 403) برای سوئیچ روی کلید بعدی
159
  if response.status_code == 429 or response.status_code >= 500:
160
  logging.warning(f"خطای {response.status_code} با کلید {key_index}. رفتن به کلید بعدی...")
161
  last_error = f"Status Code: {response.status_code}"
162
+ continue
163
 
 
164
  if response.status_code == 403:
165
  logging.warning(f"کلید {key_index} نامعتبر است (403). رفتن به کلید بعدی...")
166
  last_error = "Invalid API Key (403)"
 
168
 
169
  response.raise_for_status()
170
 
 
 
 
171
  data_received = False
172
  for line in response.iter_lines():
173
  if line:
 
192
  except (json.JSONDecodeError, IndexError, KeyError):
193
  continue
194
 
 
195
  if data_received:
196
  return
197
  else:
 
198
  last_error = "Empty response"
199
  continue
200
 
201
  except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.ChunkedEncodingError) as e:
202
+ logging.warning(f"خطای شبکه با کلید {key_index}: {str(e)}. تلاش مجدد...")
203
  last_error = str(e)
204
+ continue
205
 
206
  except Exception as e:
207
  logging.error(f"خطای غیرمنتظره با کلید {key_index}: {e}")
208
  last_error = str(e)
209
+ continue
210
 
211
+ # اگر هیچ کلیدی کار نکرد، پیام خطای ملایم به کاربر بده (نه ارور قرمز)
212
+ error_message = "سیستم در حال پردازش سنگین است. لطفا مجددا تلاش کنید."
213
+ error_payload = {"choices": [{"delta": {"content": error_message}}]}
 
 
 
 
214
  yield f"data: {json.dumps(error_payload)}\n\n"
215
 
216
  return Response(stream_response(), mimetype='text/event-stream')
217
 
218
  if __name__ == '__main__':
 
 
219
  app.run(debug=True, host='0.0.0.0', port=os.environ.get("PORT", 7860))
220
 
221
  # --- END OF FILE app.py ---