From 6bc71a9991a24ab506a67aac28db0af401e3f115 Mon Sep 17 00:00:00 2001 From: 16337 <1633794139@qq.com> Date: Mon, 23 Mar 2026 15:01:48 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=EF=BC=9AAgent=E6=84=8F?= =?UTF-8?q?=E5=9B=BE=E8=AF=86=E5=88=AB=E4=BC=98=E5=85=88=E4=BA=8E=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE=E7=8A=B6=E6=80=81=E6=9C=BA=EF=BC=8C=E9=98=B2=E6=AD=A2?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E8=A2=AB=E8=AF=AF=E5=88=A4=E4=B8=BA=E4=BD=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 _looks_like_new_intent() 方法,识别查询/取消等明确非位置意图 - 收紧 _looks_like_location() 规则,去掉2-30字的宽松兜底,必须包含位置关键词 - waiting_location 状态下先判断新意图,再判断位置,最后兜底退出状态机 - 修复「今天有多少告警」被当成位置信息创建工单的问题 --- app/services/agent_dispatcher.py | 52 ++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/app/services/agent_dispatcher.py b/app/services/agent_dispatcher.py index 898e91e..e579487 100644 --- a/app/services/agent_dispatcher.py +++ b/app/services/agent_dispatcher.py @@ -103,16 +103,14 @@ class AgentDispatcher: # 状态机:等待位置信息 if session.state == "waiting_location": - # 判断用户是否真的在回答位置,还是在说别的 - if self._looks_like_location(content): + if self._looks_like_new_intent(content): + # 用户明显在换话题(查询/取消等),退出位置等待,走正常意图识别 + session.reset() + elif self._looks_like_location(content): return await self._handle_location_reply(user_id, session, content) else: - # 不像位置信息,退出状态机回到正常对话 + # 不确定是位置还是新意图,退出状态机走 VLM 判断 session.reset() - session.add_history("user", content) - reply = await self._chat(session) - session.add_history("assistant", reply) - return reply # 状态机:等待确认 if session.state == "waiting_confirm": @@ -253,33 +251,43 @@ class AgentDispatcher: return "请回复「是」确认或「否」取消。" @staticmethod - def _looks_like_location(text: str) -> bool: - """简单判断文本是否像位置信息""" + def _looks_like_new_intent(text: str) -> bool: + """判断文本是否像新的意图/查询,而非位置信息""" text = text.strip() - # 太短(<2字)或是疑问句,大概率不是位置 - if len(text) < 2: - return False + # 查询/操作类关键词 → 明显不是位置 + intent_keywords = [ + "查询", "查看", "查一下", "看看", "多少", "统计", "报表", "导出", + "告警", "工单", "告警", "处理", "今天", "今日", "本周", "本月", + "帮我", "请问", "怎么", "如何", "什么", "哪些", "有没有", + "取消", "算了", "不要了", "不用了", "没事", "不了", "退出", + "你好", "在吗", "你是谁", + ] + for kw in intent_keywords: + if kw in text: + return True + # 以问号结尾 if text.endswith("?") or text.endswith("?"): + return True + return False + + @staticmethod + def _looks_like_location(text: str) -> bool: + """判断文本是否像位置信息(收紧规则,必须包含位置关键词)""" + text = text.strip() + if len(text) < 2 or len(text) > 50: 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: