从群消息到工单看板:用智能体工作台搭建电梯报修自动化流程

发布时间:2026/9/11 5:50:22
从群消息到工单看板:用智能体工作台搭建电梯报修自动化流程 别说这个事儿我一开始真没觉得有多大技术含量。直到有一天我在业主群里看到有人连着刷了十几条“3栋电梯又坏了”物业在群里回了个“收到”然后就没有然后了我才意识到电梯报修这种高频、低技术门槛、但又极其影响居住体验的场景居然还在用“微信群里吼一嗓子”的方式运转。后来我用 WorkBuddy 搭了一套流程把业主群里的电梯报修消息自动采集、解析、去重、分类再落到数据库里最后变成一块实时数据看板。跑了两周效果出奇的好。物业经理现在每天早上先打开看板看一眼昨天哪几台电梯报修了哪几台还在处理中哪几台超时没人管全在一条页面上。业主群里的消息还是那些消息但后台已经完全是另一套逻辑了。这篇文章就把整个从 0 到 1 的过程拆开讲清楚包括设计思路、关键配置、遇到的坑、以及我现在仍在用的字段规则和处理策略。1. 先把问题拆清楚电梯报修真正常见的那些坑1.1 所谓“报修”本质上是一个“消息到工单”的转换问题电梯报修表面上是设备问题其实是信息流转问题。业主在群里发一句“2栋电梯卡人了快来”本质上是一条带有时间、地点、故障类型、紧急程度的事件消息。但这条消息的问题在于它淹没在聊天流里。前后可能有“今天菜好咸”的吐槽、有“谁家狗在电梯里尿了”的投诉、还有“物业费催缴通知”的公告。如果靠人肉盯群消息一多必漏。而电梯这类设备一旦漏了报修后果不是用户体验问题是安全问题。所以整个项目的核心思路就一句话把业主群里和电梯相关的消息自动转成一条条结构化工单再让工单的状态变化实时反应到看板上。1.2 为什么群里的报修消息很难直接拿来用最开始我天真地以为写好关键词规则让机器人识别“电梯”两个字就行。跑了一天发现完全不靠谱至少有三个坑。第一个坑是消息口径太乱。业主不会按标准格式报修。有人写“3栋电梯坏了”有人写“二单元那个电梯吱吱响”有人拍一张电梯照片说“这还能坐吗”甚至有人直接在群里物业说“你们自己去看”。关键词规则能抓到“电梯”但抓不出是哪栋哪单元也判断不了故障等级。第二个坑是聊天串台。业主群消息是串行流一条报修消息后面往往跟着五六条评论“我家也这样”“上次就报过”“物业装死”。如果按单条消息处理会把评论当新报修产生重复工单。第三个坑是状态无法跟踪。群里说“电梯坏了”之后没有人会在修好的时候正经发一句“3栋电梯已恢复运行”最多是有人问一句“电梯好了吗”然后有人回“好了”。从报修到恢复中间过程全靠人脑记忆没有任何系统记录。这些坑决定了只靠关键词过滤是远远不够的必须对每条消息做语义理解、上下文聚合和状态推断这也是我选择用 WorkBuddy 这类智能体工作台来跑流程的原因因为它能让我把“大模型理解语义”和“确定性程序处理数据”组合在同一条流水线里。1.3 数据看板到底看什么不是看报了多少次而是看“有没有人管”看板做出来不是为了好看的。很多物业其实不缺台账缺的是对处理过程的实时感知。我设计这块看板的时候核心指标就三块今日新增报修数、当前待处理数、超时未处理数。外加一个按楼栋拆分的小分组一眼能看出哪栋楼的电梯故障最集中。这些指标背后对应的是一个很朴素的管理逻辑报修是否被记录、是否被分派、是否在规定时间内处理完。换句话说看板不是“电梯故障统计报表”而是“物业响应能力的实时仪表盘”。理解了这一点后面所有字段设计、状态迁移、预警规则都是围绕这个目标展开的。2. 整体设计思路把“群消息”变成“工单系统”再变成“看板”2.1 为什么选 WorkBuddy 来承担这个角色先说清楚 WorkBuddy 在这套流程里扮演的角色。它不是一个单纯的聊天机器人也不是 BI 工具而是一个能把“事件感知、语义理解、任务执行、数据流转”串起来的智能体工作台。你可以把它理解成一个管家它监听群消息调用大模型理解内容再按照你预先定义好的 Skill技能去执行具体的程序逻辑比如写数据库、发通知、更新状态。我选它而不是从零写一个企业微信机器人原因很实在第一它天然对接群机器人。业主群用的是企业微信企业微信自带的机器人只支持关键词回复不支持复杂的语义解析。WorkBuddy 可以通过 webhook 或者连接器方式接到群消息事件上然后把消息内容交给后面的流程处理。第二它把“AI 能力”和“确定性代码”做了解耦。纯粹的 LLM 调用会面临乱解析的问题纯粹的规则代码又应对不了业主各种口语化表达。WorkBuddy 的 Skill 机制允许我定义“先走规则、再走模型、最后校验”的多段处理逻辑而不是一刀切全丢给大模型。第三它可以本地部署数据不会经过第三方平台。这个场景虽然不涉及什么机密数据但毕竟涉及小区业主的手机号、房号这些个人信息能本地跑我就会尽量本地跑省得隐私上说不清。2.2 三层架构接入层、解析层、展示层整个系统的结构不复杂我拆成了三层每层职责单一出了问题也好排查。接入层负责“听”。它接收业主群里的所有新消息过滤掉非文本内容做一些基础清洗然后把文本和消息元数据打包成 JSON 传给下一层。这一层我用的是企业微信群机器人回调 一个简单的 Webhook 中转服务这样 WorkBuddy 只需要关注业务逻辑不用处理 IM 平台差异。解析层负责“懂”。这是整个系统的核心也是 WorkBuddy 发挥价值的地方。它会调用我定义的一个叫 elevator_fault_parse 的 Skill把一段群消息文本解析成标准字段楼栋、单元、故障类型、紧急程度、是否新报修。这个 Skill 内部先跑正则规则做粗提取拿不准的再交给 LLM 补全最后用规则校验一遍结果。展示层负责“看”。解析完成的结构化工单会写入 SQLite然后通过 WorkBuddy 的看板组件定时刷新数据或者直接接到第三方可视化工具上显示实时卡片。分层之后最大的好处是群机器人掉线、解析模型抽风、看板显示异常这三类问题可以独立排查不会互相干扰。2.3 关键取舍哪些用 AI哪些不用 AI这是整套方案里我最想强调的部分。很多人一提到智能体就恨不得所有环节都用大模型实际这么做必翻车。我的原则是能用规则解决的坚决不用模型模型只负责“理解”不负责“决策”。比如判断“这条消息是不是在报修电梯”我会先用正则过滤消息文本里必须包含“电梯”“检修”“卡人”“困人”等关键词之一不包含的直接丢掉。只有通过关键词初筛的消息才会进入 LLM 解析环节。这一步能把 90% 的无关消息挡在门外大幅降低模型调用量和幻觉概率。再比如工单状态迁移从“待处理”到“处理中”再到“已完成”这个流程我完全用代码写死不让模型瞎猜。因为状态流转是有逻辑的必须有明确的触发条件比如“处理人点击开始处理”才置为处理中“处理人上报完成”才置为已完成。模型在这个环节的唯一职责是帮我在聊天流里识别“哪句话意味着状态变化”比如“电梯修好了”这句本身要被正确理解为对某条旧工单的完成信号而不是一条新报修。这样设计的好处是模型即使抽风说错一两句话也不会把整个工单系统搞乱最坏的结果就是漏解析了一条消息状态流始终稳得住。3. 核心细节解析消息识别、去重、工单状态机3.1 一条报修消息最少要包含哪些信息设计字段的时候我一开始列得很复杂什么故障代码、维保单位、责任人、配件类型全往里塞。后来发现根本维护不动因为现场的原始信息就那几个字LLM 再能编也不可能从“电梯坏了”里猜出配件型号。最后我把字段收敛到六个够用且稳定字段说明示例楼栋提取楼栋号或楼栋名3栋、二单元位置更细的位置描述3栋2单元、客梯故障类型电梯类问题细分困人、异响、无法运行、按键失灵紧急程度系统根据故障类型推断高/中/低报修来源哪个业主群、哪条消息一期业主群、消息ID原始消息留存原文便于回溯“3栋电梯又坏了快来个人”其中“紧急程度”这个字段我放弃了让模型直接打分而是用规则映射故障类型里命中了困人、卡人、坠梯这些词直接置为“高”异响、按键失灵这类置为“中”报修但无明确故障描述的置为“低”。规则确定可见不会因为同一句话今天说“严重”明天说“一般”就飘忽不定。3.2 去重与合并防止同一个故障被刷屏电梯故障有一个显著特点一条报修消息发出来后面必然跟着一串“1”“我家也一样”的跟风消息。如果不做去重处理看板上的数量会被刷得完全没有参考价值。我的去重策略分三层。第一层是短时间窗口去重如果 10 分钟内出现两条楼栋相同、故障类型相同的报修消息只保留第一条第二条自动归入“同事件反馈”不计入新增工单。第二层是相似度合并。有时候业主描述很不一致比如“3栋电梯停了”和“三栋那个电梯不动了”关键词和楼栋号都对得上但表面文本完全不同。我的做法是先把解析结果里的“楼栋故障类型”拼成一个事件指纹在 2 小时时间窗内相同指纹的消息自动合并成一张工单并在工单备注里累计“反馈人数”。这个指标也很有意思同一个故障用的人越多说明影响面越大优先级会自动上调一级。第三层是人工兜底。有些特殊情况机器确实判断不了比如“上次那个电梯又坏了”这个“上次”指哪一条只有结合上下文才能知道。这种情况工单会标记为“待确认”由物业人员在看板上一键合并或拆分。3.3 工单状态机待处理、处理中、已完成工单状态我设计了五个覆盖电梯报修的完整生命周期状态触发条件说明待处理新报修生成等待物业分派处理中物业/维保点击开始处理表示已经有人接手已完成上报维修完成故障修复已关闭超时无人处理自动关闭需要人工复核已撤销误报或重复保留记录不计入未完成整个状态机用一张表维护WorkBuddy 的 Skill 里嵌了一套 if-else 逻辑来执行状态流转。这里有个细节必须提醒状态更新绝对不能让 LLM 直接改数据库只能让它“建议”状态变化然后由代码校验当前状态和动作是否符合迁移规则。否则会出现“已完成”变成“待处理”这种乌龙。4. 实操过程在 WorkBuddy 里搭出整套流程4.1 准备工作群机器人、Webhook、数据库动手之前先把基础环境备好。我这边用的 WorkBuddy 版本是 3.0可以本地部署。如果你用的环境不一样菜单名称可能略有差异但整体逻辑是通用的。机器是 Windows 系统跑了一个 Python 3.11 的 Webhook 中转服务数据库用的 SQLite零配置、文件型、好备份。第一步在企业微信小程序后台建一个群机器人拿到 Webhook 地址。注意企业微信机器人的对外回调有个限制它只能主动往群里发消息不能接收群消息。想接收群消息需要用到企业微信的“客户联系-回调”能力或者像我这样用一个具备群消息监听能力的机器人框架把消息实时推送到本地 Webhook。这里我推荐用 Hyperspace 这类开源机器人网关也可以用企业微信机器人框架 hook 的方式逻辑都一样收到群消息POST 到本地接口接口再做后续处理。如果后续你只是想验证流程也可以用 Docker 起一个模拟器把历史聊天记录导进去批量测试等流程稳了再切到实时入口。第二步在 WorkBuddy 里建一个项目起个名字叫“电梯报修工单系统”。项目的核心作用是提供 WorkBuddy 运行环境并管理 Skill、连接器配置。我用的是它的本地工作空间模式把代码和配置放在同一目录方便版本管理。第三步在 WorkBuddy 连接器里注册两个连接一个是“群消息回调”用来接收上方 Webhook 推送过来的消息另一个是“SQLite 数据源”指向本地数据库文件。注册连接器这一步做完后面 Skill 就能直接调用这些资源不用每次手动配鉴权。4.2 关键配置Skill 的输入输出字段这一步是整个流程的“翻译层”。我要让 WorkBuddy 能理解“3栋电梯又坏了”这句话该被拆成哪几个字段。WorkBuddy 里 Skill 的输入输出可以当作一个可复用的 API 定义来看待你需要为它指定类型字段说明输入raw_text群消息原始文本输入msg_time消息时间输入group_id群 ID输入msg_id消息 ID用于去重输出building楼栋输出unit单元输出fault_type故障类型输出urgency紧急程度输出is_new是否为新报修输出matched_event_id命中的历史事件 ID合并用注意这里有一个非常关键的细节输出结果不要直接让模型“自由发挥”要给模型提供可选枚举值和格式约束。比如“building”字段我会在 Skill 描述里设置一个可选楼栋清单模型只能从清单里选不能自己造词。凡是解析结果不在清单内的直接标记为“待确认”人工处理。这个约束让后续所有统计都不会出现数据口径不一致的问题。4.3 核心脚本消息解析为结构化工单的参考实现下面这段是我实际在用的 Python 脚本精简版职责是接收群消息、调 WorkBuddy Skill、解析结果、写库。之所以贴完整代码是因为我觉得这套流程无论用什么智能体工具这一步始终绕不开可以作为参考模板。import sqlite3 import json import time import re import requests # WorkBuddy Skill 调用接口本地地址 WORKBUDDY_URL http://localhost:8765/api/skill/elevator_fault_parse DB_PATH elevator_orders.db # 电梯相关关键词先做初筛减轻模型负担 ELEVATOR_KEYWORDS [电梯, 升降梯, 客梯, 货梯, 困人, 卡人] def init_db(): conn sqlite3.connect(DB_PATH) conn.execute( CREATE TABLE IF NOT EXISTS orders ( id INTEGER PRIMARY KEY AUTOINCREMENT, event_id TEXT, building TEXT, unit TEXT, fault_type TEXT, urgency TEXT, detail TEXT, status TEXT DEFAULT 待处理, feedback_count INTEGER DEFAULT 1, first_msg_time TEXT, last_msg_time TEXT, raw_text TEXT, msg_id TEXT UNIQUE ) ) conn.commit() conn.close() def is_elevator_msg(text: str) - bool: return any(kw in text for kw in ELEVATOR_KEYWORDS) def call_workbuddy_skill(raw_text: str): payload {raw_text: raw_text} resp requests.post(WORKBUDDY_URL, jsonpayload) resp.raise_for_status() return resp.json() def check_existing_event(conn, building, fault_type): # 2小时时间窗内相同楼栋故障类型的工单视为同一事件 window_start time.strftime(%Y-%m-%d %H:%M:%S, time.localtime(time.time() - 7200)) cur conn.execute( SELECT id, event_id FROM orders WHERE building ? AND fault_type ? AND first_msg_time ? LIMIT 1 , (building, fault_type, window_start)) return cur.fetchone() def insert_order(conn, event_id, parsed, raw_text, msg_id, msg_time): conn.execute( INSERT INTO orders (event_id, building, unit, fault_type, urgency, detail, status, feedback_count, first_msg_time, last_msg_time, raw_text, msg_id) VALUES (?, ?, ?, ?, ?, ?, 待处理, 1, ?, ?, ?, ?) , ( event_id, parsed[building], parsed.get(unit, ), parsed[fault_type], parsed[urgency], parsed.get(detail, ), msg_time, msg_time, raw_text, msg_id )) conn.commit() def handle_message(payload): raw_text payload[raw_text] msg_id payload[msg_id] msg_time payload[msg_time] if not is_elevator_msg(raw_text): return {action: ignored} # 调用 WorkBuddy Skill 做语义解析 parsed call_workbuddy_skill(raw_text) if not parsed or parsed.get(is_new) is False: return {action: ignored, reason: not_new} conn sqlite3.connect(DB_PATH) # 先检查是否已存在同一事件 matched check_existing_event(conn, parsed[building], parsed[fault_type]) if matched: order_id, event_id matched conn.execute( UPDATE orders SET feedback_count feedback_count 1, last_msg_time ? WHERE id ? , (msg_time, order_id)) conn.commit() conn.close() return {action: merged, order_id: order_id, event_id: event_id} event_id fEVT-{int(time.time() * 1000)} insert_order(conn, event_id, parsed, raw_text, msg_id, msg_time) conn.close() return {action: created, event_id: event_id}这套代码的核心逻辑是先用关键词把明显无关的消息丢出去减少无效调用再通过 WorkBuddy Skill 拿到结构化解析结果最后用时间窗口和事件指纹去重合并。你会发现代码本身不复杂但刚好卡在“模型能力”和“确定性逻辑”的中间两边各取所长。这里再补充一个我在实操中优化过的点WorkBuddy 的 Skill 调用并不是越快越好。最开始我让每一条消息都实时调 LLM高峰期直接超时。后来我在本地做了一层缓存对完全相同的文本直接走缓存结果窗口 5 分钟省掉了至少 20% 的解析请求。4.4 看板端把数据流实时可视化的两种方案数据落库之后看板就有数据源了。我试了两种方式各有适用场景你可以按自己的条件选。第一种是用 WorkBuddy 内置看板组件做实时统计。它还自带了连接 SQLite 的能力直接出一条查询语句比如SELECT status, COUNT(*) AS cnt FROM orders WHERE date(first_msg_time) date(now) GROUP BY status;查询结果会渲染成卡片每分钟自动刷新一次。这种方式的优势是零额外依赖几分钟就能搭好适合小范围试点。劣势是自定义能力有限图表类型做不了太复杂的分析。第二种是把数据接到外部可视化工具。如果你们物业办公室本来就有大屏或者管理团队习惯看电脑端报表可以把 SQLite 数据定时同步到 MySQL然后接 DataV 或 Grafana。这样看板的美观度和交互能力会强很多。但运维成本也上去了相当于多了一条数据同步链路。我目前的线上方案是两种混用日常盯盘用 WorkBuddy 内置看板每周复盘把数据导出来做一次 Excel 报告。你如果第一次搭建建议先用内置看板跑通流程确认解析质量稳定之后再考虑上外部大屏。还有一点特别重要看板一定要有超时预警这是我踩坑后加进去的。我设置了 2 小时未处理的待办会自动变红同时向物业值班群推送一条提醒。没有这个机制看板就只是个统计报表而不是问题驱动工具。5. 常见问题与排查技巧实录5.1 消息重复触发工单重复创建怎么办这个问题是最早遇到的。企业微信的群消息回调存在重试机制同一事件可能推送两次另外业主刷屏也会导致重复。我的处理方式是两层保障代码层给 msg_id 建了唯一索引重复消息直接抛异常跳过业务层用事件指纹做了 2 小时窗口合并。两层叠加之后重复创建的问题基本绝迹。如果你自己搭遇到重复问题建议先查中间的 Webhook 路由是不是做了失败重试很多重复不是业务逻辑造成的而是接入层重发了。5.2 LLM 把“电梯修好了”解析成一条新报修这是最容易让人头疼的模型幻觉问题。业主在群里说“电梯修好了”这句话本身没有任何故障描述但包含“电梯”关键词会被送入解析流程。如果模型没理解上下文就会当成一条新的“电梯报修”建单看板上多一条假工单。我给 WorkBuddy Skill 加了一条前置规则消息中出现“好了”“修好”“恢复”“可以用了”“正常了”这些完成态词汇时先走“状态更新”分支而不是“新建工单”分支。换句话说解析前先判断消息意图意图是“更新状态”的消息直接去匹配待处理或处理中的同楼栋工单标记为已完成匹配不到才提示人工确认。这个改动特别有效它把报修流水线上的“误报率”降到了一个很低的水平。而且也印证了我前面说的那条经验不要让模型一个人决定一切用确定性规则管住模型的行为边界。5.3 多个业主群同时接入数据口径怎么统一有些小区分好几个业主群一期、二期、三期各一个报修分布在不同的群里。模型解析每一条消息是没问题的但统计的时候如果不区分来源群会出现楼栋号一样的歧义。比如一期有“3栋”二期也有“3栋”单纯按“building3栋”合并事件就会把两个不同区域的故障合并成一个工单。我最后的方案是group_id来源群 building楼栋 fault_type故障类型三者一起作为事件指纹。不同群、同楼栋、同故障依然视为两个独立事件。看板上再加一个“区域/群”维度的筛选下拉框默认全量可下钻到具体某个群的工单明细。这个小改造让看板从“好看”变成了“真正能用于管理”。5.4 故障排查速查表这里整理一份我实际排障时用的速查表不是标准答案但能帮你在出问题时快速定位现象可能原因排查方向看板上一直没有新工单群消息回调未触发检查接入层 Webhook 日志确认消息是否到达本地端点有报修但解析结果为空关键词初筛没过确认消息文本里是否包含“电梯”等关键词工单楼栋为空模型没有从文本中提取到检查 Skill 的楼栋枚举清单是否覆盖小区所有楼栋同一故障出现多条工单时间窗口太短或事件指纹不同检查 2 小时窗口设置和 fault_type 枚举工单状态一直“待处理”状态流转规则未匹配确认“状态更新”分支里是否包含对应的完成态词汇WorkBuddy 启动很慢本地模型初始化资源把工作目录放 SSD关闭不用的 Skill注意检查本地网络鉴权设置这里顺便提一句网上有人问 WorkBuddy 启动非常慢、报 3002 连接错误之类的问题。我遇到过的“启动慢”十有八九是首次加载模型资源导致的。解决思路很简单不要频繁重启初始构建完配置之后保持长驻运行即可如果碰到连接错误优先检查本地网络鉴权和连接器配置比如回调地址是否写成了 127.0.0.1 而服务部署在远程机器上。像这类问题排查起来都需要看日志所以项目一开始日志最好按天轮转保留至少 7 天别图省事只输出到控制台。5.5 数据准确性验证拿历史聊天记录做盲测系统上线前不要急着切真实流量。我强烈建议拿至少一周的历史聊天记录做盲测把这批消息按时间顺序重新推给接入层让系统跑一遍然后人工核对生成的工单与真实情况的吻合度。我当时测完发现解析准确率在 86% 左右不高不低。仔细看错误样本后发现大部分错误集中在“楼栋号识别”和“是否为重复报修判断”上。于是我把 Skill 提示词里的楼栋描述改得更具体去重窗口从 30 分钟调到 2 小时又加上了完成态词汇的前置意图判断准确率才终于拉到了 95% 以上。这一步不能省准确率不达标就上线看板只会变成新的数据垃圾场。另外线下验证阶段也可以顺便把“模拟业主消息”和“真实历史消息”混在一起测看看系统对不同说话风格的鲁棒性。比如有人喜欢发“电梯又抽风了”有人喜欢一口一个“你们物业是不是不想干”这种情绪化消息不能被关键词规则误杀那也是模型的活。6. 踩过坑之后的几句实在话这套系统跑了大半个月我个人最大的感受是做这类“群消息智能处理”的项目真正难的不是让 AI 听懂人话而是设计一套规则让 AI 在使用边界内稳定输出。WorkBuddy 在这里承担的角色更像一个工作台它把监听、解析、存储、展示串成一条流水线但流水线的节拍器始终是业务规则本身。最后分享一个我现在觉得最有价值的小设计看板上专门留了一列叫“同一故障反馈人数”。电梯被困这种事一个人说可能是偶发一群人吐槽就说明问题已经非常严重了。这个数字比故障代码更接近真实生活物业经理看到反馈人数超过 3 就会主动打电话催维保而不是等系统报警。数据看板说到底不是为了冷冰冰地统计而是帮人更快做出判断。如果你手里正好也有类似“业主群报修”“客户群反馈”这种脏乱差的消息流不妨用这套思路试一遍。先别急着上高大上的可视化大屏把消息解析和工单状态做扎实了看板自然就立得起来。