yangtb24 commited on
Commit
f101853
·
verified ·
1 Parent(s): 5c9132f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +403 -301
app.py CHANGED
@@ -944,13 +944,13 @@ def handsome_chat_completions():
944
  return jsonify({"error": "Invalid request data"}), 400
945
 
946
  model_name = data['model']
947
-
948
  request_type = determine_request_type(
949
  model_name,
950
  text_models + image_models,
951
  free_text_models + free_image_models
952
  )
953
-
954
  api_key = select_key(request_type, model_name)
955
 
956
  if not api_key:
@@ -968,303 +968,322 @@ def handsome_chat_completions():
968
  "Authorization": f"Bearer {api_key}",
969
  "Content-Type": "application/json"
970
  }
971
-
972
- if model_name in image_models:
973
- user_content = ""
974
- messages = data.get("messages", [])
975
- for message in messages:
976
- if message["role"] == "user":
977
- if isinstance(message["content"], str):
978
- user_content += message["content"] + " "
979
- elif isinstance(message["content"], list):
980
- for item in message["content"]:
981
- if (
982
- isinstance(item, dict) and
983
- item.get("type") == "text"
984
- ):
985
- user_content += (
986
- item.get("text", "") +
987
- " "
988
- )
989
- user_content = user_content.strip()
990
 
991
- siliconflow_data = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
992
  "model": model_name,
993
  "prompt": user_content,
994
-
995
  }
996
- if model_name == "black-forest-labs/FLUX.1-pro":
997
- siliconflow_data["width"] = data.get("width", 1024)
998
- siliconflow_data["height"] = data.get("height", 768)
999
- siliconflow_data["prompt_upsampling"] = data.get("prompt_upsampling", False)
1000
- siliconflow_data["image_prompt"] = data.get("image_prompt")
1001
- siliconflow_data["steps"] = data.get("steps", 20)
1002
- siliconflow_data["guidance"] = data.get("guidance", 3)
1003
- siliconflow_data["safety_tolerance"] = data.get("safety_tolerance", 2)
1004
- siliconflow_data["interval"] = data.get("interval", 2)
1005
- siliconflow_data["output_format"] = data.get("output_format", "png")
1006
- seed = data.get("seed")
1007
- if isinstance(seed, int) and 0 < seed < 9999999999:
1008
- siliconflow_data["seed"] = seed
1009
- if siliconflow_data["width"] < 256 or siliconflow_data["width"] > 1440 or siliconflow_data["width"] % 32 != 0:
1010
- siliconflow_data["width"] = 1024
1011
- if siliconflow_data["height"] < 256 or siliconflow_data["height"] > 1440 or siliconflow_data["height"] % 32 != 0:
1012
- siliconflow_data["height"] = 768
1013
-
1014
- if siliconflow_data["steps"] < 1 or siliconflow_data["steps"] > 50:
1015
- siliconflow_data["steps"] = 20
1016
- if siliconflow_data["guidance"] < 1.5 or siliconflow_data["guidance"] > 5:
1017
- siliconflow_data["guidance"] = 3
1018
- if siliconflow_data["safety_tolerance"] < 0 or siliconflow_data["safety_tolerance"] > 6:
1019
- siliconflow_data["safety_tolerance"] = 2
1020
- if siliconflow_data["interval"] < 1 or siliconflow_data["interval"] > 4 :
1021
- siliconflow_data["interval"] = 2
1022
- else:
1023
- siliconflow_data["image_size"] = "1024x1024"
1024
- siliconflow_data["batch_size"] = 1
1025
- siliconflow_data["num_inference_steps"] = 20
1026
- siliconflow_data["guidance_scale"] = 7.5
1027
- siliconflow_data["prompt_enhancement"] = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1028
 
