Files
sentinel-home-ai/fam-edge/config/config.yaml
ericwyuan 61db82cb9b refactor(fam-edge): 重构第一阶段 - 人物图片零额外调用 + 运行时稳定性 + 工程质量
人物图片功能重做: bbox 随核心视频分析那一次 Gemini 调用一并产出(prompts.py 加
person_appearances.bbox 字段, [ymin,xmin,ymax,xmax] 0-1000 归一化), frame_service
直接用存好的 bbox 裁剪头像/事件缩略图, 删除原来"展示时额外调用 Gemini 定位人物"的
整套逻辑(locate_person_bbox/VLM 校验/熔断), 从架构上消除与核心视频分析共抢配额的
问题; 用真实数据验证裁剪结果正确框住人物本体。

NVIDIA 模型修复: 实测原配置的 3 个模型均不可用(asset_id 引用 500/400, 不支持视频),
改用 nemotron-3-nano-omni 的 base64 内嵌视频方式(唯一实测打通), 加 max_base64_mb
防止对大文件做注定失败的编码。

Gemini 多 Key 轮换: 支持 extra_api_keys 配置多个独立项目的 key, 配额用尽时依次
换 key 重试(每换 key 需重新上传, Files API 按项目隔离)。

稳定性加固: CircuitBreaker HALF_OPEN 清空旧失败计数(修复探测一失败就重新 OPEN 的
bug); chat() 统一接入熔断器(原来只有视频分析路径检查); NVIDIA 适配器改用共享
json_parser(原来自己重复实现且不做 schema 校验); Gemini Files API 上传超时也尝试
清理远程孤儿文件; video_processor/video_queue 里直接操作 OracleDB._conn 的裸 SQL
改走新增的 set_event_start_time/mark_video_invalid/reset_video_to_pending 方法;
/health 加入队列线程存活状态; 密钥改用 ${ENV_VAR} 引用(.env 已支持自动加载),
不再明文写入 config.yaml。

工程质量: 新增 fam-edge/tests(32 个单元测试, 覆盖熔断器状态机/JSON 解析容错/
时间戳解析/bbox 坐标换算/多 key 解析), 新增 scripts/smoke_test.py(发版前接口
稳定性检查); 清理死代码(OllamaAdapter.analyze_frames、get_sync_delta 死分支、
未使用的 vision_timeout/max_concurrent_tasks 配置项); 修正 get_events_for_label
排序(改最近优先 + 过滤畸形历史时间戳)。

已部署 Oracle 并跑通 smoke test 全部 6 项检查。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 00:22:57 +08:00

