然后很快大家发现确实卷不动,于是开始冷静下来,找切实的落地场景,所以24年都在做应用,AI应用三巨头依次是:AIGC(窗口生成文案)、工作流AI、然后就是AI客服了。
而后25年在AI视觉这块需求变多、成熟的AI Coding异军突起,但复杂的AI客服依旧有很大的需求,AI客服这个也被认为是RAG类的应用,看上去简单,只不过很多公司却做不好。
所以,我们这里以一个生产案例作为课件,带大家深入浅出的了解一个AI客服是怎么打磨好的:
案例说明
这个AI客服案例来源于我们去年AI 2C的创业项目:空气小猪。他是一款基于社交的语言学习App,从上线之后一直是我们自己在做客服工作,每天都会消耗2-3小时的时间,这种状态已经持续了半年多了,占用了大量时间。
这期间,我们也尝试找过兼职客服做过一段时间,发现效果很差。一方面,兼职人员不太上心;
另一方面,由于对产品理念和定位理解不够深入,往往无法准确、有效地回应用户问题,整体服务质量难以保障。
其实用户的问题基本都是重复的,高频问题就那些,每天去人工重复回答这些问题确实挺费时间的,既低效也不具备可持续性。所以关于简单AI客服的系统,我们之前就形成了一套方法论:

简单场景照着做就行(虽然最后证明其他同学会在其他地方掉坑里);复杂场景的话又有另外一套方法论,由此我们也几乎可以得出一个结论:
客服工作,无论简单复杂,在未来大概率会被AI替换
在线客服工作本身具有较强的重复性,因此“降本增效”始终是客服系统演进的核心目标。基于大模型的AI客服,可同时显著提升产品能力和用户体验,还能大幅降低运维成本。
随着 AI Agent 的成熟应用,AI客服系统在成本、效率和可扩展性方面进一步优化,逐渐会成为最优解。
那么这里又有同学会有疑问:为什么不一开始就上AI客服,还要每天花几小时去自己做?
答案很简单:我们也需要积累原始数据啊…
在这半年多的时间里,创始人与用户之间沉淀了大量真实、高质量的对话语料,这为我们提供了宝贵的数据基础。在基础问题开始不断重复的时候:就是构建一套 AI 客服系统的时机了。
这里目标就简单了:把我们从每天2小时的人工客服时间释放出来!这也是整体项目背景了,下面我们将详细的介绍空气小猪AI客服从0到1 的整个实践过程,以及落地的关键步骤。
技术选型
在实现环节我们面临一个选择:是采用智能体低代码开发平台,还是直接进行工程化代码开发?
从技术角度来看,这两种方式都可以实现目标,但真的要做肯定是直接选择工程化代码方案啊,好处很多,最重要的是对这块有更深入的技术实践,所有这一切都会体现在自主可控性这点,但也可以将选型过程简单说下,各位可以考虑看看:
在智能体开发平台的选型中,主要考虑的是Dify,前面我们介绍过coze、dify、fastgpt、n8n的技术选型。
整体来看,Dify的能力算是这些平台中最均衡的,没有明显的短板,尤其适合企业场景下的智能体开发、工作流的编排以及知识库驱动型应用。
但是最终没有选择Dify,主要是基于下面几个方面考虑:
-
我们对知识库检索能力有较高要求,希望在召回策略、排序逻辑、上下文拼接等环节进行深度优化。这部分是 AI 客服的核心能力,我们更希望逻辑完全自主可控。 -
私有化部署也需要额外的服务器的成本和运维成本,对我们当前阶段而言是没有必要的(真实使用你们才知道开源版本会少了什么)。 -
在实际测试中,我们发现 Dify 的执行链路相对较长,尤其在知识检索节点,整体响应时间偏长,不完全符合我们对实时性的要求。 -
即使使用Dify,实际落地过程中依然会涉及系统对接、数据适配和定制开发等工作,并非零成本集成。
综合这些因素,我们最终决定自己写代码,从底层能力开始搭建,虽然前期投入更高,但在可控性、性能优化空间以及长期演进能力方面更有优势。
并且自己写代码,事实上成本也并不高…
解决了第一个问题,很多同学第二个问题也就出现了:那么我们的AI客服要不要直接用Agent模式呢?
Workflow还是Agent?
项目开始阶段,除了要决定使用Dify还是工程化代码,开发模式也需要在Workflow和Agent中做出选择。
Agent是具有高度自主性的智能体,但是结果的确定性、性能等都不占优势,通常客服场景会选择比较保守的做法:先按照Workflow的方式,搭建稳定的流程,来追求确定的、能控制的结果。
从工作流程入手,逐步引入并解决每一个遇到的问题,同时兼顾效果、成本和可控制程度。
至于后期要不要“升级”Agent版本,完全看业务需要,业务上几乎不追求这些时髦的东西。
基础流程设计
在确定基础技术选型后,就可以进行流程设计了,在第一个版本中,我们把意图分为产品咨询和闲聊,大致的流程如下:

