diff --git a/app/services/agent_dispatcher.py b/app/services/agent_dispatcher.py index 6263dc0..b775de6 100644 --- a/app/services/agent_dispatcher.py +++ b/app/services/agent_dispatcher.py @@ -27,20 +27,22 @@ SYSTEM_PROMPT = """你是物业安防AI助手。你可以: 4. 导出告警报表 5. 分析处理结果图片,确认异常是否消除 -规则: +重要规则: +- 正常跟用户对话,不要把无关闲聊强行关联到工单或告警 +- 只有用户明确表达"上报问题""创建工单""发现异常"等意图时才触发工单流程 +- 用户随便聊天、问问题时,正常友好回复即可 - 当用户发送图片时,分析图片内容,判断是否有安全隐患 -- 如果识别到异常,描述异常并询问具体位置 -- 回复简洁专业,不超过100字 +- 回复简洁友好,不超过100字 - 不要编造不存在的信息 -当需要识别意图时,在回复末尾附加JSON标记: +当且仅当用户明确要执行以下操作时,在回复末尾附加JSON标记: -可选意图: -- create_work_order: 用户要创建工单或上报问题 +可选意图(仅在用户明确请求时使用): +- create_work_order: 用户明确要创建工单或上报问题 - query_alarm: 用户要查询告警数据(params: time_range=today/week/month, alarm_type=leave_post/intrusion/all) - export_report: 用户要导出报表(params: time_range=today/week/month) -- general_chat: 其他对话(无需附加标记)""" +- 普通对话不要附加任何标记""" IMAGE_ANALYZE_PROMPT = """分析这张图片,判断是否存在安全隐患或异常情况。 请用JSON格式回复: @@ -88,7 +90,16 @@ class AgentDispatcher: # 状态机:等待位置信息 if session.state == "waiting_location": - return await self._handle_location_reply(user_id, session, content) + # 判断用户是否真的在回答位置,还是在说别的 + if self._looks_like_location(content): + return await self._handle_location_reply(user_id, session, content) + else: + # 不像位置信息,退出状态机回到正常对话 + session.reset() + session.add_history("user", content) + reply = await self._chat(session) + session.add_history("assistant", reply) + return reply # 状态机:等待确认 if session.state == "waiting_confirm": @@ -224,6 +235,36 @@ class AgentDispatcher: else: return "请回复「是」确认或「否」取消。" + @staticmethod + def _looks_like_location(text: str) -> bool: + """简单判断文本是否像位置信息""" + text = text.strip() + # 太短(<2字)或是疑问句,大概率不是位置 + if len(text) < 2: + return False + if text.endswith("?") or text.endswith("?"): + return False + # 包含位置关键词 + location_keywords = [ + "栋", "楼", "层", "室", "号", "区", "门", "厅", "台", "廊", + "走廊", "大堂", "停车场", "电梯", "楼梯", "通道", "出口", "入口", + "东", "西", "南", "北", "左", "右", "前", "后", + "A座", "B座", "C座", "一楼", "二楼", "三楼", + "1楼", "2楼", "3楼", "1层", "2层", "3层", + ] + for kw in location_keywords: + if kw in text: + return True + # 包含"取消""算了""不要了"等放弃词 + cancel_words = ["取消", "算了", "不要了", "不用了", "没事", "不了"] + for w in cancel_words: + if w in text: + return False + # 长度适中(2-30字)且不含问号,可能是位置 + if 2 <= len(text) <= 30: + return True + return False + async def _handle_close_photo(self, user_id: str, session, image_url: str, object_key: str) -> str: """分析结单图片""" previous_issue = session.pending_analysis or "之前的异常"