keungliang commited on
Commit
efa55c2
·
verified ·
1 Parent(s): c0bc423

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +173 -73
app.py CHANGED
@@ -86,15 +86,16 @@ if not DATA_DIR.exists():
86
  DATA_DIR.mkdir(parents=True, exist_ok=True)
87
  CONFIG = {
88
  "MODELS": {
89
- 'grok-2': 'grok-latest',
90
- 'grok-2-imageGen': 'grok-latest',
91
- 'grok-2-search': 'grok-latest',
92
  "grok-3": "grok-3",
93
  "grok-3-search": "grok-3",
94
  "grok-3-imageGen": "grok-3",
95
  "grok-3-deepsearch": "grok-3",
96
  "grok-3-deepersearch": "grok-3",
97
- "grok-3-reasoning": "grok-3"
 
 
 
 
98
  },
99
  "API": {
100
  "IS_TEMP_CONVERSATION": os.environ.get("IS_TEMP_CONVERSATION", "true").lower() == "true",
@@ -121,13 +122,15 @@ CONFIG = {
121
  "MAX_ATTEMPTS": 2
122
  },
123
  "TOKEN_STATUS_FILE": str(DATA_DIR / "token_status.json"),
124
- "SHOW_THINKING": os.environ.get("SHOW_THINKING") == "true",
125
  "IS_THINKING": False,
126
  "IS_IMG_GEN": False,
127
  "IS_IMG_GEN2": False,
128
- "ISSHOW_SEARCH_RESULTS": os.environ.get("ISSHOW_SEARCH_RESULTS", "true").lower() == "true"
 
129
  }
130
 
 
131
  DEFAULT_HEADERS = {
132
  'Accept': '*/*',
133
  'Accept-Language': 'zh-CN,zh;q=0.9',
@@ -136,16 +139,15 @@ DEFAULT_HEADERS = {
136
  'Connection': 'keep-alive',
137
  'Origin': 'https://grok.com',
138
  'Priority': 'u=1, i',
139
- 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
140
- 'Sec-Ch-Ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
141
  'Sec-Ch-Ua-Mobile': '?0',
142
- 'Sec-Ch-Ua-Platform': '"Windows"',
143
  'Sec-Fetch-Dest': 'empty',
144
  'Sec-Fetch-Mode': 'cors',
145
  'Sec-Fetch-Site': 'same-origin',
146
- 'x-statsig-id': 'ZTpUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkIChyZWFkaW5nICdjaGlsZE5vZGVzJyk=',
147
- 'x-xai-request-id': str(uuid.uuid4()),
148
- 'Baggage': 'sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c'
149
  }
150
 
151
  class AuthTokenManager:
@@ -153,32 +155,49 @@ class AuthTokenManager:
153
  self.token_model_map = {}
154
  self.expired_tokens = set()
155
  self.token_status_map = {}
156
-
157
- self.model_config = {
158
- "grok-2": {
159
- "RequestFrequency": 30,
160
- "ExpirationTime": 1 * 60 * 60 * 1000 # 1小时
161
- },
162
- "grok-3": {
163
- "RequestFrequency": 20,
164
- "ExpirationTime": 2 * 60 * 60 * 1000 # 2小时
165
- },
166
- "grok-3-deepsearch": {
167
- "RequestFrequency": 10,
168
- "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
169
- },
170
- "grok-3-deepersearch": {
171
- "RequestFrequency": 3,
172
- "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
173
- },
174
- "grok-3-reasoning": {
175
- "RequestFrequency": 10,
176
- "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
177
  }
178
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
  self.token_reset_switch = False
180
  self.token_reset_timer = None
181
- self.load_token_status() # 加载令牌状态
182
  def save_token_status(self):
183
  try:
184
  with open(CONFIG["TOKEN_STATUS_FILE"], 'w', encoding='utf-8') as f:
@@ -196,47 +215,67 @@ class AuthTokenManager:
196
  logger.info("已从配置文件加载令牌状态", "TokenManager")
197
  except Exception as error:
198
  logger.error(f"加载令牌状态失败: {str(error)}", "TokenManager")
199
- def add_token(self, token,isinitialization=False):
200
- sso = token.split("sso=")[1].split(";")[0]
 
 
 
 
 
 
 
201
  for model in self.model_config.keys():
202
  if model not in self.token_model_map:
203
  self.token_model_map[model] = []
204
  if sso not in self.token_status_map:
205
  self.token_status_map[sso] = {}
206
 
207
- existing_token_entry = next((entry for entry in self.token_model_map[model] if entry["token"] == token), None)
208
 
209
  if not existing_token_entry:
210
  self.token_model_map[model].append({
211
- "token": token,
 
212
  "RequestCount": 0,
213
  "AddedTime": int(time.time() * 1000),
214
- "StartCallTime": None
 
215
  })
216
 
217
  if model not in self.token_status_map[sso]:
218
  self.token_status_map[sso][model] = {
219
  "isValid": True,
220
  "invalidatedTime": None,
221
- "totalRequestCount": 0
 
222
  }
223
  if not isinitialization:
224
  self.save_token_status()
225
 
226
- def set_token(self, token):
 
 
 
 
 
 
 
227
  models = list(self.model_config.keys())
228
  self.token_model_map = {model: [{
229
- "token": token,
 
230
  "RequestCount": 0,
231
  "AddedTime": int(time.time() * 1000),
232
- "StartCallTime": None
 
233
  }] for model in models}
234
 
235
- sso = token.split("sso=")[1].split(";")[0]
236
  self.token_status_map[sso] = {model: {
237
  "isValid": True,
238
  "invalidatedTime": None,
239
- "totalRequestCount": 0
 
240
  } for model in models}
241
 
242
  def delete_token(self, token):
@@ -295,10 +334,15 @@ class AuthTokenManager:
295
  return None
296
 
297
  token_entry = self.token_model_map[normalized_model][0]
 
298
  if is_return:
299
  return token_entry["token"]
300
 
301
  if token_entry:
 
 
 
 
302
  if token_entry["StartCallTime"] is None:
303
  token_entry["StartCallTime"] = int(time.time() * 1000)
304
 
@@ -308,18 +352,21 @@ class AuthTokenManager:
308
 
309
  token_entry["RequestCount"] += 1
310
 
311
- if token_entry["RequestCount"] > self.model_config[normalized_model]["RequestFrequency"]:
312
  self.remove_token_from_model(normalized_model, token_entry["token"])
313
  next_token_entry = self.token_model_map[normalized_model][0] if self.token_model_map[normalized_model] else None
314
  return next_token_entry["token"] if next_token_entry else None
315
 
316
  sso = token_entry["token"].split("sso=")[1].split(";")[0]
 
317
  if sso in self.token_status_map and normalized_model in self.token_status_map[sso]:
318
  if token_entry["RequestCount"] == self.model_config[normalized_model]["RequestFrequency"]:
319
  self.token_status_map[sso][normalized_model]["isValid"] = False
320
  self.token_status_map[sso][normalized_model]["invalidatedTime"] = int(time.time() * 1000)
321
  self.token_status_map[sso][normalized_model]["totalRequestCount"] += 1
322
 
 
 
323
  self.save_token_status()
324
 
325
  return token_entry["token"]
@@ -341,7 +388,8 @@ class AuthTokenManager:
341
  self.expired_tokens.add((
342
  removed_token_entry["token"],
343
  normalized_model,
344
- int(time.time() * 1000)
 
345
  ))
346
 
347
  if not self.token_reset_switch:
@@ -358,7 +406,7 @@ class AuthTokenManager:
358
  return list(self.expired_tokens)
359
 
360
  def normalize_model_name(self, model):
361
- if model.startswith('grok-') and 'deepsearch' not in model and 'reasoning' not in model:
362
  return '-'.join(model.split('-')[:2])
363
  return model
364
 
@@ -371,8 +419,8 @@ class AuthTokenManager:
371
 
372
  for model in self.model_config.keys():
373
  model_tokens = self.token_model_map.get(model, [])
374
- model_request_frequency = self.model_config[model]["RequestFrequency"]
375
-
376
  total_used_requests = sum(token_entry.get("RequestCount", 0) for token_entry in model_tokens)
377
 
378
  remaining_capacity = (len(model_tokens) * model_request_frequency) - total_used_requests
@@ -388,10 +436,13 @@ class AuthTokenManager:
388
  def reset_expired_tokens():
389
  now = int(time.time() * 1000)
390
 
 
391
  tokens_to_remove = set()
392
  for token_info in self.expired_tokens:
393
- token, model, expired_time = token_info
394
- expiration_time = self.model_config[model]["ExpirationTime"]
 
 
395
 
396
  if now - expired_time >= expiration_time:
397
  if not any(entry["token"] == token for entry in self.token_model_map.get(model, [])):
@@ -400,9 +451,11 @@ class AuthTokenManager:
400
 
401
  self.token_model_map[model].append({
402
  "token": token,
 
403
  "RequestCount": 0,
404
  "AddedTime": now,
405
- "StartCallTime": None
 
406
  })
407
 
408
  sso = token.split("sso=")[1].split(";")[0]
@@ -410,12 +463,13 @@ class AuthTokenManager:
410
  self.token_status_map[sso][model]["isValid"] = True
411
  self.token_status_map[sso][model]["invalidatedTime"] = None
412
  self.token_status_map[sso][model]["totalRequestCount"] = 0
 
413
 
414
  tokens_to_remove.add(token_info)
415
 
416
  self.expired_tokens -= tokens_to_remove
417
 
418
- for model in self.model_config.keys():
419
  if model not in self.token_model_map:
420
  continue
421
 
@@ -423,13 +477,14 @@ class AuthTokenManager:
423
  if not token_entry.get("StartCallTime"):
424
  continue
425
 
426
- expiration_time = self.model_config[model]["ExpirationTime"]
427
  if now - token_entry["StartCallTime"] >= expiration_time:
428
  sso = token_entry["token"].split("sso=")[1].split(";")[0]
429
  if sso in self.token_status_map and model in self.token_status_map[sso]:
430
  self.token_status_map[sso][model]["isValid"] = True
431
  self.token_status_map[sso][model]["invalidatedTime"] = None
432
  self.token_status_map[sso][model]["totalRequestCount"] = 0
 
433
 
434
  token_entry["RequestCount"] = 0
435
  token_entry["StartCallTime"] = None
@@ -632,14 +687,14 @@ class GrokApiClient:
632
  # logger.error(str(error), "Server")
633
  # raise ValueError(error)
634
  def prepare_chat_request(self, request):
635
- if ((request["model"] == 'grok-2-imageGen' or request["model"] == 'grok-3-imageGen') and
636
  not CONFIG["API"]["PICGO_KEY"] and not CONFIG["API"]["TUMY_KEY"] and
637
  request.get("stream", False)):
638
  raise ValueError("该模型流式输出需要配置PICGO或者TUMY图床密钥!")
639
 
640
  # system_message, todo_messages = self.convert_system_messages(request["messages"]).values()
641
  todo_messages = request["messages"]
642
- if request["model"] in ['grok-2-imageGen', 'grok-3-imageGen', 'grok-3-deepsearch']:
643
  last_message = todo_messages[-1]
644
  if last_message["role"] != 'user':
645
  raise ValueError('此模型最后一条消息必须是用户消息!')
@@ -651,7 +706,7 @@ class GrokApiClient:
651
  message_length = 0
652
  convert_to_file = False
653
  last_message_content = ''
654
- search = request["model"] in ['grok-2-search', 'grok-3-search']
655
  deepsearchPreset = ''
656
  if request["model"] == 'grok-3-deepsearch':
657
  deepsearchPreset = 'default'
@@ -743,7 +798,7 @@ class GrokApiClient:
743
  "imageGenerationCount": 1,
744
  "forceConcise": False,
745
  "toolOverrides": {
746
- "imageGen": request["model"] in ['grok-2-imageGen', 'grok-3-imageGen'],
747
  "webSearch": search,
748
  "xSearch": search,
749
  "xMediaSearch": search,
@@ -800,17 +855,14 @@ def process_model_response(response, model):
800
  if response.get("cachedImageGenerationResponse") and not CONFIG["IS_IMG_GEN2"]:
801
  result["imageUrl"] = response["cachedImageGenerationResponse"]["imageUrl"]
802
  return result
803
-
804
- if model == 'grok-2':
805
  result["token"] = response.get("token")
806
- elif model in ['grok-2-search', 'grok-3-search']:
807
  if response.get("webSearchResults") and CONFIG["ISSHOW_SEARCH_RESULTS"]:
808
  result["token"] = f"\r\n<think>{Utils.organize_search_results(response['webSearchResults'])}</think>\r\n"
809
  else:
810
  result["token"] = response.get("token")
811
- elif model == 'grok-3':
812
- result["token"] = response.get("token")
813
- elif model in ['grok-3-deepsearch', 'grok-3-deepersearch']:
814
  if response.get("messageStepId") and not CONFIG["SHOW_THINKING"]:
815
  return result
816
  if response.get("messageStepId") and not CONFIG["IS_THINKING"]:
@@ -838,6 +890,37 @@ def process_model_response(response, model):
838
  else:
839
  result["token"] = response.get("token")
840
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
841
  return result
842
 
843
  def handle_image_response(image_url):
@@ -1022,20 +1105,36 @@ def handle_stream_response(response, model):
1022
 
1023
  def initialization():
1024
  sso_array = os.environ.get("SSO", "").split(',')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1025
  logger.info("开始加载令牌", "Server")
1026
  token_manager.load_token_status()
1027
- for sso in sso_array:
1028
- if sso:
1029
- token_manager.add_token(f"sso-rw={sso};sso={sso}",True)
1030
  token_manager.save_token_status()
1031
 
1032
  logger.info(f"成功加载令牌: {json.dumps(token_manager.get_all_tokens(), indent=2)}", "Server")
1033
- logger.info(f"令牌加载完成,共加载: {len(token_manager.get_all_tokens())}个令牌", "Server")
 
1034
 
1035
  if CONFIG["API"]["PROXY"]:
1036
  logger.info(f"代理已设置: {CONFIG['API']['PROXY']}", "Server")
1037
 
1038
- logger.info("初始化完成", "Server")
1039
 
1040
 
1041
  app = Flask(__name__)
@@ -1079,7 +1178,7 @@ def add_manager_token():
1079
  sso = request.json.get('sso')
1080
  if not sso:
1081
  return jsonify({"error": "SSO token is required"}), 400
1082
- token_manager.add_token(f"sso-rw={sso};sso={sso}")
1083
  return jsonify({"success": True})
1084
  except Exception as e:
1085
  return jsonify({"error": str(e)}), 500
@@ -1130,7 +1229,7 @@ def add_token():
1130
 
1131
  try:
1132
  sso = request.json.get('sso')
1133
- token_manager.add_token(f"sso-rw={sso};sso={sso}")
1134
  return jsonify(token_manager.get_token_status_map().get(sso, {})), 200
1135
  except Exception as error:
1136
  logger.error(str(error), "Server")
@@ -1202,6 +1301,7 @@ def chat_completions():
1202
  retry_count = 0
1203
  grok_client = GrokApiClient(model)
1204
  request_payload = grok_client.prepare_chat_request(data)
 
1205
  logger.info(json.dumps(request_payload,indent=2))
1206
 
1207
  while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]:
 
86
  DATA_DIR.mkdir(parents=True, exist_ok=True)
87
  CONFIG = {
88
  "MODELS": {
 
 
 
89
  "grok-3": "grok-3",
90
  "grok-3-search": "grok-3",
91
  "grok-3-imageGen": "grok-3",
92
  "grok-3-deepsearch": "grok-3",
93
  "grok-3-deepersearch": "grok-3",
94
+ "grok-3-reasoning": "grok-3",
95
+ 'grok-4': 'grok-4',
96
+ 'grok-4-reasoning': 'grok-4',
97
+ 'grok-4-imageGen': 'grok-4',
98
+ 'grok-4-deepsearch': 'grok-4'
99
  },
100
  "API": {
101
  "IS_TEMP_CONVERSATION": os.environ.get("IS_TEMP_CONVERSATION", "true").lower() == "true",
 
122
  "MAX_ATTEMPTS": 2
123
  },
124
  "TOKEN_STATUS_FILE": str(DATA_DIR / "token_status.json"),
125
+ "SHOW_THINKING": os.environ.get("SHOW_THINKING").lower() == "true",
126
  "IS_THINKING": False,
127
  "IS_IMG_GEN": False,
128
  "IS_IMG_GEN2": False,
129
+ "ISSHOW_SEARCH_RESULTS": os.environ.get("ISSHOW_SEARCH_RESULTS", "true").lower() == "true",
130
+ "IS_SUPER_GROK": os.environ.get("IS_SUPER_GROK", "false").lower() == "true"
131
  }
132
 
133
+
134
  DEFAULT_HEADERS = {
135
  'Accept': '*/*',
136
  'Accept-Language': 'zh-CN,zh;q=0.9',
 
139
  'Connection': 'keep-alive',
140
  'Origin': 'https://grok.com',
141
  'Priority': 'u=1, i',
142
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36',
143
+ 'Sec-Ch-Ua': '"Not(A:Brand";v="99", "Google Chrome";v="133", "Chromium";v="133"',
144
  'Sec-Ch-Ua-Mobile': '?0',
145
+ 'Sec-Ch-Ua-Platform': '"macOS"',
146
  'Sec-Fetch-Dest': 'empty',
147
  'Sec-Fetch-Mode': 'cors',
148
  'Sec-Fetch-Site': 'same-origin',
149
+ 'Baggage': 'sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c',
150
+ 'x-statsig-id': 'ZTpUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkIChyZWFkaW5nICdjaGlsZE5vZGVzJyk='
 
151
  }
152
 
153
  class AuthTokenManager:
 
155
  self.token_model_map = {}
156
  self.expired_tokens = set()
157
  self.token_status_map = {}
158
+ self.model_super_config = {
159
+ "grok-3": {
160
+ "RequestFrequency": 100,
161
+ "ExpirationTime": 3 * 60 * 60 * 1000 # 3小时
162
+ },
163
+ "grok-3-deepsearch": {
164
+ "RequestFrequency": 30,
165
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 3小时
166
+ },
167
+ "grok-3-deepersearch": {
168
+ "RequestFrequency": 10,
169
+ "ExpirationTime": 3 * 60 * 60 * 1000 # 23小时
170
+ },
171
+ "grok-3-reasoning": {
172
+ "RequestFrequency": 30,
173
+ "ExpirationTime": 3 * 60 * 60 * 1000 # 3小时
174
+ },
175
+ "grok-4": {
176
+ "RequestFrequency": 20,
177
+ "ExpirationTime": 3 * 60 * 60 * 1000 # 3小时
178
+ }
179
  }
180
+ self.model_normal_config = {
181
+ "grok-3": {
182
+ "RequestFrequency": 20,
183
+ "ExpirationTime": 3 * 60 * 60 * 1000 # 3小时
184
+ },
185
+ "grok-3-deepsearch": {
186
+ "RequestFrequency": 10,
187
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
188
+ },
189
+ "grok-3-deepersearch": {
190
+ "RequestFrequency": 3,
191
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
192
+ },
193
+ "grok-3-reasoning": {
194
+ "RequestFrequency": 8,
195
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
196
+ }
197
+ }
198
+ self.model_config = self.model_normal_config
199
  self.token_reset_switch = False
200
  self.token_reset_timer = None
 
201
  def save_token_status(self):
202
  try:
203
  with open(CONFIG["TOKEN_STATUS_FILE"], 'w', encoding='utf-8') as f:
 
215
  logger.info("已从配置文件加载令牌状态", "TokenManager")
216
  except Exception as error:
217
  logger.error(f"加载令牌状态失败: {str(error)}", "TokenManager")
218
+ def add_token(self, tokens, isinitialization=False):
219
+ tokenType = tokens.get("type")
220
+ tokenSso = tokens.get("token")
221
+ if tokenType == "normal":
222
+ self.model_config = self.model_normal_config
223
+ else:
224
+ self.model_config = self.model_super_config
225
+ sso = tokenSso.split("sso=")[1].split(";")[0]
226
+
227
  for model in self.model_config.keys():
228
  if model not in self.token_model_map:
229
  self.token_model_map[model] = []
230
  if sso not in self.token_status_map:
231
  self.token_status_map[sso] = {}
232
 
233
+ existing_token_entry = next((entry for entry in self.token_model_map[model] if entry["token"] == tokenSso), None)
234
 
235
  if not existing_token_entry:
236
  self.token_model_map[model].append({
237
+ "token": tokenSso,
238
+ "MaxRequestCount": self.model_config[model]["RequestFrequency"],
239
  "RequestCount": 0,
240
  "AddedTime": int(time.time() * 1000),
241
+ "StartCallTime": None,
242
+ "type": tokenType
243
  })
244
 
245
  if model not in self.token_status_map[sso]:
246
  self.token_status_map[sso][model] = {
247
  "isValid": True,
248
  "invalidatedTime": None,
249
+ "totalRequestCount": 0,
250
+ "isSuper":tokenType == "super"
251
  }
252
  if not isinitialization:
253
  self.save_token_status()
254
 
255
+ def set_token(self, tokens):
256
+ tokenType = tokens.get("type")
257
+ tokenSso = tokens.get("token")
258
+ if tokenType == "normal":
259
+ self.model_config = self.model_normal_config
260
+ else:
261
+ self.model_config = self.model_super_config
262
+
263
  models = list(self.model_config.keys())
264
  self.token_model_map = {model: [{
265
+ "token": tokenSso,
266
+ "MaxRequestCount": self.model_config[model]["RequestFrequency"],
267
  "RequestCount": 0,
268
  "AddedTime": int(time.time() * 1000),
269
+ "StartCallTime": None,
270
+ "type": tokenType
271
  }] for model in models}
272
 
273
+ sso = tokenSso.split("sso=")[1].split(";")[0]
274
  self.token_status_map[sso] = {model: {
275
  "isValid": True,
276
  "invalidatedTime": None,
277
+ "totalRequestCount": 0,
278
+ "isSuper":tokenType == "super"
279
  } for model in models}
280
 
281
  def delete_token(self, token):
 
334
  return None
335
 
336
  token_entry = self.token_model_map[normalized_model][0]
337
+ logger.info(f"token_entry: {token_entry}", "TokenManager")
338
  if is_return:
339
  return token_entry["token"]
340
 
341
  if token_entry:
342
+ if token_entry["type"] == "super":
343
+ self.model_config = self.model_super_config
344
+ else:
345
+ self.model_config = self.model_normal_config
346
  if token_entry["StartCallTime"] is None:
347
  token_entry["StartCallTime"] = int(time.time() * 1000)
348
 
 
352
 
353
  token_entry["RequestCount"] += 1
354
 
355
+ if token_entry["RequestCount"] > token_entry["MaxRequestCount"]:
356
  self.remove_token_from_model(normalized_model, token_entry["token"])
357
  next_token_entry = self.token_model_map[normalized_model][0] if self.token_model_map[normalized_model] else None
358
  return next_token_entry["token"] if next_token_entry else None
359
 
360
  sso = token_entry["token"].split("sso=")[1].split(";")[0]
361
+
362
  if sso in self.token_status_map and normalized_model in self.token_status_map[sso]:
363
  if token_entry["RequestCount"] == self.model_config[normalized_model]["RequestFrequency"]:
364
  self.token_status_map[sso][normalized_model]["isValid"] = False
365
  self.token_status_map[sso][normalized_model]["invalidatedTime"] = int(time.time() * 1000)
366
  self.token_status_map[sso][normalized_model]["totalRequestCount"] += 1
367
 
368
+
369
+
370
  self.save_token_status()
371
 
372
  return token_entry["token"]
 
388
  self.expired_tokens.add((
389
  removed_token_entry["token"],
390
  normalized_model,
391
+ int(time.time() * 1000),
392
+ removed_token_entry["type"]
393
  ))
394
 
395
  if not self.token_reset_switch:
 
406
  return list(self.expired_tokens)
407
 
408
  def normalize_model_name(self, model):
409
+ if model.startswith('grok-') and not any(keyword in model for keyword in ['deepsearch','deepersearch','reasoning']):
410
  return '-'.join(model.split('-')[:2])
411
  return model
412
 
 
419
 
420
  for model in self.model_config.keys():
421
  model_tokens = self.token_model_map.get(model, [])
422
+
423
+ model_request_frequency = sum(token_entry.get("MaxRequestCount", 0) for token_entry in model_tokens)
424
  total_used_requests = sum(token_entry.get("RequestCount", 0) for token_entry in model_tokens)
425
 
426
  remaining_capacity = (len(model_tokens) * model_request_frequency) - total_used_requests
 
436
  def reset_expired_tokens():
437
  now = int(time.time() * 1000)
438
 
439
+ model_config = self.model_normal_config
440
  tokens_to_remove = set()
441
  for token_info in self.expired_tokens:
442
+ token, model, expired_time ,type = token_info
443
+ if type == "super":
444
+ model_config = self.model_super_config
445
+ expiration_time = model_config[model]["ExpirationTime"]
446
 
447
  if now - expired_time >= expiration_time:
448
  if not any(entry["token"] == token for entry in self.token_model_map.get(model, [])):
 
451
 
452
  self.token_model_map[model].append({
453
  "token": token,
454
+ "MaxRequestCount": model_config[model]["RequestFrequency"],
455
  "RequestCount": 0,
456
  "AddedTime": now,
457
+ "StartCallTime": None,
458
+ "type": type
459
  })
460
 
461
  sso = token.split("sso=")[1].split(";")[0]
 
463
  self.token_status_map[sso][model]["isValid"] = True
464
  self.token_status_map[sso][model]["invalidatedTime"] = None
465
  self.token_status_map[sso][model]["totalRequestCount"] = 0
466
+ self.token_status_map[sso][model]["isSuper"] = type == "super"
467
 
468
  tokens_to_remove.add(token_info)
469
 
470
  self.expired_tokens -= tokens_to_remove
471
 
472
+ for model in model_config.keys():
473
  if model not in self.token_model_map:
474
  continue
475
 
 
477
  if not token_entry.get("StartCallTime"):
478
  continue
479
 
480
+ expiration_time = model_config[model]["ExpirationTime"]
481
  if now - token_entry["StartCallTime"] >= expiration_time:
482
  sso = token_entry["token"].split("sso=")[1].split(";")[0]
483
  if sso in self.token_status_map and model in self.token_status_map[sso]:
484
  self.token_status_map[sso][model]["isValid"] = True
485
  self.token_status_map[sso][model]["invalidatedTime"] = None
486
  self.token_status_map[sso][model]["totalRequestCount"] = 0
487
+ self.token_status_map[sso][model]["isSuper"] = token_entry["type"] == "super"
488
 
489
  token_entry["RequestCount"] = 0
490
  token_entry["StartCallTime"] = None
 
687
  # logger.error(str(error), "Server")
688
  # raise ValueError(error)
689
  def prepare_chat_request(self, request):
690
+ if ((request["model"] == 'grok-4-imageGen' or request["model"] == 'grok-3-imageGen') and
691
  not CONFIG["API"]["PICGO_KEY"] and not CONFIG["API"]["TUMY_KEY"] and
692
  request.get("stream", False)):
693
  raise ValueError("该模型流式输出需要配置PICGO或者TUMY图床密钥!")
694
 
695
  # system_message, todo_messages = self.convert_system_messages(request["messages"]).values()
696
  todo_messages = request["messages"]
697
+ if request["model"] in ['grok-4-imageGen', 'grok-3-imageGen', 'grok-3-deepsearch']:
698
  last_message = todo_messages[-1]
699
  if last_message["role"] != 'user':
700
  raise ValueError('此模型最后一条消息必须是用户消息!')
 
706
  message_length = 0
707
  convert_to_file = False
708
  last_message_content = ''
709
+ search = request["model"] in ['grok-4-deepsearch', 'grok-3-search']
710
  deepsearchPreset = ''
711
  if request["model"] == 'grok-3-deepsearch':
712
  deepsearchPreset = 'default'
 
798
  "imageGenerationCount": 1,
799
  "forceConcise": False,
800
  "toolOverrides": {
801
+ "imageGen": request["model"] in ['grok-4-imageGen', 'grok-3-imageGen'],
802
  "webSearch": search,
803
  "xSearch": search,
804
  "xMediaSearch": search,
 
855
  if response.get("cachedImageGenerationResponse") and not CONFIG["IS_IMG_GEN2"]:
856
  result["imageUrl"] = response["cachedImageGenerationResponse"]["imageUrl"]
857
  return result
858
+ if model == 'grok-3':
 
859
  result["token"] = response.get("token")
860
+ elif model in ['grok-3-search']:
861
  if response.get("webSearchResults") and CONFIG["ISSHOW_SEARCH_RESULTS"]:
862
  result["token"] = f"\r\n<think>{Utils.organize_search_results(response['webSearchResults'])}</think>\r\n"
863
  else:
864
  result["token"] = response.get("token")
865
+ elif model in ['grok-3-deepsearch', 'grok-3-deepersearch','grok-4-deepsearch']:
 
 
866
  if response.get("messageStepId") and not CONFIG["SHOW_THINKING"]:
867
  return result
868
  if response.get("messageStepId") and not CONFIG["IS_THINKING"]:
 
890
  else:
891
  result["token"] = response.get("token")
892
 
893
+ elif model == 'grok-4':
894
+ if response.get("isThinking"):
895
+ return result
896
+ result["token"] = response.get("token")
897
+ elif model == 'grok-4-reasoning':
898
+ if response.get("isThinking") and not CONFIG["SHOW_THINKING"]:
899
+ return result
900
+ if response.get("isThinking") and not CONFIG["IS_THINKING"] and response.get("messageTag") == "assistant":
901
+ result["token"] = "<think>" + response.get("token", "")
902
+ CONFIG["IS_THINKING"] = True
903
+ elif not response.get("isThinking") and CONFIG["IS_THINKING"] and response.get("messageTag") == "final":
904
+ result["token"] = "</think>" + response.get("token", "")
905
+ CONFIG["IS_THINKING"] = False
906
+ else:
907
+ result["token"] = response.get("token")
908
+ elif model in ['grok-4-deepsearch']:
909
+ if response.get("messageStepId") and not CONFIG["SHOW_THINKING"]:
910
+ return result
911
+ if response.get("messageStepId") and not CONFIG["IS_THINKING"] and response.get("messageTag") == "assistant":
912
+ result["token"] = "<think>" + response.get("token", "")
913
+ CONFIG["IS_THINKING"] = True
914
+ elif not response.get("messageStepId") and CONFIG["IS_THINKING"] and response.get("messageTag") == "final":
915
+ result["token"] = "</think>" + response.get("token", "")
916
+ CONFIG["IS_THINKING"] = False
917
+ elif (response.get("messageStepId") and CONFIG["IS_THINKING"] and response.get("messageTag") == "assistant") or response.get("messageTag") == "final":
918
+ result["token"] = response.get("token","")
919
+ elif (CONFIG["IS_THINKING"] and response.get("token","").get("action","") == "webSearch"):
920
+ result["token"] = response.get("token","").get("action_input","").get("query","")
921
+ elif (CONFIG["IS_THINKING"] and response.get("webSearchResults")):
922
+ result["token"] = Utils.organize_search_results(response['webSearchResults'])
923
+
924
  return result
925
 
926
  def handle_image_response(image_url):
 
1105
 
1106
  def initialization():
1107
  sso_array = os.environ.get("SSO", "").split(',')
1108
+ sso_array_super = os.environ.get("SSO_SUPER", "").split(',')
1109
+
1110
+ combined_dict = []
1111
+ for value in sso_array_super:
1112
+ combined_dict.append({
1113
+ "token": f"sso-rw={value};sso={value}",
1114
+ "type": "super"
1115
+ })
1116
+ for value in sso_array:
1117
+ combined_dict.append({
1118
+ "token": f"sso-rw={value};sso={value}",
1119
+ "type": "normal"
1120
+ })
1121
+
1122
+
1123
  logger.info("开始加载令牌", "Server")
1124
  token_manager.load_token_status()
1125
+ for tokens in combined_dict:
1126
+ if tokens:
1127
+ token_manager.add_token(tokens,True)
1128
  token_manager.save_token_status()
1129
 
1130
  logger.info(f"成功加载令牌: {json.dumps(token_manager.get_all_tokens(), indent=2)}", "Server")
1131
+ logger.info(f"令牌加载完成,共加载: {len(sso_array)+len(sso_array_super)}个令牌", "Server")
1132
+ logger.info(f"其中共加载: {len(sso_array_super)}个super会员令牌", "Server")
1133
 
1134
  if CONFIG["API"]["PROXY"]:
1135
  logger.info(f"代理已设置: {CONFIG['API']['PROXY']}", "Server")
1136
 
1137
+ logger.info("初始化完成", "Server")
1138
 
1139
 
1140
  app = Flask(__name__)
 
1178
  sso = request.json.get('sso')
1179
  if not sso:
1180
  return jsonify({"error": "SSO token is required"}), 400
1181
+ token_manager.add_token({"token":f"sso-rw={sso};sso={sso}","type":"normal"})
1182
  return jsonify({"success": True})
1183
  except Exception as e:
1184
  return jsonify({"error": str(e)}), 500
 
1229
 
1230
  try:
1231
  sso = request.json.get('sso')
1232
+ token_manager.add_token({"token":f"sso-rw={sso};sso={sso}","type":"normal"})
1233
  return jsonify(token_manager.get_token_status_map().get(sso, {})), 200
1234
  except Exception as error:
1235
  logger.error(str(error), "Server")
 
1301
  retry_count = 0
1302
  grok_client = GrokApiClient(model)
1303
  request_payload = grok_client.prepare_chat_request(data)
1304
+
1305
  logger.info(json.dumps(request_payload,indent=2))
1306
 
1307
  while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]: