1. 为什么银行对话内容不能直接“怼”给大模型做摘要
1.1 银行对话记录的特殊形态:它不是一段普通聊天文本
银行场景里的对话记录,和你平时在文档里看到的客服工单、会议纪要完全是两回事。拿我们接手最多的业务线来看,一条完整的对客服务会话,往往同时包含语音转写文本、即时消息、内部备注、工单流转记录,甚至还有电话录音转出来的带时间戳的逐字稿。这些内容既不干净,也不规整,最关键的是一个“会话”根本不是一次独立对话,而是跨渠道、跨时间、跨坐席的多轮交互。
比如一个客户申请贷款被拒,第一天在手机银行里问过进度,第三天又打了客服电话,第五天到线下网点补充了资料。如果只摘其中某一段对话,摘要写出来必然是不完整的。你摘了电话里那句“我明天去柜台补流水”,但没有摘到前两天App里已经问过的最新收入证明要求,后端的审批系统拿到这份摘要去判断客户真实意图,就可能出现偏差。
我们一开始试过直接把整段原始文本丢给通用大模型API,让它输出一段自然语言摘要。效果怎么说呢:单看文字很通顺,也确实把“说话最多的人”当作主角了,但银行真正关心的要素它基本总结不准——比如客户身份识别结果、业务诉求类型、承诺还款时间、情绪倾向、敏感词命中情况。这类要素其实不是“摘要”,而是一种结构化抽取,通用模型不会自觉按银行口径输出。
所以第一课就一句话:银行场景的对话摘要,第一步不是选模型,而是定义“什么是这段对话里值得留下的信息”。AUTOSUMM在设计之初就定下一个硬性约定——摘要产物必须是“结构化字段 + 一段自然语言概述”的组合,而不是纯自然语言。这一步想清楚了,后面的幻觉检测也好做得多。
1.2 摘要之外还有一层硬约束:不能让模型“补全”客户没说的事
对客服务摘要最容易出事的不是你漏了什么信息,而是模型把客户“可能想要”的内容写成了客户“已经表达”的内容。我曾经在一次内部Demo里看到一个真实案例:客户只是问了一句“还款日能不能改到发薪日后面几天”,摘要里竟然出现了“客户希望将还款日调整至每月10日,理由为发薪日为每月9日”。可原文里根本没有出现过“9日”“10日”这些数字,模型是根据常识自行脑补的。
这种错误在通用场景里可能是一种体贴,但在银行场景里就是高风险。摘要一旦进入后续审批流程、风控判断、客户异议处理,就会被当作事实依据。客户完全可能说“我从来没说过要改到10日”,这时候一旦责任倒查,AI生成的摘要就是最大的雷。
我们给AUTOSUMM定的验收红线很简单:摘要中的每一处关键事实,必须能在原始对话中找到出处;找不到出处的字段,一律不允许出现在输出里。这句话执行起来比听起来难得多,因为它本质上把传统的“生成任务”拆解成了“抽取 + 归因 + 生成”三段式。幻觉检测框架也因此在项目里不是一个加分模块,而是一等公民,从第一天就参与架构设计。
1.3 通用摘要产品做不到的事情,AUTOSUMM补上了什么
| 能力项 | 通用文档摘要方案 | AUTOSUMM在银行场景中的要求 |
|---|---|---|
| 输入处理 | 一段完整文本 | 多轮、跨渠道、含噪声的会话流,需要清洗与分段 |
| 输出格式 | 自然语言概述 | 结构化字段+自然语言概述,字段口径业务可配 |
| 关键事实完整性 | 按模型兴趣决定 | 按银行字段模板强制抽取 |
| 幻觉水位 | 偶发,影响有限 | 每条关键事实要求证据归因,拦截不可信输出 |
| 风险分级 | 无 | 按摘要产物风险等级决定是否需要人工复核 |
| 审计诉求 | 无 | 保留原始会话、摘要、证据的完整链路,可回溯 |
真正动手做过的人都知道,表格里每一行都是一堆细节。比如“保留完整链路”看起来简单,实际做的时候我们要给每一次摘要请求生成全局唯一的任务ID,把输入会话的分片ID、模型版本、提示词版本、温度参数、输出原文、检测结论全部落库。否则出了纠纷根本说不清这份摘要是什么时候、由什么配置产生的。
这一章想表达的核心判断是:银行场景做对话摘要,本质上是在做一个“有证据约束的结构化转写工具”,而不是套壳一个聊天助手。下面开始讲框架的具体设计。
2. 摘要主链路设计:从原始会话流到合格的结构化产出
2.1 输入治理:先把一坨会话变成可以喂给LLM的干净片段
原始会话数据进入AUTOSUMM后,第一站不是模型,而是一条清洗流水线。我们内部把它叫做“会话时间线重建”,因为银行原始转录数据经常出现三种让人崩溃的情况:一是语音转写把同一句话重复识别两遍;二是不同渠道的消息时间戳用的是不同的时区基准;三是坐席内部备注和客户原话混在同一条消息里。
我们最终的处理方式是:先按会话ID聚合全部消息,统一转为绝对时间戳,再根据“发言人角色”字段把内部备注分离到独立子列表,最后做一次跨句去重。去重不能简单按文本重复来,因为语音转写误差会导致相同内容不同文字表达,我们用的是“归一化文本相似度 + 时间窗口二次过滤”,实测能把重复片段压缩掉大约25%的无效输入。
清洗之后就要做分段。银行对话长短差异极大——短的几十个字,长的涉及几十轮、上万字的复杂投诉。直接把上万字塞进上下文窗口既不经济,也容易让模型丢失重点。AUTOSUMM采用一种动态滑动窗口分段策略:以“语义完整轮次”为最小单位,每段控制在3000字以内,段与段之间保留重叠的最后一组问答对,避免在分段边界切断核心信息。
分段这块有个容易踩的坑:如果单纯按字符数硬切,经常会把客户的一句长诉求切到两段里,等后面摘要合并的时候,这段诉求要么丢失,要么被模型各自猜一半。我们在工程上做了一个“软切点”逻辑——优先在客户说完或坐席给出回应的自然轮次处切分,字符数只是一个辅助参考,不是硬性上限。
2.2 提示词结构:让LLM按银行字段输出,而不是自由发挥
输入清理干净了,接下来就是核心的提示词设计。直接把“请摘要这段对话”的提示词投给模型,输出一定五花八门;说严重点,同一个模型跑十次能给你十种格式。我们的应对办法是建立一套固定骨架的银行摘要提示词,主要包含四个部分:系统角色定义、输出字段模板、断言约束、示例引导。
系统角色定义这块要写清楚“你是一个银行对话分析引擎,不是通用聊天助手”,并且明确禁止模型补充原文没有的内容。这部分看着像个形式,但实测对降低幻觉率有明显作用——角色一旦被限定为“转写分析器”,模型默认的“帮你补全”倾向会显著收敛。
输出字段模板是整套提示词里最重要的部分。每个字段都写明了类型、取值枚举和缺失时的处理方式。举个例子,针对“业务诉求类型”这个字段,我们定义了一组枚举值,包括“查询”“办理”“投诉”“撤销申请”等,模型不能自由发明新的业务类型;如果对话里没有明确诉求,就必须输出“未识别”,而不是靠上下文强行推断。
我需要特别强调“断言约束”这一层。我们在提示词里写了一段类似这样的话:“以下每个字段的值都必须有对应的原文支撑,如果找不到直接证据,字段输出为null,并给出evidence为原文中的引用片段。”这既是在约束生成,也是在为后面的幻觉检测提供原始佐证。
2.3 长对话的分层摘要与窗口合并策略
分段之后面临一个新问题:如果整段对话被切成6段,你总不能输出6份独立摘要让业务人员自己拼。AUTOSUMM的处理是两层结构:第一层对每个分段分别做细粒度摘要和字段抽取,第二层把各分段结果合并成一份全局摘要。
合并策略我们对比过两种方案。方案A是把所有分段摘要拼在一起,再次调用模型做二次摘要;方案B是把分段结果按字段聚合,关键字段直接取出现次数最多或置信度最高的值,自然语言部分再做一次融合。实测下来方案B的字段准确率更高,尤其适合“客户在多个分段里反复表达同一诉求”的情况。因为方案A在二次摘要时还是会引入压缩损失,简单地把高频诉求给抹掉;方案B则做了一个朴素但是可靠的投票机制。
合并之后还有一层全局归一化。比如客户在早段说了“想提前还款”,晚段又问了“剩余本金怎么查”,两段摘要的诉求字段分别是“提前还款处理”和“余额查询”,全局层就要识别这两个诉求确实属于同一次业务咨询的不同环节,生成一个“客户咨询提前还款事宜,并核实剩余本金”的合并描述。这一步靠的是字段模板和模型的双重配合,单靠规则很难写周全。
2.4 稳定性兜底:输出约束与后处理
提示词写得再细,模型仍然有概率输出非法JSON、字段拼写错误、或者在JSON里嵌套一大段解释性文字。AUTOSUMM在主链路里专门加了一个输出后处理层,职责是“把模型输出转成业务系统一定能解析的对象”。
第一步是JSON容错解析。我们见过的Bug千奇百怪:有多余逗号的、有单引号当双引号用的、有在字符串里混入换行符导致解析失败的。写一个健壮的解析器当然可以,但我更推荐的做法是:在提示词里明确让模型“只输出JSON对象,不要输出任何解释、前言或代码块标记”,同时在代码里做一次“截取首个合法JSON大括号”的容错。
第二步是字段白名单校验。根据当前会话的业务场景,把模型输出的字段和预期字段模板做比对,出现未知字段时直接丢弃并记录告警。这一步防止模型在迭代版本中自己悄悄新增字段,导致下游系统解析时发现新字段但不知道含义,处理逻辑出现异常。
第三步是空值兜底。凡是协议里要求“非空”但模型输出了空值的字段,我们不会强行填一个默认值,而是把该字段标记为“待复核”,交给后续的人工或规则补全环节。在银行系统里,宁愿缺失也不能给一个错误的默认值,这是很朴素的价值观。
3. 幻觉检测模块:两道防线挡住“编造”
3.1 前置防线:生成约束与证据抽取
幻觉检测不是摘要生成完再启动的事,AUTOSUMM把它做成了两道防线。第一道防线在生成阶段就介入,核心手段是“证据抽取先行、摘要生成在后”,而不是让模型先写一段话再去查。
具体执行时,我们在提示词的第一步让模型先输出一个“关键事实候选列表”,每个事实只包含主体、动作、对象、时间四个要素,不要求成句。然后要求模型为每个要素指明“证据”:原文中的起始位置和一段引用文本。模型只有在完成这一步之后,才开始写正式摘要。这样做的好处是,模型先把注意力放在原文事实的登记整理上,写摘要时是在已有事实列表上进行复述,而不是从零开始“回忆”,虚构空间被大幅压缩。
前置防线还包括一组显式的禁止指令。我们在提示词里固化了几条禁令:不得虚构客户身份信息、不得虚构金额和日期、不得推断客户未表达的情绪、不得补充坐席未做出的承诺。这四条不是摆设,它们其实在引导模型分配注意力,让模型在生成金额、日期这类高敏感词时更倾向于直引原文。
3.2 后置防线:事实一致性打分
生成完成之后,第二道防线开始工作。AUTOSUMM的幻觉检测模块会对最终摘要逐条做事实一致性校验。检测方式不是简单把摘要和原文拼起来让模型评分,而是采用“单事实抽取 + 局部判定”的方法。
先看整体流程:将摘要句子拆成若干条原子断言,每条断言是“主谓宾 + 关键修饰限定”的单一事实。接着对每一条断言,查找它对应的证据片段;如果证据缺失,就判定该断言“无证据”。如果有证据,就把断言和证据片段放在一起,让一个专门的小模型或同一个基座模型以审查者视角判断是否语义一致,输出“一致 / 不一致 / 存疑”三档。
这里有个很关键的设计:审查模型不能沿用摘要模型同样的提示词,必须换一个独立的“验证角色”提示词,并且最好把温度参数调得比生成时更低。为什么?因为如果生成和审查共用同一套思维模式,模型很容易对自己的产出“过度自信”,出现生成时的逻辑漏洞在审查时也被原样放过的情况。我们把审查器视为另一个独立的模型角色,给它设定“必须对原文负责,不信任输入摘要”的审查人设。
3.3 检测结果的归因与拦截策略
检测模块只给出“不一致”结论还不够,工程上必须回答“哪一条摘要字段出了问题、证据长什么样、应该怎么处置”。AUTOSUMM对每条原子断言都会返回一个结构化的检测记录,包含字段名称、断言原文、判定结果、证据文本、置信度。
处理策略上,我们按字段类型分了三个层级。第一类是“硬性敏感字段”,包括金额、日期、账号、客户承诺等,这类字段一旦判定为不一致,整个摘要直接进入人工复核队列,不允许自动流转到下游系统。第二类是“常规业务字段”,如诉求类型、渠道来源,不一致时先自动回溯上一轮摘要结果,如果仍然无法通过,才转入人工。第三类是“修饰性内容”,像语气、态度这类描述性字段,不一致时直接丢弃处理,不影响摘要整体流转。
拦截不是要追求“零幻觉”,而是把幻觉控制在可承受范围内。银行场景真正可怕的是幻觉悄悄混入并被下游当作事实采信。每一份被放行的摘要,其关键事实都必须有检测通过的标记;没有标记的摘要,业务系统根本拿不到。想做到这一点,意味着幻觉检测模块的召回率比精确率更重要——宁可误判多拦几份,也不能放过一份确定有问题的。
# 伪代码示意:一条摘要事实怎么走完检测链路 def check_fact(summary_claim): evidence = retrieve_evidence(summary_claim, original_dialog) if not evidence: return {"result": "no_evidence", "action": "human_review"} consistency = verify_with_llm( claim=summary_claim, evidence=evidence, role="independent_verifier", temperature=0.1 ) if consistency == "consistent": return {"result": "pass", "action": "auto_release"} elif consistency == "contradict": # 按字段风险等级决定动作 return {"result": "fail", "action": risk_based_action(summary_claim.field)} else: return {"result": "uncertain", "action": "human_review"}这个流程看起来不复杂,但它把所有可能的取巧空间都堵死了。证据检索用的是BM25和向量召回混合机制,先按关键词找到最可能相关的原文片段,再用向量相似度做二次排序。实测混合召回比单一向量召回更稳定,因为银行专有名词、简称、错别字经常让纯向量召回找不到精准出处。
4. 评测体系与实测结果:先证明它真的有效
4.1 内部测试集到底怎么构造
任何框架说自己有效,都得先过评测这一关。AUTOSUMM上线之前我们建了一套内部评测体系,整个构造过程比想象中费劲。测试集来自两个渠道:一是脱敏后的真实对客会话,二是由业务人员按历史案例重新编排的模拟会话。两者比例大概是7比3,模拟数据是为了覆盖真实数据里数量很少但风险极高的场景,比如客户恶意投诉、坐席口头承诺超权限内容等。
每一条测试样本的标注分两轮。第一轮由一组业务骨干独立标注出他们眼中“这份摘要必须包含的信息点”;第二轮由算法同学基于业务标注做归一化,合并同义信息点,去掉无关干扰项。最终标签体系包含三部分:必备字段值、可选字段值、禁止出现的幻觉点。所谓幻觉点,是指业务人员明确标注“这句话在原文里没有对应,绝不能出现在摘要里”的内容。
还必须说清楚一点:真实会话脱敏不是简单删除姓名电话就完事,姓名、账号、住宅地址、单位名称都要做泛化替换,有时候还需要重写部分地名。脱敏后的数据语义结构也会有微调,所以我们在测试集里单独标注每条数据是否经过深度改写。训练或评测的时候不能把深度改写的数据和原始数据混在一起而不做区分,否则指标会显得虚高。
4.2 摘要质量与幻觉率分开看,别被一个分数骗了
很多团队评估摘要质量时只看一个ROUGE-L分数,我自己以前也这么干,后来发现这个指标在银行场景里会骗人。ROUGE衡量的是字面重叠度,而银行摘要更关心的是关键字段是否准确、有没有编造,对行文是否优美要求很低。
AUTOSUMM的评测指标体系拆成两个维度。第一维度是“摘要信息完整度”,把输出摘要里的信息和人工标注的必备信息点做匹配,计算召回率和精确率。这里不要求字面一致,而是通过语义相似度加字段模板来判定某个信息点是否出现。第二维度是“幻觉发生率”,统计输出摘要里有多少条原子断言被判定为在原文中找不到证据或与原文矛盾,除以全部原子断言数得到幻觉率。这两个指标要一起看:如果完整度很高但幻觉率也很高,说明模型在“努力编造”;如果完整度低但幻觉率低,说明模型过于保守,漏了大量信息。我们要的是高完整度、低幻觉率,二者缺一不可。
每条测试样本还会输出一个细粒度报告,从字段维度观察到底是哪个字段容易出错。我们发现不同模型的“薄弱字段”差异很大:有些模型在“客户情绪”字段上经常编造,有些模型在“坐席承诺”字段上容易漏掉关键内容。没有这个粒度,你只知道模型不好,但说不清它哪里不好,优化起来等于盲人摸象。
4.3 内部实测数据与失败案例复盘
在内部测试集上,我们对比了直接调用通用大模型API和接入AUTOSUMM完整链路的效果。直接调用的基线在摘要信息完整度上大概71%,幻觉率在8.2%左右,也就是说每100条原子断言里大约有8条存在无证据或矛盾情况。接入AUTOSUMM后,经过结构化字段约束与前置证据抽取的约束,信息完整度提升到84%,幻觉率压到3.6%。再加后置幻觉检测和拦截策略,最终自动放行摘要的幻觉率维持在0.8%上下,其余疑似问题全部转入人工复核。
数字看起来不错,但复盘失败案例时还是能发现几个反复出现的模式。第一种是“跨轮联想”:客户在第3轮说过要申请调整额度,第10轮又说了一句“那就算了吧”,模型在摘要里却写成“客户希望继续推进调整额度申请”,漏掉了反悔信息。这不是模型没读懂,而是摘要的“时间维度”没有做好,没有区分早期意图和最终意图。后来我们在字段模板里增加了“诉求状态”维度,才显著改善。
第二种是“常识补全”:客户说“我工资卡是你们行的”,摘要里就被写成了“客户工资卡开户行为某分行”,开户行这个细节原文根本没有。这类幻觉最难检测,因为模型补得合理、通顺、像真的。我们发现优势是证据抽取前置能大幅减少这类问题,因为关键事实登记时模型就找不到对应证据,自然就不会进入后续摘要。
第三种是“引用错位”:摘要里说的内容原文其实有,但指的是另一个时间段或另一件事。例如原文客户先问“信用卡还款方式”再问“分期手续费”,摘要把分期手续费算成了客户关心的主要问题,虽然两个词都出现过,但因果关系错位了。这种错位单靠摘要评估指标根本看不出来,必须依赖逐条断言的事实一致性判定。
5. 落地过程中踩过的坑和最终收敛的经验
5.1 “摘要准确但业务不认”——人和流程的问题比模型更大
框架评测全部通过之后,我们以为马上就能上线,结果发现真正的阻力不在技术,而在业务侧的使用惯例上。业务人员长期习惯看原始对话记录,他们对一份AI生成的摘要天然不信任;更麻烦的是,坐席在发生纠纷时习惯把原始记录翻出来逐字核对,摘要对他们的意义并没有想象中那么大。
后来我们调整了产品定位:AUTOSUMM的摘要不是替代人工记录,而是作为“初稿”。人工坐席在会话结束时看到一份预生成的摘要,可以修改、补充、确认后保存为正式记录。这个看似多了一步的人工确认,反而让业务方放心了,因为最终的责任主体还是人,AI只是辅助助手。上线一段时间后,坐席对摘要模板的实际修改率逐步降低,才真正开始按“AI自动生成,人工抽检”的模式运转。
这里有个教训:在银行场景里,AI系统的价值不仅是把活干好,还要让流程中的“人”能清楚地看到AI干了什么、有没有依据。技术负责人如果只盯着模型指标而忽略使用流程的重构,项目很容易死在试用阶段。
5.2 模型选型和prompt调优,到底该把力气花在哪
很多团队纠结于换更大的模型还是继续调prompt。AUTOSUMM的结论是:在银行场景里,先做约束工程,再做模型选型。我们早期拿一个小参数量的开源基座模型跑完整链路,幻觉率始终压不下来,后来并行测试了更大的商用大模型API,幻觉率确实下降了一个档次,但成本也同步上升了一截。真正让幻觉率产生质变的,不是换模型那一下,而是我们把“结构化字段约束 + 证据前置抽取 + 独立审查器”这条链路彻底跑通。
我的建议是,如果业务场景对幻觉非常敏感,先把框架搭对再升级模型。同一套链路在不同模型上迁移时,主要改动集中在提示词的角色描述和输出格式示例部分,核心逻辑不用动。这让我们在后来的模型升级中省了很大力气,直接替换接入层即可。
同时要留意模型版本升级带来的“隐式行为漂移”。同一个提示词在上一个版本模型上能稳定输出合法JSON,升级后可能开始偶尔在JSON前后附加解释性文字。我们在模型gateway层加了一个每日输出格式质检任务,定时用一组固定样本巡检,发现问题立刻告警并回滚模型版本。这种保障措施在银行环境里很重要,因为没有人能接受生产模型悄悄改变行为。
5.3 场景分级、字段模板配置化和人工介入的平衡
最后聊一下AUTOSUMM的可配置能力。银行内部场景非常多,对客服务、电话营销、投诉处理、贷后管理各有各的字段侧重点。如果把字段模板写死在代码里,每接一个新场景都要开发,根本跑不起来。
AUTOSUMM把场景差异抽象成了一组配置文件,每个场景对应一套字段模板、一组枚举值、一组敏感字段名单和一个风险处置策略。新场景接入时,产品经理和业务专家只需填写配置表,不用改代码。这份配置表本身也会经过合规评审,确认字段范围不越界。
人工介入的比例根据场景风险等级动态调整。低风险场景(比如常规业务咨询)自动放行率达到95%,中风险场景(比如涉及费用争议)自动放行率降到70%,高风险场景(比如投诉升级、涉及承诺或赔付)基本全量人工复核。这样一个分级体系既保证了安全底线,又把人工成本用在最该用的地方。
6. 我做这个项目最深的几个体会
项目做完复盘时,我反复想到的是开头那个“客户说改还款日,模型脑补出10号”的例子。技术同学可能觉得这是个幻觉检测评分问题,业务同学觉得这是个责任归属问题,但归根结底,它暴露的是整个系统在“事实边界”意识上的缺失。模型不知道什么是自己知道的边界,所以框架必须替它画好。
AUTOSUMM最终沉淀下来的东西其实不复杂:结构化输出模板、证据前置抽取、独立审查器、场景化配置。每一个单独拎出来都不新鲜,但组合在一起,并且针对银行对话数据做了大量细节适配之后,效果是实打实的。如果你正在做类似的LLM落地项目,我的建议是不要先追求模型跑得快,先想清楚你的系统如何回答“这句话凭什么可信”。把这个问题的答案固化到流程里,后面的路会顺很多。
最后分享一个开发期的小技巧:幻觉检测模块不要只拿正例调优,一定要保留一批“看似通顺但有微妙错误”的难例。这类数据才是区分真检测能力和表面精度的关键。我们在内部每周都会从生产环境抽检数据里筛选新的难例补充进测试集,这个习惯比任何超参数调优都更能长期提升系统的可靠性。