1029
- if data.get("size"):
1030
- siliconflow_data["image_size"] = data.get("size")
1031
- if data.get("n"):
1032
- siliconflow_data["batch_size"] = data.get("n")
1033
- if data.get("steps"):
1034
- siliconflow_data["num_inference_steps"] = data.get("steps")
1035
- if data.get("guidance_scale"):
1036
- siliconflow_data["guidance_scale"] = data.get("guidance_scale")
1037
- if data.get("negative_prompt"):
1038
- siliconflow_data["negative_prompt"] = data.get("negative_prompt")
1039
- if data.get("seed"):
1040
- siliconflow_data["seed"] = data.get("seed")
1041
- if data.get("prompt_enhancement"):
1042
- siliconflow_data["prompt_enhancement"] = data.get("prompt_enhancement")
1043
-
1044
- if siliconflow_data["batch_size"] < 1:
1045
- siliconflow_data["batch_size"] = 1
1046
- if siliconflow_data["batch_size"] > 4:
1047
- siliconflow_data["batch_size"] = 4
1048
-
1049
- if siliconflow_data["num_inference_steps"] < 1:
1050
- siliconflow_data["num_inference_steps"] = 1
1051
- if siliconflow_data["num_inference_steps"] > 50:
1052
- siliconflow_data["num_inference_steps"] = 50
1053
-
1054
- if siliconflow_data["guidance_scale"] < 0:
1055
- siliconflow_data["guidance_scale"] = 0
1056
- if siliconflow_data["guidance_scale"] > 100:
1057
- siliconflow_data["guidance_scale"] = 100
1058
-
1059
- if siliconflow_data["image_size"] not in ["1024x1024", "512x1024", "768x512", "768x1024", "1024x576", "576x1024", "960x1280", "720x1440", "720x1280"]:
1060
- siliconflow_data["image_size"] = "1024x1024"
1061
-
1062
- try:
1063
- start_time = time.time()
1064
- response = requests.post(
1065
- "https://api.siliconflow.cn/v1/images/generations",
1066
- headers=headers,
1067
- json=siliconflow_data,
1068
- timeout=120,
1069
- stream=data.get("stream", False)
1070
- )
1071
-
1072
- if response.status_code == 429:
1073
- return jsonify(response.json()), 429
1074
-
1075
- if data.get("stream", False):
1076
- def generate():
1077
- first_chunk_time = None
1078
- full_response_content = ""
1079
- try:
1080
- response.raise_for_status()
1081
- end_time = time.time()
1082
- response_json = response.json()
1083
- total_time = end_time - start_time
1084
-
1085
- images = response_json.get("images", [])
1086
-
1087
- image_url = ""
1088
- if images and isinstance(images[0], dict) and "url" in images[0]:
1089
- image_url = images[0]["url"]
1090
- logging.info(f"Extracted image URL: {image_url}")
1091
- elif images and isinstance(images[0], str):
1092
- image_url = images[0]
1093
- logging.info(f"Extracted image URL: {image_url}")
1094
-
1095
- markdown_image_link = f"![image]({image_url})"
1096
- if image_url:
1097
- chunk_data = {
1098
- "id": f"chatcmpl-{uuid.uuid4()}",
1099
- "object": "chat.completion.chunk",
1100
- "created": int(time.time()),
1101
- "model": model_name,
1102
- "choices": [
1103
- {
1104
- "index": 0,
1105
- "delta": {
1106
- "role": "assistant",
1107
- "content": markdown_image_link
1108
- },
1109
- "finish_reason": None
1110
- }
1111
- ]
1112
- }
1113
- yield f"data: {json.dumps(chunk_data)}\n\n".encode('utf-8')
1114
- full_response_content = markdown_image_link
1115
- else:
1116
- chunk_data = {
1117
- "id": f"chatcmpl-{uuid.uuid4()}",
1118
- "object": "chat.completion.chunk",
1119
- "created": int(time.time()),
1120
- "model": model_name,
1121
- "choices": [
1122
- {
1123
- "index": 0,
1124
- "delta": {
1125
- "role": "assistant",
1126
- "content": "Failed to generate image"
1127
- },
1128
- "finish_reason": None
1129
- }
1130
- ]
1131
- }
1132
- yield f"data: {json.dumps(chunk_data)}\n\n".encode('utf-8')
1133
- full_response_content = "Failed to generate image"
1134
-
1135
- end_chunk_data = {
1136
- "id": f"chatcmpl-{uuid.uuid4()}",
1137
- "object": "chat.completion.chunk",
1138
- "created": int(time.time()),
1139
- "model": model_name,
1140
- "choices": [
1141
- {
1142
- "index": 0,
1143
- "delta": {},
1144
- "finish_reason": "stop"
1145
- }
1146
- ]
1147
- }
1148
- yield f"data: {json.dumps(end_chunk_data)}\n\n".encode('utf-8')
1149
- with data_lock:
1150
- request_timestamps.append(time.time())
1151
- token_counts.append(0)
1152
- except requests.exceptions.RequestException as e:
1153
- logging.error(f"请求转发异常: {e}")
1154
- error_chunk_data = {
1155
- "id": f"chatcmpl-{uuid.uuid4()}",
1156
- "object": "chat.completion.chunk",
1157
- "created": int(time.time()),
1158
- "model": model_name,
1159
- "choices": [
1160
- {
1161
- "index": 0,
1162
- "delta": {
1163
- "role": "assistant",
1164
- "content": f"Error: {str(e)}"
1165
- },
1166
- "finish_reason": None
1167
- }
1168
- ]
1169
- }
1170
- yield f"data: {json.dumps(error_chunk_data)}\n\n".encode('utf-8')
1171
- end_chunk_data = {
1172
- "id": f"chatcmpl-{uuid.uuid4()}",
1173
- "object": "chat.completion.chunk",
1174
- "created": int(time.time()),
1175
- "model": model_name,
1176
- "choices": [
1177
- {
1178
- "index": 0,
1179
- "delta": {},
1180
- "finish_reason": "stop"
1181
- }
1182
- ]
1183
- }
1184
- yield f"data: {json.dumps(end_chunk_data)}\n\n".encode('utf-8')
1185
- logging.info(
1186
- f"使用的key: {api_key}, "
1187
- f"使用的模型: {model_name}"
1188
- )
1189
- yield "data: [DONE]\n\n".encode('utf-8')
1190
- return Response(stream_with_context(generate()), content_type='text/event-stream')
1191
-
1192
- else:
1193
- response.raise_for_status()
1194
- end_time = time.time()
1195
- response_json = response.json()
1196
- total_time = end_time - start_time
1197
-
1198
- try:
1199
- images = response_json.get("images", [])
1200
-
1201
- image_url = ""
1202
- if images and isinstance(images[0], dict) and "url" in images[0]:
1203
- image_url = images[0]["url"]
1204
- logging.info(f"Extracted image URL: {image_url}")
1205
- elif images and isinstance(images[0], str):
1206
- image_url = images[0]
1207
- logging.info(f"Extracted image URL: {image_url}")
1208
-
1209
- markdown_image_link = f"![image]({image_url})"
1210
- response_data = {
1211
- "id": f"chatcmpl-{uuid.uuid4()}",
1212
- "object": "chat.completion",
1213
- "created": int(time.time()),
1214
- "model": model_name,
1215
- "choices": [
1216
- {
1217
- "index": 0,
1218
- "message": {
1219
- "role": "assistant",
1220
- "content": markdown_image_link if image_url else "Failed to generate image",
1221
- },
1222
- "finish_reason": "stop",
1223
- }
1224
- ],
1225
- }
1226
- except (KeyError, ValueError, IndexError) as e:
1227
- logging.error(
1228
- f"解析响应 JSON 失败: {e}, "
1229
- f"完整内容: {response_json}"
1230
- )
1231
- response_data = {
1232
- "id": f"chatcmpl-{uuid.uuid4()}",
1233
- "object": "chat.completion",
1234
- "created": int(time.time()),
1235
- "model": model_name,
1236
- "choices": [
1237
- {
1238
- "index": 0,
1239
- "message": {
1240
- "role": "assistant",
1241
- "content": "Failed to process image data",
1242
- },
1243
- "finish_reason": "stop",
1244
- }
1245
- ],
1246
- }
1247
 
1248
- logging.info(
1249
- f"使用的key: {api_key}, "
1250
- f"总共用时: {total_time:.4f}秒, "
1251
- f"使用的模型: {model_name}"
1252
- )
1253
- with data_lock:
1254
- request_timestamps.append(time.time())
1255
- token_counts.append(0)
1256
- return jsonify(response_data)
1257
 
1258
- except requests.exceptions.RequestException as e:
1259
- logging.error(f"请求转发异常: {e}")
1260
- return jsonify({"error": str(e)}), 500
1261
- else:
1262
  try:
1263
  start_time = time.time()
1264
  response = requests.post(
1265
  TEST_MODEL_ENDPOINT,
1266
  headers=headers,
1267
- json=data,
1268
  stream=data.get("stream", False),
1269
  timeout=60
1270
  )
@@ -1293,6 +1312,7 @@ def handsome_chat_completions():
1293
  prompt_tokens = 0
1294
  completion_tokens = 0
1295
  response_content = ""
 
1296
  for line in full_response_content.splitlines():
1297
  if line.startswith("data:"):
1298
  line = line[5:].strip()
@@ -1311,15 +1331,22 @@ def handsome_chat_completions():
1311
 
1312
  if (
1313
  "choices" in response_json and
1314
- len(response_json["choices"]) > 0 and
1315
- "delta" in response_json["choices"][0] and
1316
- "content" in response_json[
1317
- "choices"
1318
- ][0]["delta"]
1319
  ):
1320
- response_content += response_json[
1321
- "choices"
1322
- ][0]["delta"]["content"]
 
 
 
 
 
 
 
 
 
 
 
1323
 
1324
  if (
1325
  "usage" in response_json and
@@ -1357,7 +1384,6 @@ def handsome_chat_completions():
1357
  )
1358
 
1359
  user_content = user_content.strip()
