fix video label

This commit is contained in:
zaiun xu
2026-04-10 10:30:01 +08:00
parent e1b514836e
commit 09736f9e15
20 changed files with 518 additions and 268 deletions

View File

@@ -8,6 +8,7 @@ weight_prediction.json、临时 pred.json 等),由 fish_api 在子进程结
from __future__ import annotations
import json
import math
import shutil
import sqlite3
from datetime import datetime, timezone
@@ -222,6 +223,86 @@ def get_latest_health(settings: Settings) -> HealthSnapshot:
conn.close()
def _coerce_finite_number(v: Any) -> Optional[float]:
if v is None:
return None
if isinstance(v, bool):
return None
if isinstance(v, (int, float)):
x = float(v)
return x if math.isfinite(x) else None
if isinstance(v, str):
s = v.strip()
if not s:
return None
try:
x = float(s)
return x if math.isfinite(x) else None
except ValueError:
return None
return None
def _coerce_track_id(v: Any) -> Optional[int]:
# bool is a subclass of int in Python
if isinstance(v, bool):
return None
if isinstance(v, int):
return v if v >= 0 else None
if isinstance(v, str):
try:
i = int(v.strip(), 10)
return i if i >= 0 else None
except ValueError:
return None
return None
def measure_result_deliverable(result: Any, error: Optional[str]) -> bool:
"""至少一条记录含有效 track id 与有限数值的 weight(g)、length(mm)。"""
if error:
return False
if not isinstance(result, list) or not result:
return False
for it in result:
if not isinstance(it, dict):
continue
tid = _coerce_track_id(it.get("id"))
w = _coerce_finite_number(it.get("weight"))
ln = _coerce_finite_number(it.get("length"))
if tid is not None and w is not None and ln is not None:
return True
return False
def measure_snapshot_deliverable(snap: MeasureSnapshot) -> bool:
return measure_result_deliverable(snap.result, snap.error)
def health_snapshot_deliverable(snap: HealthSnapshot) -> bool:
if snap.error:
return False
b = (snap.behavior_result or "").strip()
h = (snap.health_result or "").strip()
r = (snap.raw_class_en or "").strip()
return bool(b or h or r)
def _health_row_deliverable(
behavior_result: str,
health_result: str,
raw_class_en: str,
error: Optional[str],
) -> bool:
snap = HealthSnapshot(
behavior_result=behavior_result or "",
health_result=health_result or "",
raw_class_en=raw_class_en or "",
error=error,
)
return health_snapshot_deliverable(snap)
def _last_delivered_id(
conn: sqlite3.Connection, kind: str, snapshots_table: str
) -> int:
@@ -243,48 +324,55 @@ def _last_delivered_id(
def pop_next_measure(
settings: Settings,
) -> Tuple[MeasureSnapshot, bool, Optional[int]]:
"""取队首未投递的 measure 快照并推进游标;无未投递时 has_new=False"""
"""取队首未投递且可交付的 measure 快照并推进游标;跳过不可交付行仅推进游标"""
init_db(settings)
conn = _connect(settings.sqlite_path)
try:
conn.execute("BEGIN IMMEDIATE")
last_id = _last_delivered_id(conn, "measure", "measure_snapshots")
next_row = conn.execute(
"""
SELECT id, created_at, result_json, video_left, video_right,
error, raw_prediction_path
FROM measure_snapshots
WHERE id > ?
ORDER BY id ASC
LIMIT 1
""",
(last_id,),
).fetchone()
while True:
next_row = conn.execute(
"""
SELECT id, created_at, result_json, video_left, video_right,
error, raw_prediction_path
FROM measure_snapshots
WHERE id > ?
ORDER BY id ASC
LIMIT 1
""",
(last_id,),
).fetchone()
if next_row is None:
conn.commit()
return MeasureSnapshot(result=[], video_left="", video_right=""), False, None
nid = int(next_row["id"])
err: Optional[str] = next_row["error"]
data: Any = json.loads(next_row["result_json"])
if not isinstance(data, list):
data = []
conn.execute(
"UPDATE delivery_cursor SET last_delivered_id = ? WHERE kind = ?",
(nid, "measure"),
)
if not measure_result_deliverable(data, err):
last_id = nid
continue
if next_row is None:
conn.commit()
return MeasureSnapshot(result=[], video_left="", video_right=""), False, None
nid = int(next_row["id"])
conn.execute(
"UPDATE delivery_cursor SET last_delivered_id = ? WHERE kind = ?",
(nid, "measure"),
)
conn.commit()
data: Any = json.loads(next_row["result_json"])
if not isinstance(data, list):
data = []
snap = MeasureSnapshot(
result=data,
video_left=next_row["video_left"] or "",
video_right=next_row["video_right"] or "",
updated_at=_parse_dt(next_row["created_at"]),
error=next_row["error"],
raw_prediction_path=next_row["raw_prediction_path"],
)
return snap, True, nid
snap = MeasureSnapshot(
result=data,
video_left=next_row["video_left"] or "",
video_right=next_row["video_right"] or "",
updated_at=_parse_dt(next_row["created_at"]),
error=err,
raw_prediction_path=next_row["raw_prediction_path"],
)
return snap, True, nid
except Exception:
conn.rollback()
raise
@@ -293,44 +381,54 @@ def pop_next_measure(
def pop_next_health(settings: Settings) -> Tuple[HealthSnapshot, bool, Optional[int]]:
"""取队首未投递的 health 快照并推进游标;无未投递时 has_new=False"""
"""取队首未投递且可交付的 health 快照并推进游标;跳过不可交付行仅推进游标"""
init_db(settings)
conn = _connect(settings.sqlite_path)
try:
conn.execute("BEGIN IMMEDIATE")
last_id = _last_delivered_id(conn, "health", "health_snapshots")
next_row = conn.execute(
"""
SELECT id, created_at, behavior_result, health_result,
raw_class_en, error
FROM health_snapshots
WHERE id > ?
ORDER BY id ASC
LIMIT 1
""",
(last_id,),
).fetchone()
while True:
next_row = conn.execute(
"""
SELECT id, created_at, behavior_result, health_result,
raw_class_en, error
FROM health_snapshots
WHERE id > ?
ORDER BY id ASC
LIMIT 1
""",
(last_id,),
).fetchone()
if next_row is None:
conn.commit()
return HealthSnapshot(behavior_result="", health_result=""), False, None
nid = int(next_row["id"])
beh = next_row["behavior_result"] or ""
hlth = next_row["health_result"] or ""
raw_en = next_row["raw_class_en"] or ""
err: Optional[str] = next_row["error"]
conn.execute(
"UPDATE delivery_cursor SET last_delivered_id = ? WHERE kind = ?",
(nid, "health"),
)
if not _health_row_deliverable(beh, hlth, raw_en, err):
last_id = nid
continue
if next_row is None:
conn.commit()
return HealthSnapshot(behavior_result="", health_result=""), False, None
nid = int(next_row["id"])
conn.execute(
"UPDATE delivery_cursor SET last_delivered_id = ? WHERE kind = ?",
(nid, "health"),
)
conn.commit()
snap = HealthSnapshot(
behavior_result=next_row["behavior_result"] or "",
health_result=next_row["health_result"] or "",
updated_at=_parse_dt(next_row["created_at"]),
error=next_row["error"],
raw_class_en=next_row["raw_class_en"] or "",
)
return snap, True, nid
snap = HealthSnapshot(
behavior_result=beh,
health_result=hlth,
updated_at=_parse_dt(next_row["created_at"]),
error=err,
raw_class_en=raw_en,
)
return snap, True, nid
except Exception:
conn.rollback()
raise