修复:Agent禁用markdown语法 + 告警详情自动发送截图图片
- 系统提示词禁止markdown图片语法,企微不支持渲染 - 告警详情查询时截图自动通过企微图片消息发送 - 工具返回中用has_snapshot替代snapshot_url,避免模型输出链接
This commit is contained in:
@@ -36,7 +36,9 @@ SYSTEM_PROMPT = """你是VSP安防AI助手,通过企业微信协助安保人
|
||||
- 用户发图片时,如果有待处理工单,询问是否作为处理结果上传
|
||||
- 用户说"处理完了"并附带描述,自动提交结单
|
||||
- 回复简洁,适合手机阅读
|
||||
- 重要信息用【】标注"""
|
||||
- 重要信息用【】标注
|
||||
- 禁止使用markdown语法(如、**加粗**、# 标题),企微聊天不支持
|
||||
- 告警截图会自动发送图片消息,文字回复中不要包含图片链接"""
|
||||
|
||||
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)"""
|
||||
|
||||
Reference in New Issue
Block a user