ltxlong commited on
Commit
7aa9617
·
verified ·
1 Parent(s): 0fc4728

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -171
app.py CHANGED
@@ -80,10 +80,7 @@ class Logger:
80
  self.logger.bind(**caller_info).info(f"请求: {request.method} {request.path}", "Request")
81
 
82
  logger = Logger(level="INFO")
83
- DATA_DIR = Path("/data")
84
 
85
- if not DATA_DIR.exists():
86
- DATA_DIR.mkdir(parents=True, exist_ok=True)
87
  CONFIG = {
88
  "MODELS": {
89
  "grok-3": "grok-3",
@@ -121,13 +118,11 @@ CONFIG = {
121
  "RETRYSWITCH": False,
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
 
@@ -147,7 +142,7 @@ DEFAULT_HEADERS = {
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,49 +150,44 @@ 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,67 +205,47 @@ class AuthTokenManager:
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,15 +304,10 @@ class AuthTokenManager:
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,21 +317,18 @@ class AuthTokenManager:
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,8 +350,7 @@ class AuthTokenManager:
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,7 +367,7 @@ class AuthTokenManager:
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,8 +380,8 @@ class AuthTokenManager:
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,13 +397,10 @@ class AuthTokenManager:
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,11 +409,9 @@ class AuthTokenManager:
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,13 +419,12 @@ class AuthTokenManager:
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,14 +432,13 @@ class AuthTokenManager:
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,14 +641,14 @@ class GrokApiClient:
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,11 +660,11 @@ class GrokApiClient:
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'
713
- elif request["model"] == 'grok-3-deepersearch':
714
  deepsearchPreset = 'deeper'
715
 
716
  # 移除<think>标签及其内容和base64图片
@@ -798,7 +752,7 @@ class GrokApiClient:
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,
@@ -809,7 +763,7 @@ class GrokApiClient:
809
  "sendFinalMetadata": True,
810
  "customPersonality": "",
811
  "deepsearchPreset": deepsearchPreset,
812
- "isReasoning": request["model"] == 'grok-3-reasoning',
813
  "disableTextFollowUps": True
814
  }
815
 
@@ -855,14 +809,15 @@ def process_model_response(response, model):
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"]:
@@ -877,7 +832,7 @@ def process_model_response(response, model):
877
  result["token"] = response.get("token","").get("action_input","").get("query","")
878
  elif (CONFIG["IS_THINKING"] and response.get("webSearchResults")):
879
  result["token"] = Utils.organize_search_results(response['webSearchResults'])
880
- elif model == 'grok-3-reasoning':
881
  if response.get("isThinking") and not CONFIG["SHOW_THINKING"]:
882
  return result
883
 
@@ -890,37 +845,6 @@ def process_model_response(response, model):
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,36 +1029,20 @@ def handle_stream_response(response, model):
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,7 +1086,7 @@ def add_manager_token():
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,7 +1137,7 @@ def add_token():
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,7 +1209,6 @@ def chat_completions():
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"]:
 
80
  self.logger.bind(**caller_info).info(f"请求: {request.method} {request.path}", "Request")
81
 
82
  logger = Logger(level="INFO")
 
83
 
 
 
84
  CONFIG = {
85
  "MODELS": {
86
  "grok-3": "grok-3",
 
118
  "RETRYSWITCH": False,
119
  "MAX_ATTEMPTS": 2
120
  },
121
+ "SHOW_THINKING": os.environ.get("SHOW_THINKING") == "true",
 
122
  "IS_THINKING": False,
123
  "IS_IMG_GEN": False,
124
  "IS_IMG_GEN2": False,
125
+ "ISSHOW_SEARCH_RESULTS": os.environ.get("ISSHOW_SEARCH_RESULTS", "true").lower() == "true"
 
126
  }
127
 
128
 
 
142
  'Sec-Fetch-Mode': 'cors',
143
  'Sec-Fetch-Site': 'same-origin',
144
  'Baggage': 'sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c',
145
+ 'x-statsig-id': 'ZTpUeXBlRXJyb3I6IENhbm5vdCByZWFkIHByb3BlcnRpZXMgb2YgdW5kZWZpbmVkIChyZWFkaW5nICdjaGlsZE5vZGVzJyk='# 暂用固定x-statsig-id,失效再看
146
  }
147
 
148
  class AuthTokenManager:
 
150
  self.token_model_map = {}
151
  self.expired_tokens = set()
152
  self.token_status_map = {}
153
+
154
+ self.model_config = {
155
+ "grok-3": {
156
+ "RequestFrequency": 20,
157
+ "ExpirationTime": 2 * 60 * 60 * 1000 # 2小时
158
+ },
159
+ "grok-3-deepsearch": {
160
+ "RequestFrequency": 10,
161
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
162
+ },
163
+ "grok-3-deepersearch": {
164
+ "RequestFrequency": 3,
165
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
166
+ },
167
+ "grok-3-reasoning": {
168
+ "RequestFrequency": 10,
169
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
170
+ },
171
+ "grok-4": {
172
+ "RequestFrequency": 20,
173
+ "ExpirationTime": 2 * 60 * 60 * 1000 # 2小时
174
+ },
175
+ "grok-4-deepsearch": {
176
+ "RequestFrequency": 10,
177
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
178
+ },
179
+ "grok-4-deepersearch": {
180
+ "RequestFrequency": 3,
181
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
182
+ },
183
+ "grok-4-reasoning": {
184
+ "RequestFrequency": 10,
185
+ "ExpirationTime": 24 * 60 * 60 * 1000 # 24小时
 
 
 
 
 
 
186
  }
187
+ }
188
  self.token_reset_switch = False
189
  self.token_reset_timer = None
190
+ self.load_token_status() # 加载令牌状态
191
  def save_token_status(self):
192
  try:
193
  with open(CONFIG["TOKEN_STATUS_FILE"], 'w', encoding='utf-8') as f:
 
205
  logger.info("已从配置文件加载令牌状态", "TokenManager")
206
  except Exception as error:
207
  logger.error(f"加载令牌状态失败: {str(error)}", "TokenManager")
208
+ def add_token(self, token,isinitialization=False):
209
+ sso = token.split("sso=")[1].split(";")[0]
 
 
 
 
 
 
 
210
  for model in self.model_config.keys():
211
  if model not in self.token_model_map:
212
  self.token_model_map[model] = []
213
  if sso not in self.token_status_map:
214
  self.token_status_map[sso] = {}
215
 
216
+ existing_token_entry = next((entry for entry in self.token_model_map[model] if entry["token"] == token), None)
217
 
218
  if not existing_token_entry:
219
  self.token_model_map[model].append({
220
+ "token": token,
 
221
  "RequestCount": 0,
222
  "AddedTime": int(time.time() * 1000),
223
+ "StartCallTime": None
 
224
  })
225
 
226
  if model not in self.token_status_map[sso]:
227
  self.token_status_map[sso][model] = {
228
  "isValid": True,
229
  "invalidatedTime": None,
230
+ "totalRequestCount": 0
 
231
  }
232
  if not isinitialization:
233
  self.save_token_status()
234
 
235
+ def set_token(self, token):
 
 
 
 
 
 
 
236
  models = list(self.model_config.keys())
237
  self.token_model_map = {model: [{
238
+ "token": token,
 
239
  "RequestCount": 0,
240
  "AddedTime": int(time.time() * 1000),
241
+ "StartCallTime": None
 
242
  }] for model in models}
243
 
244
+ sso = token.split("sso=")[1].split(";")[0]
245
  self.token_status_map[sso] = {model: {
246
  "isValid": True,
247
  "invalidatedTime": None,
248
+ "totalRequestCount": 0
 
249
  } for model in models}
250
 
251
  def delete_token(self, token):
 
304
  return None
305
 
306
  token_entry = self.token_model_map[normalized_model][0]
 
307
  if is_return:
308
  return token_entry["token"]
309
 
310
  if token_entry:
 
 
 
 
311
  if token_entry["StartCallTime"] is None:
312
  token_entry["StartCallTime"] = int(time.time() * 1000)
313
 
 
317
 
318
  token_entry["RequestCount"] += 1
319
 
320
+ if token_entry["RequestCount"] > self.model_config[normalized_model]["RequestFrequency"]:
321
  self.remove_token_from_model(normalized_model, token_entry["token"])
322
  next_token_entry = self.token_model_map[normalized_model][0] if self.token_model_map[normalized_model] else None
323
  return next_token_entry["token"] if next_token_entry else None
324
 
325
  sso = token_entry["token"].split("sso=")[1].split(";")[0]
 
326
  if sso in self.token_status_map and normalized_model in self.token_status_map[sso]:
327
  if token_entry["RequestCount"] == self.model_config[normalized_model]["RequestFrequency"]:
328
  self.token_status_map[sso][normalized_model]["isValid"] = False
329
  self.token_status_map[sso][normalized_model]["invalidatedTime"] = int(time.time() * 1000)
330
  self.token_status_map[sso][normalized_model]["totalRequestCount"] += 1
331
 
 
 
332
  self.save_token_status()
333
 
334
  return token_entry["token"]
 
350
  self.expired_tokens.add((
351
  removed_token_entry["token"],
352
  normalized_model,
353
+ int(time.time() * 1000)
 
354
  ))
355
 
356
  if not self.token_reset_switch:
 
367
  return list(self.expired_tokens)
368
 
369
  def normalize_model_name(self, model):
370
+ if model.startswith('grok-') and 'deepsearch' not in model and 'reasoning' not in model:
371
  return '-'.join(model.split('-')[:2])
372
  return model
373
 
 
380
 
381
  for model in self.model_config.keys():
382
  model_tokens = self.token_model_map.get(model, [])
383
+ model_request_frequency = self.model_config[model]["RequestFrequency"]
384
+
385
  total_used_requests = sum(token_entry.get("RequestCount", 0) for token_entry in model_tokens)
386
 
387
  remaining_capacity = (len(model_tokens) * model_request_frequency) - total_used_requests
 
397
  def reset_expired_tokens():
398
  now = int(time.time() * 1000)
399
 
 
400
  tokens_to_remove = set()
401
  for token_info in self.expired_tokens:
402
+ token, model, expired_time = token_info
403
+ expiration_time = self.model_config[model]["ExpirationTime"]
 
 
404
 
405
  if now - expired_time >= expiration_time:
406
  if not any(entry["token"] == token for entry in self.token_model_map.get(model, [])):
 
409
 
410
  self.token_model_map[model].append({
411
  "token": token,
 
412
  "RequestCount": 0,
413
  "AddedTime": now,
414
+ "StartCallTime": None
 
415
  })
416
 
417
  sso = token.split("sso=")[1].split(";")[0]
 
419
  self.token_status_map[sso][model]["isValid"] = True
420
  self.token_status_map[sso][model]["invalidatedTime"] = None
421
  self.token_status_map[sso][model]["totalRequestCount"] = 0
 
422
 
423
  tokens_to_remove.add(token_info)
424
 
425
  self.expired_tokens -= tokens_to_remove
426
 
427
+ for model in self.model_config.keys():
428
  if model not in self.token_model_map:
429
  continue
430
 
 
432
  if not token_entry.get("StartCallTime"):
433
  continue
434
 
435
+ expiration_time = self.model_config[model]["ExpirationTime"]
436
  if now - token_entry["StartCallTime"] >= expiration_time:
437
  sso = token_entry["token"].split("sso=")[1].split(";")[0]
438
  if sso in self.token_status_map and model in self.token_status_map[sso]:
439
  self.token_status_map[sso][model]["isValid"] = True
440
  self.token_status_map[sso][model]["invalidatedTime"] = None
441
  self.token_status_map[sso][model]["totalRequestCount"] = 0
 
442
 
443
  token_entry["RequestCount"] = 0
444
  token_entry["StartCallTime"] = None
 
641
  # logger.error(str(error), "Server")
642
  # raise ValueError(error)
643
  def prepare_chat_request(self, request):
644
+ if ((request["model"] == 'grok-3-imageGen' or request["model"] == 'grok-4-imageGen') and
645
  not CONFIG["API"]["PICGO_KEY"] and not CONFIG["API"]["TUMY_KEY"] and
646
  request.get("stream", False)):
647
  raise ValueError("该模型流式输出需要配置PICGO或者TUMY图床密钥!")
648
 
649
  # system_message, todo_messages = self.convert_system_messages(request["messages"]).values()
650
  todo_messages = request["messages"]
651
+ if request["model"] in ['grok-3-imageGen', 'grok-3-deepsearch', 'grok-4-imageGen', 'grok-4-deepsearch']:
652
  last_message = todo_messages[-1]
653
  if last_message["role"] != 'user':
654
  raise ValueError('此模型最后一条消息必须是用户消息!')
 
660
  message_length = 0
661
  convert_to_file = False
662
  last_message_content = ''
663
+ search = request["model"] in ['grok-3-search', 'grok-4-search']
664
  deepsearchPreset = ''
665
+ if request["model"] in ['grok-3-deepsearch', 'grok-4-deepsearch']:
666
  deepsearchPreset = 'default'
667
+ elif request["model"] in ['grok-3-deepersearch', 'grok-4-deepersearch']:
668
  deepsearchPreset = 'deeper'
669
 
670
  # 移除<think>标签及其内容和base64图片
 
752
  "imageGenerationCount": 1,
753
  "forceConcise": False,
754
  "toolOverrides": {
755
+ "imageGen": request["model"] in ['grok-3-imageGen', 'grok-4-imageGen'],
756
  "webSearch": search,
757
  "xSearch": search,
758
  "xMediaSearch": search,
 
763
  "sendFinalMetadata": True,
764
  "customPersonality": "",
765
  "deepsearchPreset": deepsearchPreset,
766
+ "isReasoning": request["model"] in ['grok-3-reasoning', 'grok-4-reasoning'],
767
  "disableTextFollowUps": True
768
  }
769
 
 
809
  if response.get("cachedImageGenerationResponse") and not CONFIG["IS_IMG_GEN2"]:
810
  result["imageUrl"] = response["cachedImageGenerationResponse"]["imageUrl"]
811
  return result
812
+
813
+ if model in ['grok-3', 'grok-4']:
814
  result["token"] = response.get("token")
815
+ elif model in ['grok-3-search', 'grok-4-search']:
816
  if response.get("webSearchResults") and CONFIG["ISSHOW_SEARCH_RESULTS"]:
817
  result["token"] = f"\r\n<think>{Utils.organize_search_results(response['webSearchResults'])}</think>\r\n"
818
  else:
819
  result["token"] = response.get("token")
820
+ elif model in ['grok-3-deepsearch', 'grok-3-deepersearch', 'grok-4-deepsearch', 'grok-4-deepersearch']:
821
  if response.get("messageStepId") and not CONFIG["SHOW_THINKING"]:
822
  return result
823
  if response.get("messageStepId") and not CONFIG["IS_THINKING"]:
 
832
  result["token"] = response.get("token","").get("action_input","").get("query","")
833
  elif (CONFIG["IS_THINKING"] and response.get("webSearchResults")):
834
  result["token"] = Utils.organize_search_results(response['webSearchResults'])
835
+ elif model in ['grok-3-reasoning', 'grok-4-reasoning']:
836
  if response.get("isThinking") and not CONFIG["SHOW_THINKING"]:
837
  return result
838
 
 
845
  else:
846
  result["token"] = response.get("token")
847
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
848
  return result
849
 
850
  def handle_image_response(image_url):
 
1029
 
1030
  def initialization():
1031
  sso_array = os.environ.get("SSO", "").split(',')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1032
  logger.info("开始加载令牌", "Server")
1033
  token_manager.load_token_status()
1034
+ for sso in sso_array:
1035
+ if sso:
1036
+ token_manager.add_token(f"sso-rw={sso};sso={sso}",True)
1037
  token_manager.save_token_status()
1038
 
1039
  logger.info(f"成功加载令牌: {json.dumps(token_manager.get_all_tokens(), indent=2)}", "Server")
1040
+ logger.info(f"令牌加载完成,共加载: {len(token_manager.get_all_tokens())}个令牌", "Server")
 
1041
 
1042
  if CONFIG["API"]["PROXY"]:
1043
  logger.info(f"代理已设置: {CONFIG['API']['PROXY']}", "Server")
1044
 
1045
+ logger.info("初始化完成", "Server")
1046
 
1047
 
1048
  app = Flask(__name__)
 
1086
  sso = request.json.get('sso')
1087
  if not sso:
1088
  return jsonify({"error": "SSO token is required"}), 400
1089
+ token_manager.add_token(f"sso-rw={sso};sso={sso}")
1090
  return jsonify({"success": True})
1091
  except Exception as e:
1092
  return jsonify({"error": str(e)}), 500
 
1137
 
1138
  try:
1139
  sso = request.json.get('sso')
1140
+ token_manager.add_token(f"sso-rw={sso};sso={sso}")
1141
  return jsonify(token_manager.get_token_status_map().get(sso, {})), 200
1142
  except Exception as error:
1143
  logger.error(str(error), "Server")
 
1209
  retry_count = 0
1210
  grok_client = GrokApiClient(model)
1211
  request_payload = grok_client.prepare_chat_request(data)
 
1212
  logger.info(json.dumps(request_payload,indent=2))
1213
 
1214
  while retry_count < CONFIG["RETRY"]["MAX_ATTEMPTS"]: