从零到一:AI客服RAG系统实战全解析与持续优化之道
之前我们探讨过,2023年是基础大模型爆发的元年,行业内主要的关注点都集中在模型本身,上演了被称为“百模大战”的激烈竞争。
然而,市场很快意识到单纯在模型层面内卷难以持续,于是业界开始回归理性,积极寻找能够切实落地的应用场景。因此,2024年的重心转向了AI应用,其中AIGC(辅助生成文案)、工作流自动化以及AI客服被视为最具代表性的三大应用方向。
进入2025年,AI视觉相关的需求显著增长,成熟的AI编程助手也异军突起。尽管如此,复杂的AI客服场景依然拥有庞大的市场需求。尽管AI客服通常被归类为RAG应用,看似原理简单,但实践中许多公司却难以将其做好,效果不尽如人意。
为此,我们将以一个真实的生产级案例作为教学素材,带领大家由浅入深地理解,一个高效可靠的AI客服系统是如何经过精心打磨而成的。
案例说明
这个AI客服案例来源于我们去年的一个AI to C创业项目:空气小猪。它是一款基于社交场景的语言学习应用程序。自上线以来,客服工作一直由团队内部成员承担,平均每天需要耗费2至3个小时,这种状态已经持续了半年之久,占据了大量的宝贵时间。
在此期间,我们也尝试过引入兼职客服,但效果并不理想。一方面,兼职人员的投入度和责任心往往不足;另一方面,由于对产品的核心理念与定位缺乏深度理解,他们常常无法准确、有效地回应用户的疑问,导致整体服务质量难以达到预期标准。
实际上,用户提出的问题绝大部分是重复性的,高频问题就那么几类。每天人工重复回答这些问题,无疑是一种低效且不可持续的工作模式。因此,针对简单的AI客服场景,我们早已形成了一套成熟的方法论。

简单场景直接套用该方法论即可(尽管后续事实证明,其他实践者可能会在其他环节遇到挑战);而对于复杂场景,我们则另有一套应对策略。由此,我们几乎可以得出一个明确的结论:
未来的客服工作,无论其简单或复杂,都将大概率被AI所替代。
在线客服工作本身具有高度的重复性特征,因此,“降本增效”始终是客服系统演进的核心驱动力。基于大模型构建的AI客服,不仅能显著提升产品服务能力和用户体验,还能大幅降低长期的运营维护成本。
随着AI Agent技术的日益成熟与普及,AI客服系统在成本控制、响应效率和可扩展性方面将进一步得到优化,逐渐成为企业客服体系的最优解。
此时,可能有读者会产生疑问:既然如此,为何不从一开始就部署AI客服,反而要每天投入数小时进行人工客服呢?
答案非常直接:我们需要积累最原始的、高质量的对话数据。
在这半年多的时间里,项目创始人与用户之间沉淀了大量真实、高质量的对话语料,这为我们提供了极其宝贵的数据基础。当基础性问题开始不断重复出现时,便是构建一套AI客服系统的最佳时机。
此时,我们的目标就变得非常清晰:**将团队从每天2小时的人工客服工作中解放出来!**以上就是项目的整体背景。接下来,我们将详尽介绍“空气小猪”AI客服从零到一的全过程实践,以及各个关键环节的落地步骤。
技术选型
在具体实现环节,我们面临一个关键抉择:是采用智能体低代码开发平台,还是进行彻底的工程化代码开发?
单纯从技术实现的角度看,两种方式都能达成目标。但若追求深度把控与长期效益,我们果断选择了工程化代码开发的方案。这样做的好处众多,最重要的是能够获得更深入的技术实践与理解,所有这些优势最终都体现在系统的自主可控性上。当然,我们也可以简要回顾一下选型过程,供各位参考:
在评估智能体开发平台时,我们主要考察了Dify。此前我们已对比过Coze、Dify、FastGPT、N8n等平台的技术特性。
整体而言,Dify的能力在这些平台中最为均衡,没有明显的短板,尤其适合企业级场景下的智能体开发、工作流编排以及知识库驱动的应用构建。
然而,我们最终没有选择Dify,主要基于以下几点考量:
- 我们对知识库的检索能力有较高要求,希望在召回策略、排序逻辑、上下文拼接等核心环节进行深度定制与优化。这部分是AI客服能力的基石,我们更希望其逻辑完全自主可控。
- 私有化部署会带来额外的服务器成本与运维负担,这对于我们当前的项目阶段而言并非必要(实际使用后才会发现开源版本缺少哪些关键功能)。
- 在实际测试中,我们发现Dify的执行链路相对较长,特别是在知识检索节点,整体响应时间偏长,无法完全满足我们对实时性的要求。
- 即便使用Dify,在实际落地过程中依然会涉及大量的系统对接、数据适配和定制开发工作,并非真正的“零代码”或“低成本”集成。
综合以上因素,我们最终决定采用自主编码的方式,从底层能力开始搭建系统。虽然前期投入更高,但在可控性、性能优化空间以及系统的长期演进能力方面,这为我们带来了显著优势。
并且,从长远来看,自主开发的实际成本也并不高昂…
解决了第一个问题,许多同学的第二个疑问随之而来:那么,我们的AI客服是否应该直接采用Agent模式呢?
Workflow 还是 Agent?
在项目启动阶段,除了决定使用Dify还是工程化开发,我们还需要在Workflow(工作流)和Agent(智能体)两种开发模式中做出选择。
Agent是具有高度自主性和推理能力的智能体,但其结果的确定性、性能表现以及可控性通常不占优势。在客服这类对准确性和稳定性要求极高的场景中,业界通常倾向于采取较为保守的策略:先按照Workflow的模式,搭建一个稳定、可控的流程框架,以追求确定且可靠的结果。
我们选择从工作流程入手,逐步引入并解决每一个遇到的问题,在保证效果、控制成本与确保可控程度之间取得平衡。
至于后期是否需要“升级”到Agent版本,完全取决于具体的业务需求。在业务层面,我们几乎不盲目追求技术上的时髦概念。
基础流程设计
确定了基础技术选型后,便可以着手进行流程设计。在第一个版本中,我们将用户意图初步划分为产品咨询和闲聊两大类,基本流程如下:

然而,我们很快发现,用户除了咨询常见的产品功能问题,还会频繁反馈产品优化建议以及程序运行故障等问题。
这部分内容的处理逻辑与单纯的产品咨询截然不同。用户反馈的问题需要被结构化地存入数据库,并根据问题的严重程度划分优先级等级,以便我们及时跟进与修复。
因此,我们在初版设计的基础上,增加了“优化建议”与“故障反馈”两类意图的处理流程。具体流程优化如下:

这便对应了我们方法论中强调的“整理意图大表”环节。在基础意图分类大致清晰后,便可以进入最为关键的知识梳理阶段。
知识整理
所有计划构建AI知识库的同行务必注意:高质量的数据才是系统的灵魂!如果有人谈论AI项目却不深入探讨数据问题,那么他很可能缺乏实战经验。
产品知识是AI客服赖以生存的基础(这也是为什么我们宁愿等待半年才启动客服AI化的原因)。只有输入优质的知识,AI才能输出优质的答案,否则就是“垃圾进,垃圾出”。
在数据基础不完备的情况下,无论进行多少工程化的优化都是徒劳。因此,RAG(检索增强生成)的本质是一个数据工程问题,大家必须深刻理解这句话背后的含义。
具体到AI客服的知识梳理工作,理论上要求极高,它最好由对产品拥有最终解释权的人来主导完成。然而,知识的完备性并非一蹴而就,需要通过持续的迭代更新才能逐步完善。
实际情况是,所有知识库应用在初始阶段都存在类似的知识覆盖不全问题。因此,我们允许初期存在知识缺口,并在后续迭代中逐步补齐。同时,采用“数据飞轮”策略来自动化地完善知识库,已成为当前的主流做法。
具体到本项目,我们的知识来源主要包括两部分:一部分是人工整理的结构化知识,另一部分则是沉淀的历史客服对话数据。

在进行知识整理时,必须思考如何组织知识才能获得更佳的检索效果。而检索效果在很大程度上取决于数据处理是否正确,例如每个文本分块是否语义完整、独立。
因此,输出的知识单元必须能够独立成块。我们可以利用Markdown格式的层级结构进行整理,在分块时依据标题进行分割。知识内容的大致形式如下:

另一方面,我们导出了所有的历史客服对话数据。这里主要按会话维度进行分析。由于数据量庞大,人工整理几乎不可能,因此我们借助AI来分析并提取每个会话中有效的问答对。
当然,我们不可能一次性将所有数据交给大模型处理,原因有二:
- 数据量过大会超出大模型的上下文长度限制;
- 数据量过大也会增加模型的“幻觉”,导致准确率下降。
我们的处理策略是分批次进行整理,例如以每10个会话为一个批次。我们借助Coze平台搭建了一个自动化处理工作流,具体流程如下:

