Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- app.py +60 -6
- templates/dashboard.html +9 -2
app.py
CHANGED
@@ -57,6 +57,7 @@ total_tokens = {
|
|
57 |
|
58 |
# 模型调用记录
|
59 |
model_usage_records = [] # 每次调用详细记录
|
|
|
60 |
|
61 |
# 计算点信息
|
62 |
compute_points = {
|
@@ -77,7 +78,41 @@ compute_points_log = {
|
|
77 |
users_compute_points = []
|
78 |
|
79 |
# 记录启动时间
|
80 |
-
START_TIME = datetime.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
|
82 |
|
83 |
def resolve_config():
|
@@ -808,7 +843,12 @@ def update_model_stats(model, prompt_tokens, completion_tokens):
|
|
808 |
global model_usage_stats, total_tokens, model_usage_records
|
809 |
|
810 |
# 添加调用记录
|
811 |
-
|
|
|
|
|
|
|
|
|
|
|
812 |
record = {
|
813 |
"model": model,
|
814 |
"call_time": call_time,
|
@@ -822,6 +862,9 @@ def update_model_stats(model, prompt_tokens, completion_tokens):
|
|
822 |
if len(model_usage_records) > 500:
|
823 |
model_usage_records.pop(0)
|
824 |
|
|
|
|
|
|
|
825 |
# 更新聚合统计
|
826 |
if model not in model_usage_stats:
|
827 |
model_usage_stats[model] = {
|
@@ -899,6 +942,9 @@ def get_compute_points():
|
|
899 |
used = total - left
|
900 |
percentage = round((used / total) * 100, 2) if total > 0 else 0
|
901 |
|
|
|
|
|
|
|
902 |
# 添加到用户列表
|
903 |
user_points = {
|
904 |
"user_id": i + 1, # 用户ID从1开始
|
@@ -906,7 +952,7 @@ def get_compute_points():
|
|
906 |
"total": total,
|
907 |
"used": used,
|
908 |
"percentage": percentage,
|
909 |
-
"last_update":
|
910 |
}
|
911 |
users_compute_points.append(user_points)
|
912 |
|
@@ -932,7 +978,7 @@ def get_compute_points():
|
|
932 |
compute_points["total"] = total_points
|
933 |
compute_points["used"] = total_points - total_left
|
934 |
compute_points["percentage"] = round((compute_points["used"] / compute_points["total"]) * 100, 2) if compute_points["total"] > 0 else 0
|
935 |
-
compute_points["last_update"] = datetime.
|
936 |
print(f"所有用户计算点总计: 剩余 {total_left}, 总计 {total_points}")
|
937 |
|
938 |
# 获取计算点使用日志
|
@@ -1007,7 +1053,9 @@ def dashboard():
|
|
1007 |
# 在每次访问仪表盘时更新计算点信息
|
1008 |
get_compute_points()
|
1009 |
|
1010 |
-
|
|
|
|
|
1011 |
days = uptime.days
|
1012 |
hours, remainder = divmod(uptime.seconds, 3600)
|
1013 |
minutes, seconds = divmod(remainder, 60)
|
@@ -1019,13 +1067,16 @@ def dashboard():
|
|
1019 |
else:
|
1020 |
uptime_str = f"{minutes}分钟 {seconds}秒"
|
1021 |
|
|
|
|
|
|
|
1022 |
return render_template(
|
1023 |
'dashboard.html',
|
1024 |
uptime=uptime_str,
|
1025 |
health_checks=health_check_counter,
|
1026 |
user_count=USER_NUM,
|
1027 |
models=sorted(list(MODELS)),
|
1028 |
-
year=
|
1029 |
model_stats=model_usage_stats,
|
1030 |
total_tokens=total_tokens,
|
1031 |
compute_points=compute_points,
|
@@ -1066,6 +1117,9 @@ if __name__ == "__main__":
|
|
1066 |
# 启动保活线程
|
1067 |
threading.Thread(target=keep_alive, daemon=True).start()
|
1068 |
|
|
|
|
|
|
|
1069 |
# 获取初始计算点信息
|
1070 |
get_compute_points()
|
1071 |
|
|
|
57 |
|
58 |
# 模型调用记录
|
59 |
model_usage_records = [] # 每次调用详细记录
|
60 |
+
MODEL_USAGE_RECORDS_FILE = "model_usage_records.json" # 调用记录保存文件
|
61 |
|
62 |
# 计算点信息
|
63 |
compute_points = {
|
|
|
78 |
users_compute_points = []
|
79 |
|
80 |
# 记录启动时间
|
81 |
+
START_TIME = datetime.utcnow() + timedelta(hours=8) # 北京时间
|
82 |
+
|
83 |
+
|
84 |
+
# 自定义JSON编码器,处理datetime对象
|
85 |
+
class DateTimeEncoder(json.JSONEncoder):
|
86 |
+
def default(self, obj):
|
87 |
+
if isinstance(obj, datetime):
|
88 |
+
return obj.strftime('%Y-%m-%d %H:%M:%S')
|
89 |
+
return super(DateTimeEncoder, self).default(obj)
|
90 |
+
|
91 |
+
|
92 |
+
# 加载模型调用记录
|
93 |
+
def load_model_usage_records():
|
94 |
+
global model_usage_records
|
95 |
+
try:
|
96 |
+
if os.path.exists(MODEL_USAGE_RECORDS_FILE):
|
97 |
+
with open(MODEL_USAGE_RECORDS_FILE, 'r', encoding='utf-8') as f:
|
98 |
+
records = json.load(f)
|
99 |
+
if isinstance(records, list):
|
100 |
+
model_usage_records = records
|
101 |
+
print(f"成功加载 {len(model_usage_records)} 条模型调用记录")
|
102 |
+
else:
|
103 |
+
print("调用记录文件格式不正确,初始化为空列表")
|
104 |
+
except Exception as e:
|
105 |
+
print(f"加载模型调用记录失败: {e}")
|
106 |
+
model_usage_records = []
|
107 |
+
|
108 |
+
# 保存模型调用记录
|
109 |
+
def save_model_usage_records():
|
110 |
+
try:
|
111 |
+
with open(MODEL_USAGE_RECORDS_FILE, 'w', encoding='utf-8') as f:
|
112 |
+
json.dump(model_usage_records, f, ensure_ascii=False, indent=2, cls=DateTimeEncoder)
|
113 |
+
print(f"成功保存 {len(model_usage_records)} 条模型调用记录")
|
114 |
+
except Exception as e:
|
115 |
+
print(f"保存模型调用记录失败: {e}")
|
116 |
|
117 |
|
118 |
def resolve_config():
|
|
|
843 |
global model_usage_stats, total_tokens, model_usage_records
|
844 |
|
845 |
# 添加调用记录
|
846 |
+
# 获取UTC时间
|
847 |
+
utc_now = datetime.utcnow()
|
848 |
+
# 转换为北京时间 (UTC+8)
|
849 |
+
beijing_time = utc_now + timedelta(hours=8)
|
850 |
+
call_time = beijing_time.strftime('%Y-%m-%d %H:%M:%S') # 北京时间
|
851 |
+
|
852 |
record = {
|
853 |
"model": model,
|
854 |
"call_time": call_time,
|
|
|
862 |
if len(model_usage_records) > 500:
|
863 |
model_usage_records.pop(0)
|
864 |
|
865 |
+
# 保存调用记录到本地文件
|
866 |
+
save_model_usage_records()
|
867 |
+
|
868 |
# 更新聚合统计
|
869 |
if model not in model_usage_stats:
|
870 |
model_usage_stats[model] = {
|
|
|
942 |
used = total - left
|
943 |
percentage = round((used / total) * 100, 2) if total > 0 else 0
|
944 |
|
945 |
+
# 获取北京时间
|
946 |
+
beijing_now = datetime.utcnow() + timedelta(hours=8)
|
947 |
+
|
948 |
# 添加到用户列表
|
949 |
user_points = {
|
950 |
"user_id": i + 1, # 用户ID从1开始
|
|
|
952 |
"total": total,
|
953 |
"used": used,
|
954 |
"percentage": percentage,
|
955 |
+
"last_update": beijing_now
|
956 |
}
|
957 |
users_compute_points.append(user_points)
|
958 |
|
|
|
978 |
compute_points["total"] = total_points
|
979 |
compute_points["used"] = total_points - total_left
|
980 |
compute_points["percentage"] = round((compute_points["used"] / compute_points["total"]) * 100, 2) if compute_points["total"] > 0 else 0
|
981 |
+
compute_points["last_update"] = datetime.utcnow() + timedelta(hours=8) # 北京时间
|
982 |
print(f"所有用户计算点总计: 剩余 {total_left}, 总计 {total_points}")
|
983 |
|
984 |
# 获取计算点使用日志
|
|
|
1053 |
# 在每次访问仪表盘时更新计算点信息
|
1054 |
get_compute_points()
|
1055 |
|
1056 |
+
# 计算运行时间(使用北京时间)
|
1057 |
+
beijing_now = datetime.utcnow() + timedelta(hours=8)
|
1058 |
+
uptime = beijing_now - START_TIME
|
1059 |
days = uptime.days
|
1060 |
hours, remainder = divmod(uptime.seconds, 3600)
|
1061 |
minutes, seconds = divmod(remainder, 60)
|
|
|
1067 |
else:
|
1068 |
uptime_str = f"{minutes}分钟 {seconds}秒"
|
1069 |
|
1070 |
+
# 当前北京年份
|
1071 |
+
beijing_year = beijing_now.year
|
1072 |
+
|
1073 |
return render_template(
|
1074 |
'dashboard.html',
|
1075 |
uptime=uptime_str,
|
1076 |
health_checks=health_check_counter,
|
1077 |
user_count=USER_NUM,
|
1078 |
models=sorted(list(MODELS)),
|
1079 |
+
year=beijing_year,
|
1080 |
model_stats=model_usage_stats,
|
1081 |
total_tokens=total_tokens,
|
1082 |
compute_points=compute_points,
|
|
|
1117 |
# 启动保活线程
|
1118 |
threading.Thread(target=keep_alive, daemon=True).start()
|
1119 |
|
1120 |
+
# 加载历史模型调用记录
|
1121 |
+
load_model_usage_records()
|
1122 |
+
|
1123 |
# 获取初始计算点信息
|
1124 |
get_compute_points()
|
1125 |
|
templates/dashboard.html
CHANGED
@@ -479,6 +479,13 @@
|
|
479 |
border: 1px solid rgba(251, 189, 35, 0.3);
|
480 |
}
|
481 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
482 |
/* 媒体查询 */
|
483 |
@media (max-width: 768px) {
|
484 |
.container {
|
@@ -716,7 +723,7 @@
|
|
716 |
<table class="data-table">
|
717 |
<thead>
|
718 |
<tr>
|
719 |
-
<th
|
720 |
<th>模型</th>
|
721 |
<th>输入Token</th>
|
722 |
<th>输出Token</th>
|
@@ -726,7 +733,7 @@
|
|
726 |
<tbody>
|
727 |
{% for record in model_usage_records|reverse %}
|
728 |
<tr class="model-row {% if loop.index > 10 %}hidden-model{% endif %}">
|
729 |
-
<td>{{ record.call_time }}</td>
|
730 |
<td>{{ record.model }}</td>
|
731 |
<td class="token-count">{{ record.prompt_tokens|int }}</td>
|
732 |
<td class="token-count">{{ record.completion_tokens|int }}</td>
|
|
|
479 |
border: 1px solid rgba(251, 189, 35, 0.3);
|
480 |
}
|
481 |
|
482 |
+
/* 时间日期样式 */
|
483 |
+
.datetime {
|
484 |
+
font-family: 'Consolas', monospace;
|
485 |
+
color: rgba(230, 230, 255, 0.8);
|
486 |
+
font-size: 0.9rem;
|
487 |
+
}
|
488 |
+
|
489 |
/* 媒体查询 */
|
490 |
@media (max-width: 768px) {
|
491 |
.container {
|
|
|
723 |
<table class="data-table">
|
724 |
<thead>
|
725 |
<tr>
|
726 |
+
<th>调用时间 (北京时间)</th>
|
727 |
<th>模型</th>
|
728 |
<th>输入Token</th>
|
729 |
<th>输出Token</th>
|
|
|
733 |
<tbody>
|
734 |
{% for record in model_usage_records|reverse %}
|
735 |
<tr class="model-row {% if loop.index > 10 %}hidden-model{% endif %}">
|
736 |
+
<td class="datetime">{{ record.call_time }}</td>
|
737 |
<td>{{ record.model }}</td>
|
738 |
<td class="token-count">{{ record.prompt_tokens|int }}</td>
|
739 |
<td class="token-count">{{ record.completion_tokens|int }}</td>
|