Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- app.py +176 -15
- templates/dashboard.html +61 -9
app.py
CHANGED
@@ -28,6 +28,8 @@ COMPUTE_POINTS_URL = "https://apps.abacus.ai/api/_getOrganizationComputePoints"
|
|
28 |
COMPUTE_POINTS_LOG_URL = "https://abacus.ai/api/v0/_getOrganizationComputePointLog"
|
29 |
CREATE_CONVERSATION_URL = "https://apps.abacus.ai/api/createDeploymentConversation"
|
30 |
DELETE_CONVERSATION_URL = "https://apps.abacus.ai/api/deleteDeploymentConversation"
|
|
|
|
|
31 |
|
32 |
|
33 |
USER_AGENTS = [
|
@@ -375,6 +377,42 @@ def init_session():
|
|
375 |
model_map, models_set = get_model_map(session, cookies, session_token)
|
376 |
all_models.update(models_set)
|
377 |
USER_DATA.append((session, cookies, session_token, conversation_id, model_map, i))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
except Exception as e:
|
379 |
print(f"配置用户 {i+1} 失败: {e}")
|
380 |
continue
|
@@ -696,7 +734,8 @@ def send_message(message, model, think=False):
|
|
696 |
"sec-fetch-mode": "cors",
|
697 |
"sec-fetch-site": "same-origin",
|
698 |
"sentry-trace": sentry_trace,
|
699 |
-
"user-agent": random.choice(USER_AGENTS)
|
|
|
700 |
}
|
701 |
|
702 |
if session_token:
|
@@ -712,9 +751,7 @@ def send_message(message, model, think=False):
|
|
712 |
"language": "zh-CN"
|
713 |
},
|
714 |
"llmName": model_map[model][1],
|
715 |
-
"externalApplicationId": model_map[model][0]
|
716 |
-
"regenerate": True,
|
717 |
-
"editPrompt": True
|
718 |
}
|
719 |
|
720 |
if think:
|
@@ -725,7 +762,8 @@ def send_message(message, model, think=False):
|
|
725 |
CHAT_URL,
|
726 |
headers=headers,
|
727 |
data=json.dumps(payload),
|
728 |
-
stream=True
|
|
|
729 |
)
|
730 |
|
731 |
response.raise_for_status()
|
@@ -789,7 +827,12 @@ def send_message(message, model, think=False):
|
|
789 |
|
790 |
# 在流式传输完成后计算token并更新统计
|
791 |
completion_result, _ = num_tokens_from_string(completion_buffer.getvalue(), model)
|
792 |
-
|
|
|
|
|
|
|
|
|
|
|
793 |
|
794 |
# 如果需要删除上一个对话且上一个对话ID不为空且与当前不同
|
795 |
if DELETE_CHAT and last_conversation_id and last_conversation_id != conversation_id:
|
@@ -834,7 +877,8 @@ def send_message_non_stream(message, model, think=False):
|
|
834 |
"sec-fetch-mode": "cors",
|
835 |
"sec-fetch-site": "same-origin",
|
836 |
"sentry-trace": sentry_trace,
|
837 |
-
"user-agent": random.choice(USER_AGENTS)
|
|
|
838 |
}
|
839 |
|
840 |
if session_token:
|
@@ -850,9 +894,7 @@ def send_message_non_stream(message, model, think=False):
|
|
850 |
"language": "zh-CN"
|
851 |
},
|
852 |
"llmName": model_map[model][1],
|
853 |
-
"externalApplicationId": model_map[model][0]
|
854 |
-
"regenerate": True,
|
855 |
-
"editPrompt": True
|
856 |
}
|
857 |
|
858 |
if think:
|
@@ -863,7 +905,8 @@ def send_message_non_stream(message, model, think=False):
|
|
863 |
CHAT_URL,
|
864 |
headers=headers,
|
865 |
data=json.dumps(payload),
|
866 |
-
stream=True
|
|
|
867 |
)
|
868 |
|
869 |
response.raise_for_status()
|
@@ -918,7 +961,12 @@ def send_message_non_stream(message, model, think=False):
|
|
918 |
|
919 |
# 计算输出token并更新统计信息
|
920 |
completion_result, _ = num_tokens_from_string(think_content + response_content, model)
|
921 |
-
|
|
|
|
|
|
|
|
|
|
|
922 |
|
923 |
# 如果需要删除上一个对话且上一个对话ID不为空且与当前不同
|
924 |
if DELETE_CHAT and last_conversation_id and last_conversation_id != conversation_id:
|
@@ -955,7 +1003,12 @@ def send_message_non_stream(message, model, think=False):
|
|
955 |
|
956 |
# 计算输出token并更新统计信息
|
957 |
completion_result, _ = num_tokens_from_string(response_content, model)
|
958 |
-
|
|
|
|
|
|
|
|
|
|
|
959 |
|
960 |
# 如果需要删除上一个对话且上一个对话ID不为空且与当前不同
|
961 |
if DELETE_CHAT and last_conversation_id and last_conversation_id != conversation_id:
|
@@ -1111,7 +1164,7 @@ def num_tokens_from_string(string, model=""):
|
|
1111 |
|
1112 |
|
1113 |
# 更新模型使用统计
|
1114 |
-
def update_model_stats(model, prompt_tokens, completion_tokens, calculation_method="estimate"):
|
1115 |
global model_usage_stats, total_tokens, model_usage_records
|
1116 |
|
1117 |
# 添加调用记录
|
@@ -1126,7 +1179,8 @@ def update_model_stats(model, prompt_tokens, completion_tokens, calculation_meth
|
|
1126 |
"call_time": call_time,
|
1127 |
"prompt_tokens": prompt_tokens,
|
1128 |
"completion_tokens": completion_tokens,
|
1129 |
-
"calculation_method": calculation_method
|
|
|
1130 |
}
|
1131 |
model_usage_records.append(record)
|
1132 |
|
@@ -1382,6 +1436,52 @@ def update_delete_chat_setting():
|
|
1382 |
return jsonify({"success": False, "error": str(e)})
|
1383 |
|
1384 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1385 |
# 获取Hugging Face Space URL
|
1386 |
def get_space_url():
|
1387 |
# 尝试从环境变量获取
|
@@ -1418,6 +1518,67 @@ if SPACE_URL:
|
|
1418 |
print("注意:Hugging Face生成的URL会自动将空间名称中的下划线(_)替换为连字符(-)")
|
1419 |
|
1420 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1421 |
if __name__ == "__main__":
|
1422 |
# 启动保活线程
|
1423 |
threading.Thread(target=keep_alive, daemon=True).start()
|
|
|
28 |
COMPUTE_POINTS_LOG_URL = "https://abacus.ai/api/v0/_getOrganizationComputePointLog"
|
29 |
CREATE_CONVERSATION_URL = "https://apps.abacus.ai/api/createDeploymentConversation"
|
30 |
DELETE_CONVERSATION_URL = "https://apps.abacus.ai/api/deleteDeploymentConversation"
|
31 |
+
GET_CONVERSATION_URL = "https://apps.abacus.ai/api/getDeploymentConversation"
|
32 |
+
COMPUTE_POINT_TOGGLE_URL = "https://abacus.ai/api/v0/_updateOrganizationComputePointToggle"
|
33 |
|
34 |
|
35 |
USER_AGENTS = [
|
|
|
377 |
model_map, models_set = get_model_map(session, cookies, session_token)
|
378 |
all_models.update(models_set)
|
379 |
USER_DATA.append((session, cookies, session_token, conversation_id, model_map, i))
|
380 |
+
|
381 |
+
# 对第一个成功配置的用户,初始化计算点数记录功能
|
382 |
+
if i == 0:
|
383 |
+
try:
|
384 |
+
headers = {
|
385 |
+
"accept": "application/json, text/plain, */*",
|
386 |
+
"accept-language": "zh-CN,zh;q=0.9",
|
387 |
+
"content-type": "application/json",
|
388 |
+
"reai-ui": "1",
|
389 |
+
"sec-ch-ua": "\"Chromium\";v=\"116\", \"Not)A;Brand\";v=\"24\", \"Google Chrome\";v=\"116\"",
|
390 |
+
"sec-ch-ua-mobile": "?0",
|
391 |
+
"sec-ch-ua-platform": "\"Windows\"",
|
392 |
+
"sec-fetch-dest": "empty",
|
393 |
+
"sec-fetch-mode": "cors",
|
394 |
+
"sec-fetch-site": "same-site",
|
395 |
+
"x-abacus-org-host": "apps",
|
396 |
+
"session-token": session_token
|
397 |
+
}
|
398 |
+
|
399 |
+
response = session.post(
|
400 |
+
COMPUTE_POINT_TOGGLE_URL,
|
401 |
+
headers=headers,
|
402 |
+
json={"alwaysDisplay": True},
|
403 |
+
cookies=None
|
404 |
+
)
|
405 |
+
|
406 |
+
if response.status_code == 200:
|
407 |
+
result = response.json()
|
408 |
+
if result.get("success"):
|
409 |
+
print("成功初始化计算点数记录功能为开启状态")
|
410 |
+
else:
|
411 |
+
print(f"初始化计算点数记录功能失败: {result.get('error', '未知错误')}")
|
412 |
+
else:
|
413 |
+
print(f"初始化计算点数记录功能失败,状态码: {response.status_code}")
|
414 |
+
except Exception as e:
|
415 |
+
print(f"初始化计算点数记录功能时出错: {e}")
|
416 |
except Exception as e:
|
417 |
print(f"配置用户 {i+1} 失败: {e}")
|
418 |
continue
|
|
|
734 |
"sec-fetch-mode": "cors",
|
735 |
"sec-fetch-site": "same-origin",
|
736 |
"sentry-trace": sentry_trace,
|
737 |
+
"user-agent": random.choice(USER_AGENTS),
|
738 |
+
"x-abacus-org-host": "apps"
|
739 |
}
|
740 |
|
741 |
if session_token:
|
|
|
751 |
"language": "zh-CN"
|
752 |
},
|
753 |
"llmName": model_map[model][1],
|
754 |
+
"externalApplicationId": model_map[model][0]
|
|
|
|
|
755 |
}
|
756 |
|
757 |
if think:
|
|
|
762 |
CHAT_URL,
|
763 |
headers=headers,
|
764 |
data=json.dumps(payload),
|
765 |
+
stream=True,
|
766 |
+
cookies=None
|
767 |
)
|
768 |
|
769 |
response.raise_for_status()
|
|
|
827 |
|
828 |
# 在流式传输完成后计算token并更新统计
|
829 |
completion_result, _ = num_tokens_from_string(completion_buffer.getvalue(), model)
|
830 |
+
|
831 |
+
# 保存对话历史并获取计算点数
|
832 |
+
_, compute_points = save_conversation_history(session, cookies, session_token, conversation_id)
|
833 |
+
|
834 |
+
# 更新统计信息
|
835 |
+
update_model_stats(model, prompt_tokens, completion_result, calculation_method, compute_points)
|
836 |
|
837 |
# 如果需要删除上一个对话且上一个对话ID不为空且与当前不同
|
838 |
if DELETE_CHAT and last_conversation_id and last_conversation_id != conversation_id:
|
|
|
877 |
"sec-fetch-mode": "cors",
|
878 |
"sec-fetch-site": "same-origin",
|
879 |
"sentry-trace": sentry_trace,
|
880 |
+
"user-agent": random.choice(USER_AGENTS),
|
881 |
+
"x-abacus-org-host": "apps"
|
882 |
}
|
883 |
|
884 |
if session_token:
|
|
|
894 |
"language": "zh-CN"
|
895 |
},
|
896 |
"llmName": model_map[model][1],
|
897 |
+
"externalApplicationId": model_map[model][0]
|
|
|
|
|
898 |
}
|
899 |
|
900 |
if think:
|
|
|
905 |
CHAT_URL,
|
906 |
headers=headers,
|
907 |
data=json.dumps(payload),
|
908 |
+
stream=True,
|
909 |
+
cookies=None
|
910 |
)
|
911 |
|
912 |
response.raise_for_status()
|
|
|
961 |
|
962 |
# 计算输出token并更新统计信息
|
963 |
completion_result, _ = num_tokens_from_string(think_content + response_content, model)
|
964 |
+
|
965 |
+
# 保存对话历史并获取计算点数
|
966 |
+
_, compute_points = save_conversation_history(session, cookies, session_token, conversation_id)
|
967 |
+
|
968 |
+
# 更新统计信息
|
969 |
+
update_model_stats(model, prompt_tokens, completion_result, calculation_method, compute_points)
|
970 |
|
971 |
# 如果需要删除上一个对话且上一个对话ID不为空且与当前不同
|
972 |
if DELETE_CHAT and last_conversation_id and last_conversation_id != conversation_id:
|
|
|
1003 |
|
1004 |
# 计算输出token并更新统计信息
|
1005 |
completion_result, _ = num_tokens_from_string(response_content, model)
|
1006 |
+
|
1007 |
+
# 保存对话历史并获取计算点数
|
1008 |
+
_, compute_points = save_conversation_history(session, cookies, session_token, conversation_id)
|
1009 |
+
|
1010 |
+
# 更新统计信息
|
1011 |
+
update_model_stats(model, prompt_tokens, completion_result, calculation_method, compute_points)
|
1012 |
|
1013 |
# 如果需要删除上一个对话且上一个对话ID不为空且与当前不同
|
1014 |
if DELETE_CHAT and last_conversation_id and last_conversation_id != conversation_id:
|
|
|
1164 |
|
1165 |
|
1166 |
# 更新模型使用统计
|
1167 |
+
def update_model_stats(model, prompt_tokens, completion_tokens, calculation_method="estimate", compute_points=None):
|
1168 |
global model_usage_stats, total_tokens, model_usage_records
|
1169 |
|
1170 |
# 添加调用记录
|
|
|
1179 |
"call_time": call_time,
|
1180 |
"prompt_tokens": prompt_tokens,
|
1181 |
"completion_tokens": completion_tokens,
|
1182 |
+
"calculation_method": calculation_method,
|
1183 |
+
"compute_points": compute_points
|
1184 |
}
|
1185 |
model_usage_records.append(record)
|
1186 |
|
|
|
1436 |
return jsonify({"success": False, "error": str(e)})
|
1437 |
|
1438 |
|
1439 |
+
# 添加更新计算点数记录设置的路由
|
1440 |
+
@app.route("/update_compute_point_toggle", methods=["POST"])
|
1441 |
+
@require_auth
|
1442 |
+
def update_compute_point_toggle():
|
1443 |
+
try:
|
1444 |
+
(session, cookies, session_token, conversation_id, model_map, user_index) = get_user_data()
|
1445 |
+
data = request.get_json()
|
1446 |
+
if data and "always_display" in data:
|
1447 |
+
headers = {
|
1448 |
+
"accept": "application/json, text/plain, */*",
|
1449 |
+
"accept-language": "zh-CN,zh;q=0.9",
|
1450 |
+
"content-type": "application/json",
|
1451 |
+
"reai-ui": "1",
|
1452 |
+
"sec-ch-ua": "\"Chromium\";v=\"116\", \"Not)A;Brand\";v=\"24\", \"Google Chrome\";v=\"116\"",
|
1453 |
+
"sec-ch-ua-mobile": "?0",
|
1454 |
+
"sec-ch-ua-platform": "\"Windows\"",
|
1455 |
+
"sec-fetch-dest": "empty",
|
1456 |
+
"sec-fetch-mode": "cors",
|
1457 |
+
"sec-fetch-site": "same-site",
|
1458 |
+
"x-abacus-org-host": "apps"
|
1459 |
+
}
|
1460 |
+
|
1461 |
+
if session_token:
|
1462 |
+
headers["session-token"] = session_token
|
1463 |
+
|
1464 |
+
response = session.post(
|
1465 |
+
COMPUTE_POINT_TOGGLE_URL,
|
1466 |
+
headers=headers,
|
1467 |
+
json={"alwaysDisplay": data["always_display"]},
|
1468 |
+
cookies=None
|
1469 |
+
)
|
1470 |
+
|
1471 |
+
if response.status_code == 200:
|
1472 |
+
result = response.json()
|
1473 |
+
if result.get("success"):
|
1474 |
+
print(f"更新计算点数记录设置为: {data['always_display']}")
|
1475 |
+
return jsonify({"success": True})
|
1476 |
+
|
1477 |
+
return jsonify({"success": False, "error": "API调用失败"})
|
1478 |
+
else:
|
1479 |
+
return jsonify({"success": False, "error": "缺少always_display参数"})
|
1480 |
+
except Exception as e:
|
1481 |
+
print(f"更新计算点数记录设置失败: {e}")
|
1482 |
+
return jsonify({"success": False, "error": str(e)})
|
1483 |
+
|
1484 |
+
|
1485 |
# 获取Hugging Face Space URL
|
1486 |
def get_space_url():
|
1487 |
# 尝试从环境变量获取
|
|
|
1518 |
print("注意:Hugging Face生成的URL会自动将空间名称中的下划线(_)替换为连字符(-)")
|
1519 |
|
1520 |
|
1521 |
+
def save_conversation_history(session, cookies, session_token, conversation_id, deployment_id="14b2a314cc"):
|
1522 |
+
"""保存对话历史,返回使用的计算点数"""
|
1523 |
+
if not conversation_id:
|
1524 |
+
return False, None
|
1525 |
+
|
1526 |
+
headers = {
|
1527 |
+
"accept": "application/json, text/plain, */*",
|
1528 |
+
"accept-language": "zh-CN,zh;q=0.9",
|
1529 |
+
"baggage": f"sentry-environment=production,sentry-release=946244517de08b08598b94f18098411f5a5352d5,sentry-public_key=3476ea6df1585dd10e92cdae3a66ff49,sentry-trace_id={TRACE_ID}",
|
1530 |
+
"reai-ui": "1",
|
1531 |
+
"sec-ch-ua": "\"Chromium\";v=\"116\", \"Not)A;Brand\";v=\"24\", \"Google Chrome\";v=\"116\"",
|
1532 |
+
"sec-ch-ua-mobile": "?0",
|
1533 |
+
"sec-ch-ua-platform": "\"Windows\"",
|
1534 |
+
"sec-fetch-dest": "empty",
|
1535 |
+
"sec-fetch-mode": "cors",
|
1536 |
+
"sec-fetch-site": "same-origin",
|
1537 |
+
"sentry-trace": f"{TRACE_ID}-800cb7f4613dec52",
|
1538 |
+
"x-abacus-org-host": "apps"
|
1539 |
+
}
|
1540 |
+
|
1541 |
+
if session_token:
|
1542 |
+
headers["session-token"] = session_token
|
1543 |
+
|
1544 |
+
params = {
|
1545 |
+
"deploymentId": deployment_id,
|
1546 |
+
"deploymentConversationId": conversation_id,
|
1547 |
+
"skipDocumentBoundingBoxes": "true",
|
1548 |
+
"filterIntermediateConversationEvents": "false",
|
1549 |
+
"getUnusedDocumentUploads": "false"
|
1550 |
+
}
|
1551 |
+
|
1552 |
+
try:
|
1553 |
+
response = session.get(
|
1554 |
+
GET_CONVERSATION_URL,
|
1555 |
+
headers=headers,
|
1556 |
+
params=params,
|
1557 |
+
cookies=None
|
1558 |
+
)
|
1559 |
+
|
1560 |
+
if response.status_code == 200:
|
1561 |
+
data = response.json()
|
1562 |
+
if data.get("success"):
|
1563 |
+
# 从最后一条BOT消息中获取计算点数
|
1564 |
+
history = data.get("result", {}).get("history", [])
|
1565 |
+
compute_points = None
|
1566 |
+
for msg in reversed(history):
|
1567 |
+
if msg.get("role") == "BOT":
|
1568 |
+
compute_points = msg.get("computePointsUsed")
|
1569 |
+
break
|
1570 |
+
print(f"成功保存对话历史: {conversation_id}, 使用计算点: {compute_points}")
|
1571 |
+
return True, compute_points
|
1572 |
+
else:
|
1573 |
+
print(f"保存对话历史失败: {data.get('error', '未知错误')}")
|
1574 |
+
else:
|
1575 |
+
print(f"保存对话历史失败,状态码: {response.status_code}")
|
1576 |
+
return False, None
|
1577 |
+
except Exception as e:
|
1578 |
+
print(f"保存对话历史时出错: {e}")
|
1579 |
+
return False, None
|
1580 |
+
|
1581 |
+
|
1582 |
if __name__ == "__main__":
|
1583 |
# 启动保活线程
|
1584 |
threading.Thread(target=keep_alive, daemon=True).start()
|
templates/dashboard.html
CHANGED
@@ -695,6 +695,20 @@
|
|
695 |
<span class="status-label">设置说明</span>
|
696 |
<span class="status-value info-text">开启后,系统将在每次对话完成后自动删除上一次对话,只保留最新对话</span>
|
697 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
698 |
</div>
|
699 |
|
700 |
<div class="grid">
|
@@ -868,7 +882,9 @@
|
|
868 |
<th>模型</th>
|
869 |
<th>输入Token</th>
|
870 |
<th>输出Token</th>
|
|
|
871 |
<th>计算方式</th>
|
|
|
872 |
</tr>
|
873 |
</thead>
|
874 |
<tbody>
|
@@ -876,15 +892,11 @@
|
|
876 |
<tr class="model-row {% if loop.index > 10 %}hidden-model{% endif %}">
|
877 |
<td class="datetime">{{ record.call_time }}</td>
|
878 |
<td>{{ record.model }}</td>
|
879 |
-
<td class="token-count">{{ record.prompt_tokens
|
880 |
-
<td class="token-count">{{ record.completion_tokens
|
881 |
-
<td>
|
882 |
-
|
883 |
-
|
884 |
-
{% else %}
|
885 |
-
<span class="token-method estimate">估算</span>
|
886 |
-
{% endif %}
|
887 |
-
</td>
|
888 |
</tr>
|
889 |
{% endfor %}
|
890 |
</tbody>
|
@@ -1025,6 +1037,46 @@
|
|
1025 |
});
|
1026 |
});
|
1027 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1028 |
});
|
1029 |
|
1030 |
// 通知函数
|
|
|
695 |
<span class="status-label">设置说明</span>
|
696 |
<span class="status-value info-text">开启后,系统将在每次对话完成后自动删除上一次对话,只保留最新对话</span>
|
697 |
</div>
|
698 |
+
<div class="status-item">
|
699 |
+
<span class="status-label">是否记录计算点数</span>
|
700 |
+
<div class="toggle-switch-container">
|
701 |
+
<label class="toggle-switch">
|
702 |
+
<input type="checkbox" id="compute-point-toggle" checked>
|
703 |
+
<span class="toggle-slider"></span>
|
704 |
+
</label>
|
705 |
+
<span class="toggle-status" id="compute-point-status">开启</span>
|
706 |
+
</div>
|
707 |
+
</div>
|
708 |
+
<div class="status-item">
|
709 |
+
<span class="status-label">设置说明</span>
|
710 |
+
<span class="status-value info-text">开启后,系统将记录每次对话使用的计算点数,用于统计和分析</span>
|
711 |
+
</div>
|
712 |
</div>
|
713 |
|
714 |
<div class="grid">
|
|
|
882 |
<th>模型</th>
|
883 |
<th>输入Token</th>
|
884 |
<th>输出Token</th>
|
885 |
+
<th>总Token</th>
|
886 |
<th>计算方式</th>
|
887 |
+
<th>计算点数</th>
|
888 |
</tr>
|
889 |
</thead>
|
890 |
<tbody>
|
|
|
892 |
<tr class="model-row {% if loop.index > 10 %}hidden-model{% endif %}">
|
893 |
<td class="datetime">{{ record.call_time }}</td>
|
894 |
<td>{{ record.model }}</td>
|
895 |
+
<td class="token-count">{{ record.prompt_tokens }}</td>
|
896 |
+
<td class="token-count">{{ record.completion_tokens }}</td>
|
897 |
+
<td>{{ record.prompt_tokens + record.completion_tokens }}</td>
|
898 |
+
<td>{{ record.calculation_method }}</td>
|
899 |
+
<td>{{ record.compute_points if record.compute_points is not none else 'null' }}</td>
|
|
|
|
|
|
|
|
|
900 |
</tr>
|
901 |
{% endfor %}
|
902 |
</tbody>
|
|
|
1037 |
});
|
1038 |
});
|
1039 |
}
|
1040 |
+
|
1041 |
+
// 处理计算点数记录开关
|
1042 |
+
const computePointToggle = document.getElementById('compute-point-toggle');
|
1043 |
+
const computePointStatus = document.getElementById('compute-point-status');
|
1044 |
+
|
1045 |
+
if (computePointToggle && computePointStatus) {
|
1046 |
+
computePointToggle.addEventListener('change', function() {
|
1047 |
+
const isChecked = this.checked;
|
1048 |
+
computePointStatus.textContent = isChecked ? '开启' : '关闭';
|
1049 |
+
|
1050 |
+
// 发送更新请求到后端
|
1051 |
+
fetch('/update_compute_point_toggle', {
|
1052 |
+
method: 'POST',
|
1053 |
+
headers: {
|
1054 |
+
'Content-Type': 'application/json',
|
1055 |
+
},
|
1056 |
+
body: JSON.stringify({ always_display: isChecked })
|
1057 |
+
})
|
1058 |
+
.then(response => response.json())
|
1059 |
+
.then(data => {
|
1060 |
+
if (data.success) {
|
1061 |
+
// 显示成功提示
|
1062 |
+
showNotification(isChecked ? '已开启计算点数记录功能' : '已关闭计算点数记录功能', 'success');
|
1063 |
+
} else {
|
1064 |
+
// 显示错误提示
|
1065 |
+
showNotification('设置更新失败: ' + data.error, 'error');
|
1066 |
+
// 回滚UI状态
|
1067 |
+
computePointToggle.checked = !isChecked;
|
1068 |
+
computePointStatus.textContent = !isChecked ? '开启' : '关闭';
|
1069 |
+
}
|
1070 |
+
})
|
1071 |
+
.catch(error => {
|
1072 |
+
console.error('更新设置出错:', error);
|
1073 |
+
showNotification('更新设置失败,请重试', 'error');
|
1074 |
+
// 回滚UI状态
|
1075 |
+
computePointToggle.checked = !isChecked;
|
1076 |
+
computePointStatus.textContent = !isChecked ? '开启' : '关闭';
|
1077 |
+
});
|
1078 |
+
});
|
1079 |
+
}
|
1080 |
});
|
1081 |
|
1082 |
// 通知函数
|