117 lines
4.3 KiB
Python
117 lines
4.3 KiB
Python
"""Read/export model diagnostics from the task's existing trace database."""
|
|
|
|
from datetime import UTC, datetime
|
|
import json
|
|
import time
|
|
|
|
from apps.admin_console.database.connection import db_session
|
|
|
|
|
|
def request_diagnostics(
|
|
session_id: str, *, db_path=None, limit: int | None = None, offset: int = 0
|
|
) -> dict:
|
|
with db_session(db_path) as conn:
|
|
session = conn.execute(
|
|
"SELECT status FROM sessions WHERE session_id = ?", (session_id,)
|
|
).fetchone()
|
|
sql = (
|
|
"SELECT payload FROM traces WHERE session_id = ? AND type = 'llm_diagnostic' "
|
|
"ORDER BY timestamp DESC"
|
|
)
|
|
params: tuple = (session_id,)
|
|
total = conn.execute(
|
|
"SELECT count(*) FROM traces WHERE session_id=? AND type='llm_diagnostic'",
|
|
params,
|
|
).fetchone()[0]
|
|
if limit is not None:
|
|
sql += " LIMIT ? OFFSET ?"
|
|
params += (limit, offset)
|
|
rows = conn.execute(sql, params).fetchall()
|
|
review_rows = conn.execute(
|
|
"SELECT payload FROM traces WHERE session_id = ? "
|
|
"AND type = 'final_review_diagnostic' ORDER BY timestamp DESC"
|
|
+ (" LIMIT ?" if limit is not None else ""),
|
|
(session_id, limit) if limit is not None else (session_id,),
|
|
).fetchall()
|
|
requests = []
|
|
seen = set()
|
|
running = bool(session and session["status"] in {"running", "resuming"})
|
|
for row in rows:
|
|
try:
|
|
value = json.loads(row["payload"])
|
|
except (ValueError, TypeError):
|
|
continue
|
|
if not isinstance(value, dict):
|
|
continue
|
|
request_id = value.get("request_id")
|
|
value["active"] = (
|
|
running
|
|
and offset == 0
|
|
and request_id not in seen
|
|
and value.get("phase")
|
|
in {
|
|
"waiting_response",
|
|
"waiting_output",
|
|
"receiving_output",
|
|
"generating_tool_arguments",
|
|
"retry_wait",
|
|
}
|
|
)
|
|
seen.add(request_id)
|
|
value["timestamps_utc"] = {
|
|
field: datetime.fromtimestamp(value[field], UTC).isoformat()
|
|
for field in (
|
|
"started_at",
|
|
"request_sent_at",
|
|
"headers_at",
|
|
"first_output_at",
|
|
"last_output_at",
|
|
"first_tool_arguments_at",
|
|
"last_tool_arguments_at",
|
|
"cancel_observed_at",
|
|
"ended_at",
|
|
"retry_at",
|
|
)
|
|
if isinstance(value.get(field), (int, float))
|
|
}
|
|
requests.append(value)
|
|
final_reviews = []
|
|
for row in review_rows:
|
|
try:
|
|
value = json.loads(row["payload"])
|
|
except (ValueError, TypeError):
|
|
continue
|
|
if not isinstance(value, dict):
|
|
continue
|
|
value["active"] = (
|
|
running and offset == 0 and not final_reviews and value.get("status") == "running"
|
|
)
|
|
if value["active"] and isinstance(value.get("started_at"), (int, float)):
|
|
value["elapsed_seconds"] = round(max(0.0, time.time() - value["started_at"]), 3)
|
|
value["remaining_seconds"] = round(
|
|
max(0.0, value.get("total_seconds", 0.0) - value["elapsed_seconds"]), 3
|
|
)
|
|
value["budget_observed_at"] = time.time()
|
|
value["timestamps_utc"] = {
|
|
field: datetime.fromtimestamp(value[field], UTC).isoformat()
|
|
for field in ("started_at", "deadline_at", "ended_at")
|
|
if isinstance(value.get(field), (int, float))
|
|
}
|
|
final_reviews.append(value)
|
|
return {
|
|
"schema_version": 1,
|
|
"session_id": session_id,
|
|
"session_status": session["status"] if session else "unknown",
|
|
"collected_at": time.time(),
|
|
"requests": requests,
|
|
"final_reviews": final_reviews,
|
|
"total": total,
|
|
"offset": offset,
|
|
"next_offset": offset + limit if limit is not None and offset + limit < total else None,
|
|
"note": "时间戳为 Unix 秒;timestamps_utc 为 UTC。HTTP 200 不代表完整输出。usage=null 表示服务未报告用量。历史任务没有记录的字段无法补推。",
|
|
}
|
|
|
|
|
|
def diagnostics_json(session_id: str) -> str:
|
|
return json.dumps(request_diagnostics(session_id), ensure_ascii=False, indent=2)
|