fix: recover_usages支持ioinfo两种存储格式
ioinfo字段有两种存储方式: 1. JSON内容(流式模型如qwen3-max) - 直接解析 2. 文件路径(异步模型如viduq3-pro) - 读取文件再解析 修改后两种情况都能正确提取usage
This commit is contained in:
parent
0d2b39ddd7
commit
fe4e8271bf
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
ns = params_kw.copy()
|
ns = params_kw.copy()
|
||||||
limit = int(ns.get('limit') or 100)
|
limit = int(ns.get('limit') or 200)
|
||||||
single_id = ns.get('id') or None
|
single_id = ns.get('id') or None
|
||||||
|
|
||||||
from ahserver.filestorage import FileStorage
|
from ahserver.filestorage import FileStorage
|
||||||
@ -9,23 +9,21 @@ import os
|
|||||||
db = DBPools()
|
db = DBPools()
|
||||||
dbname = get_module_dbname('llmage')
|
dbname = get_module_dbname('llmage')
|
||||||
|
|
||||||
details = []
|
|
||||||
recovered = 0
|
recovered = 0
|
||||||
failed = 0
|
failed = 0
|
||||||
skipped = 0
|
skipped = 0
|
||||||
|
errors = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
async with db.sqlorContext(dbname) as sor:
|
async with db.sqlorContext(dbname) as sor:
|
||||||
if single_id:
|
if single_id:
|
||||||
sql = """select a.id, a.llmid, a.ioinfo, a.status, a.use_date,
|
sql = """select a.id, a.llmid, a.ioinfo, a.status, b.model
|
||||||
b.model
|
|
||||||
from llmusage a
|
from llmusage a
|
||||||
left join llm b on a.llmid = b.id
|
left join llm b on a.llmid = b.id
|
||||||
where a.id = ${id}$"""
|
where a.id = ${id}$"""
|
||||||
params = {'id': single_id}
|
params = {'id': single_id}
|
||||||
else:
|
else:
|
||||||
sql = """select a.id, a.llmid, a.ioinfo, a.status, a.use_date,
|
sql = """select a.id, a.llmid, a.ioinfo, a.status, b.model
|
||||||
b.model
|
|
||||||
from llmusage a
|
from llmusage a
|
||||||
left join llm b on a.llmid = b.id
|
left join llm b on a.llmid = b.id
|
||||||
where a.usages is null
|
where a.usages is null
|
||||||
@ -63,20 +61,28 @@ try:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
try:
|
try:
|
||||||
real_path = fs.realPath(ioinfo)
|
# ioinfo 可能是 JSON 内容,也可能是文件路径
|
||||||
if not os.path.isfile(real_path):
|
io_data = None
|
||||||
failed += 1
|
if ioinfo.startswith('{') or ioinfo.startswith('"'):
|
||||||
continue
|
# 直接是 JSON 内容
|
||||||
|
io_data = json.loads(ioinfo)
|
||||||
with open(real_path, 'r', encoding='utf-8') as f:
|
else:
|
||||||
io_data = json.load(f)
|
# 文件路径
|
||||||
|
real_path = fs.realPath(ioinfo)
|
||||||
|
if not os.path.isfile(real_path):
|
||||||
|
errors.append(f'{rid}: 文件不存在')
|
||||||
|
failed += 1
|
||||||
|
continue
|
||||||
|
with open(real_path, 'r', encoding='utf-8') as f:
|
||||||
|
io_data = json.load(f)
|
||||||
|
|
||||||
outputs = io_data.get('output', [])
|
outputs = io_data.get('output', [])
|
||||||
if not outputs:
|
if not outputs:
|
||||||
|
errors.append(f'{rid}: output为空')
|
||||||
failed += 1
|
failed += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 从最后一条output中获取usage
|
# 从最后一条output开始倒序找usage
|
||||||
usage = None
|
usage = None
|
||||||
for out in reversed(outputs):
|
for out in reversed(outputs):
|
||||||
if isinstance(out, dict) and out.get('usage'):
|
if isinstance(out, dict) and out.get('usage'):
|
||||||
@ -84,6 +90,7 @@ try:
|
|||||||
break
|
break
|
||||||
|
|
||||||
if not usage:
|
if not usage:
|
||||||
|
errors.append(f'{rid}: output中未找到usage')
|
||||||
failed += 1
|
failed += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -96,6 +103,7 @@ try:
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug(f'recover_usages error for {rid}: {e}')
|
debug(f'recover_usages error for {rid}: {e}')
|
||||||
|
errors.append(f'{rid}: {e}')
|
||||||
failed += 1
|
failed += 1
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -113,14 +121,16 @@ except Exception as e:
|
|||||||
|
|
||||||
total = recovered + failed + skipped
|
total = recovered + failed + skipped
|
||||||
msg = f"处理 {total} 条: 恢复成功 {recovered}, 失败 {failed}, 跳过 {skipped}"
|
msg = f"处理 {total} 条: 恢复成功 {recovered}, 失败 {failed}, 跳过 {skipped}"
|
||||||
|
if errors:
|
||||||
|
msg += f"\n失败详情(前5条): {'; '.join(errors[:5])}"
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"widgettype": "Message",
|
"widgettype": "Message",
|
||||||
"options": {
|
"options": {
|
||||||
"title": "恢复Usages完成",
|
"title": "恢复Usages完成",
|
||||||
"cwidth": 24,
|
"cwidth": 30,
|
||||||
"cheight": 5,
|
"cheight": 6,
|
||||||
"timeout": 6,
|
"timeout": 8,
|
||||||
"message": msg
|
"message": msg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user