补充说明:由此可见,我们并非完全不用Coze这类平台,但通常只将其用于一些自动化的轻量级操作,用完即走。
从数据库导出会话记录时,每10个会话被导出为一个独立的记录文件,最终会生成若干个此类文件。将这些文件上传至Coze工作流进行批量处理后,生成的问答对内容会被自动写入飞书多维表格中。
最终表格中的内容必然存在重复项。我们将表格的全部内容再次交由大模型进行分析,进行去重处理,从而形成最终的、纯净的问答对数据集。
通过以上两种方式的结合,我们最终获得了高质量的产品知识数据。这一步至关重要,也极其耗费精力,并且必须由真正理解产品内核的人员参与,才能取得理想的效果。
可以断言:如果这一步没有做好,那么AI客服的最终效果一定会大打折扣!
数据整理完毕后,便进入了知识库的构建环节。
知识库构建
这里的技术实现方案为:Python + FAISS + MySQL + Qwen(text-embedding-v4)。
向量检索库我们选择了Meta公司开源的FAISS,它非常轻量高效。嵌入模型则采用了千问的text-embedding-v4(1024维度),该模型在中文语境下的表现更为出色。
数据存储结构
整个知识库由“库”、“集合”和“数据”三部分层级构成。
- “集合”可以简单理解为一个知识文件。
- 一个“库”中可以包含多个“集合”。
- 一个“集合”中可以包含多组“数据”。 最小的搜索单位是“库”。这意味着,在进行知识检索时,是对整个“库”进行搜索。“集合”仅用于对数据进行分类管理,与搜索效果本身无直接关系。

向量存储结构
我们采用Faiss作为向量检索引擎,使用MySQL作为业务数据存储数据库,实现了知识入库与向量召回的分离式架构设计。
在此架构中,Faiss仅负责向量的存储与相似度检索,MySQL则负责存储原始知识数据及相关的业务字段。未来,向量检索引擎可以独立替换为其他向量数据库(如Milvus、Weaviate等),而不会影响业务数据库的结构。
两者之间的关联通过“向量ID”字段建立。在MySQL的dataset.datas表中,存储着向量原数据的详细信息,其中一个名为vectorId的字段,专门用于记录其对应的向量ID。

知识入库是一个离线过程,大致流程如下:
- 首先加载知识文档,并对文档进行分块处理。
- 将分块后的数据存入MySQL业务数据库,此时其向量化状态标记为“待向量化”,向量ID字段为null。
- 通过异步事件驱动,使用向量模型对每一个分块chunk进行向量化,得到向量坐标后,将其存入Faiss向量库。
- 向量成功存入Faiss后,会生成一个唯一的向量ID。随后,将此向量ID回填至MySQL中对应该chunk记录的
vectorId字段,并将向量化状态更新为“已向量化”。

知识检索流程如下:
- 使用向量模型对用户的问题进行向量化,得到问题向量。
- 使用Faiss执行相似度搜索,召回TopK个最相似的向量ID,同时获取对应的相似度得分。
- 拿到召回结果(向量ID列表)后,根据这些ID去MySQL数据库中查询对应的原始文档chunk数据。

知识入库实践
在知识整理完成后,我们使用代码对Markdown格式的知识文档,按照其结构层级进行智能分块,得到结构化的JSON数据,然后将其存入业务数据库和向量库中。
具体规则是:将一级标题设置为category字段,将最后一级标题设置为questions列表,段落内容设置为answer字段。如果存在三级以上的标题层级,则将第1到n-1级标题用“-”连接作为category字段,第n级标题作为questions。我们得到的分块数据结构如下(仅列举核心字段):
{
"category": "产品概念",
"questions": [
"空气小猪解决的核心问题是什么?"
],
"answer": "很多用户长期学外语遇到的真实问题包括:\n外语只存在于“学习时间”,无法进入日常生活\n输入和输出被割裂,学到的语言很难迁移到真实使用\n听力和阅读材料与个人生活无关,难以长期坚持\n空气小猪并不通过增加学习任务来解决这些问题,而是通过重用已经发生的聊天内容,为用户建立一个长期、低成本、真实相关的外语环境。",
"keywords": []
}
得到若干个上述结构的分块后,按照前述流程,将每个分块存入MySQL数据库,并同步存入向量库。
需要注意的是,进行向量化的文档内容并非直接对整个JSON字符串操作。这里的JSON结构主要用于获取文档分块的结构化元信息,方便存储和管理。真正被送入向量模型生成嵌入向量的文本,是category、questions和answer字段内容的拼接。
在这一步,我们最初曾犯过一个错误:我们使用大模型对原始分块中的问题进行了“泛化”处理。泛化后的结构如下:
{
"category": "产品概念",
"questions": [
"空气小猪解决的核心问题是什么?",
"空气小猪主要解决了什么问题?",
"空气小猪的核心价值是什么?"
],
"answer": "...(同上)...",
"keywords": []
}
即,将一个核心问题泛化为多个可能的同义或相关问法,意图提升检索召回率。在存储时,我们按照“一问一答”的结构分别存储,即“问题1+答案”、“问题2+答案”、“问题3+答案”各自存储为一个独立的向量。
但这样做在后续知识召回时出现了严重问题:同一个答案,因对应多个相似问题,在向量空间中位置极其接近,导致一次查询很容易同时召回这些高度相似的文档,并且它们的得分都很高。在取Top-K时,召回的结果实质上是同一份答案的多个变体,这直接挤占了其他潜在相关内容的召回机会,降低了结果的多样性。
接下来,我们将进入检索流程的详细说明。
检索过程
在RAG系统中,检索环节的核心要点之一是意图识别。
因此,前置的意图分类步骤至关重要。真实用户的提问往往非常发散,第一步就需要对用户的意图进行收敛。收敛的目的是为了匹配后续的处理流程,并更精准地对接知识库中的相关内容。
我们将一级大类意图拆分为产品咨询、故障反馈、闲聊三类,然后通过代码逻辑进行路由分发,使其进入不同的处理管线。
然而,要让大模型准确判断属于哪一类意图,还需要进一步细化用户的二级意图。例如,明确在何种情况下应归类为产品咨询,何种情况下属于故障反馈。你需要为大模型提供一个清晰的评价标准,二级意图正是辅助大模型进行一级意图判断的重要依据。否则,意图识别步骤一旦出错,后续的回答必然南辕北辙。
这里将我们整理二级意图的思路简要分享如下:
- 一是从产品本体出发进行梳理(我们提供了什么功能、主要解决什么痛点);
- 二是从用户视角出发进行梳理(我能获得什么价值、对我的语言学习有何帮助、如何使用); 最终将两者进行有机融合。
通过分析历史客服问答数据,我们提炼了用户的高频问题类型,这为意图梳理提供了极具价值的参考。以下是我们梳理的部分高频问题类别示例:

这里摘录部分意图识别的提示词设计:
## 角色
你是 空气小猪 App 智能客服系统的专业意图识别器。
你的输出将被直接用于自动路由和客服决策,请严格遵循规则,不得自由发挥。
## 总体目标
基于【对话历史】和【用户最新消息】,完成以下两个任务:
1. 指代消解(必须先完成)
2. 意图识别(基于指代消解后的问题)
## 任务一:指代消解
目标:
结合【对话历史】,对【用户最新消息】中的所有指代性表达进行消解,你需要生成一条单句、语义完整、无任何模糊指代的用户问题
处理规则:
1.必须结合【对话历史】进行还原
2.如果用户问题本身已经明确,不要强行改写
3.不得引入对话中不存在的新信息
4.输出必须是一个完整问题句
输出字段:resolved_question
## 任务二:意图识别
基于 resolved_question,结合【对话历史】信息进行理解,将其准确分类到以下三个意图之一,并且按照顺序依次判断:
1. **产品咨询(SUPPORT)** , 判断标准为 {
空气小猪小猪相关问题
产品功能介绍/产品价值/能解决什么问题
使用方法/操作步骤/使用教程
下载安装/注册登录/账号相关
产品定价/会员/付费
与竞品的比较
翻译/语言支持/语言学习相关
播放/播客/朗读
聊天/加好友/社交/翻译对话相关
任何“如何用空气小猪做某事”的问题
}
2. **问题反馈(FEEDBACK)**, 判断标准为 {
用户明确提出对空气小猪产品功能优化建议、希望增加功能、优化建议、故障反馈,比如:功能异常、报错、打不开、点不动、卡顿、无法使用等
}
3. **闲聊(CHAT)**,判断标准为 {
当不属于以上两类时,一律归为 CHAT,例如问候、寒暄、玩笑、调侃、情感倾诉、模糊无意义输入
}
## 输入信息
### 对话历史 { %s }
### 用户最新消息 { %s }
## 输出要求
1. 用户输入的翻译,翻译为%s
2. **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"confidence": "0.0-1.0",
"intent": "SUPPORT" | "FEEDBACK" | "CHAT",
"resolved_question": "指代消解后的明确问题",
"translation": "用户输入的翻译",
"reason": "简要分类理由(说明上下文如何影响判断)"
}
从提示词设计可以看出,我们不仅对用户提问进行意图识别,在此之前还增加了“指代消解”的预处理步骤。即先完成指代消解,再进行意图判断。
补充说明:严格来说,也可以将这个复杂的提示词拆分为两个独立的、符合“原子性”原则的提示词。我们此处因为以案例讲解为主,为求简洁未作拆分。
之所以需要指代消解,是因为实际对话中,用户常将一个完整问题分多次说出,或在后续提问中使用大量代词指代前文内容。例如,用户先问“空气小猪是干什么的?”,接着问“它怎么用?”。若直接用“它怎么用?”进行检索,很可能无法命中有效知识。而经指代消解后,问题应还原为“空气小猪怎么使用?”。这能极大提升后续意图识别和知识检索的准确性,保证对话的连贯性。
在意图识别环节,我们经历了模型选型的迭代,从最初的GPT-4.1作为效果标杆,到尝试Qwen-plus-latest、Qwen-max-latest,再到评估Qwen3-max、Qwen-plus。GPT-4.1效果卓越,而Qwen系列模型需要通过提示词优化或流程拆分来提升表现。值得注意的是,Qwen-plus在未大幅修改提示词的情况下,效果已有不错提升。
鉴于我们的场景复杂度适中,为平衡成本与效果,最终线上模型选择了Qwen-plus。若对效果有极致要求,可考虑Qwen3-max或GPT-4.x等更强大的模型。
模型选择策略可根据项目阶段动态调整:项目初期为快速验证和上线,可选用参数较大的标杆模型;后期在保证意图识别准确率不下降的前提下,逐步迁移至成本更低的模型,实现效果与成本的最佳平衡。
简言之,我们在每个项目的验证阶段都会使用效果最好的模型,而最终上线时,成本是必须纳入考量的关键因素。
问题泛化
在正式进入向量检索阶段之前,需要对用户问题进行一系列语义层面的预处理,以最大限度提升后续检索的召回率与覆盖面。
首先,通过指代消解技术,还原问题中的代词、模糊指称和上下文依赖表达。例如,将“这个功能”、“那个错误”等模糊表达,结合对话历史明确为具体的功能名或错误描述,避免因语义歧义导致检索遗漏。
其次,我们基于消解后的明确问题,进行多问题生成。利用大模型的语义理解和重写能力,从不同角度、用不同表达方式对同一问题进行改写和扩展。具体包括:同义词替换与句式重构、从不同维度拆解出子问题、将抽象问题转化为更具体、更易检索的表述。
通过这种策略,可以将一个单一的用户查询,扩展为多个语义相关但表达各异的查询语句集合。这种“多路查询”机制能够覆盖知识库中更多潜在的匹配项,有效提升召回率,同时减少因用户表达口语化、非标准而导致的“语义鸿沟”问题。
以下是我们使用的多问题生成提示词示例:
## 角色
你是“空气小猪”智能客服系统的查询优化专家,专门处理**产品咨询**类查询的泛化改写任务,把用户问题泛化成检索友好的中文查询,用于知识库向量检索。
## 改写规则
1. 如上下文中出现了关键实体(产品名、功能名、版本、平台、错误码、按钮文案等),改写需保持一致。
2. 不要引入上下文里不存在的具体数值、版本号、错误码、功能名。
3. 生成的每条查询都要尽量短、包含关键关键词、便于命中知识库。
4. 若用户输入不是中文,请先理解其含义,再用中文生成改写查询。
5. 改写要有多样性,每条改写应有不同侧重点。
## 输入信息
### 对话历史 { %s }
### 用户最新消息 { %s }
## 输出要求
- rewritten_queries 严格生成 5 条,每条为 string。
- **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"original_query": "string",
"rewritten_queries": [
"string",
"string",
"string",
"string",
"string"
]
}
上下文管理
每次调用大模型进行意图识别、问题泛化或生成最终回答时,除了传入用户最新的消息,还必须传入历史会话消息,以确保大模型能够理解完整的对话语境。
但这里存在一个关键问题:应该携带多少条历史消息才合适?携带过少,会丢失重要的上下文信息,导致模型回答偏离语境;携带过多,则会降低响应速度、增加Token消耗,过多的干扰信息还可能诱发模型产生“幻觉”。
如果简单地固定携带最近10-20条消息,在多数情况下可行,但仍存在明显缺陷:更早的关键对话信息可能会永久丢失。因此,单纯采用“固定条数”的策略难以在上下文完整性与资源成本之间取得良好平衡。
为此,我们实施了一项优化策略:对对话记忆进行分层管理,划分为短期记忆和长期记忆。
短期记忆易于理解,即每次携带最近N条原始会话消息。这部分信息保持其原始表述,不做压缩,旨在保证对话语境的连续性和即时性。
此外,我们还会携带“历史消息的摘要信息”。摘要信息的生成规则是:每当对话积累满N条消息,就触发一轮异步压缩,并将生成的摘要持久化存储到业务数据库中。
需要注意的是,携带的历史摘要信息并非全量。举例说明:假设每30条消息压缩成一条摘要,若我们携带10条摘要,则相当于涵盖了最近300条消息的浓缩信息。通常,用户的对话焦点可能早已转移,无需携带过于久远的历史。
以下是生成历史消息摘要的提示词示例:
# 角色
你是一个对话总结助手,任务是把下面的对话片段总结为一条可用于后续意图识别的“历史摘要”,要求尽量节省token但保留关键信息。
# 规则:
1. 只总结事实与诉求:用户关心点、问题、偏好、已给出的关键信息、未解决点
2. 不要杜撰,不要引入对话中没有的信息
3. 输出长度建议 120-220 字/词左右(按语言自然长度)
# 对话片段:{ %s }
# 输出要求:
返回如下JSON格式,不要返回多余内容:
{
"summary": "string"
}
在调用大模型进行意图识别、问题泛化或回答时,我们构建的消息上下文结构如下:

当然,除了按固定条数进行压缩,也可以设定在达到一定Token数量时触发压缩。具体策略可根据实际场景灵活选择。
检索方案
如前所述,我们对用户原始问题进行了泛化处理,将其改写为多种不同的表达方式,利用多路查询提升召回率。接着,针对泛化后产生的每一个查询,我们采用混合检索策略进行搜索。
此处的“混合检索”是指语义检索(向量检索)与全文检索(关键词检索)的组合使用。采用这种方式是因为两者在能力上具有互补性:语义检索擅长理解深层的语义相似性,而全文检索则擅长精确匹配关键词,从而弥补单一检索方式的局限性。
语义检索通过计算用户问题向量与知识库内容向量在高维空间中的距离(如余弦相似度)来评估“相似度”。需要注意的是,这是数学空间中的邻近性,而非严格的语言学相似。其优势在于能捕捉语义相近的内容,但精度可能受关键词匹配和句子完整度影响。
全文检索我们采用经典的BM25算法。BM25主要基于词频和逆文档频率进行加权计算,对文档进行排序。它特别擅长处理查询和文档间有直接关键词匹配的任务,对于专有名词、错误码等精确匹配场景效果显著。
通过“多问题查询 + 混合检索”,我们会获得一个规模较大、质量不一的候选知识集合。此时,需要进一步的精筛和排序,才能得到最相关的最终结果。
我们的处理流程如下: 首先,对同一种检索方式(如多个泛化问题的向量检索结果)内部的结果,使用RRF(倒数排序融合)方法进行初步合并,分别得到向量检索和BM25检索的两类候选结果集。 由于混合检索后候选集较大,仅依靠原始的相似度分数难以有效过滤。因此,我们引入重排模型对候选结果进行精细化的重新评分和排序。重排模型能够输出一个0到1之间的相关度得分,该得分通常比原始的向量相似度得分更为精准,我们可以据此设定阈值进行过滤。 最后,我们再次使用RRF方法,对经过重排的向量结果、原始的向量检索结果以及BM25检索结果进行最终融合,得到排序后的最终搜索结果。

单个问题的向量检索流程与前述知识库构建环节描述的一致。多问题并行向量检索的整体流程如下:

