fix: 优化VLM提示词,输出更简洁,传入算法类型和区域名称

- prompt要求≤15字直接说结论,不再描述画面
- 加入算法类型中文名(离岗/周界入侵)让VLM更准确判断
- roi_name改为查询区域名称,不再传UUID
- 给出告警成立和误报的示例引导输出格式

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 10:32:50 +08:00
parent 26f1512a1c
commit 78e0076f4a
2 changed files with 36 additions and 12 deletions

View File

@@ -46,7 +46,11 @@ async def process_alarm_notification(alarm_data: Dict):
# ========== 1. VLM 复核 ========== # ========== 1. VLM 复核 ==========
vlm_service = get_vlm_service() vlm_service = get_vlm_service()
camera_name = alarm_data.get("camera_name", device_id) camera_name = alarm_data.get("camera_name", device_id)
roi_name = alarm_data.get("scene_id", "") scene_id = alarm_data.get("scene_id", "")
# 查找区域名称用于 VLM prompt比 UUID 更有意义)
area_name_for_vlm, _ = _get_notify_persons(device_id, alarm_level)
roi_name = area_name_for_vlm if area_name_for_vlm != "未知区域" else scene_id
# snapshot_url 可能是 COS object key需转为可访问的预签名URL # snapshot_url 可能是 COS object key需转为可访问的预签名URL
vlm_snapshot_url = snapshot_url vlm_snapshot_url = snapshot_url
@@ -77,7 +81,9 @@ async def process_alarm_notification(alarm_data: Dict):
# ========== 2. 查表获取通知人员 ========== # ========== 2. 查表获取通知人员 ==========
description = vlm_result.get("description", "") description = vlm_result.get("description", "")
area_name, persons = _get_notify_persons(device_id, alarm_level) # 复用 VLM 阶段已查询的 area_name重新查人员列表
area_name = area_name_for_vlm
_, persons = _get_notify_persons(device_id, alarm_level)
# 演示模式:数据库无人员时,使用配置的测试 userid # 演示模式:数据库无人员时,使用配置的测试 userid
if not persons and settings.wechat.test_uids: if not persons and settings.wechat.test_uids:

View File

@@ -13,23 +13,39 @@ from openai import AsyncOpenAI
from app.utils.logger import logger from app.utils.logger import logger
# 算法类型中文映射
ALARM_TYPE_NAMES = {
"leave_post": "离岗",
"intrusion": "周界入侵",
}
# 算法类型 → VLM Prompt 模板 # 算法类型 → VLM Prompt 模板
VLM_PROMPTS = { VLM_PROMPTS = {
"leave_post": """你是安防监控AI复核员。判断{roi_name}岗位区域内是否有人在岗 "leave_post": """你是安防监控AI复核员。算法类型:离岗检测,监控区域:{roi_name}
confirmed=true表示确实无人在岗告警成立false表示有人误报 判断该区域是否有人在岗
description用≤25字描述画面。 - confirmed=true无人在岗告警成立
- confirmed=false有人在岗误报
description要求≤15字直接说结论。
告警成立示例:"该区域无人在岗"
误报示例:"画面中无人员离岗情况"
仅输出JSON{{"confirmed":true,"description":"..."}}""", 仅输出JSON{{"confirmed":true,"description":"..."}}""",
"intrusion": """你是安防监控AI复核员。判断{roi_name}周界区域内是否有人员入侵 "intrusion": """你是安防监控AI复核员。算法类型:周界入侵检测,监控区域:{roi_name}
confirmed=true表示确实有人入侵告警成立false表示无人误报 判断该区域是否有人入侵。
description用≤25字描述画面。 - confirmed=true有人入侵告警成立
- confirmed=false无人入侵误报
description要求≤15字直接说结论。
告警成立示例:"有人员进入周界区域"
误报示例:"画面中无周界入侵情况"
仅输出JSON{{"confirmed":true,"description":"..."}}""", 仅输出JSON{{"confirmed":true,"description":"..."}}""",
} }
# 通用降级 prompt未知算法类型时使用 # 通用降级 prompt未知算法类型时使用
DEFAULT_PROMPT = """你是安防监控AI复核员。边缘AI触发了{alarm_type}告警,判断告警是否属实 DEFAULT_PROMPT = """你是安防监控AI复核员。算法类型:{alarm_type_name},监控区域:{roi_name}
confirmed=true表示告警成立false表示误报 判断告警是否属实
description用≤25字描述画面。 - confirmed=true告警成立
- confirmed=false误报
description要求≤15字直接说结论。
仅输出JSON{{"confirmed":true,"description":"..."}}""" 仅输出JSON{{"confirmed":true,"description":"..."}}"""
@@ -102,10 +118,12 @@ class VLMService:
# 选择 prompt 模板 # 选择 prompt 模板
template = VLM_PROMPTS.get(alarm_type, DEFAULT_PROMPT) template = VLM_PROMPTS.get(alarm_type, DEFAULT_PROMPT)
alarm_type_name = ALARM_TYPE_NAMES.get(alarm_type, alarm_type)
prompt = template.format( prompt = template.format(
camera_name=camera_name or "未知位置", camera_name=camera_name or "未知位置",
roi_name=roi_name or "未知区域", roi_name=roi_name or "监控区域",
alarm_type=alarm_type, alarm_type=alarm_type,
alarm_type_name=alarm_type_name,
) )
try: try: