给银行做AI助手踩过的三个坑,和我后来一步步填坑的办法行里想要的东西很简单:让客户经理、风控、合规能随口问一句"这个客户的授信额度批了多少"、"这条监管口径现在按哪版执行",AI直接给答案。我把信贷合同、风控报告、内部制度、企业微信几年的记录灌进向量库,套个对话框,五天出了demo。演示那天答得有模有样,几个行领导轮流问,没问倒。我心里想,这活儿不就这样嘛。然后是接下来的三个月。模型那部分我大概只花了5%的精力,剩下全砸在数据上。集中爆发的是三个问题,我先把现场讲清楚,后面再说怎么解。一是版本。一个客户经理问某笔贷款的利率和担保条件,AI翻出来的是去年还没过会的草稿版,他直接拿去跟客户谈了。同一笔业务,OA一版、共享盘一版、个人电脑还存一版,向量库根本分不清哪个作数——它只看到两个挨得很近的向量,就把废稿和终版一起捞了出来。二是权限。一个零售条线的员工问"对公那边某大客户的授信情况",按规矩他根本无权看。要是AI把对公材料念给他,这不是bug,是要上报的合规事故。三是数据接入。我代码库里九成都是连接器。科技部把共享盘目录重新归类,我的同步任务半夜就挂了,第二天AI全在答三天前的旧数据。解法一:把"文档状态"做成检索的硬过滤,而不是让模型去猜核心原则一句话:作废和过期的文件,压根不该进入候选集。 别指望模型读出来之后自己判断哪个有效。具体分五步:1)入库时给每个chunk打全套元数据。至少包括:doc_id(文档唯一号)、biz_key(业务主键,比如合同号或"客户号+业务类型")、version、status(draft/effective/superseded/void)、effective_date、source_path。这些字段在切块时就写进向量库的 payload,不要事后补。2)用 biz_key 把同一份东西的多个版本归成一个"文档族"。 同一笔贷款的草稿、终版、补充协议,doc_id 不同但 biz_key 相同。这是后面去重的基础。3)检索时强制带元数据过滤。 查询语句固定加上 status == effective(或排除 draft/void)。主流向量库(Milvus、Qdrant、Weaviate、PGVector)都支持 metadata filtering,把它当成和向量相似度同等的硬条件,而不是软加权。4)检索后按文档族去重,只留最新。召回的结果里如果同一个biz_key出现多个版本,按effective_date倒序,只保留第一条再喂给模型。这一步拦住"漏网"的旧版。5)入库时自动维护状态。写一个轻量job:新版本入库时,按biz_key把同族的旧版标成superseded。这样状态是自动流转的,不靠人记得去改。最后留个兜底:让AI在答案末尾附上来源文件名+生效日期,业务人员一眼能核。出错时也方便追是哪一步漏了。解法二:权限不要在 AI 层重写,前移到接入层并默认拒绝银行里跨条线、跨支行、前台和风控之间的墙特别厚。我走过的弯路是想在 AI 这头从零造一套权限逻辑,结果每次调用都要现查现拼,又慢又容易漏。后来改成下面这套:1)复用源系统已有的权限,别自己发明。AD、OA、核心系统里本来就有部门、条线、角色、密级。直接读它们,不要在AI侧另搞一份对照表——两份迟早会不一致,不一致就是事故。2)入库时把权限标签写到chunk上。 每个chunk继承它来源文件的访问控制,打上allowed_groups、条线、密级 等字段。权限信息和内容一起进库。3)查询链路先解析用户身份,再注入成强制过滤。用户提问时,先用工号查出他的条线/权限组/密级,把这些作为metadata filter直接加到向量检索的 query里。关键是过滤发生在检索引擎层,模型根本看不到他无权看的chunk——而不是检索出来再让模型"装作没看见"。4)默认拒绝(deny by default)。没有明确授权标签的chunk一律不进候选。宁可少答,不可错给。5)建权限红线测试集,定期回归。准备一批"必须答无权限"的问题(跨条线问授信、低密级问高密级文件),每次改完检索逻辑都跑一遍。这一关不过,不许上线。6)全程留审计日志。每次检索记录who(工号)、what(问题)、which docs(命中的文档)。出问题能倒查,也是过合规审查的必备材料。我代码库九成是连接器、还特别脆,这件事本身就说明架构错了——你以为在做AI,其实在做数据搬运。这里先做一个判断,再决定怎么搭:先算一笔账,决定自建还是用现成的。 数据源就一两个、文档量不大、几乎不变,那自己写连接器没问题。我那家行是几万份文档加多个孤岛、还天天变,自建的维护成本就是无底洞。这种情况我后来引入了托管的"上下文层"接管接入,自己只保留检索策略的控制权。1)增量同步,别每次全量。基于文件的修改时间或版本号,只同步变过的,省时间也少出错。2)幂等+断点续传。同一批数据重跑一遍结果要一致;中途挂了能从断点接着来,而不是从头再灌一遍。3)schema变更要有告警。源系统改了字段、目录结构变了,连接器要能主动报错,而不是默默同步出一堆脏数据——我那次半夜挂掉就是没有这个。不管自建还是买,监控必须上。 把每个数据源的同步延迟、失败率、"最近成功同步时间"做成一块看板,超过阈值就报警。我后来加了个"文档新鲜度"指标:如果某个源超过 N 小时没更新成功,先告警,必要时让 AI 对这个源的问题主动说明"数据可能不是最新的"。上线用灰度。 先接一两个高价值、相对干净的数据源(比如信贷合同库)跑通全链路,验证版本和权限都没问题,再逐步扩到其他孤岛。一上来全接,出了问题根本定位不到是哪个源。回头看,这三个解法其实是同一件事的三个面:真正决定AI答得对不对的,不是模型,是它检索的那一步给了什么。 版本、权限、新鲜度,全都要在"召回候选集"这一层就处理干净,而不是丢给模型去事后补救。如果只让我留一条经验:在向量相似度之外,把"状态过滤"、"权限过滤"、"按文档族去重"这三道闸做成检索的标配。 缺一道,银行里的代价都不是答错题,是出事。