116 lines
5.8 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# FAM-Edge 配置文件 (Oracle 端) - 新架构 v2
#
# 新架构2026-08-21 重构):
# 1. 不再切片/抽帧:整视频直传云端 VLMGemini 用 Files APINVIDIA 用整视频 video_url
# 2. 视频来源rclone 从 Google 硬盘实时同步到本地 local_dir监听目录处理新视频
# 3. Oracle 自建 SQLite 库存储所有视频摘要/事件/人物,并对外提供同步接口供 NAS 拉取
# 4. 独立 person_service 汇总全量人物 -> LLM 合并为规范人物表 -> 回灌视频提示
# 5. NAS 仅作管理后台,每 30 分钟从甲骨文拉增量镜像到本地 MariaDB
# Oracle 端 HTTP 服务
server:
host: "0.0.0.0"
port: 5000
# Google 硬盘同步rclone 负责同步落地,本段仅描述监听行为)
gdrive_sync:
enabled: true
local_dir: "/opt/fam-edge/gdrive_videos" # rclone 同步落地目录video_processing 监听此目录)
watch_interval_sec: 30 # 监听新视频的轮询间隔
camera_name: "客厅" # 摄像头名称(注入视频提示)
# 文件名解析开始时间:监控文件名含时间戳时使用(如 2026-08-21_081500.mp4
parse_start_from_filename: true
# Oracle 本地库(视频摘要/事件/人物)
oracle_db:
path: "/opt/fam-edge/data/oracle.db"
# NAS 拉取同步接口鉴权 token与 NAS oracle_sync.token 一致,走 .env不明文入库
sync_api:
token: "${ORACLE_SYNC_TOKEN}"
# 人物识别服务
person_service:
enabled: true
schedule_interval_sec: 1800 # 每 30 分钟重新汇总一次人物
model: "gemini" # 用哪个模型做人物合并vision 模型也支持纯文本)
# 视频处理
video_processing:
max_concurrent: 1 # 消费者线程数(串行处理,避免云端并发超额)
timeout: 900 # 兜底单视频分析超时
timeout_multiplier: 2 # 模型消费超时倍数:在 models[i].timeout 原值上 ×2大视频上传+分析耗时)
max_retries: 10 # 单视频失败最大重试次数(配额/过载等瞬时故障给足重试机会)
retry_interval_sec: 3600 # 失败重试最小间隔:距上次失败 ≥1h 才重新入队,等配额恢复
file_validate: true # 登记入队前用 ffprobe 校验文件可解码;失败标记 invalid 不入队
stable_window_sec: 60 # 文件 mtime 稳定窗口写入中rclone 同步未完成)的文件跳过本轮
# 降级顺序:先 gemini 整视频,失败再 nvidia 整视频;两者都失败 -> 标记 failed
vision_order: ["gemini", "nvidia"]
# 智能问答降级链与视频分析独立Gemini -> NVIDIA -> 本地 Ollama
models:
- provider: "gemini"
role: "vision"
enabled: true
model_name: "gemini-flash-latest" # 主模型(每日免费配额 20 请求,按模型独立)
fallback_models:
- "gemini-flash-lite-latest"
api_key: "${GEMINI_API_KEY}"
# 多 Key 轮换(各自独立 Google Cloud 项目,配额互不影响):主 key 配额用尽时
# 依次尝试这些 key每个 key 都会重新走一遍模型 fallback 链。key 本身放 .env
# 这里只放环境变量名,不直接写密钥。
extra_api_keys:
- "${GEMINI_API_KEY_2}"
- "${GEMINI_API_KEY_3}"
- "${GEMINI_API_KEY_4}"
timeout: 600
# 模型级独立超时(最终值,不参与编排层 ×2 放大)
# gemini-flash-lite 实测 ~22-34s按用户要求放宽至 8 分钟480s避免大视频/排队时过早切断
model_timeouts:
"gemini-flash-lite-latest": 480
circuit_breaker:
enabled: true
threshold: 5
cooldown: 300
- provider: "nvidia"
role: "vision"
enabled: true
# 模型可用性实测记录2026-08-21用真实短视频逐个探测 chat.completions 接口):
# omni本行 model_namevideo_url 只认 base64 data URINVCF asset_id 引用
# 方式对它直接 500"Only base64 data URLs are supported for now")——本适配器
# 已改为 base64 内嵌整段视频,见 max_base64_mb。确认可用真实返回结构化 JSON
# nemotron-nano-12b-v2-vl走 asset_id 引用需要 NVCF-ASSET-DIR/
# NVCF-FUNCTION-ASSET-IDS 请求头,这两个头的值由 NVCF 服务端按内部路径生成,
# 客户端传什么都 400 "Invalid NVCF-ASSET-DIR",标准 OpenAI 兼容调用打不通,已移除。
# meta/llama-3.2-11b-vision-instruct明确不支持视频输入
# "At most 0 video(s) may be provided"),只能单图,已移除。
# base64 方案受请求体大小限制(实测约 25MB 上限),真实监控视频压缩后通常在
# 20MB 上下,超过 max_base64_mb 直接跳过(不做注定失败的慢速编码),不是本地
# 故意限制过窄——这是当前唯一能打通的 NVIDIA 视频理解路径。
model_name: "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning"
fallback_models: []
base_url: "https://integrate.api.nvidia.com/v1"
api_key: "${NVIDIA_API_KEY}"
timeout: 600
max_base64_mb: 20 # 超过此大小直接跳过 NVIDIA不做注定失败的编码+上传
switch_interval_sec: 5 # 模型切换间隔:一个失败后等待再试下一个(未来加模型时用)
model_timeouts: # 模型级独立超时(最终值,不参与 ×2
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": 300
circuit_breaker:
enabled: true
threshold: 5
cooldown: 300
# 本地模型:纯文本 qwen2.5:7b仅参与智能问答兜底
- provider: "ollama"
role: "text"
usage: "qa_fallback"
enabled: true
model_name: "qwen2.5:7b"
base_url: "http://localhost:11434"
timeout: 120
num_predict: 512
circuit_breaker:
enabled: false