feat(fish_api): SQLite 快照投递、日志与 watch 空闲告警
- 新增 SQLite:measure/health 快照、delivery_cursor 单消费者 pop;clear/start_fresh 可清空库 - biomass GET 仅返回约定 data 字段,X-Fish-Biomass-New 表示是否有新快照;poller 读响应头 - loguru 桥接 uvicorn,子进程 stdout 流式输出;format_json_pretty 与算法摘要日志 - measure/action watch 无新任务时限流 WARNING;watch_idle 共用逻辑 - 依赖 loguru;新增 db、logging_config、subprocess_run、watch_idle、启动脚本 FishMeasure: 更新 fish_video_weight_evaluation 与 predict_weigth_from_svo2;移除未用 refbox/segmentation 脚本 Made-with: Cursor
This commit is contained in:
@@ -2,14 +2,16 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from app.logging_config import format_json_pretty
|
||||
from app.settings import Settings
|
||||
from app.state import HealthSnapshot
|
||||
from app.subprocess_run import run_subprocess_with_log
|
||||
from loguru import logger
|
||||
|
||||
BEHAVIOR_EN_TO_ZH = {
|
||||
"feeding": "吃饵",
|
||||
@@ -67,15 +69,14 @@ def run_action_subprocess(mp4_path: Path, settings: Settings) -> str:
|
||||
"--log_interval",
|
||||
"0",
|
||||
]
|
||||
proc = subprocess.run(
|
||||
proc = run_subprocess_with_log(
|
||||
cmd,
|
||||
cwd=str(settings.fish_action_root),
|
||||
env=os.environ.copy(),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
log_name="FishAction",
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
err = (proc.stderr or "") + (proc.stdout or "")
|
||||
err = proc.stdout or ""
|
||||
raise RuntimeError(
|
||||
f"predict_video_x3d_3class.py failed ({proc.returncode}): {err[-4000:]}"
|
||||
)
|
||||
@@ -86,6 +87,10 @@ def run_action_subprocess(mp4_path: Path, settings: Settings) -> str:
|
||||
if not rows:
|
||||
raise RuntimeError("Empty prediction JSON")
|
||||
pred_en = str(rows[0].get("pred_3class", "")).strip().lower()
|
||||
logger.info(
|
||||
"[FishAction] prediction row:\n{}",
|
||||
format_json_pretty(rows[0]),
|
||||
)
|
||||
if pred_en not in BEHAVIOR_EN_TO_ZH:
|
||||
raise RuntimeError(f"Unexpected pred_3class: {pred_en!r}")
|
||||
return pred_en
|
||||
@@ -95,9 +100,17 @@ def run_action_subprocess(mp4_path: Path, settings: Settings) -> str:
|
||||
|
||||
|
||||
def run_full_action(mp4_path: Path, settings: Settings) -> HealthSnapshot:
|
||||
logger.info("[FishAction] start mp4={}", mp4_path.resolve())
|
||||
pred_en = run_action_subprocess(mp4_path, settings)
|
||||
zh = BEHAVIOR_EN_TO_ZH[pred_en]
|
||||
health = behavior_to_health(pred_en)
|
||||
logger.info(
|
||||
"[FishAction] done mp4={} pred_3class={} behavior_zh={} health={}",
|
||||
mp4_path.name,
|
||||
pred_en,
|
||||
zh,
|
||||
health,
|
||||
)
|
||||
return HealthSnapshot(
|
||||
behavior_result=zh,
|
||||
health_result=health,
|
||||
|
||||
Reference in New Issue
Block a user