feat(v3): 人物模块重构 - 大模型结构化特征值替代 OpenCV 帧定位。prompt 增加 person_appearances(uid+7特征+action)并重写合并 prompt(稳定特征优先比对);gemini 透传特征字段;oracle_db events/people 加 person_appearances_json/features_json/display_uid + _merge_features;video_processor 去 cv2 改 ffprobe 校验、_store_result 聚合 uid 特征落 people、删缩略图/事件截图;person_service 聚合特征后基于特征文本 LLM 合并;api_gateway 删 3 个图接口;NAS 镜像+DDL 加新字段;fam-ui 特征卡替代头像、事件时间线人物特征块
This commit is contained in:
@@ -12,7 +12,13 @@
|
||||
"events": [ # 有用时间点 + 画面信息
|
||||
{"timestamp": "2026-08-21 08:15:30", # 绝对北京时间(event_start_time 推算)
|
||||
"description": str,
|
||||
"people": [str],
|
||||
"people": [str], # 该时刻出现的人物标识
|
||||
"person_appearances": [ # 该时刻每个人物的结构化特征
|
||||
{"uid": str, # 与 people 数组里的标识一致
|
||||
"features": { # 客观可见特征,看不清写 "unknown"
|
||||
"gender, age_band, build, hair, clothing, face, distinguishing"
|
||||
},
|
||||
"action": str}],
|
||||
"is_attention_event": bool}, ...],
|
||||
"people_mentioned": [str], # 本视频出现的人物标识/真名
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ class GeminiAdapter(BaseModelAdapter):
|
||||
|
||||
@staticmethod
|
||||
def _normalize(result: dict) -> dict:
|
||||
"""统一字段名:frame_details -> events(兼容旧结构)。"""
|
||||
"""统一字段名:frame_details -> events(兼容旧结构),保留 person_appearances 特征。"""
|
||||
events = result.get('events')
|
||||
if events is None and 'frame_details' in result:
|
||||
events = []
|
||||
@@ -308,13 +308,25 @@ class GeminiAdapter(BaseModelAdapter):
|
||||
})
|
||||
if events is None:
|
||||
events = []
|
||||
# 透传 events 内全部字段(含 person_appearances + features),不丢特征
|
||||
norm_events = []
|
||||
for ev in events:
|
||||
if not isinstance(ev, dict):
|
||||
continue
|
||||
item = dict(ev) # 保留原模型输出的所有字段(含 person_appearances)
|
||||
# 保证 people 字段为字符串数组
|
||||
people = ev.get('people') or []
|
||||
if isinstance(people, str):
|
||||
people = [people]
|
||||
item['people'] = [str(p) for p in people if p]
|
||||
norm_events.append(item)
|
||||
people = result.get('people_mentioned') or result.get('entities_json') or []
|
||||
if isinstance(people, list) and people and isinstance(people[0], dict):
|
||||
people = [p.get('person', '') for p in people]
|
||||
people = [p.get('person', '') or p.get('uid', '') for p in people]
|
||||
people = [p for p in people if p]
|
||||
return {
|
||||
"global_summary": result.get('global_summary', ''),
|
||||
"events": events,
|
||||
"events": norm_events,
|
||||
"people_mentioned": people,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user