Spaces:
Paused
Paused
Upload 4 files
Browse files
app.py
CHANGED
|
@@ -21,6 +21,8 @@ API_ENDPOINT_URL = "https://abacus.ai/api/v0/describeDeployment"
|
|
| 21 |
MODEL_LIST_URL = "https://abacus.ai/api/v0/listExternalApplications"
|
| 22 |
CHAT_URL = "https://apps.abacus.ai/api/_chatLLMSendMessageSSE"
|
| 23 |
USER_INFO_URL = "https://abacus.ai/api/v0/_getUserInfo"
|
|
|
|
|
|
|
| 24 |
|
| 25 |
|
| 26 |
USER_AGENTS = [
|
|
@@ -51,6 +53,21 @@ total_tokens = {
|
|
| 51 |
"total": 0 # 总token统计
|
| 52 |
}
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
# HTML模板
|
| 56 |
INDEX_HTML = """
|
|
@@ -123,6 +140,9 @@ INDEX_HTML = """
|
|
| 123 |
.status-value.warning {
|
| 124 |
color: #ffc107;
|
| 125 |
}
|
|
|
|
|
|
|
|
|
|
| 126 |
.footer {
|
| 127 |
margin-top: 2rem;
|
| 128 |
text-align: center;
|
|
@@ -183,6 +203,30 @@ INDEX_HTML = """
|
|
| 183 |
font-family: monospace;
|
| 184 |
color: #28a745;
|
| 185 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 186 |
@media (max-width: 768px) {
|
| 187 |
.container {
|
| 188 |
padding: 1rem;
|
|
@@ -224,6 +268,61 @@ INDEX_HTML = """
|
|
| 224 |
</div>
|
| 225 |
</div>
|
| 226 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
<h2>🔍 模型使用统计</h2>
|
| 228 |
<div class="status-card">
|
| 229 |
<div class="status-item">
|
|
@@ -983,6 +1082,9 @@ def keep_alive():
|
|
| 983 |
|
| 984 |
@app.route("/", methods=["GET"])
|
| 985 |
def index():
|
|
|
|
|
|
|
|
|
|
| 986 |
uptime = datetime.now() - START_TIME
|
| 987 |
days = uptime.days
|
| 988 |
hours, remainder = divmod(uptime.seconds, 3600)
|
|
@@ -1003,7 +1105,9 @@ def index():
|
|
| 1003 |
models=sorted(list(MODELS)),
|
| 1004 |
year=datetime.now().year,
|
| 1005 |
model_stats=model_usage_stats,
|
| 1006 |
-
total_tokens=total_tokens
|
|
|
|
|
|
|
| 1007 |
)
|
| 1008 |
|
| 1009 |
|
|
@@ -1042,8 +1146,115 @@ def update_model_stats(model, prompt_tokens, completion_tokens):
|
|
| 1042 |
total_tokens["total"] += (prompt_tokens + completion_tokens)
|
| 1043 |
|
| 1044 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1045 |
if __name__ == "__main__":
|
| 1046 |
# 启动保活线程
|
| 1047 |
threading.Thread(target=keep_alive, daemon=True).start()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1048 |
port = int(os.environ.get("PORT", 9876))
|
| 1049 |
app.run(port=port, host="0.0.0.0")
|
|
|
|
| 21 |
MODEL_LIST_URL = "https://abacus.ai/api/v0/listExternalApplications"
|
| 22 |
CHAT_URL = "https://apps.abacus.ai/api/_chatLLMSendMessageSSE"
|
| 23 |
USER_INFO_URL = "https://abacus.ai/api/v0/_getUserInfo"
|
| 24 |
+
COMPUTE_POINTS_URL = "https://apps.abacus.ai/api/_getOrganizationComputePoints"
|
| 25 |
+
COMPUTE_POINTS_LOG_URL = "https://abacus.ai/api/v0/_getOrganizationComputePointLog"
|
| 26 |
|
| 27 |
|
| 28 |
USER_AGENTS = [
|
|
|
|
| 53 |
"total": 0 # 总token统计
|
| 54 |
}
|
| 55 |
|
| 56 |
+
# 计算点信息
|
| 57 |
+
compute_points = {
|
| 58 |
+
"left": 0, # 剩余计算点
|
| 59 |
+
"total": 0, # 总计算点
|
| 60 |
+
"used": 0, # 已使用计算点
|
| 61 |
+
"percentage": 0, # 使用百分比
|
| 62 |
+
"last_update": None # 最后更新时间
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
# 计算点使用日志
|
| 66 |
+
compute_points_log = {
|
| 67 |
+
"columns": {}, # 列名
|
| 68 |
+
"log": [] # 日志数据
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
|
| 72 |
# HTML模板
|
| 73 |
INDEX_HTML = """
|
|
|
|
| 140 |
.status-value.warning {
|
| 141 |
color: #ffc107;
|
| 142 |
}
|
| 143 |
+
.status-value.danger {
|
| 144 |
+
color: #dc3545;
|
| 145 |
+
}
|
| 146 |
.footer {
|
| 147 |
margin-top: 2rem;
|
| 148 |
text-align: center;
|
|
|
|
| 203 |
font-family: monospace;
|
| 204 |
color: #28a745;
|
| 205 |
}
|
| 206 |
+
.compute-points {
|
| 207 |
+
font-family: monospace;
|
| 208 |
+
color: #6f42c1;
|
| 209 |
+
font-weight: bold;
|
| 210 |
+
}
|
| 211 |
+
.progress-container {
|
| 212 |
+
width: 100%;
|
| 213 |
+
height: 10px;
|
| 214 |
+
background-color: #e9ecef;
|
| 215 |
+
border-radius: 5px;
|
| 216 |
+
margin-top: 0.5rem;
|
| 217 |
+
overflow: hidden;
|
| 218 |
+
}
|
| 219 |
+
.progress-bar {
|
| 220 |
+
height: 100%;
|
| 221 |
+
border-radius: 5px;
|
| 222 |
+
background-color: #28a745;
|
| 223 |
+
}
|
| 224 |
+
.progress-bar.warning {
|
| 225 |
+
background-color: #ffc107;
|
| 226 |
+
}
|
| 227 |
+
.progress-bar.danger {
|
| 228 |
+
background-color: #dc3545;
|
| 229 |
+
}
|
| 230 |
@media (max-width: 768px) {
|
| 231 |
.container {
|
| 232 |
padding: 1rem;
|
|
|
|
| 268 |
</div>
|
| 269 |
</div>
|
| 270 |
|
| 271 |
+
<h2>💰 计算点信息</h2>
|
| 272 |
+
<div class="status-card">
|
| 273 |
+
<div class="status-item">
|
| 274 |
+
<span class="status-label">总计算点</span>
|
| 275 |
+
<span class="status-value compute-points">{{ compute_points.total|int }}</span>
|
| 276 |
+
</div>
|
| 277 |
+
<div class="status-item">
|
| 278 |
+
<span class="status-label">已使用</span>
|
| 279 |
+
<span class="status-value compute-points">{{ compute_points.used|int }}</span>
|
| 280 |
+
</div>
|
| 281 |
+
<div class="status-item">
|
| 282 |
+
<span class="status-label">剩余</span>
|
| 283 |
+
<span class="status-value compute-points">{{ compute_points.left|int }}</span>
|
| 284 |
+
</div>
|
| 285 |
+
<div class="status-item">
|
| 286 |
+
<span class="status-label">使用比例</span>
|
| 287 |
+
<div style="width: 100%; text-align: right;">
|
| 288 |
+
<span class="status-value compute-points {% if compute_points.percentage > 80 %}danger{% elif compute_points.percentage > 50 %}warning{% endif %}">
|
| 289 |
+
{{ compute_points.percentage }}%
|
| 290 |
+
</span>
|
| 291 |
+
<div class="progress-container">
|
| 292 |
+
<div class="progress-bar {% if compute_points.percentage > 80 %}danger{% elif compute_points.percentage > 50 %}warning{% endif %}" style="width: {{ compute_points.percentage }}%"></div>
|
| 293 |
+
</div>
|
| 294 |
+
</div>
|
| 295 |
+
</div>
|
| 296 |
+
{% if compute_points.last_update %}
|
| 297 |
+
<div class="status-item">
|
| 298 |
+
<span class="status-label">最后更新时间</span>
|
| 299 |
+
<span class="status-value">{{ compute_points.last_update.strftime('%Y-%m-%d %H:%M:%S') }}</span>
|
| 300 |
+
</div>
|
| 301 |
+
{% endif %}
|
| 302 |
+
</div>
|
| 303 |
+
|
| 304 |
+
<h2>📊 计算点使用日志</h2>
|
| 305 |
+
<div class="status-card">
|
| 306 |
+
<table class="usage-table">
|
| 307 |
+
<thead>
|
| 308 |
+
<tr>
|
| 309 |
+
{% for key, value in compute_points_log.columns.items() %}
|
| 310 |
+
<th>{{ value }}</th>
|
| 311 |
+
{% endfor %}
|
| 312 |
+
</tr>
|
| 313 |
+
</thead>
|
| 314 |
+
<tbody>
|
| 315 |
+
{% for entry in compute_points_log.log %}
|
| 316 |
+
<tr>
|
| 317 |
+
{% for key, value in compute_points_log.columns.items() %}
|
| 318 |
+
<td class="compute-points">{{ entry.get(key, 0) }}</td>
|
| 319 |
+
{% endfor %}
|
| 320 |
+
</tr>
|
| 321 |
+
{% endfor %}
|
| 322 |
+
</tbody>
|
| 323 |
+
</table>
|
| 324 |
+
</div>
|
| 325 |
+
|
| 326 |
<h2>🔍 模型使用统计</h2>
|
| 327 |
<div class="status-card">
|
| 328 |
<div class="status-item">
|
|
|
|
| 1082 |
|
| 1083 |
@app.route("/", methods=["GET"])
|
| 1084 |
def index():
|
| 1085 |
+
# 在每次访问首页时更新计算点信息
|
| 1086 |
+
get_compute_points()
|
| 1087 |
+
|
| 1088 |
uptime = datetime.now() - START_TIME
|
| 1089 |
days = uptime.days
|
| 1090 |
hours, remainder = divmod(uptime.seconds, 3600)
|
|
|
|
| 1105 |
models=sorted(list(MODELS)),
|
| 1106 |
year=datetime.now().year,
|
| 1107 |
model_stats=model_usage_stats,
|
| 1108 |
+
total_tokens=total_tokens,
|
| 1109 |
+
compute_points=compute_points,
|
| 1110 |
+
compute_points_log=compute_points_log
|
| 1111 |
)
|
| 1112 |
|
| 1113 |
|
|
|
|
| 1146 |
total_tokens["total"] += (prompt_tokens + completion_tokens)
|
| 1147 |
|
| 1148 |
|
| 1149 |
+
# 获取计算点信息
|
| 1150 |
+
def get_compute_points():
|
| 1151 |
+
global compute_points, USER_DATA
|
| 1152 |
+
|
| 1153 |
+
if USER_NUM == 0:
|
| 1154 |
+
return
|
| 1155 |
+
|
| 1156 |
+
try:
|
| 1157 |
+
# 使用第一个用户的会话和凭据
|
| 1158 |
+
session, cookies, session_token, _, _ = USER_DATA[0]
|
| 1159 |
+
|
| 1160 |
+
# 检查token是否有效
|
| 1161 |
+
if is_token_expired(session_token):
|
| 1162 |
+
session_token = refresh_token(session, cookies)
|
| 1163 |
+
if not session_token:
|
| 1164 |
+
print("刷新token失败,无法获取计算点信息")
|
| 1165 |
+
return
|
| 1166 |
+
USER_DATA[0] = (session, cookies, session_token, USER_DATA[0][3], USER_DATA[0][4])
|
| 1167 |
+
|
| 1168 |
+
headers = {
|
| 1169 |
+
"accept": "application/json, text/plain, */*",
|
| 1170 |
+
"accept-language": "zh-CN,zh;q=0.9",
|
| 1171 |
+
"baggage": f"sentry-environment=production,sentry-release=93da8385541a6ce339b1f41b0c94428c70657e22,sentry-public_key=3476ea6df1585dd10e92cdae3a66ff49,sentry-trace_id={TRACE_ID}",
|
| 1172 |
+
"reai-ui": "1",
|
| 1173 |
+
"sec-ch-ua": "\"Chromium\";v=\"116\", \"Not)A;Brand\";v=\"24\", \"Google Chrome\";v=\"116\"",
|
| 1174 |
+
"sec-ch-ua-mobile": "?0",
|
| 1175 |
+
"sec-ch-ua-platform": "\"Windows\"",
|
| 1176 |
+
"sec-fetch-dest": "empty",
|
| 1177 |
+
"sec-fetch-mode": "cors",
|
| 1178 |
+
"sec-fetch-site": "same-origin",
|
| 1179 |
+
"sentry-trace": SENTRY_TRACE,
|
| 1180 |
+
"session-token": session_token,
|
| 1181 |
+
"x-abacus-org-host": "apps",
|
| 1182 |
+
"cookie": cookies
|
| 1183 |
+
}
|
| 1184 |
+
|
| 1185 |
+
response = session.get(
|
| 1186 |
+
COMPUTE_POINTS_URL,
|
| 1187 |
+
headers=headers
|
| 1188 |
+
)
|
| 1189 |
+
|
| 1190 |
+
if response.status_code == 200:
|
| 1191 |
+
result = response.json()
|
| 1192 |
+
if result.get("success") and "result" in result:
|
| 1193 |
+
data = result["result"]
|
| 1194 |
+
compute_points["left"] = data.get("computePointsLeft", 0)
|
| 1195 |
+
compute_points["total"] = data.get("totalComputePoints", 0)
|
| 1196 |
+
compute_points["used"] = compute_points["total"] - compute_points["left"]
|
| 1197 |
+
compute_points["percentage"] = round((compute_points["used"] / compute_points["total"]) * 100, 2) if compute_points["total"] > 0 else 0
|
| 1198 |
+
compute_points["last_update"] = datetime.now()
|
| 1199 |
+
print(f"计算点信息更新成功: 剩余 {compute_points['left']}, 总计 {compute_points['total']}")
|
| 1200 |
+
|
| 1201 |
+
# 获取计算点使用日志
|
| 1202 |
+
get_compute_points_log(session, cookies, session_token)
|
| 1203 |
+
else:
|
| 1204 |
+
print(f"获取计算点信息失败: {result.get('error', '未知错误')}")
|
| 1205 |
+
else:
|
| 1206 |
+
print(f"获取计算点信息失败,状态码: {response.status_code}")
|
| 1207 |
+
except Exception as e:
|
| 1208 |
+
print(f"获取计算点信息异常: {e}")
|
| 1209 |
+
|
| 1210 |
+
# 获取计算点使用日志
|
| 1211 |
+
def get_compute_points_log(session, cookies, session_token):
|
| 1212 |
+
global compute_points_log
|
| 1213 |
+
|
| 1214 |
+
try:
|
| 1215 |
+
headers = {
|
| 1216 |
+
"accept": "application/json, text/plain, */*",
|
| 1217 |
+
"accept-language": "zh-CN,zh;q=0.9",
|
| 1218 |
+
"content-type": "application/json",
|
| 1219 |
+
"reai-ui": "1",
|
| 1220 |
+
"sec-ch-ua": "\"Chromium\";v=\"116\", \"Not)A;Brand\";v=\"24\", \"Google Chrome\";v=\"116\"",
|
| 1221 |
+
"sec-ch-ua-mobile": "?0",
|
| 1222 |
+
"sec-ch-ua-platform": "\"Windows\"",
|
| 1223 |
+
"sec-fetch-dest": "empty",
|
| 1224 |
+
"sec-fetch-mode": "cors",
|
| 1225 |
+
"sec-fetch-site": "same-site",
|
| 1226 |
+
"session-token": session_token,
|
| 1227 |
+
"x-abacus-org-host": "apps",
|
| 1228 |
+
"cookie": cookies
|
| 1229 |
+
}
|
| 1230 |
+
|
| 1231 |
+
response = session.post(
|
| 1232 |
+
COMPUTE_POINTS_LOG_URL,
|
| 1233 |
+
headers=headers,
|
| 1234 |
+
json={"byLlm": True}
|
| 1235 |
+
)
|
| 1236 |
+
|
| 1237 |
+
if response.status_code == 200:
|
| 1238 |
+
result = response.json()
|
| 1239 |
+
if result.get("success") and "result" in result:
|
| 1240 |
+
data = result["result"]
|
| 1241 |
+
compute_points_log["columns"] = data.get("columns", {})
|
| 1242 |
+
compute_points_log["log"] = data.get("log", [])
|
| 1243 |
+
print(f"计算点使用日志更新成功,获取到 {len(compute_points_log['log'])} 条记录")
|
| 1244 |
+
else:
|
| 1245 |
+
print(f"获取计算点使用日志失败: {result.get('error', '未知错误')}")
|
| 1246 |
+
else:
|
| 1247 |
+
print(f"获取计算点使用日志失败,状态码: {response.status_code}")
|
| 1248 |
+
except Exception as e:
|
| 1249 |
+
print(f"获取计算点��用日志异常: {e}")
|
| 1250 |
+
|
| 1251 |
+
|
| 1252 |
if __name__ == "__main__":
|
| 1253 |
# 启动保活线程
|
| 1254 |
threading.Thread(target=keep_alive, daemon=True).start()
|
| 1255 |
+
|
| 1256 |
+
# 获取初始计算点信息
|
| 1257 |
+
get_compute_points()
|
| 1258 |
+
|
| 1259 |
port = int(os.environ.get("PORT", 9876))
|
| 1260 |
app.run(port=port, host="0.0.0.0")
|