业内有句话我印象很深:物业公司的信息化预算,过去十年大半花在了“把纸搬到屏幕上”,OA、收费系统、工单系统、设备台账,一个个孤岛建起来,数据进去了,但知识没出来。现在数智化转型的口号一响,很多物企的第一反应是“我们要搞个物业行业大模型”。可真把通用大模型接进来,客服问一句“3栋2单元电梯昨晚又困人了,按预案我现在该先做什么”,模型回一段“电梯困人时应保持冷静、及时救援”的通用话术,一线秩序主管看完只会觉得这东西不如翻手里的作业指导书。
真正能落地的路径,是用检索增强生成(RAG)给通用模型装上“本项目的大脑”——把制度、SOP、应急预案、设备台账、维保合同、历史工单这些私域知识,变成可检索、可引用、可追溯的答案来源。这篇东西写给正在做或者准备做物业行业大模型落地的技术负责人、信息化主管、产品经理,也写给那些被老板一句话推上项目、手里只有一套OA和一堆扫描件的同行。我会把从语料盘点到分块打标、从混合检索到引用回链、从评测集构建到工程兜底的完整链路拆开讲,中间穿插我自己和同行踩过的坑,能抄的配置尽量给全。
1. 通用大模型在物业场景里最先崩掉的几个点
1.1 幻觉不是“偶尔说错”,在物业场景是直接产生成本
很多人对幻觉的理解还停留在“模型瞎编一个不存在的参考文献”。物业场景的幻觉后果要具体得多。业主问“我这个户型装修押金收多少”,模型凭训练语料的普遍印象答“通常为2000元”,而项目实际执行标准是“建筑面积100平以下2000元,以上3000元,装修验收合格后15个工作日内退还”。这个答案一旦被截图发到业主群,第二天客服中心就要面对十几户要求按2000元退押金的业主。
更麻烦的是安全类知识。消防通道占用、高空抛物、电动车上楼充电、有限空间作业,这些事项在物业行业都有明确的处置流程和留痕要求。通用模型给出的“建议劝阻并上报”听起来没错,但缺了“劝阻记录需双人签字、上报时限为发现后30分钟内、需同步推送项目负责人和区域安全专员”这些真正决定责任归属的动作。一旦出事,系统里留着一条“AI给过建议”的记录,反而成了举证上的麻烦。
所以我一直主张:物业大模型的第一性原则不是“答得聪明”,而是“答得可查”。答案里的每一个关键数字、每一条处置动作,必须能指回一份具体文件的具体条款。RAG 的价值就在这里,它把“生成”这个不可控动作,锚定在“检索到的原文”这个可控动作上。
1.2 微调、提示工程、RAG,物业场景为什么优先选RAG
这三条路经常被拿来比较,但落到物业行业,选择其实不太纠结。我把关键差异列成表,方便直接拿去和业务方对齐。
| 维度 | 全量微调 | 提示工程 | RAG |
|---|---|---|---|
| 知识更新成本 | 重新训练,周期以周计 | 改提示词,快但塞不进大量知识 | 增量重建索引,分钟到小时级 |
| 答案可追溯 | 几乎不可能 | 无 | 天然支持引用回链 |
| 数据需求量 | 数千到数万条高质量样本 | 不需要样本 | 不需要标注样本,需要语料 |
| 私域知识容量 | 受模型容量限制,易遗忘 | 受上下文窗口限制 | 理论上无上限 |
| 出错后的修复 | 重新训练 | 调提示词 | 删掉/修正那一份文档即可 |
| 适合的场景 | 固定话术风格、意图分类 | 轻量任务 | 制度问答、SOP检索、台账查询 |
物业行业的知识更新频率决定了RAG是更务实的选择。收费标准一年一调,应急预案按季度修订,设备台账天天在变,维保合同一年一签,集团制度每年下发新版。你不可能每改一次文件就微调一次模型。而RAG的修复动作极其朴素:把错的那份文档下架,重跑一次索引,问题就消失了。
微调也不是完全没用。我的经验是把微调用在“风格”和“意图”上,比如让模型学会用物业客服的语气说话、学会判断用户问的是收费类还是报修类问题;把RAG用在“事实”上。风格微调 + 事实检索,这个组合在小样本条件下最稳。
1.3 物业知识的“四层结构”决定了系统必须分层设计
我在多个项目上梳理过知识资产,发现物业知识天然是分层的,而且不同层对检索的要求完全不同:
第一层是集团级制度,比如《前期物业服务协议范本》《专项维修资金使用管理办法》,特点是权威、更新慢、覆盖面广。
第二层是条线SOP,秩序、环境、工程、客服四条线各自的作业指导书,特点是流程性强、步骤明确、经常带表格。
第三层是项目级细则,同一个制度在不同项目有差异,比如A项目的地下车库限高2.1米、B项目限高2.4米,这类知识必须按项目过滤。
第四层是动态台账与工单,设备编号、维保到期日、历史故障记录,特点是结构化、时效性强、必须精确匹配。
这四层如果混在一个向量库里,检索结果会非常混乱:问一个具体项目的电梯维保周期,可能召回集团通用制度里那句“按厂家要求执行”,而真正有答案的项目设备台账排在第十位。所以架构设计的第一步不是选模型,而是把元数据打清楚,让检索能按层过滤。这一点后面第3节会详细展开。
2. 先别急着建向量库,把语料底账盘清楚
2.1 物业语料的真实样貌:比你想象的更脏
我见过太多团队,拿到需求第一周就开始搭 LangChain、装向量数据库、跑 embedding,两周后 Demo 效果不错,一个月后上线翻车。翻车的原因九成不在模型,而在语料。
先说清楚一家中等规模物企(管理面积两千万平米左右)典型的知识存放在哪:
- 制度文件:Word 和 PDF 混杂,PDF 里有一半是扫描件,没有文本层
- 作业指导书:Word 为主,大量表格,跨页断行严重
- 应急预案:PDF,带版本号和修订记录,但文件名往往是“应急预案最终版(2)(修订).pdf”
- 设备设施台账:Excel,一个项目一个文件,字段命名不统一,有的叫“设备编号”有的叫“资产编码”
- 维保合同:扫描件 PDF,关键信息(维保周期、响应时限、违约责任)藏在正文里
- 工单记录:结构化数据,但“问题描述”字段是客服手打的口语,错别字多
- 培训课件:PPT,图文混排,很多关键信息在图里
- 图纸:CAD 和 PDF,这个建议第一版直接放弃,投入产出比太低
我把常见脏点和处理方式整理成下表,可以直接当清洗 checklist 用:
| 语料类型 | 典型脏点 | 处理方式 | 优先级 |
|---|---|---|---|
| 扫描件PDF | 无文本层、歪斜、印章遮挡 | OCR(中文识别需专门调优)、倾斜校正 | 高 |
| Word表格 | 跨页断行、合并单元格 | 按单元格结构化提取,转Markdown表格 | 高 |
| 多版本文件 | 新旧版并存、命名混乱 | 哈希去重 + 版本号提取 + 手动确认 | 最高 |
| 项目级差异 | 同制度多项目版本 | 按 project_id 打标,不合并 | 高 |
| 工单文本 | 错别字、口语、缩写 | 清洗 + 自定义词典补充 | 中 |
| PPT课件 | 关键信息在图里 | 第一版跳过,或只取文本框 | 低 |
| CAD图纸 | 无法解析 | 直接排除 | 低 |
2.2 去重和版本治理,是整个项目里最不性感但最值钱的一步
我踩过最深的坑,是一个项目上同时存在《电梯困人应急预案》的三个版本:2019版、2021修订版、2023版,文件名分别叫“电梯困人应急预案.pdf”“电梯困人应急预案(修订).pdf”“电梯困人应急预案-2023.3”。三个版本对“到场时限”的规定分别是15分钟、10分钟、5分钟。
如果你的索引里三份都在,模型检索到哪一份完全看运气,答案会在5分钟、10分钟、15分钟之间随机跳。这种不确定性比答错还可怕,因为它让一线人员彻底失去信任。
我的处理流程是这样的:
- 文件级去重:先算文件哈希,完全相同的直接去掉。
- 文本级近重复检测:对每个文件提取纯文本,用 SimHash 或 MinHash 算相似度,相似度超过 0.9 的聚成一簇。
- 簇内版本判定:优先看文件名里的日期和版本号;文件名看不出来就看文档内部的“修订记录”页;两样都没有,就人工确认,别偷懒。
- 作废标记而非删除:旧版本不物理删除,而是打上
expired: true和superseded_by字段。检索时默认过滤,但保留追溯能力。有些合规场景需要查历史版本,删了就找不回来了。
这一步做完,语料量通常会缩减 20% 到 40%,检索准确率的提升立竿见影。我的判断是,语料治理的投入应该占到整个项目工作量的 40% 以上,低于这个比例,后面所有环节都在给脏数据擦屁股。
2.3 结构化数据要不要进RAG:设备台账和工单的正确用法
这里有个常见误区:把所有 Excel 台账也切成文本块塞进向量库。这是灾难性的。设备台账的特点是“一行一个实体,多列属性”,你把它切成 300 字的块,等于把一行数据切碎,模型看到的是一堆没有表头的数字,完全无法回答“3栋的消防水泵上次维保是什么时候”。
正确的做法是结构化数据走结构化查询,非结构化数据走向量检索,然后在生成层做融合。具体来说:
- 设备台账、工单记录、收费明细,走 Text-to-SQL 或者预定义查询接口。用户问“哪些设备本月维保到期”,系统识别意图后直接查表,把结果作为上下文喂给模型。
- 制度、SOP、合同、预案,走 RAG。
- 混合型问题(“3栋电梯的维保单位是谁,他们的响应时限是多少”),先查台账拿到维保单位名称,再用这个名称去检索合同条款,两跳完成。
这个架构比“全部塞向量库”复杂,但它是唯一能保证数值准确的路。物业行业里数字错一位就是钱的事,容不得模糊。
3. 切分与元数据:把楼栋门牌和条款号变成检索锚点
3.1 中文物业文档的切分,固定长度是最差的选择
大多数教程教你按 512 token 固定切分,加 50 token 重叠。这个方法在通用语料上还行,在物业文档上会制造大量无意义片段。原因很简单:物业文档的结构性极强,一条制度通常就是 200 到 600 字的完整语义单元,你按固定长度切,很容易把“第X条”的条件和后果切到两个块里,检索到前半句“有下列情形之一的,应当……”却检索不到后半句的具体情形。
我的做法是结构感知切分优先,长度约束兜底:
第一步,按文档的标题层级切。Word 的 Heading 样式、PDF 的书签、Markdown 的#标题,都能提取出层级结构。切到三级标题(章-节-条)就基本够用了。
第二步,块内如果超过 800 字,再按段落切;段落还超,按句号切。中文标点的句号、分号是天然的语义边界。
第三步,设置 15% 左右的重叠,主要是防止“上一条的结尾”和“下一条的开头”之间的指代断裂。
对于表格,绝对不要按字符切。做法是把表头提取出来,每一行转成一句自然语言,比如:
设备编号:SB-3-021 | 设备名称:消防水泵 | 位置:3栋地下二层泵房 | 维保周期:季度 | 上次维保:2024-03-12 | 下次维保:2024-06-12 | 维保单位:某机电服务商这样每一行都是一个自包含的语义单元,检索“3栋消防水泵维保”能精准命中,而且模型读起来也不会丢表头。
3.2 元数据字段怎么定:少一个字段,多一堆错答案
元数据是RAG系统里最容易被低估的部分。我一般会给每个 chunk 挂下面这套字段,可以直接拿去当设计稿:
| 字段 | 类型 | 为什么必须有 | 缺失的后果 |
|---|---|---|---|
| doc_id | string | 文档唯一标识,用于引用回链 | 无法追溯答案来源 |
| doc_type | enum | 制度/SOP/合同/台账/工单/预案 | 无法按知识层级过滤,通用制度压过项目细则 |
| project_id | string | 所属项目 | 跨项目串答案,A项目标准答到B项目 |
| line | enum | 秩序/环境/工程/客服/综合 | 条线问题召回其他条线文档,噪音大 |
| version | string | 版本号 | 新旧版混答,答案自相矛盾 |
| effective_date | date | 生效日期 | 无法判断是否适用当前时点 |
| expired | bool | 是否作废 | 已废止制度继续被引用 |
| section_path | string | 章节路径,如“第三章>第二节” | 引用时无法定位到原文位置 |
| security_level | int | 密级,1-4 | 权限失控,客服看到财务合同 |
| source_page | int | 原文页码 | 用户无法翻原文核对 |
说一个真实教训。有个项目上线后发现,客服问“装修垃圾清运费怎么收”,系统一会儿答“按建筑面积8元/平米”,一会儿答“按户收取300元”。查了两天才发现,前者是集团指导价文件,后者是某个项目的实际执行细则,两份文档都在库里,都没打 project_id。加上项目过滤之后问题立刻消失。这就是一个字段的价值。
3.3 中文分词的坑:通用词典认不出“承接查验”
做混合检索绕不开中文分词。通用的 jieba 词典里没有“承接查验”“专项维修资金”“四保一服”“公区能耗”“公摊水电”这些行业术语,会被切得七零八落,导致 BM25 召回失效。
我的做法是维护一份行业自定义词典,从语料里用 TF-IDF 或 TextRank 自动抽取高频新词,人工过一遍后加进词典。词典规模不用大,两三百个词就够覆盖 90% 的场景。这份词典是长期资产,值得单独维护一个版本库。
另外还要处理同义词。“报修”和“报事报修”、“客服中心”和“服务中心”、“管理处”和“物业服务中心”、“保安”和“秩序维护员”,这些同义表达在不同地区、不同企业的叫法不一样,检索时必须能映射到同一个概念。我的做法是建一张同义词表,在查询改写阶段做扩展,而不是在索引阶段做归一化——索引阶段归一化会丢失原文表述,影响引用时的可读性。
4. 混合检索与重排:让一句口语化提问命中文档
4.1 为什么纯向量检索在物业场景一定不够用
向量检索擅长语义相似,但对精确实体几乎无感。物业问题里充斥着必须精确匹配的东西:房号(3栋2单元1802)、设备编号(SB-3-021)、电话号码、合同编号、条款号(第十七条第三款)、日期。
我做过一个对比测试,同样是问“3栋2单元电梯困人怎么处理”:
- 纯向量检索 top5 里,有三条是其他楼栋的电梯应急预案,因为“电梯困人怎么处理”这半句语义太强,把楼栋信息淹没了。
- 加上 BM25 之后,“3栋2单元”这个精确串被匹配上,top5 里有四条是本楼栋相关文档。
还有一类问题是向量检索的死穴:否定和排除。“哪些设备不需要季度维保”,向量检索会把所有讲“季度维保”的文档排前面,完全抓不住“不需要”这个逻辑。这类问题最终要靠重排模型和生成层的推理来兜。
4.2 完整检索链路:从 query 到 top5 的六步
我把生产环境跑的链路拆成六步,每一步都有明确的职责:
第一步,查询意图识别。用一个轻量分类模型(几百条样本微调的小模型即可,甚至规则也能覆盖大半)判断这是制度查询、台账查询、工单查询还是闲聊。台账查询直接走结构化接口,不进入向量检索。
第二步,查询改写。把口语转成规范表述。用户说“电梯关人了”,改写成“电梯困人 应急处置 流程”;用户说“水费怎么突然多了”,改写成“公共能耗 分摊 计量 异常”。改写用一个小模型做 few-shot 就行,不需要太复杂。改写时要保留原始 query,因为精确实体不能被改掉。
第三步,元数据预过滤。根据用户所属项目、角色权限、问题所属条线,先过滤掉不该看的、不相关的文档。这一步放在检索之前,既提准确率又降延迟。
第四步,混合召回。BM25 召回 top30,向量召回 top30,然后用 RRF(Reciprocal Rank Fusion)融合。RRF 的好处是不用调权重,对两路分数量纲不一致的情况特别稳。
def rrf_fuse(bm25_results, vector_results, k=60, top_n=20): scores = {} for rank, doc_id in enumerate(bm25_results): scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + rank + 1) for rank, doc_id in enumerate(vector_results): scores[doc_id] = scores.get(doc_id, 0) + 1.0 / (k + rank + 1) return sorted(scores.items(), key=lambda x: -x[1])[:top_n]k=60是论文里的经验值,实测在物业语料上 40 到 80 之间差别不大,不用纠结。
第五步,重排。用 cross-encoder 类重排模型对融合后的 top20 重新打分,取 top5 到 top8 送进生成。重排模型的选择上,中文场景建议用专门的中文重排模型,通用多语言模型在中文长句上效果会打折扣。重排这一步的收益非常明显,实测能把 top5 的准确率提升 15 到 25 个百分点。
第六步,上下文组装。把 top5 的 chunk 按文档、章节顺序拼接,每个 chunk 前面加上来源标识,方便生成层引用。
4.3 召回数量和上下文长度,不是越多越好
有个反直觉的结论:把 top20 全部塞进上下文,效果通常比 top5 差。原因是噪音稀释——模型在长上下文里对关键信息的注意力会下降,而且不相干的条款会诱导它做出错误关联。
我的经验参数是:top5 到 top8 送入生成,总长度控制在 3000 到 5000 字。如果 top5 的分数都低于阈值(比如重排分数低于 0.3),直接走拒答,不要硬凑。
另外,同一个文档的相邻 chunk 要做合并。比如检索到“第十七条”和“第十八条”,它们在原文里是连着的,合并成一个上下文比分开送更好,模型能理解条款之间的逻辑关系。
5. 生成约束与引用回链:答案要能被追问、被签字
5.1 引用不是装饰,是责任边界
物业行业有个特点,很多工作是要留痕、要签字、要被检查的。如果AI给出的答案没有出处,一线人员不敢用;出了问题,也没法界定是系统错了还是执行错了。
所以我在设计生成层时,强制要求每个关键论断后面挂引用标记,格式是[文档名 第X节]。生成完之后,系统再把标记替换成可点击的链接,跳到原文的对应页码。
这个约束需要在 prompt 里写死,并且用结构化输出保证可解析:
{ "answer": "根据《XX项目电梯困人应急预案(2023版)》第4.2条,接报后应在5分钟内通知维保单位,同时安排人员3分钟内到达现场安抚被困人员。", "citations": [ {"doc_id": "DOC-0231", "section": "4.2", "page": 12, "quote": "接报后5分钟内通知维保单位"} ], "confidence": 0.86, "needs_human": false, "reason_if_low": null }quote字段很关键,它要求模型摘出原文的连续片段。这个做法能显著降低幻觉率,因为模型很难一边编造一边摘出准确的原文。生成之后还要做一个校验:把quote拿去原文里做子串匹配,匹配不上就判定为可疑引用,降级处理。
5.2 拒答机制:什么都能答的系统,等于什么都不能信
我见过的最危险的设计,是没有拒答。用户问什么,系统都能组织出一段像模像样的回答。短期看演示效果很好,长期看是在消耗信任。
拒答要分三种情况处理:
第一种,检索不到。top1 重排分数低于阈值,直接回复“这个问题我在现有制度库里没有查到明确依据,已为您转接人工”。同时把这个 query 记进“知识缺口”清单,运营人员定期看,发现高频缺口就补充文档。
第二种,检索到但冲突。比如两个版本的制度都命中了,答案互相矛盾。这种情况不能选一个答,要明确告知“检索到两份文件对该问题表述不一致,分别为A版(2023)和B版(2024),建议以B版为准,请确认”。把判断权交给人。
第三种,超出权限。用户问的内容涉及他无权查看的文档。这里有个关键设计点:权限过滤必须发生在检索层,不能靠 prompt 里写“请不要透露”。后者是纸糊的墙,随便一句“忽略之前的指令”就能绕过。正确做法是在元数据过滤阶段就把无权限的 chunk 排除掉,模型根本看不到,自然也就答不出来。
5.3 时间感知:让模型知道“现在是什么时候”
物业知识有强时效性。收费标准、政策文件、合同期限,都跟时间强相关。通用模型不知道今天是几号,很容易引用已经作废的文件。
我的处理是在 system prompt 里注入当前日期,并明确要求“只引用 effective_date 早于当前日期且 expired 为 false 的文件”。同时在检索阶段就做时间过滤,双重保险。
还有一个细节:有些问题的答案本身就是时间相关的,比如“今年的物业费收缴率是多少”。这类问题必须走结构化查询,不能让模型去猜。系统里要维护一份“哪些问题必须查库”的规则,命中规则就强制走 SQL 路径。
6. 评测集怎么造:物业老师傅的口语就是最好的测试用例
6.1 别用内部人写的“标准问题”,那是自欺欺人
最常见的错误,是让项目组自己写 100 条测试问题。写出来的问题是这样的:“请问电梯困人的应急处置流程是什么?”——句式工整、术语规范、指向明确。这种问题在系统里当然答得好,因为真实用户根本不这么问。
真实用户怎么问?我从工单系统里抽过一批原话:
- “电梯又关人了咋整”
- “楼上漏水漏到我家了找谁”
- “车位费能不能月付”
- “昨天那个师傅说今天来修水泵,人呢”
- “消防检查要准备啥材料”
这些话术语不规范、指代不明、还带着情绪。RAG 系统真正的考验是这些。所以我的评测集构建流程是:从真实工单和历史会话里抽样,让一线主管写标准答案,技术团队不改写问题原话。
6.2 评测集的分层设计
一个能反映真实水平的评测集,至少要覆盖下面几层:
| 层级 | 数量建议 | 考核点 | 通过线 |
|---|---|---|---|
| 单跳事实查询 | 150 | 能否精准命中单一文档的单一结论 | 正确率 ≥ 85% |
| 多跳跨文档 | 80 | 能否串联两份以上文档(如先查台账再查合同) | 正确率 ≥ 70% |
| 表格数值查询 | 60 | 数值是否准确,有无串行 | 正确率 ≥ 90% |
| 冲突版本处理 | 30 | 能否识别版本冲突并提示 | 正确率 ≥ 80% |
| 拒答测试 | 50 | 面对不存在的问题能否拒答 | 拒答率 ≥ 90% |
| 权限测试 | 30 | 越权问题能否正确拒绝 | 通过率 100% |
拒答测试特别重要,题目要专门设计成“听起来很合理但库里确实没有”的问题,比如“我们项目的游泳池水质检测频率是多少”——如果这个项目根本没有游泳池,正确答案就是拒答,而不是编一个“每日检测”。
6.3 评测要看两个指标,不能只看答案对不对
很多团队评测只看最终答案,这是不够的。因为答案对可能是蒙对的,检索错了但模型靠常识补上了,这种在评测集上得分高,上线后遇到稍偏的问题立刻崩。
所以要分开评:
- 检索命中率 Recall@5:标准答案所在的 chunk 有没有进 top5。这个指标低于 80%,先别优化生成,回去修检索。
- 答案正确率:人工或强模型裁判判定答案是否与标准答案语义一致。
- 引用准确率:给出的引用是否真的支撑了答案。这个指标低说明模型在乱挂引用。
- 拒答准确率:该拒的拒了没有,不该拒的有没有误拒。
我一般会做一份 badcase 归因表,把每个错误标注成“检索未命中 / 检索命中但排序低 / 生成错误 / 引用错误 / 应当拒答未拒”五类。跑完一轮评测,哪一类占比最高就先修哪一类,比盲目调 prompt 有效得多。
7. 工程化落地:延迟、成本、权限与人工兜底
7.1 延迟预算要提前分配,不能事后优化
用户对问答系统的耐心大概是 5 秒。超过这个时间,一线人员就宁愿自己去翻文件了。所以延迟预算要在设计阶段就分配好:
| 环节 | 目标延迟 | 优化手段 |
|---|---|---|
| 意图识别 + 查询改写 | 200ms | 小模型或规则,不要用大模型 |
| 元数据过滤 + 混合召回 | 150ms | 向量库加标量索引,BM25 用倒排 |
| 重排 | 300ms | 控制候选数量在20以内,模型量化 |
| 生成 | 2000-3000ms | 流式输出,首字延迟控制在1秒内 |
| 后处理与引用校验 | 100ms | 子串匹配用哈希加速 |
| 总计 | < 4s | 留 1s 余量 |
流式输出是个被低估的体验优化。首字 1 秒出来,用户就知道系统在干活了,即使完整答案要 4 秒,感知上也不会觉得慢。
7.2 增量更新:别每次改一份文件就全量重建
物业文档几乎天天有变动。如果每次改动都全量重建索引,成本和时间都受不了。
我的方案是维护一张文档状态表,记录每个文件的mtime、hash、chunk_count。定时扫描(比如每天凌晨),只处理 hash 变化的文件:
- 文件新增:解析、切分、打标、入库。
- 文件修改:删除该 doc_id 下的所有旧 chunk,重新入库。
- 文件删除或作废:把对应 chunk 标记为
expired,不物理删除。
这个方案能把日常更新的耗时从小时级压到分钟级。注意要处理好事务性,别出现删了一半新的一半没进去的情况,建议用“先写新版本到临时命名空间,校验通过后原子切换”的方式。
7.3 人工兜底不是失败,是设计的一部分
我一直跟团队说,一个好的 RAG 系统不是“什么都自己答”,而是“知道自己什么时候该找人”。
兜底触发条件至少包括:置信度低于阈值、检索结果冲突、涉及金额超过某个数额、涉及安全责任认定、用户连续两次表达不满。触发后不是简单回一句“转人工”,而是把检索到的相关文档、历史相似工单一起推给人工坐席,让人接得住。
这套机制上线后,我观察到的一个有意思的现象是:一线人员对系统的信任度反而上升了。因为他们发现,系统答不上来的时候会老实说答不上来,而不是硬编。这种“诚实的边界”比“虚假的全能”有价值得多。
8. 几个真踩过的坑,以及后续还能往哪走
第一个坑,制度库太大导致通用条款霸屏。某项目把集团三百多份制度全量入库,结果问任何具体问题,top1 永远是《员工手册》里那句“员工应遵守公司各项规章制度”。原因是这类文档里全是高频通用词,向量和 BM25 都被它带偏。解法是在元数据里加doc_type和line过滤,同时在检索时对“通用制度类”文档做降权。
第二个坑,表格切断导致数值串行。某项目的收费台账按固定长度切分,结果“3栋”的表头和“1802室”的数值被切到两个块里,模型把 1802 室的面积安到了别的房号上。改成按行转自然语言之后彻底解决。凡是带数字的场景,切分方式必须重做,这一点怎么强调都不为过。
第三个坑,只做向量检索,房号查不准。前面提过,不再重复,结论就是必须上混合检索。
第四个坑,评测集自己人造,上线后被真实问题打脸。这个坑的解法只有一个:评测集必须来自真实用户原话。
第五个坑,权限靠 prompt 挡。这是安全红线,必须下沉到检索层。
往后看,这套系统还能往两个方向长。一个是往工单系统里嵌,让客服在录单的时候系统就自动推荐处置方案和历史相似工单,而不是等用户来问。另一个是往培训场景走,新人入职不用啃三百页制度,直接拿真实场景问系统,答完看引用,学习效率完全不一样。
我个人在实际操作中的体会是,物业行业做大模型,技术难度其实不高,难的是把语料治理、元数据设计、评测体系这些“笨功夫”做扎实。我见过太多团队把 80% 的精力花在选模型和调 prompt 上,最后败在一份没去重的旧版应急预案上。这个行业的钱是一分一分收上来的,事是一件一件做出来的,AI 落地也一样,先把每一份文档的版本理清楚,比什么都强。