但是很快我们发现,用户除了咨询常见的产品功能问题,还会反馈一些产品建议以及程序故障等问题。
而这一部分内容的处理逻辑与单纯的产品咨询其实是不太一样的,用户反馈的问题是需要存入数据库,并且根据问题的严重程度划分等级,方便我们及时跟进修复处理。
在初版的基础上面我们增加了优化建议、故障反馈的意图处理流程。具体流程如下:

这也就是我们方法论中所述的整理大表了,在基础意图整理差不多后就可以进入最重要的知识梳理环节了:
知识整理
要做AI知识库的同学一定要注意:数据才是灵魂!如果有人说做AI项目不深度聊数据,那么他大概率是没做过的…
产品知识是AI客服的基础(这也是为什么我们非要等半年才做客服的原因),只有提供优质的知识才能让AI输出优质的回答,否则就是垃圾进垃圾出。
在数据不全的情况下,不管做再多的工程化优化都是无用功,所以说RAG的本质是个数据工程,大家一定要去理解这到底是在说撒。
具体在做AI客服知识梳理时,理论上来说要求是很高的,它最好来自这个产品最有解释权的人,但是知识的完备性需要持续的迭代更新才能覆盖完全。
真实情况是:所有知识库应用初始阶段都存在类似的情况,所以允许知识覆盖不全,在迭代中逐步补齐知识,并且后面用数据飞轮的策略来自动化的完善知识不足的问题变成了主流。
具体到这个项目,我们的知识来源于两部分内容:一部分内容是人工整理的,另外一部分是历史客服数据。

在进行知识整理时,就需要考虑如何组织知识才能有更好的检索效果,而检索的效果很大程度是取决于数据处理是否正确,比如每个分块的语义是否完整独立。
因此输出的知识一定要能够单独成块,可以利用Markdown格式进行结构的化层级进行整理,在分块时,可以根据标题进行分割,知识内容大致形式如下:

另一方面,我们导出了所有历史客服对话数据,这里主要根据会话维度进行分析,因为数据较多,不太可能人工整理,可借助AI分析提取每个会话中有效的问答记录。
当然这里也不能一次性把所有的数据给到大模型整理,有两个原因:
-
一是数据太多会超出大模型上下文限制; -
二是数据太多,幻觉增加,准确率会降低;
处理的策略是拆分为多个批次进行整理,比如每10个会话为一个批次,我们借助Coze搭建了一个自动化处理工作流,流程如下:

PS:这里也可以看出来,我们其实也使用Coze,但一般是来做一些自动化小操作,用完就走
从数据库导出会话记录时,每10个会话导出为一个会话记录文件,最终会导出若干个会话记录文件,然后把这些文件上传到coze工作流上进行批量处理,生成的问答对内容都会被写入飞书多维表格中。
最终表格中的内容必定会存在重复的内容,再把表格中整个内容给到大模型进行分析,把内容去重处理,形成最终的问答对。
通过这两种方式,我们就得到了最终的产品知识数据,这一步非常重要,也非常耗费精力,并且需要真正懂这个产品的人来做才能取得好的效果。
可以认为:这一步没做好,那么AI客服的效果一定会差!
在数据整理结束后,就进入了知识库构建环节:
知识库构建
这里技术实现:Python + FAISS + MYSQL + qwen(text-embedding-v4)
向量库选择Meta公司开源的FAISS,非常轻量,嵌入模型使用千问的text-embedding-v4(1024维度),它在中文场景下表现更好。
数据存储的结构
整个知识库由库、集合和数据 3 部分组成。
集合可以简单理解为一个文件,一个库中可以包含多个集合,一个集合中可以包含多组数据;
最小的搜索单位是库,也就是说,知识库搜索时,是对整个库进行搜索,而集合仅是为了对数据进行分类管理,与搜索效果无关。

向量存储的结构
使用 Faiss 作为向量检索引擎,使用 MySQL 作为业务数据存储数据库,实现知识入库与向量召回的分离式架构设计。
这里Faiss只负责向量存储与相似度检索,MySQL负责原始知识数据与业务字段存储,向量检索引擎可独立替换为其它向量数据库(比如Milvus、Weaviate等),不影响业务数据库结构。
而这两者间的关系通过向量ID进行关联,在MySQL的dataset.datas表中,会存储向量原数据的信息,同时有一个vectorId字段,会记录其对应的向量ID。

知识入库是一个离线过程,大致流程如下:
-
先加载知识文档,对文档进行分块 -
然后把分块存入到mysql业务数据库中,此时向量化状态为待向量化,向量ID字段为null -
然后通过异步事件驱动把每一个分块chunk使用向量模型进行向量化,得到向量坐标之后,存入Faiss向量库中 -
存入向量库完成后,会生成向量ID,然后在把这个向量ID存入到mysql对应的chunk中的vectorId字段,并且将向量化状态更新为已向量化

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

知识入库
在知识整理完之后,使用代码对markdown格式的知识,按照结构层级进行分块,得到结构化的JSON数据,然后存入业务数据库和向量库中。
把一级标题设置为category字段,把最后一级标题设置为questions,段落内容设置为answer字段,如果存在三级以上的层级,把1到n级标题通过“-”链接设置为category字段,n级标题设置为questions字段。我们得到的分块内容如下结构,这里只列举核心字段:
{
"category": "产品概念",
"questions": [
"空气小猪解决的核心问题是什么?"
],
"answer": "很多用户长期学外语遇到的真实问题包括:n外语只存在于“学习时间”,无法进入日常生活n输入和输出被割裂,学到的语言很难迁移到真实使用n听力和阅读材料与个人生活无关,难以长期坚持n空气小猪并不通过增加学习任务来解决这些问题,而是通过重用已经发生的聊天内容,为用户建立一个长期、低成本、真实相关的外语环境。",
"keywords": []
}
得到若干上述分块结构之后,按照前面的流程把每个分块存入mysql数据库,并存入向量库中。
需要注意的是,向量化的文档内容并不是直接把这个JSON进行向量化,这里JSON结构主要是为了拿到文档分块的结构化信息,方便元信息获取及存储。
向量化的真正文本内容为category+quesions+answer的拼接内容。
在这一步我们最初犯了一个错误,我们把生成的原始chunk使用大模型针对问题进行了泛化处理,泛化后的结构为:
{
"category": "产品概念",
"questions": [
"空气小猪解决的核心问题是什么?",
"空气小猪主要解决了什么问题?",
"空气小猪的核心价值是什么?"
],
"answer": "很多用户长期学外语遇到的真实问题包括:n外语只存在于“学习时间”,无法进入日常生活n输入和输出被割裂,学到的语言很难迁移到真实使用n听力和阅读材料与个人生活无关,难以长期坚持n空气小猪并不通过增加学习任务来解决这些问题,而是通过重用已经发生的聊天内容,为用户建立一个长期、低成本、真实相关的外语环境。",
"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": "简要分类理由(说明上下文如何影响判断)"
}
从提示词的设计可以看出,我们不仅对用户的提问进行了意图识别,还在这之前增加了指代消解的处理步骤。也就是说,在完成指代消解之后,才进入意图识别阶段。
PS:事实上也可以将这个提示词再拆分,以符合提示词原子性的要求,我们这里因为是做案例讲解就不麻烦了
至于之所以需要进行指代消解,是因为在实际使用过程中,我们发现用户往往会将一个完整的问题拆分成两句话,或者在后续提问中使用上下文中的指代词;
例如,用户先问“空气小猪是干什么的?”,接着又问“它怎么用?”如果将第二句话直接用于检索,很可能无法获得有效结果;而真正符合用户意图的检索语句应该是“空气小猪怎么使用?”。
因此,我们借助大模型结合上下文语境,对用户最新的问题进行指代消解,将其中的指代词还原为具体对象。这样可以提高意图识别、以及检索的准确性,使整体流程更加连贯和高效。
在意图识别这个环节中,模型经历了从GPT-4.1到Qwen-plus-latest、Qwen-max-latest,再到Qwen3-max、Qwen-plus的选择过程。
GPT-4.1作为效果标杆,Qwen系列则需要通过提示词优化或节点拆分来提升表现。值得一提的是,Qwen-plus在未修改提示词的情况下即有提升,整体效果还可以。
我们这里场景不算复杂,为了均衡成本和效果,我们模型最终选择了Qwen-plus, 如果需要更好的效果可以考虑Qwen3-max或GPT4.x等模型。
模型的选择可以根据项目阶段来确定,项目初期选择参数较大的模型进行验证并快速上线;后期则在保证意图识别准确率不下降的前提下,逐步替换为成本更低的模型,以实现效果与成本的平衡。
总之,我们每个项目做的时候都会用最好的模型,后续实际上线,都是各种成本考虑…
问题泛化
在正式进入检索阶段之前,需要先对用户问题进行一系列语义预处理,最大程度提升后续检索的召回率与覆盖面。
首先,通过指代消解技术,对问题中的代词、模糊指称和上下文依赖表达进行还原。
例如,将“他”“这个”“那个”等模糊表达,结合上下文明确为具体的名称,从而避免检索阶段因语义歧义而遗漏关键信息。
其次,我们基于原始问题进行多问题生成(Query Expansion & Multi-Query Generation)。利用大模型的语义理解和重写能力,从不同角度、不同表达方式对同一问题进行改写扩展。
比如:同义词替换与表达重构、从不同维度拆解子问题、将抽象问题转化为更具体、可检索的表达语句。
通过这种方式,可以将一个单一问题扩展为多个语义相关但表达不同的查询语句。
这种多路查询策略能够覆盖更多潜在的匹配结果,以提升召回率,同时减少因表达方式单一或者口语化而导致的信息遗漏。
## 角色
你是“空气小猪”智能客服系统的查询优化专家,专门处理**产品咨询**类查询的泛化改写任务,把用户问题泛化成检索友好的中文查询,用于知识库向量检索
## 改写规则
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主要基于词频和逆文档频率(TF-IDF)的加权搜索模型来对文档进行排序和检索。它特别适用于处理较为简单的匹配任务,尤其是当查询和文档中的关键词有直接匹配。
为此通过“多问题查询 + 混合检索”,我们会获得一批候选知识。但此时的结果集合规模较大、质量参差不齐,因此还需要进一步筛选,才能得到真正符合需求的内容。
那我们应该如何处理呢?
首先对相同检索方式的结果使用RRF进行合并,得到两类候选结果,分别为向量检索结果、BM25检索结果,由于混合检索后的查找范围很大,单纯依赖原始相似度分数难以直接过滤结果,因此需要引入重排模型进行精细排序。
重排模型(reranker)对候选结果重新评分,并根据相关度重新排序,绝大多数情况下,可以有效提高搜索结果的准确率。重排后可以得到一个0-1得分,代表着搜索内容与问题的相关度,该分数通常比向量的得分更加精确,可以根据得分进行过滤。
最后我们会使用 RRF 对重排结果、向量搜索结果、全文检索结果进行合并,得到最终的搜索结果。

