修复:Agent禁用markdown语法 + 告警详情自动发送截图图片

- 系统提示词禁止markdown图片语法,企微不支持渲染
- 告警详情查询时截图自动通过企微图片消息发送
- 工具返回中用has_snapshot替代snapshot_url,避免模型输出链接
This commit is contained in:
2026-03-24 11:50:54 +08:00
parent b51c5cc46d
commit fbdd340a8e

View File

@@ -36,7 +36,9 @@ SYSTEM_PROMPT = """你是VSP安防AI助手通过企业微信协助安保人
- 用户发图片时,如果有待处理工单,询问是否作为处理结果上传
- 用户说"处理完了"并附带描述,自动提交结单
- 回复简洁,适合手机阅读
- 重要信息用【】标注"""
- 重要信息用【】标注
- 禁止使用markdown语法如![](url)、**加粗**、# 标题),企微聊天不支持
- 告警截图会自动发送图片消息,文字回复中不要包含图片链接"""
IMAGE_ANALYZE_PROMPT = """你是物业安防图片分析员。分析这张图片,判断是否存在安全隐患或需要上报的情况。
@@ -231,6 +233,8 @@ class AgentDispatcher:
self._client: Optional[AsyncOpenAI] = None
self._vlm_client: Optional[AsyncOpenAI] = None
self._enabled = False
# 临时存储:工具执行期间需要发送的图片 URL
self._pending_images: Dict[str, List[str]] = {} # user_id -> [image_urls]
def init(self, config):
"""初始化Agent"""
@@ -261,12 +265,20 @@ class AgentDispatcher:
session = get_session_manager().get(user_id)
session.add_history("user", content)
# 清空待发图片队列
self._pending_images[user_id] = []
try:
reply = await self._chat_with_tools(session, user_id)
except Exception as e:
logger.error(f"Agent FC 对话失败: {e}", exc_info=True)
reply = "抱歉AI助手暂时无法响应请稍后重试。"
# 发送工具执行期间收集的图片(如告警截图)
pending = self._pending_images.pop(user_id, [])
if pending:
await self._send_images_to_user(user_id, pending)
session.add_history("assistant", reply)
return reply
@@ -371,7 +383,7 @@ class AgentDispatcher:
elif name == "list_alarms":
return await self._tool_list_alarms(args)
elif name == "get_alarm_detail":
return await self._tool_get_alarm_detail(args)
return await self._tool_get_alarm_detail(args, user_id)
elif name == "update_alarm_status":
return await self._tool_update_alarm_status(args, user_id)
elif name == "list_my_orders":
@@ -475,7 +487,7 @@ class AgentDispatcher:
return {"range": range_label, "total": total, "items": items}
async def _tool_get_alarm_detail(self, args: dict) -> dict:
async def _tool_get_alarm_detail(self, args: dict, user_id: str) -> dict:
"""告警详情"""
from app.services.alarm_event_service import get_alarm_event_service
svc = get_alarm_event_service()
@@ -485,6 +497,13 @@ class AgentDispatcher:
if not detail:
return {"error": f"未找到告警: {alarm_id}"}
# 截图:加入待发图片队列,由 handle_message 统一发送
snapshot_url = detail.get("snapshot_url", "")
if snapshot_url:
if user_id not in self._pending_images:
self._pending_images[user_id] = []
self._pending_images[user_id].append(snapshot_url)
result = {
"alarm_id": detail.get("alarm_id"),
"alarm_type": ALARM_TYPE_NAMES.get(detail.get("alarm_type", ""), detail.get("alarm_type", "")),
@@ -494,7 +513,7 @@ class AgentDispatcher:
"event_time": str(detail.get("event_time", ""))[:19],
"handle_status": detail.get("handle_status"),
"handler": detail.get("handler"),
"snapshot_url": detail.get("snapshot_url", ""),
"has_snapshot": bool(snapshot_url),
}
# 摄像头名称
@@ -746,6 +765,32 @@ class AgentDispatcher:
# ==================== 辅助方法 ====================
async def _send_images_to_user(self, user_id: str, image_urls: List[str]):
"""通过企微发送图片消息给用户"""
from app.services.wechat_service import get_wechat_service
wechat = get_wechat_service()
if not wechat.enabled:
return
for url in image_urls:
try:
media_id = await wechat.upload_media_from_url(url)
if media_id:
# 发送图片消息(复用企微发送图片的能力)
access_token = await wechat._get_access_token()
import httpx
msg = {
"touser": user_id,
"msgtype": "image",
"agentid": wechat.agent_id_int,
"image": {"media_id": media_id},
}
api_url = f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={access_token}"
async with httpx.AsyncClient(timeout=10) as client:
await client.post(api_url, json=msg)
except Exception as e:
logger.error(f"发送告警截图失败: user={user_id}, error={e}")
@staticmethod
def _parse_time_range(time_range: str):
"""解析时间范围,返回 (start_time, label)"""