Spaces:
Paused
Paused
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 |
// 通知函数
|