单个问题的向量检索流程与前面讲解的流程一致,这里多问题并行向量检索的流程如下:

我们使用的Faiss向量库以及MySQL并不直接支持BM25检索,我们采用的策略是:先拿到所有的知识分块片段,并结合用户的问题,利用LangChain提供的BM25Retrieve进行计算,核心代码逻辑如下:
# 使用 BM25Retriever
bm25_retriever = BM25Retriever.from_documents(splitsDoc)
bm25_retriever.k = 3 # 返回前3个最相关的文档
# 使用
bm25_doc= bm25_retriever.invoke(query)
print(f"bm25_retriever检索到 {len(bm25_doc)} 个相关文档块:")
至此,其实AI客服的核心流程都被覆盖了,剩下的也就是最后的生成环节,反而简单了:
生成阶段
我们把大的意图分为了三个,分别是产品咨询、故障反馈、闲聊,进入每个意图后,处理的逻辑是存在差异的,因此大模型生成回答的提示词是不同的。
提示词的重点是构造上下文信息,拼装召回的知识、最新的N条对话历史消息、更旧的历史摘要消息以及用户最新的问题。下面是具体的提示词:
需要注意的是,知识召回后,在大模型真正生成回答时,会让他再次判断召回的知识是否可以回答用户问题,如果没用则拒绝回答,并且把useful字段设置为false;否则,设置为true。
这个字段的用处在于,我们会对大模型回答的问题进行标记,不能回答的问题,会进入低置信度问题池列表,便于后续知识补足和复盘,是为后面的数据飞轮做准备的:
## 角色
你是空气小猪产品客服助手,你需要根据对话历史、用户最新消息、以及知识回答用户问题
## 回复原则
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
}
## 处理流程
仔细阅读【产品核心理念】、【知识】、【上下信息】,按照如下要求进行处理:
### 1. 功能建议处理流程
#### 第一步:功能状态判断
首先判断用户建议的功能是否**已经存在**:
- **已存在**:明确告知用户该功能已支持,并提供简要使用指引
- **不存在**:进入下一步评估
#### 第二步:原则性评估
检查建议是否符合:
- **产品核心原则**:符合空气小猪产品定位和核心价值观
- **明确不做清单**:是否属于已明确排除的功能范畴
评估结果处理:
- **符合原则且不在排除清单**:
- 回复:**“感谢您的宝贵建议!我已经记录并反馈给产品团队进行评估,我们会认真考虑这个功能的可行性。”**
- 无需承诺具体实现时间
- **不符合原则或在排除清单**:
- 友好、明确地拒绝
- 回复示例:**“感谢您的建议。不过这个功能目前不符合我们的产品方向。期待您提出其他改进建议!”**
### 2. 故障反馈处理
- 引导用户详细描述问题现象
- 告知用户已反馈给技术团队
## 回复原则
1. **简洁明确**:直接回答,不绕弯,不要超过100字
2. **友好专业**:保持礼貌,体现专业性
3. **不过度承诺**:不承诺功能上线时间或具体解决方案
4. **客观事实**:不要胡编乱造,必须要从知识中拿到可靠的依据
## 知识
{
%s
}
## 上下文消息
### 对话历史
{
%s
}
### 用户最新消息
{
%s
}
## 输出要求
1. 用中文回复,不超过100字
2. 给出回复内容的%s翻译
3. **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"content": "string",
"translation": "string"
}
对于严肃型产品服务场景(如电商、医疗、金融等),通常不建议提供闲聊功能,应优先保证回答的准确性和可靠性;在无法确认答案时,宁可不回答,也不应提供可能误导用户的信息。
但在语言学习类应用中,我们有意引入“闲聊意图”,目标是让 AI 客服具有更自然、有温度的互动体验,而不是仅提供机械式回复。
通过适度的闲聊能力,可以增强用户参与感与陪伴感,从而提升整体使用体验与产品黏性:
## 角色
你是空气小猪产品客服助手,擅长陪伴用户进行轻松有趣的闲聊。你的核心任务是在自然对话中传递产品价值,并收集有助于改进的用户反馈。
## 产品核心理念
{
%s
}
## 对话风格
- 亲切、自然,像朋友聊天一样
- 避免推销感,注重倾听和共鸣
- 根据用户回答灵活调整,不强行推进问题
- 在解释产品理念时,尽量用口语化的例子或场景说明
## 引导反馈(顺势、递进、不要一次问完):
1. 你是怎么了解到我们产品的呀?
2. 最近使用起来感觉怎么样?有没有特别喜欢的部分?
3. 如果让你提一个建议,你会希望我们改进什么?
4. 方便问一下,你现在是学生还是已经工作了吗?
## 输入信息
### 对话历史
{
%s
}
### 用户最新消息
{
%s
}
## 输出要求
1. 用中文回复,不超过50字。
2. 给出回复内容的%s翻译
3. **必须**使用以下JSON格式返回,不得包含任何其他文本:
{
"content": "string",
"translation": "string"
}
再说可观测性
前面的内容,整个客服的流程就已经拉通了,从知识整理、知识入库到问答流程。
现在我们需要进一步调优,就要观察关键的环节是否符合我们的预期,比如意图识别准不准、指代消解对不对、问题改写质量如何、知识召回质量高不高、提示词有没有问题,我们需要对每个环节的耗时进行观测。
为此,我们在流程关键节点对核心信息进行了结构化存储,包括:
-
指代消解、用户问题改写 -
意图识别结果 -
向量召回的候选结果列表及置信度 -
最终命中的知识内容及回复结果 -
大模型调用日志
在后台管理系统中,可以看到全流程关键节点的输入和输出信息,可以直观地观测整个 AI 客服的运行状态。
比如:意图识别轨迹列表、客服向量召回结果列表、问题改写列表……
通过对这些核心节点的持续监测、分析,可以将原本不可见的系统运行过程由“黑盒”转变为“透明”,从而实现问题可定位、效果可评估、策略可优化,支撑整体能力的持续迭代与提升。
数据飞轮
这里必须说清楚,我们搭建的客服系统,知识现在仍然不是很完备,无法覆盖用户所有的问题,除了人工补齐的方案,我们也增加数据飞轮系统功能。
数据飞轮本质上是一种持续反馈的闭环机制:
通过从用户交互中不断收集数据 → 处理 → 优化 → 再反哺系统 让 AI 在真实业务中越用越准
当然这里并不是把所有的问题都放进知识库,而是:
-
识别哪些问题值得沉淀; -
持续补全真正有价值的知识缺口;
下面结合实际系统设计,介绍在 AI 客服中,如何对低置信度问题进行收集,并持续优化知识库。
置信度
在前文我们提到过,AI 客服的第一步是 意图识别。当用户提问后:
-
系统会先给问题打标签(例如:产品咨询); -
在对应标签下,进行向量召回; -
每条召回结果,都会有一个 置信度(score);
这个置信度,代表的是:
-
用户问题 与 知识库内容 的语义匹配程度; -
分值越高,说明命中越精准; -
分值越低,往往意味着知识库存在缺失或覆盖不足;
在系统中,我将置信度阈值设置为 0.5。当召回置信度 ≥ 0.5时,直接走正常回答流程;当召回置信度 < 0.5时,认为当前知识库匹配度较低,此时,系统会异步处理这条问题数据,进入数据飞轮流程。
问题标准化
模型会基于下面的提示词,完成两件关键事情:
-
将用户的原始提问进行标准化处理 -
生成一个示例答案,作为后续处理与参考依据
例如:
用户原话: “我在日本,用 +81 的手机号能不能注册啊?不行我就换国内的”
整理后的标准问题:国外手机号(非中国大陆)是否支持平台注册?
这一步在信息检索领域中,通常被称为 Question Canonicalization(问题规范化),因为用户的表达通常是口语化、上下文依赖很强,并不适合用于直接存储或检索;
在进入数据飞轮流程前,需要先将问题转化为结构清晰、语义稳定的标准形式,以提升后续召回、匹配与分析效果。
你是智能客服的知识运营助手。你要把“用户原话”整理成可入库的标准问题,并尝试与候选问题合并。
目标:
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知识库,以及AI知识库如何落地会有更深的理解了。
最后,文章篇幅已经很长了,这里就不再赘述,只是再强调下数据才是AI客服的灵魂…
