v1.3.0 热度排行+搜索+详情+水印下载:速度项按钮改+对比(去购物车图标);排行默认按热度显示前10(后台可配)+顶部模型搜索框(点击显示热门5个:配置简介+模型,支持手动搜索,速度项热度/个数/简介后台可改);每行详情链接到具体详情页;图表带水印(默认首页网址,后台可配)+生成图片下载按钮(首页/对比页)
This commit is contained in:
+174
-4
@@ -61,6 +61,23 @@ CREATE TABLE IF NOT EXISTS capabilities(
|
||||
updated_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS speed_items(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
provider TEXT DEFAULT '',
|
||||
model TEXT DEFAULT '',
|
||||
heat INTEGER DEFAULT 0,
|
||||
intro TEXT DEFAULT '',
|
||||
count INTEGER DEFAULT 0,
|
||||
remark TEXT DEFAULT '',
|
||||
updated_at TEXT DEFAULT (datetime('now','localtime'))
|
||||
);
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_si_model ON speed_items(provider, model);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS settings(
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT DEFAULT ''
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sub_model ON submissions(model, provider);
|
||||
CREATE INDEX IF NOT EXISTS idx_sub_account ON submissions(account_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sub_created ON submissions(created_at);
|
||||
@@ -313,14 +330,16 @@ def get_stats():
|
||||
conn.close()
|
||||
|
||||
|
||||
def leaderboard(sort="avg_decode_speed", order="desc", limit=200):
|
||||
"""按 (provider, model) 聚合所有提交 → 模型速度排行(含硬件)"""
|
||||
def leaderboard(sort="heat", order="desc", limit=500):
|
||||
"""按 (provider, model) 聚合所有提交 → 模型速度排行(含热度/配置简介/硬件)
|
||||
默认按热度(heat)倒序;sort 支持 heat/avg_decode_speed 等"""
|
||||
sort_whitelist = {
|
||||
"heat": "heat",
|
||||
"avg_decode_speed": "avg_decode_speed", "avg_prefill_speed": "avg_prefill_speed",
|
||||
"avg_ttft_ms": "avg_ttft_ms", "best_decode": "best_decode",
|
||||
"cnt": "cnt", "last_tested": "last_tested", "avg_stream_decode": "avg_stream_decode",
|
||||
}
|
||||
srt = sort_whitelist.get(sort, "avg_decode_speed")
|
||||
srt = sort_whitelist.get(sort, "heat")
|
||||
od = "DESC" if order == "asc" and srt not in ("avg_ttft_ms", "avg_total_ms") else (
|
||||
"ASC" if order == "asc" else "DESC")
|
||||
with _lock:
|
||||
@@ -338,10 +357,15 @@ def leaderboard(sort="avg_decode_speed", order="desc", limit=200):
|
||||
"AVG(s.avg_total_ms) AS avg_total_ms, "
|
||||
"MAX(s.avg_decode_speed) AS best_decode, "
|
||||
"MAX(s.created_at) AS last_tested, "
|
||||
"COALESCE(MAX(si.heat), 0) AS heat, "
|
||||
"MAX(si.intro) AS intro, "
|
||||
"COALESCE(MAX(si.count), 0) AS count_override, "
|
||||
"(SELECT s2.hardware FROM submissions s2 "
|
||||
" WHERE s2.provider=s.provider AND s2.model=s.model AND s2.hardware<>'' "
|
||||
" ORDER BY s2.id DESC LIMIT 1) AS hardware "
|
||||
"FROM submissions s WHERE s.model<>'' "
|
||||
"FROM submissions s "
|
||||
"LEFT JOIN speed_items si ON si.provider=s.provider AND si.model=s.model "
|
||||
"WHERE s.model<>'' "
|
||||
"GROUP BY s.provider, s.model ORDER BY %s %s LIMIT ?" % (srt, od),
|
||||
(limit,)).fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
@@ -502,3 +526,149 @@ def delete_capability(cid: int):
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# ───────────────────────── 速度项(热度/配置简介/个数,后台可改) ─────────────────────────
|
||||
|
||||
def touch_speed_item(provider, model):
|
||||
"""提交到达时确保速度项存在;不存在则以当前提交数为默认热度"""
|
||||
provider = provider or ""
|
||||
model = (model or "").strip()
|
||||
if not model:
|
||||
return None
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
r = conn.execute("SELECT id FROM speed_items WHERE provider=? AND model=?",
|
||||
(provider, model)).fetchone()
|
||||
if r:
|
||||
return r["id"]
|
||||
cnt = conn.execute("SELECT COUNT(*) c FROM submissions WHERE provider=? AND model=?",
|
||||
(provider, model)).fetchone()["c"]
|
||||
cur = conn.execute(
|
||||
"INSERT INTO speed_items(provider,model,heat,intro,count) VALUES(?,?,?,?,?)",
|
||||
(provider, model, cnt, "", cnt))
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def list_speed_items():
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT si.*, "
|
||||
"(SELECT COUNT(*) FROM submissions s WHERE s.provider=si.provider AND s.model=si.model) AS real_cnt "
|
||||
"FROM speed_items si ORDER BY si.heat DESC, si.model").fetchall()
|
||||
return [dict(r) for r in rows]
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def add_speed_item(provider, model, heat=0, intro="", count=0, remark=""):
|
||||
provider = provider or ""
|
||||
model = (model or "").strip()
|
||||
if not model:
|
||||
raise ValueError("模型名称不能为空")
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
r = conn.execute("SELECT id FROM speed_items WHERE provider=? AND model=?",
|
||||
(provider, model)).fetchone()
|
||||
if r:
|
||||
raise ValueError("该速度项已存在")
|
||||
cur = conn.execute(
|
||||
"INSERT INTO speed_items(provider,model,heat,intro,count,remark) VALUES(?,?,?,?,?,?)",
|
||||
(provider, model, int(heat or 0), intro or "", int(count or 0), remark or ""))
|
||||
conn.commit()
|
||||
return cur.lastrowid
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def update_speed_item(sid: int, data: dict):
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
conn.execute(
|
||||
"UPDATE speed_items SET provider=?,model=?,heat=?,intro=?,count=?,remark=?,"
|
||||
"updated_at=datetime('now','localtime') WHERE id=?",
|
||||
((data.get("provider") or "").strip(),
|
||||
(data.get("model") or "").strip(),
|
||||
int(data.get("heat") or 0),
|
||||
(data.get("intro") or "").strip(),
|
||||
int(data.get("count") or 0),
|
||||
(data.get("remark") or "").strip(),
|
||||
sid))
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def delete_speed_item(sid: int):
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
conn.execute("DELETE FROM speed_items WHERE id=?", (sid,))
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def sync_speed_items():
|
||||
"""从提交自动同步速度项:为所有有提交的模型建速度项(默认热度=提交数)"""
|
||||
added = 0
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
rows = conn.execute(
|
||||
"SELECT provider, model, COUNT(*) c FROM submissions WHERE model<>'' "
|
||||
"GROUP BY provider, model").fetchall()
|
||||
for r in rows:
|
||||
r0 = conn.execute("SELECT id FROM speed_items WHERE provider=? AND model=?",
|
||||
(r["provider"], r["model"])).fetchone()
|
||||
if r0:
|
||||
continue
|
||||
conn.execute(
|
||||
"INSERT INTO speed_items(provider,model,heat,intro,count) VALUES(?,?,?,?,?)",
|
||||
(r["provider"], r["model"], r["c"], "", r["c"]))
|
||||
added += 1
|
||||
conn.commit()
|
||||
return added
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
# ───────────────────────── 设置(水印/默认条数等) ─────────────────────────
|
||||
|
||||
def get_setting(key, default=""):
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
r = conn.execute("SELECT value FROM settings WHERE key=?", (key,)).fetchone()
|
||||
return r["value"] if r else default
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def set_setting(key, value):
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
conn.execute("INSERT OR REPLACE INTO settings(key,value) VALUES(?,?)",
|
||||
(key, str(value or "")))
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def get_all_settings():
|
||||
with _lock:
|
||||
conn = _connect()
|
||||
try:
|
||||
rows = conn.execute("SELECT key,value FROM settings").fetchall()
|
||||
return {r["key"]: r["value"] for r in rows}
|
||||
finally:
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user