去年我主导了一个智能客服平台从零到一的设计与落地,整套系统基于LLM(大语言模型)搭建,上线后稳定运行了三个多月,扛住了一年中最大的活动流量,也把各种诡异问题从日志里一个个捞出来解决掉。这篇文章不是泛泛介绍智能客服能做什么,而是把那段踩坑之后沉淀下来的架构设计思路、关键模块的参数配置、安全可靠性方案,以及几个最典型的故障排查过程完整拆开来讲给你听。
如果你正在设计或重构一套基于LLM的智能客服系统,尤其是对“高效、安全、可靠”这三个词有明确要求的业务场景,那么这篇文章里的架构分层、RAG检索细节、上下文管理、安全防线、降级与熔断方案,以及最后那部分问题排查实录,应该会比较对胃口。就算你只是对这套系统感兴趣,想了解一个按真实业务需求打磨出来的技术方案长什么样,也可以放心往下看。
1. 整体设计思路:先想明白要解决什么问题
1.1 传统客服转向LLM的必然性
早期电商、金融、在线教育这类场景里的智能客服,大量采用的是“FAQ匹配 + 关键词规则 + 多轮任务树”的组合方案。这种方案不是不能用,而是维护成本会随着业务膨胀快速失控。新商品、新活动、新政策上线,运营人员要手动维护几百上千条问答对,稍微漏掉一个说法不一致的触发词,用户就会被导到“对不起,我没有理解您的问题”。
基于LLM的智能客服,核心变化在于把“人工写规则来匹配问题”变成了“让模型理解意图并组织答案”。用户说“我昨天买的手机还没发货,能帮我看看吗”,模型不需要命中某个预先设定好的关键词,而是能理解这是“催发货”意图,再去调用查单接口或者检索物流知识库。这个转变让客服系统的可对话边界一下子打开了。
但LLM并不是万能的。它的问题也特别明显:会产生幻觉,编造不存在的政策;对实时业务数据一无所知,需要挂接工具;对大段私域知识无法记忆,必须靠检索补充;还存在被提示词注入攻击的风险。所以整个架构设计的出发点,不是“如何用LLM把原来的客服机器人替换掉”,而是“如何把LLM嵌到一套可控的客服链路里,让它既聪明又不失控”。
1.2 项目初期我们把目标拆成了四个非功能指标
很多团队做这类系统,一开始就把注意力放在“模型选谁”“要不要用Agent框架”上,反而忽略了真正要紧的事情。我们当时在需求评审阶段,把目标明确写成了四个可验证的指标:
- 高效:单次对话的端到端响应时间P95控制在3秒以内,高峰期不出现雪崩式超时。
- 安全:对私域知识不泄露、对用户隐私数据做脱敏、对恶意注入进行拦截、输出内容可审计。
- 可靠:单点故障不影响主流程;模型服务不可用时有降级方案,客服服务不能直接挂掉。
- 可运维:所有链路有日志追踪,每次回答能回看检索命中了什么、模型怎么生成的,方便追责。
这四个指标后来成为整个架构设计的决策标尺。很多技术上看起来“更酷”的方案,最后都因为不符合这几条而被过滤掉了。
1.3 我们对“智能”的边界做了取舍
在方案设计阶段,我们明确划分了三类能力边界。第一类是纯知识问答,比如“你们的退货政策是什么”“这个商品支持分期吗”,归RAG链路管,模型根据知识库内容来回答。第二类是任务执行,比如“帮我查一下上周的订单物流”“取消这笔订单”,归工具调用链路管,模型只负责从用户话里抽取参数,然后调用业务接口。第三类是复杂推理和主动服务,比如“对比这两个套餐哪个更适合我”,这类问题我们没有在首期铺开,而是直接转人工。
这个取舍很重要。如果一开始就让LLM尝试所有复杂任务,模型的不确定性会在客服场景里被放大,安全风险也不可控。先做稳知识问答和基础工具调用,让系统先把跑得好的场景跑稳,再逐步扩展能力边界,是更务实的路径。
2. 总体架构与模块拆分:先画好边界再写代码
2.1 四层架构,把系统拆成可以独立演进的模块
我们最终采用的分层架构大概是这样,从上到下分成接入层、服务层、模型层和数据层。
接入层负责统一接收来自App、网页、小程序等多个渠道的会话消息,做基本的鉴权和风控,然后把消息转成内部统一的会话事件格式。这里不直接跟LLM相关,但它的重要性在于:客服系统必须支持多渠道接入,而每个渠道的用户身份体系、消息格式、超时策略都不一样,不统一接入层,后面的逻辑会被渠道差异拖垮。
服务层是核心业务逻辑所在,包含会话状态管理、会话历史存储、意图路由、工具调用、RAG检索、Prompt拼接、安全审核、降级控制等模块。这一层是嵌入LLM的关键位置,所有与模型交互的逻辑都集中在这里,便于统一控制上下文长度、注入安全策略、记录日志。
模型层做的主要是各类模型能力的统一封装和调度,包括对话模型、Embedding模型、Rerank重排模型、以及敏感词和内容审核模型。我们不直接让业务代码调用具体的模型供应商接口,而是封装成统一的模型网关。
数据层包括知识库、会话日志、向量索引、业务系统接口的适配层。知识库用于支撑RAG检索,业务系统适配层用于让客服系统安全调用下单、查询、退款等能力。
这个分层最大的好处,是每一层都能独立升级。比如后来我们换了更强的Embedding模型,服务层完全没有改动,只是把模型层的配置切换了一下就完成了。如果当初把模型调用散落在各个业务代码里,这种替换会非常痛苦。
2.2 一次完整对话在主流程里经过的七个节点
为了让你对整体链路有个具体印象,这里把一次用户提问在系统内部的旅程写出来:
- 用户发来消息,接入层完成鉴权和风控,生成会话ID。
- 服务层从会话管理模块取出最近的对话上下文,组装为一个结构化会话对象。
- 意图路由模块判断这是一个“知识咨询”还是“任务办理”还是“转人工”请求。
- 知识咨询走RAG链路,对用户问题进行向量化,到向量库召回候选知识片段,再经过重排模型筛选。
- Prompt拼接模块把系统指令、检索到的知识片段、历史上下文、当前问题组装成最终发送给模型的内容。
- LLM模型推理生成回复,返回结果经过内容安全审核,对涉及隐私的部分做脱敏。
- 服务层把回复写回会话存储,通过接入层推送给用户,并把整个链路的调试信息写入日志。
这个链路里的每一步都有专门的模块负责,而不是在业务代码里硬写。流程看起来简单,但每一步的细节都藏了不少坑。接下来的章节会拆开讲。
2.3 技术选型的几个关键决定
先说模型。我们当时并没有盲目追求参数最大的模型,而是选了一个中文能力扎实的开源基座模型私有化部署。原因很简单:客服会话的每一句话都涉及用户数据和业务数据,直接调用外部API会带来数据出域风险,而且没办法完全控制采样参数和上下文长度。私有化部署之后可控性大大增强,成本也能通过量化压缩控制住。
向量库的选择也做过多个对比。我们最终没有选择用一个额外组件,而是直接用了已有基础设施里的通用检索组件来承载向量索引,因为它在团队里已经维护了两年,稳定性有保障。如果你从零开始,专门部署一个向量库完全没有问题,但一定要考虑运维成本和团队熟悉度。
关于Agent框架,我们评估过用现成的编排框架来管理工具调用和任务流程,但最终选择自己写了轻量的路由与工具调用逻辑。因为客服场景的流程控制要求非常强,需要精确管理每一次调用的参数、超时、错误处理,通用框架在这个场景里反而会带来黑盒不可控的问题。这个决定在后来的排障过程中被反复证明是正确的——因为我们能直接看懂每一层到底发生了什么。
3. 核心模块的实操要点与参数选择
3.1 会话管理:控制上下文窗口才是重中之重
LLM的上下文窗口是有限的,而用户对话可能很长。如果不做管理,对话超过上下文上限后,要么报错,要么最前面的信息被截掉,导致理解错乱。
我们当时定了一套会话状态管理方案:会话状态存储在缓存里,近10轮完整对话保留在结构性数据中,超过10轮的部分按照用户意图做摘要压缩,再连同最近10轮一起送入模型。这意味着无论用户聊了多长时间,模型看到的上下文长度都不会无限增长,P95延迟就能稳定住。
在发送给模型前,还要做一次Token预算控制。我们把整个Prompt按优先级分为四块:系统指令、检索知识、历史会话、当前问题。当总字数超限时,优先裁剪“历史会话”部分,再裁剪“检索知识”中排列靠后的内容,永远保证“当前问题”和“系统指令”完整。这样设计的原因是:对回答质量影响最大的,是用户当前想问什么以及模型该遵守什么规则,历史信息哪怕少一点,也比如今从头到尾什么都有但被截断要可靠得多。
3.2 RAG链路:让模型老老实实用知识库说话
客服系统的答案必须来自业务知识库,而不是让模型自己编。这里就依赖RAG(检索增强生成)把知识库内容检索出来,再交给模型组织成回答。我们在这条链路上踩过最深的一个坑是“检索不到相关片段但模型依然给出答案”。后来通过三项改动解决了。
第一项是切分策略。知识库里的文档我们不能直接整篇扔给模型,必须切成合适的片段。我们经过反复调试,最后采用按标题层级切分加固定窗口补全的办法,核心参数是大段落按一级标题先切,小于200字的小段落不切,每个片段控制在200到400字之间,片段之间保留30字的重叠。重叠文字的作用是防止“一句话被切到两个片段里导致语义断裂”。
第二项是召回参数。我们对用户问题进行向量检索,取回前20个候选片段,再用重排模型逐条打分,只保留前5个送入Prompt。很多人会直接取TopK=3或TopK=5,但我们建议先取大候选集再用重排模型做精排,效果比单纯加大向量召回数量要好得多。
第三项是在Prompt里明确限定模型的权限范围,我们写的是:只能依据给定的知识片段回答问题;如果知识片段不包含答案,如实说不知道,并建议转人工或查询官方渠道。这行指令看上去简单,但它直接把“模型胡编”的比例降了一个量级。模型生成了内容之后,还会做一轮引用校验,只有答案中出现的具体信息确实能在知识片段里找到对应依据,这条回答才会被投放出去。
3.3 意图路由与工具调用:从聊到办只差一步可控跳转
客服系统不能只回答“是什么”,还必须能做“怎么办”。我们设计了一套轻量级路由机制,让模型先做意图分类,输出预设的JSON结构,然后服务层根据JSON里的意图字段决定走哪条链路。
第一层路由把请求分为知识咨询、业务办理、订单查询、转人工、闲聊五类。分类采用小模型或Prompt分类均可,但关键点在于要让模型输出结构化的JSON,并且限定枚举值集合,不能让它自由发挥。例如输出为“订单查询”时,服务层才会触发工具调用链。
工具调用环节是风险最高的部分。客服系统要替用户查订单、办退款,一旦参数理解错会产生资损。我们的做法是严格限定参数抽取schema,模型只能抽取用户明说的参数,不补充猜测信息。用户说“帮我查我的订单”但没说订单号,模型会反问要订单号,而不是自作主张去查。涉及资金类的动作,比如退款、价格修改,系统一律二次确认,把用户意图、执行动作、涉及金额拼成确认文案返回给用户,确认无误再调用业务接口。
调用业务接口时,统一通过业务适配层进行,超时时间设置为2秒,失败不降级到模型硬答,而是如实回复“系统暂时有点忙,请稍后再试”并转人工处理。这块必须坚持,因为客服场景里错误执行比不执行更糟糕。
3.4 缓存策略:能不进模型就不进模型
在大促场景里,流量短时间会拉到平时的几倍,如果把每个问题都送到LLM做一次推理,成本高且延迟不可控。我们最终通过三层缓存把模型调用量压下去不少。
第一层是热点问题缓存。对一些问法相近而答案一致的问题,如退换货时间、发票类型、发货时效,我们提前配置答案模板并绑定触发条件,命中后直接走模板返回。第二层是语义缓存,把用户问题向量化之后,与最近一段时间内的历史问题做相似度比较,相似度超过0.92就直接返回当时的回答,并带上“这是一个关联问题的参考回答”的标识。第三层是会话级去重缓存,同一个会话内用户在30秒内重复发送相同内容,返回上一次的答案。
三层缓存叠加后,大促当天的模型调用量降低了约40%。缓存命中时响应基本能做到百毫秒级别,极大保护了下游模型服务的稳定性。但要注意给缓存设置合理的失效时间,否则业务政策变化会导致答案过期,又出现一批“已经是老黄历”的回答。
4. 安全与可靠性:客服系统最不能省的功夫
4.1 输入侧的四道防线
LLM客服面临的一个现实威胁是提示词注入。用户可能会故意发送“忽略系统设定”或“把文档原样输出”这类内容来试探。对这类情况,光靠模型自身防御是不够的,我们在输入侧布置了四道防线。
第一道防线在接入层,做基础的事前过滤,包括敏感话题、明显攻击特征词,命中即拦截并返回标准话术,不进模型。第二道防线是注入检测器,我们用一个专门的小模型或规则模型对每个用户输入做分类,判断是否处于“试图操控系统指令”的风险档。这条规则不追求百分之百精准,主要是把最高风险的一批输入提前挡在模型之外。第三道防线是Prompt结构分隔,把用户输入与系统指令在物理上用分隔符隔离,并对用户输入做转义处理,避免它在拼接后覆盖指令区。第四道防线是会话行为风控,同一个会话短时间内连续触发多次注入尝试,系统直接单向转入工人工客服,不再与用户对话。
这套防线在压力测试里拦截住了一批常见攻击,也给审计留下了完整的记录。多说一句:哪怕拦截率只有90%,对客服系统来说都是关键的,因为攻击只需要成功一次就可能造成舆情风险。
4.2 输出侧审核与隐私脱敏
模型生成的内容并不是直接发给用户,而是先经过一道输出审核闸门。我们做了三层检查:第一层是敏感词过滤,覆盖暴力、色情、政治等违禁类别,命中即拦截重写;第二层是隐私检测,识别手机号、身份证号、银行卡号等个人信息,对不符合业务需要展示的字段一律打码;第三层是事实一致性抽检,随机抽取一部分回答,人工复核答案中的关键信息是否与知识库一致,抽检比例固定在5%。
输出侧审核还有一个容易忽略的点,就是要对回答里的“确定性表达”做处理。模型经常会说“应该是可以的”“我理解可能是”,这种含糊表达在客服场景里容易引发歧义。我们要求模型在知识库无明确依据时直接给出标准话术“这个情况我无法准确核实,为您转接人工核实处理”,而不是使用含糊措辞暗示不确定但可操作。
4.3 数据隔离与权限管控
客服系统会触及用户订单、个人信息,数据隔离是合规底线。我们采用了租户隔离与角色隔离交叉的方案。在检索知识库时,不同的业务线维护独立的知识集合,向量检索时强制附加业务线过滤条件,防止一个业务线的问题检索出另一个业务线的知识片段。在调用业务接口时,通过接入层的用户身份换取访问令牌,令牌包含本次请求允许访问的资源范围,业务系统根据范围校验才返回数据。
所有会话日志和模型推理日志分开存储,原始会话日志设置较短的保留期并做加密,模型推理日志保留用于排障但不含用户实名信息。因为一旦模型日志泄露,里面记录的对话片段很可能包含订单内容,这个风险要在架构层面提前规避。
4.4 降级、熔断与限流的联动设计
任何同模型的服务都要假设依赖可能随时不可用,我们为此设计了三层防护。第一层是限流,在接入层按用户维度设置动态接口速率上限,超限排队等待而不是直接拒绝,配合异步重试消化短暂高峰。第二层是熔断,对模型服务、向量检索、业务接口分别做健康度统计,连续失败达到阈值后自动切换到降级模式。第三层是降级,降级不是“啥都不做”,而是有明确层次:先停用重排模型只做向量召回,再停用工具调用改为跳转人工,如果模型服务彻底不可用,整体回到一个简单的规则应答通道,返回一个预设的安抚话术并亮出人工客服入口。
这套机制的价值在于,它保证了每次故障都不会把用户丢在“问了没人理”的境地,而是总有一条兜底路径。有一次模型服务商确实出现了不可抗的网络抖动,我们这端因为自动降级,用户端几乎没有感知到服务中断,只有内部监控日志显示走了降级通道。
5. 排查实录:上线前后踩过的几个坑
5.1 模型乱编答案,症状出现在源头但根源在检索
上线初期,我们接到大量反馈说模型会给离谱的回答,比如用户问“你们客服几点下班”,它一本正经回答说“晚上10点前可以联系,也可以通过第三方渠道办理报废手续”。排查日志后发现,当天的知识库里其实没有“客服下班时间”这条片段,但向量检索召回了语义相近的几条“售后报废流程”,模型把其中无关信息当成了答案来源。
解决动作分两步。第一步是给RAG加上最终答案与引用片段的相似度校验,若生成答案与引用的片段语义关联过弱,则判定为不可信回答,改回复固定转人工话术。第二步是建立知识库拓扑巡检任务,定时扫描“用户高频提问命中到的知识片段但与问题本身的匹配度过低”的记录,反推优化知识库的片段切分和覆盖度。那之后,类似的无来源编造基本绝迹。
5.2 上下文窗口装不下长对话,裁剪策略要不断调
对话超过十五轮时,我们发现模型开始出现“记忆错乱”,把用户早期说的地址当成刚才说的地址。打开模型日志,确认原因是会话历史超过了窗口限制,而我们的裁剪策略是按时间从最老的开始丢掉,后面模型看到的其实是断断续续的碎片。
后来调整了两个点。一是增加关键信息槽位的概念,在会话状态里单独维护用户可能提及过的上下文槽位,比如订单号、地址、诉求类型、时间节点,这些信息每次都会放回Prompt。二是对超出限制的历史部分生成一段语义摘要,而不是简单切断。摘要与关键信息槽位组合,替换原始历史内容。调整后,长对话的语境连续性明显改善。
5.3 检索开慢了之把延迟问题从单环找到了并行链路
大促前压测时,P95延迟一度到了5秒,明显超标。逐段埋点后发现主要时间花在了重排模型串行等待上。我们的链路里嵌入模型和重排模型是前后两个步骤,而且重排模型的输入是固定的20个候选片段,排队和推理各占了不少时间。
优化做了三件事:候选从20降到12,同时限制重排只对向量召回排名在前20的片段操作;把重排阶段改成批量并行请求而不是单条逐条推理;最后给重排设置了硬性超时300毫秒,一旦超时就直接跳过重排,用第一次召回的Top5作为结果。优化后P95降到1.8秒左右,达到了预设目标,而且稳定性得到了明显提升。
5.4 高峰期的限流配合,该让用户有点耐心排队
还有一次是切流当天流量突然翻了三倍,虽然服务没挂,但部分用户出现了长时间等待。排查结果是接入层限流策略里的等待机制配置过保守,队列太短导致大量请求在等待后被拒。
调整方案是把有限的等待时间分块,比如等待超过3秒就返回“当前咨询人数较多,已为您安排,请继续等待”的提示,同时保持请求在队列内异步轮询处理。配上一个前端自动重发按钮,用户不需要手动刷新,体感上好了很多。这个案例也说明限流不能只考虑服务端保护,还必须考虑用户体验的反馈节奏,否则用户会不断重试,反而加剧系统压力。
6. 一点经验沉淀与后续演进方向
6.1 架构设计上我比较坚持的几条原则
整个项目做完,我自己沉淀了几个比较坚持的原则。第一是对动态能力保持约束,LLM适合做开放理解,不适合做不可控执行。所有会引发真实业务动作的环节都必须有明确的schema校验和硬性二次确认,绝不能出现“模型自由调用接口”。第二是检索质量就是回答质量,与其反复调Prompt,不如先把知识库拆好、索引配好、召回与重排节奏调好,RAG链路里检索的优先级比生成高得多。第三是任何依赖都要有降级路径,这是服务可靠性的底牌,模型挂了、向量库延迟了、业务接口超时了,都必须有明确的自救行为,而不是任由用户经历漫长的等待后失败。
这些原则现在回头想,救活了我们很多次。宁可代码多写几行降级分支,也不要在大促当天面对一个查不了原因的系统干瞪眼。
6.2 后续想继续尝试的方向
这套架构首期跑顺后,我们规划了几个明显的扩展点。一个是主动服务质量,让模型能识别用户的情绪状态,出现不满时更早转人工并同步历史摘要;另一个是复杂多步任务编排,比如“帮我对比三个套餐并推荐办理方案”,这类任务单靠现在的基础链路还撑不住,需要引入更稳健的规划和校验机制。
我个人的体会是,基于LLM的智能客服是一个不断往“让人更省心”的方向演进的事情,但每一次能力外沿的扩张,都必须配一轮更细的安全和可靠性加固。如果你正在搭类似的系统,建议先从知识问答和受控工具调用这两个场景切入,把链路、日志、降级都打磨顺了,再去看更酷的Agent能力。毕竟对于客服平台来说,稳定、安全、不胡说,永远比什么都能聊重要得多。