1360
-
1361
  user_content_replaced = user_content.replace(
1362
  '\n', '\\n'
1363
  ).replace('\r', '\\n')
@@ -1365,7 +1391,7 @@ def handsome_chat_completions():
1365
  '\n', '\\n'
1366
  ).replace('\r', '\\n')
1367
 
1368
- logging.info(
1369
  f"使用的key: {api_key}, "
1370
  f"提示token: {prompt_tokens}, "
1371
  f"输出token: {completion_tokens}, "
@@ -1375,11 +1401,56 @@ def handsome_chat_completions():
1375
  f"用户的内容: {user_content_replaced}, "
1376
  f"输出的内容: {response_content_replaced}"
1377
  )
 
 
 
 
1378
 
1379
  with data_lock:
1380
  request_timestamps.append(time.time())
1381
  token_counts.append(prompt_tokens+completion_tokens)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1382
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1383
  return Response(
1384
  stream_with_context(generate()),
1385
  content_type=response.headers['Content-Type']
@@ -1398,6 +1469,11 @@ def handsome_chat_completions():
1398
  response_content = response_json[
1399
  "choices"
1400
  ][0]["message"]["content"]
 
 
 
 
 
1401
  except (KeyError, ValueError, IndexError) as e:
1402
  logging.error(
1403
  f"解析非流式响应 JSON 失败: {e}, "
@@ -1406,6 +1482,7 @@ def handsome_chat_completions():
1406
  prompt_tokens = 0
1407
  completion_tokens = 0
1408
  response_content = ""
 
1409
 
1410
  user_content = ""
1411
  messages = data.get("messages", [])
@@ -1431,8 +1508,8 @@ def handsome_chat_completions():
1431
  response_content_replaced = response_content.replace(
1432
  '\n', '\\n'
1433
  ).replace('\r', '\\n')
1434
-
1435
- logging.info(
1436
  f"使用的key: {api_key}, "
1437
  f"提示token: {prompt_tokens}, "
1438
  f"输出token: {completion_tokens}, "
@@ -1442,15 +1519,40 @@ def handsome_chat_completions():
1442
  f"用户的内容: {user_content_replaced}, "
1443
  f"输出的内容: {response_content_replaced}"
1444
  )
 
 
 
 
 
1445
  with data_lock:
1446
  request_timestamps.append(time.time())
1447
  if "prompt_tokens" in response_json["usage"] and "completion_tokens" in response_json["usage"]:
1448
  token_counts.append(response_json["usage"]["prompt_tokens"] + response_json["usage"]["completion_tokens"])
1449
  else:
1450
  token_counts.append(0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1451
 
1452
- return jsonify(response_json)
1453
-
1454
  except requests.exceptions.RequestException as e:
1455
  logging.error(f"请求转发异常: {e}")
1456
  return jsonify({"error": str(e)}), 500
 
944
  return jsonify({"error": "Invalid request data"}), 400
945
 
946
  model_name = data['model']
947
+
948
  request_type = determine_request_type(
949
  model_name,
950
  text_models + image_models,
951
  free_text_models + free_image_models
952
  )
953
+
954
  api_key = select_key(request_type, model_name)
955
 
956
  if not api_key:
 
968
  "Authorization": f"Bearer {api_key}",
969
  "Content-Type": "application/json"
970
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
971
 
972
+ if model_name in image_models:
973
+ user_content = ""
974
+ messages = data.get("messages", [])
975
+ for message in messages:
976
+ if message["role"] == "user":
977
+ if isinstance(message["content"], str):
978
+ user_content += message["content"] + " "
979
+ elif isinstance(message["content"], list):
980
+ for item in message["content"]:
981
+ if (
982
+ isinstance(item, dict) and
983
+ item.get("type") == "text"
984
+ ):
985
+ user_content += (
986
+ item.get("text", "") +
987
+ " "
988
+ )
989
+ user_content = user_content.strip()
990
+
991
+ siliconflow_data = {
992
  "model": model_name,
993
  "prompt": user_content,
994
+
995
  }
996
+ if model_name == "black-forest-labs/FLUX.1-pro":
997
+ siliconflow_data["width"] = data.get("width", 1024)
998
+ siliconflow_data["height"] = data.get("height", 768)
999
+ siliconflow_data["prompt_upsampling"] = data.get("prompt_upsampling", False)
1000
+ siliconflow_data["image_prompt"] = data.get("image_prompt")
1001
+ siliconflow_data["steps"] = data.get("steps", 20)
1002
+ siliconflow_data["guidance"] = data.get("guidance", 3)
1003
+ siliconflow_data["safety_tolerance"] = data.get("safety_tolerance", 2)
1004
+ siliconflow_data["interval"] = data.get("interval", 2)
1005
+ siliconflow_data["output_format"] = data.get("output_format", "png")
1006
+ seed = data.get("seed")
1007
+ if isinstance(seed, int) and 0 < seed < 9999999999:
1008
+ siliconflow_data["seed"] = seed
1009
+ if siliconflow_data["width"] < 256 or siliconflow_data["width"] > 1440 or siliconflow_data["width"] % 32 != 0:
1010
+ siliconflow_data["width"] = 1024
1011
+ if siliconflow_data["height"] < 256 or siliconflow_data["height"] > 1440 or siliconflow_data["height"] % 32 != 0:
1012
+ siliconflow_data["height"] = 768
1013
+
1014
+ if siliconflow_data["steps"] < 1 or siliconflow_data["steps"] > 50:
1015
+ siliconflow_data["steps"] = 20
1016
+ if siliconflow_data["guidance"] < 1.5 or siliconflow_data["guidance"] > 5:
1017
+ siliconflow_data["guidance"] = 3
1018
+ if siliconflow_data["safety_tolerance"] < 0 or siliconflow_data["safety_tolerance"] > 6:
1019
+ siliconflow_data["safety_tolerance"] = 2
1020
+ if siliconflow_data["interval"] < 1 or siliconflow_data["interval"] > 4 :
1021
+ siliconflow_data["interval"] = 2
1022
+ else:
1023
+ siliconflow_data["image_size"] = "1024x1024"
1024
+ siliconflow_data["batch_size"] = 1
1025
+ siliconflow_data["num_inference_steps"] = 20
1026
+ siliconflow_data["guidance_scale"] = 7.5
1027
+ siliconflow_data["prompt_enhancement"] = False
1028
+
1029
+ if data.get("size"):
1030
+ siliconflow_data["image_size"] = data.get("size")
1031
+ if data.get("n"):
1032
+ siliconflow_data["batch_size"] = data.get("n")
1033
+ if data.get("steps"):
1034
+ siliconflow_data["num_inference_steps"] = data.get("steps")
1035
+ if data.get("guidance_scale"):
1036
+ siliconflow_data["guidance_scale"] = data.get("guidance_scale")
1037
+ if data.get("negative_prompt"):
1038
+ siliconflow_data["negative_prompt"] = data.get("negative_prompt")
1039
+ if data.get("seed"):
1040
+ siliconflow_data["seed"] = data.get("seed")
1041
+ if data.get("prompt_enhancement"):
1042
+ siliconflow_data["prompt_enhancement"] = data.get("prompt_enhancement")
1043
+
1044
+ if siliconflow_data["batch_size"] < 1:
1045
+ siliconflow_data["batch_size"] = 1
1046
+ if siliconflow_data["batch_size"] > 4:
1047
+ siliconflow_data["batch_size"] = 4
1048
+
1049
+ if siliconflow_data["num_inference_steps"] < 1:
1050
+ siliconflow_data["num_inference_steps"] = 1
1051
+ if siliconflow_data["num_inference_steps"] > 50:
1052
+ siliconflow_data["num_inference_steps"] = 50
1053
+
1054
+ if siliconflow_data["guidance_scale"] < 0:
1055
+ siliconflow_data["guidance_scale"] = 0
1056
+ if siliconflow_data["guidance_scale"] > 100:
1057
+ siliconflow_data["guidance_scale"] = 100
1058
+
1059
+ if siliconflow_data["image_size"] not in ["1024x1024", "512x1024", "768x512", "768x1024", "1024x576", "576x1024", "960x1280", "720x1440", "720x1280"]:
1060
+ siliconflow_data["image_size"] = "1024x1024"
1061
+ try:
1062
+ start_time = time.time()
1063
+ response = requests.post(
1064
+ "https://api-st.siliconflow.cn/v1/images/generations",
1065
+ headers=headers,
1066
+ json=siliconflow_data,
1067
+ timeout=120,
1068
+ stream=data.get("stream", False)
1069
+ )
1070
 
1071
+ if response.status_code == 429:
1072
+ return jsonify(response.json()), 429
1073
+
1074
+ if data.get("stream", False):
1075
+ def generate():
1076
+ first_chunk_time = None
1077
+ full_response_content = ""
1078
+ try:
1079
+ response.raise_for_status()
1080
+ end_time = time.time()
1081
+ response_json = response.json()
1082
+ total_time = end_time - start_time
1083
+
1084
+ images = response_json.get("images", [])
1085
+
1086
+ image_url = ""
1087
+ if images and isinstance(images[0], dict) and "url" in images[0]:
1088
+ image_url = images[0]["url"]
1089
+ logging.info(f"Extracted image URL: {image_url}")
1090
+ elif images and isinstance(images[0], str):
1091
+ image_url = images[0]
1092
+ logging.info(f"Extracted image URL: {image_url}")
1093
+
1094
+ markdown_image_link = f"![image]({image_url})"
1095
+ if image_url:
1096
+ chunk_data = {
1097
+ "id": f"chatcmpl-{uuid.uuid4()}",
1098
+ "object": "chat.completion.chunk",
1099
+ "created": int(time.time()),
1100
+ "model": model_name,
1101
+ "choices": [
1102
+ {
1103
+ "index": 0,
1104
+ "delta": {
1105
+ "role": "assistant",
1106
+ "content": markdown_image_link
1107
+ },
1108
+ "finish_reason": None
1109
+ }
1110
+ ]
1111
+ }
1112
+ yield f"data: {json.dumps(chunk_data)}\n\n".encode('utf-8')
1113
+ full_response_content = markdown_image_link
1114
+ else:
1115
+ chunk_data = {
1116
+ "id": f"chatcmpl-{uuid.uuid4()}",
1117
+ "object": "chat.completion.chunk",
1118
+ "created": int(time.time()),
1119
+ "model": model_name,
1120
+ "choices": [
1121
+ {
1122
+ "index": 0,
1123
+ "delta": {
1124
+ "role": "assistant",
1125
+ "content": "Failed to generate image"
1126
+ },
1127
+ "finish_reason": None
1128
+ }
1129
+ ]
1130
+ }
1131
+ yield f"data: {json.dumps(chunk_data)}\n\n".encode('utf-8')
1132
+ full_response_content = "Failed to generate image"
1133
+
1134
+ end_chunk_data = {
1135
+ "id": f"chatcmpl-{uuid.uuid4()}",
1136
+ "object": "chat.completion.chunk",
1137
+ "created": int(time.time()),
1138
+ "model": model_name,
1139
+ "choices": [
1140
+ {
1141
+ "index": 0,
1142
+ "delta": {},
1143
+ "finish_reason": "stop"
1144
+ }
1145
+ ]
1146
+ }
1147
+ yield f"data: {json.dumps(end_chunk_data)}\n\n".encode('utf-8')
1148
+ with data_lock:
1149
+ request_timestamps.append(time.time())
1150
+ token_counts.append(0)
1151
+ except requests.exceptions.RequestException as e:
1152
+ logging.error(f"请求转发异常: {e}")
1153
+ error_chunk_data = {
1154
+ "id": f"chatcmpl-{uuid.uuid4()}",
1155
+ "object": "chat.completion.chunk",
1156
+ "created": int(time.time()),
1157
+ "model": model_name,
1158
+ "choices": [
1159
+ {
1160
+ "index": 0,
1161
+ "delta": {
1162
+ "role": "assistant",
1163
+ "content": f"Error: {str(e)}"
1164
+ },
1165
+ "finish_reason": None
1166
+ }
1167
+ ]
1168
+ }
1169
+ yield f"data: {json.dumps(error_chunk_data)}\n\n".encode('utf-8')
1170
+ end_chunk_data = {
1171
+ "id": f"chatcmpl-{uuid.uuid4()}",
1172
+ "object": "chat.completion.chunk",
1173
+ "created": int(time.time()),
1174
+ "model": model_name,
1175
+ "choices": [
1176
+ {
1177
+ "index": 0,
1178
+ "delta": {},
1179
+ "finish_reason": "stop"
1180
+ }
1181
+ ]
1182
+ }
1183
+ yield f"data: {json.dumps(end_chunk_data)}\n\n".encode('utf-8')
1184
+ logging.info(
1185
+ f"使用的key: {api_key}, "
1186
+ f"使用的模型: {model_name}"
1187
+ )
1188
+ yield "data: [DONE]\n\n".encode('utf-8')
1189
+ return Response(stream_with_context(generate()), content_type='text/event-stream')
1190
+
1191
+ else:
1192
+ response.raise_for_status()
1193
+ end_time = time.time()
1194
+ response_json = response.json()
1195
+ total_time = end_time - start_time
1196
+
1197
+ try:
1198
+ images = response_json.get("images", [])
1199
+
1200
+ image_url = ""
1201
+ if images and isinstance(images[0], dict) and "url" in images[0]:
1202
+ image_url = images[0]["url"]
1203
+ logging.info(f"Extracted image URL: {image_url}")
1204
+ elif images and isinstance(images[0], str):
1205
+ image_url = images[0]
1206
+ logging.info(f"Extracted image URL: {image_url}")
1207
+
1208
+ markdown_image_link = f"![image]({image_url})"
1209
+ response_data = {
1210
+ "id": f"chatcmpl-{uuid.uuid4()}",
1211
+ "object": "chat.completion",
1212
+ "created": int(time.time()),
1213
+ "model": model_name,
1214
+ "choices": [
1215
+ {
1216
+ "index": 0,
1217
+ "message": {
1218
+ "role": "assistant",
1219
+ "content": markdown_image_link if image_url else "Failed to generate image",
1220
+ },
1221
+ "finish_reason": "stop",
1222
+ }
1223
+ ],
1224
+ }
1225
+ except (KeyError, ValueError, IndexError) as e:
1226
+ logging.error(
1227
+ f"解析响应 JSON 失败: {e}, "
1228
+ f"完整内容: {response_json}"
1229
+ )
1230
+ response_data = {
1231
+ "id": f"chatcmpl-{uuid.uuid4()}",
1232
+ "object": "chat.completion",
1233
+ "created": int(time.time()),
1234
+ "model": model_name,
1235
+ "choices": [
1236
+ {
1237
+ "index": 0,
1238
+ "message": {
1239
+ "role": "assistant",
1240
+ "content": "Failed to process image data",
1241
+ },
1242
+ "finish_reason": "stop",
1243
+ }
1244
+ ],
1245
+ }
1246
+
1247
+ logging.info(
1248
+ f"使用的key: {api_key}, "
1249
+ f"总共用时: {total_time:.4f}秒, "
1250
+ f"使用的模型: {model_name}"
1251
+ )
1252
+ with data_lock:
1253
+ request_timestamps.append(time.time())
1254
+ token_counts.append(0)
1255
+ return jsonify(response_data)
1256
+
1257
+ except requests.exceptions.RequestException as e:
1258
+ logging.error(f"请求转发异常: {e}")
1259
+ return jsonify({"error": str(e)}), 500
1260
+ else:
1261
+ tools = data.get("tools")
1262
+ tool_choice = data.get("tool_choice")
1263
+
1264
+ siliconflow_data = {
1265
+ "model": model_name,
1266
+ "messages": data.get("messages", []),
1267
+ "stream": data.get("stream", False),
1268
+ "max_tokens": data.get("max_tokens"),
1269
+ "temperature": data.get("temperature"),
1270
+ "top_p": data.get("top_p"),
1271
+ "frequency_penalty": data.get("frequency_penalty"),
1272
+ "presence_penalty": data.get("presence_penalty"),
1273
+ "stop": data.get("stop"),
1274
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1275
 
1276
+ if tools:
1277
+ siliconflow_data["tools"] = tools
1278
+ if tool_choice:
1279
+ siliconflow_data["tool_choice"] = tool_choice
 
 
 
 
 
1280
 
 
 
 
 
1281
  try:
1282
  start_time = time.time()
1283
  response = requests.post(
1284
  TEST_MODEL_ENDPOINT,
1285
  headers=headers,
1286
+ json=siliconflow_data,
1287
  stream=data.get("stream", False),
1288
  timeout=60
1289
  )
 
1312
  prompt_tokens = 0
1313
  completion_tokens = 0
1314
  response_content = ""
1315
+ tool_calls = []
1316
  for line in full_response_content.splitlines():
1317
  if line.startswith("data:"):
1318
  line = line[5:].strip()
 
1331
 
1332
  if (
1333
  "choices" in response_json and
1334
+ len(response_json["choices"]) > 0
 
 
 
 
1335
  ):
1336
+ choice = response_json["choices"][0]
1337
+ if "delta" in choice:
1338
+ delta = choice["delta"]
1339
+ if "content" in delta:
1340
+ response_content += delta["content"]
1341
+ if "tool_calls" in delta:
1342
+ tool_calls.extend(delta["tool_calls"])
1343
+ elif "message" in choice:
1344
+ message = choice["message"]
1345
+ if "content" in message and message["content"]:
1346
+ response_content += message["content"]
1347
+ if "tool_calls" in message:
1348
+ tool_calls.extend(message["tool_calls"])
1349
+
1350
 
1351
  if (
1352
  "usage" in response_json and
 
1384
  )
1385
 
1386
  user_content = user_content.strip()
 
1387
  user_content_replaced = user_content.replace(
1388
  '\n', '\\n'
1389
  ).replace('\r', '\\n')
 
1391
  '\n', '\\n'
1392
  ).replace('\r', '\\n')
1393
 
1394
+ log_message = (
1395
  f"使用的key: {api_key}, "
1396
  f"提示token: {prompt_tokens}, "
1397
  f"输出token: {completion_tokens}, "
 
1401
  f"用户的内容: {user_content_replaced}, "
1402
  f"输出的内容: {response_content_replaced}"
1403
  )
1404
+ if tool_calls:
1405
+ log_message += f", tool_calls: {tool_calls}"
1406
+
1407
+ logging.info(log_message)
1408
 
1409
  with data_lock:
1410
  request_timestamps.append(time.time())
1411
  token_counts.append(prompt_tokens+completion_tokens)
1412
+
1413
+
1414
+
1415
+ # 构造 OpenAI 格式的响应数据
1416
+ response_data = {
1417
+ "id": f"chatcmpl-{uuid.uuid4()}",
1418
+ "object": "chat.completion.chunk",
1419
+ "created": int(time.time()),
1420
+ "model": model_name,
1421
+ "choices": [
1422
+ {
1423
+ "index": 0,
1424
+ "delta": {
1425
+ "role": "assistant",
1426
+ },
1427
+ "finish_reason": None
1428
+ }
1429
+ ]
1430
+ }
1431
+
1432
+ if response_content:
1433
+ response_data["choices"][0]["delta"]["content"] = response_content
1434
+
1435
+ if tool_calls:
1436
+ response_data["choices"][0]["delta"]["tool_calls"] = tool_calls
1437
+
1438
+ yield f"data: {json.dumps(response_data)}\n\n".encode('utf-8')
1439
 
1440
+ end_chunk_data = {
1441
+ "id": f"chatcmpl-{uuid.uuid4()}",
1442
+ "object": "chat.completion.chunk",
1443
+ "created": int(time.time()),
1444
+ "model": model_name,
1445
+ "choices": [
1446
+ {
1447
+ "index": 0,
1448
+ "delta": {},
1449
+ "finish_reason": "stop"
1450
+ }
1451
+ ]
1452
+ }
1453
+ yield f"data: {json.dumps(end_chunk_data)}\n\n".encode('utf-8')
1454
  return Response(
1455
  stream_with_context(generate()),
1456
  content_type=response.headers['Content-Type']
 
1469
  response_content = response_json[
1470
  "choices"
1471
  ][0]["message"]["content"]
1472
+
1473
+ if "tool_calls" in response_json["choices"][0]["message"]:
1474
+ tool_calls = response_json["choices"][0]["message"]["tool_calls"]
1475
+ else:
1476
+ tool_calls = []
1477
  except (KeyError, ValueError, IndexError) as e:
1478
  logging.error(
1479
  f"解析非流式响应 JSON 失败: {e}, "
 
1482
  prompt_tokens = 0
1483
  completion_tokens = 0
1484
  response_content = ""
1485
+ tool_calls = []
1486
 
1487
  user_content = ""
1488
  messages = data.get("messages", [])
 
1508
  response_content_replaced = response_content.replace(
1509
  '\n', '\\n'
1510
  ).replace('\r', '\\n')
1511
+
1512
+ log_message = (
1513
  f"使用的key: {api_key}, "
1514
  f"提示token: {prompt_tokens}, "
1515
  f"输出token: {completion_tokens}, "
 
1519
  f"用户的内容: {user_content_replaced}, "
1520
  f"输出的内容: {response_content_replaced}"
1521
  )
1522
+
1523
+ if tool_calls:
1524
+ log_message += f", tool_calls: {tool_calls}"
1525
+
1526
+ logging.info(log_message)
1527
  with data_lock:
1528
  request_timestamps.append(time.time())
1529
  if "prompt_tokens" in response_json["usage"] and "completion_tokens" in response_json["usage"]:
1530
  token_counts.append(response_json["usage"]["prompt_tokens"] + response_json["usage"]["completion_tokens"])
1531
  else:
1532
  token_counts.append(0)
1533
+
1534
+ # 构造 OpenAI 格式的响应数据
1535
+ response_data = {
1536
+ "id": f"chatcmpl-{uuid.uuid4()}",
1537
+ "object": "chat.completion",
1538
+ "created": int(time.time()),
1539
+ "model": model_name,
1540
+ "choices": [
1541
+ {
1542
+ "index": 0,
1543
+ "message": {
1544
+ "role": "assistant",
1545
+ "content": response_content,
1546
+ },
1547
+ "finish_reason": "stop",
1548
+ }
1549
+ ],
1550
+ }
1551
+
1552
+ if tool_calls:
1553
+ response_data["choices"][0]["message"]["tool_calls"] = tool_calls
1554
 
1555
+ return jsonify(response_data)
 
1556
  except requests.exceptions.RequestException as e:
1557
  logging.error(f"请求转发异常: {e}")
1558
  return jsonify({"error": str(e)}), 500