从 FastAPI 到 RAG:我如何搭建一个 AI 客服中台

_

我做 aibotchat 的时候,脑子里一直有个很明确的目标:我不想再做一个只能演示两分钟的聊天 Demo,我想做的是一个能真的接住客服问题的系统。

因为真正的客服对话,和“问一句答一句”的体验完全不是一回事。用户会追问,会改口,会突然插进一个订单问题,也会一边问规则一边抱怨体验。如果系统只有一个漂亮的聊天框,那它顶多算展示模型,不算解决问题。

我为什么会把它往“中台”方向做

一开始我也想过,是不是把大模型接上,再配一个知识库就差不多了。用户问什么我就答什么,大不了从文档里面去查询一些相关信息再回复,后面越做越发现,这种想法太乐观了。

客服系统不是单点能力,而是一条完整链路。它至少要处理三件事:一是记住上下文,二是知道什么时候去知识库里找答案,三是判断什么时候应该调用工具,或者干脆交给人工。少了任何一个,系统都很容易在真实问题里露怯。同时一旦开始考虑这些问题,接着就有一个接一个的问题开始慢慢浮现,rag要怎么做,无价值的问题我回答不回答,怎么区分无价值的问题,怎么优化token的消耗等一系列的问题。

也正因为这样,我最后没有把项目做成一个单接口应用,而是明确拆成了对话、检索、工具、转人工和观测几个层次。现在回头看,这个决定是对的。因为系统越往后长,越需要清楚边界,而不是靠一个越来越长的处理函数硬扛。

我当时是怎么想这套结构的

我比较在意的一点,是不要让所有逻辑都直接压在路由层。路由负责接请求,这没有问题,但真正决定系统质量的,是下面那层编排能力。开发其实现在使用vibe coding已经可以快速的完成一个系统的开发了,并且可以干的很不错。难点在于你想要什么,对本项目来说,怎么架构这个系统才是我最需要考虑的东西,怎么编排运行逻辑才是提升效果的绝招。

所以我在做的时候,会更愿意把关注点放在这些地方:

  • 上下文要单独管理,不要让每次请求都临时拼历史消息。

  • 知识库检索要有自己的链路,不是所有问题都无脑走 RAG。

  • 工具调用要和知识问答分开考虑,不然问题一复杂,链路很快就会打架。

  • 人工接管不能只是一个按钮,而要成为对话流程的一部分。

说白了,我想做的不是“模型会回答”,而是“系统知道自己现在该干什么”。这个差别,决定了项目最后是一个玩具,还是一个能长期维护的服务。

真正让我头疼的不是模型,而是边界

做这类系统时,本身这个客服性质的项目不需要一个能力超强的模型来支撑使用。所以我最深的感受反而不是如何选择模型,而是边界有多难处理。

比如上下文一旦不控制,回答就会越来越慢;RAG 一旦没有路由,很多根本不需要检索的问题也会被送进知识库;工具调用如果没有顺序控制,最后出来的不是“智能”,而是调试地狱。

还有一个特别现实的问题是,客服系统比普通问答更怕不稳定。你可以接受模型偶尔答得不够漂亮,但很难接受它查错订单、乱讲规则,或者该转人工的时候还在硬答。所以我后来会越来越在意限流、幂等、防注入、敏感词和输出控制这些看起来“不酷”的东西。因为它们才是系统能不能真的接业务的底线。

再后来为了控制token消耗,我加入了一层意图判断想要把一些提问排到不使用llm回答,但是让我最为头疼的一点出现了——怎么判断意图,开始我有两个想法:

  • 罗列常见关键词进行正则匹配

  • 先用轻量模型进行一次意图识别

然后我发现都各有优劣,方案1不消耗额外的token,但是很显然局限性也很大。方案2会有一部分的token消耗降低,但是可能复杂信息意图识别不够精准。

这个项目给我最大的收获

如果现在让我用一句话总结这个项目,我会说:它让我第一次真正把“大模型应用”当成了工程系统,而不是功能拼装。

以前我也会把一些 AI 能力接进项目里,但很多时候做完就结束了。aibotchat 不一样,它逼着我去思考结构、责任边界、检索链路、工具协作和人工兜底这些更长期的问题。也正是因为这些问题都开始被认真处理,它才慢慢有了“agent”的味道。

写在最后

我现在越来越确定,做 AI 系统最难的,从来不是把模型调用起来,而是把 上下文检索工具人工兜底可观测性 这几件事稳稳地组织到一起。至少对我来说,aibotchat 真正有价值的部分,不是它接了多少能力,而是它开始像一个完整系统了。

仓库地址:https://github.com/ShadowHunt-yi/aibotchat

客服知识库检索实战:BM25、向量检索、RRF 与 Reranker 的组合 2026-04-11

评论区