我们使用的Faiss和MySQL并不直接支持BM25检索。我们的策略是:先将所有知识分块片段加载到内存中,结合用户查询,利用LangChain提供的BM25Retriever工具进行计算。核心代码逻辑示例如下:
# 使用 BM25Retriever
bm25_retriever = BM25Retriever.from_documents(splitsDoc)
bm25_retriever.k = 3 # 返回前3个最相关的文档
# 执行检索
bm25_docs = bm25_retriever.invoke(query)
print(f"bm25_retriever检索到 {len(bm25_docs)} 个相关文档块:")
至此,AI客服的核心检索流程已完整覆盖。剩下的生成环节,相对而言反而更为直接。
生成阶段
我们将一级意图分为三类:产品咨询、故障反馈、闲聊。进入每个意图后,处理逻辑存在差异,因此为大模型生成回答所设计的提示词也各不相同。
提示词设计的重点在于构造丰富的上下文信息,通常需要拼接以下内容:召回的相关知识、最新的N条原始对话历史、更早的历史对话摘要以及用户当前的问题。
需要注意的是,在知识召回后、大模型生成最终答案前,我们会要求模型再次判断召回的知识是否足以回答用户问题。如果不足以回答,则要求其拒绝回答,并将useful字段设置为false;否则,设置为true。这个字段非常关键,它用于标记那些AI无法回答的问题,这些低置信度问题会自动进入待处理问题池,便于后续进行知识补全和效果复盘,为“数据飞轮”的运转提供了源头活水。
以下是用于“产品咨询”意图的生成提示词示例:
## 角色
你是空气小猪产品客服助手,你需要根据对话历史、用户最新消息、以及知识回答用户问题。
## 回复原则
1. **简洁明确**:直接回答,不绕弯,不要超过100字。
2. **友好专业**:保持礼貌,体现专业性。
3. **客观公正**:遵循客观事实,不要胡编乱造,所有回答的内容都需要在【知识】内容中有迹可循,宁可不答也不要错答。
4. 如果知识库资料与用户反馈高度相关,给出可执行的解决/排查步骤或替代方案,并将 useful=true。
5. 如果资料不相关或不足以解决,将 useful=false,并回复用户:暂时不能回答这个问题。
## 知识 { %s }
## 上下文消息
### 对话历史 { %s }
### 用户最新消息 { %s }
## 输出要求
1. 用中文回复,不超过100字。
2. 给出回复内容的%s翻译。
3. **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"useful": boolean,
"content": "string",
"translation": "string"
}
当用户意图被识别为“故障反馈”或“功能建议”时,流程更为复杂。需先确认用户反馈的具体内容,并检查相关功能是否已存在:
- 如果功能已存在,则引导用户正确使用或提供解决方案。
- 如果功能不存在,则需要评估该需求是否符合产品核心原则,以及是否属于明确“不做”的范围:
- 若属于“不做”范围,则需明确且友好地予以拒绝。
- 若不属于,则继续收集更详细的信息。在信息不足时,引导用户补充描述;随后对反馈进行数据清洗,判断其属于“故障”还是“优化建议”,再分类存入业务数据库,以便后续跟踪处理。
以下是“故障反馈/功能建议”意图的提示词框架(部分):
## 角色
你是空气小猪产品客服助手,专门负责处理用户建议和产品故障反馈。
## 产品核心理念 { %s }
## 知识 { %s }
## 上下文消息
### 对话历史 { %s }
### 用户最新消息 { %s }
## 输出要求
1. 用中文回复,不超过100字。
2. 给出回复内容的%s翻译。
3. **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"content": "string",
"translation": "string"
}
对于严肃型服务场景,通常不建议开启闲聊功能,应优先保证答案的准确性和可靠性。在无法确认答案时,宁可拒绝回答,也绝不提供可能产生误导的信息。
但在“空气小猪”这类语言学习应用中,我们有意引入了“闲聊意图”。其目标是让AI客服具备更自然、更有温度的互动能力,而非仅提供机械式应答。适度的闲聊可以增强用户的参与感与陪伴感,从而提升产品的整体使用体验和用户黏性。
以下是“闲聊”意图的提示词示例:
## 角色
你是空气小猪产品客服助手,擅长陪伴用户进行轻松有趣的闲聊。你的核心任务是在自然对话中传递产品价值,并收集有助于改进的用户反馈。
## 产品核心理念 { %s }
## 对话历史 { %s }
## 用户最新消息 { %s }
## 输出要求
1. 用中文回复,不超过50字。
2. 给出回复内容的%s翻译。
3. **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"content": "string",
"translation": "string"
}
再说可观测性
至此,整个AI客服的核心流程——从知识整理、入库到问答生成——已经全部贯通。
为了进一步优化系统,我们必须能够观察关键环节的运行状态是否符合预期。例如,意图识别是否准确、指代消解是否正确、问题改写质量如何、知识召回质量高低、提示词设计是否存在缺陷,以及每个环节的耗时情况。
为此,我们在流程的关键节点对核心信息进行了结构化存储,内容包括:
- 指代消解前后的文本、用户问题改写列表。
- 意图识别的结果及置信度。
- 向量检索召回的候选结果列表及其相似度得分。
- 最终命中的知识内容及AI生成的回复结果。
- 大模型调用的完整日志(输入/输出)。
在配套的后台管理系统中,可以直观地查看全流程各关键节点的输入和输出信息,从而实现对AI客服运行状态的透明化观测。例如,意图识别轨迹列表、客服向量召回结果详情、问题改写对比列表等。
通过对这些核心节点的持续监控与分析,我们可以将原本不可见的系统内部运行过程从“黑盒”转变为“白盒”,从而实现问题快速定位、效果量化评估、策略动态优化,为系统能力的持续迭代与提升提供坚实的数据支撑。
数据飞轮
必须明确指出,我们目前搭建的客服系统,其知识库仍然不够完备,无法覆盖用户可能提出的所有问题。除了依靠人工持续补充知识,我们还设计并引入了“数据飞轮”系统功能。
数据飞轮本质上是一种基于持续反馈的闭环优化机制:
通过不断从真实用户交互中收集数据 → 处理与分析 → 优化系统 → 再反哺到系统中,让AI在真实的业务流中越用越精准。
当然,这并非意味着将所有未回答的问题都盲目加入知识库。关键在于:
- 识别哪些问题是真正值得沉淀的共性知识。
- 持续补全那些确实存在且具有价值的知识缺口。
下面结合我们的系统设计,具体阐述如何在AI客服中收集低置信度问题,并利用数据飞轮持续优化知识库。
置信度阈值
前文提到,AI客服的第一步是意图识别。当用户提问后:
- 系统会先为问题打上意图标签。
- 在对应标签下进行知识检索(向量召回)。
- 每条召回的知识都会有一个“置信度”得分。
这个置信度得分表征了“用户问题”与“知识库内容”的语义匹配程度。分值越高,代表命中越精准;分值越低,则往往意味着知识库在当前问题上存在覆盖不足。
在我们的系统中,将置信度阈值设定为0.5。当召回的Top结果置信度≥0.5时,走正常回答流程;当置信度<0.5时,则认为当前知识库匹配度较低。此时,系统会异步将这条问题数据纳入“数据飞轮”处理流程。
问题标准化
大模型会基于专门的提示词,完成两项关键任务:
- 将用户的原始、口语化提问,转化为结构清晰、语义明确的标准问题。
- 基于当前知识,尝试生成一个示例答案,作为后续人工审核的参考。
例如: 用户原话:“我在日本,用 +81 的手机号能不能注册啊?不行我就换国内的” 标准化后问题:“国外手机号(非中国大陆)是否支持平台注册?”
这一步在信息检索领域通常被称为“问题规范化”。因为用户的自然语言表达常常是口语化、片段化且依赖于上下文的,不适合直接存储或用于检索。在进入数据飞轮流程前,必须先将其转化为结构稳定、语义清晰的标准形式,以提升后续处理的效率与效果。
以下是用于问题标准化的提示词示例:
你是智能客服的知识运营助手。你要把“用户原话”整理成可入库的标准问题,并尝试与候选问题合并。
目标:
1) 去噪:去掉情绪、口语、无关碎片,只保留核心诉求。
2) 标准化:输出“真实意图”的标准问题,用中文,尽量像FAQ标题。
3) 合并:判断是否与候选问题同一意图;如果是,返回 matched_question_id;否则返回 null。
4) 初步解答:基于标准问题给出一段中文初步解答;如果信息不足,说明需要用户补充哪些信息。
约束:
- normalized_question 必须是单行文本,长度不超过 120 字。
- 如果候选列表里没有同一意图的问题,matched_question_id 必须为 null。
- 只返回严格 JSON,不要输出多余内容。
候选问题(JSON数组):{ %s1 }
用户原话:{ %s2 }
输出JSON:
{
"normalized_question": "string",
"matched_question_id": 123,
"ai_suggested_answer": "string"
}
数据入库与分工协作
处理完成后的标准化问题数据,将进入入库流程。整体分工如下:
- 用户端:负责原始数据的采集。低置信度问题被自动识别并送入待处理队列。
- 后台管理端:由人工进行审核,并最终决定是否将问题及其答案正式写入知识库。
问题审核
并非所有被标记为低置信度的问题都值得沉淀为知识。在后台,人工审核员需要首先对问题进行筛选:

当看到某条问题的召回置信度低于0.5时,审核员需要判断:
- 这是否是一个真实、合理的业务问题?
- 是否存在垃圾信息、无意义输入或不当内容?
- 等等。
同时,也需评估问题是否适合入库:
- 出现频率极低的“一次性”问题不值得沉淀。
- 具有强时效性的问题会自然过期。
- 系统可能存在误判,某些问题实际上知识库已能覆盖(即假阴性)。
只有通过审核的问题,才会被标记为待向量化。系统也会记录相似问题出现的频次,帮助判断其普遍性和重要性:

效果验证
完成向量化并入库后,知识库中便新增了一条知识元数据:

当下次有用户提出语义相近的问题时,向量检索将能够命中这条新知识,AI客服便可以给出更准确、更贴合的回答。通过这种“数据飞轮”的闭环设计,系统得以实现自我学习和持续进化,真正做到越用越智能。
结语
通过“空气小猪”AI客服项目的完整实践,相信各位对于什么是可落地的AI知识库系统,以及如何从零开始构建并优化它,已经有了更为深入和直观的理解。
文章篇幅已然不短,此处不再过多总结。但最后仍需再次强调,在AI客服乃至所有RAG类应用中,高质量的数据工程和持续的数据运营,才是决定系统成败的灵魂所在。