大模型在小爱同学应用实践
导读 本文将介绍大模型在小爱同学产品上的应用,分享在意图分发、意图理解、回复生成等方面的实践。
主要内容包括以下几大部分:1. 小爱同学概要介绍
2. 大模型意图分发
3. 大模型垂域意图理解
4. 大模型回复生成
分享嘉宾|杜鑫 小米公司 高级算法工程师
编辑整理|朱伟
内容校对|李瑶
出品社区|DataFun
小爱同学概要介绍
大模型意图分发
1. 意图分发介绍
2. 大模型尝试
大模型输出的意图跟我们预定义的意图不一致。
大模型没有办法有效地遵循指令。在实践过程中发现,只有百亿级或者千亿级的模型才会遵循指令,更小的模型会倾向于直接去回答问题。
3. 大模型微调
大模型垂域意图理解
1. 传统意图理解方式
2. 小爱意图理解方式
3. Function calling 难点
小爱场景下 Function calling 是满足的基础,需要保证 100% 的指令遵循,通用大模型 prompt engineering 很难满足。大模型微调的话也是分了两步,第一步是做了继续预训练,方法与意图分发的继续训练模型基本上是一样的,稍微不同的是不同的垂域可以提供不同的继续预训练的数据;第二步就是做指令的微调,也跟意图分发是一样的。
串行的方式,类似 ReAct。主要有两个操作,一个是 reasoning 推理规划,另一个是 acting,这是单 function 的执行。对于一个请求,ReAct 首先进行 Resoning 推理,决定下一步的操作,在意图理解里就是输出 Function,每次推理只会输出一个 Function。然后 Acting 执行,即 Function 执行。得到执行结果后,再重复上述过程,直到满足用户需求。如果一个需求,需要多 Function 执行,那么 ReAct 执行链路会很长,在实际应用中难以落地。
解决多 Function 并行可以用编程语义来表达,类似 LLMCompiler。可以并行的 Function 会同时执行,可以减少响应时间。
LLMCompiler 会有三个组件:LLM Planner 大模型规划,Task Fetching Unit 任务获取,Executor 执行。
LLM Planner
利用 LLMs 的推理能力,规划分解为子任务,并识别各子任务的依赖关系,生成一个子任务序列及其依赖关系,形成一个有向无环图。
如果一个任务依赖于之前的任务,它将使用占位符变量,用该任务的实际输出替换该受量。
Task Fetching Unit
无依赖关系的子任务,并行执行。
有依赖关系的子任务,在完成上一任务后,再进行分发执行。
Executor
以异步和并发的方式执行从任务获取单元获取的任务。
执行器配备了用户提供的工具,并将任务给关联的工具(如:API 调用)。每个任务都有专用的内存来存储其中间结果。任务完成后,最终结果将作为输入转发给依赖于它们的其他任务。
我们采用的是类似 LLMCompiler 的方式。但是在我们的场景下,更多的是单Function 需求。整体的执行效率没有体现。
除此之外,最近也有一些 Tree-based Planning,比如 Tree of thought、language Agent Tree Search(LATS),可以同时考虑多个可行的计划,以作出最佳选择,耗时会过高,因此,在我们的场景下没有采用。
输入优化
在大模型微调过程中让其记住 function 的定义和参数,这样可以减少生成的 token 数。但这样做的缺点是大模型需要频繁更新以应对变化,通用性较差。为缓解这一问题,我们让每一个垂域先虚拟一些 function,让大模型具备处理垂域 function 的能力。
推理优化
一方面是减少生成的 tokens 数,另一方面就是减少推理的次数。减少 tokens 数一般有三种方式,第一个就是选择高压缩率的底座模型,在实践中,我们对比过两个开源模型,压缩比在 1.4-2 之间,如果选择了高压缩率的底座模型,生成的 tokens 数据会明显地减少。第二种方式是扩充词表,我们尝试发现如果直接扩充词表而不去做继续预训练,那么大模型性能是急剧恶化的,所以如果要扩充词表,还是要去做一个继续训练。第三种是做 token 的替换,有的时候可能 function 名字或者参数的名字会被切成多个 token,可以在已有词表里边选择一个相近的 token 来替换,这种方法不够通用,建议慎重使用。
减少推理次数的方法就是投机采样,其核心是通过一个小模型推理 n 次生成 n 个 token,再让大模型进行评估。在 Function calling 的应用中,小模型用 n-gram 即可实现 2-3 倍的推理速度提升。
大模型回复生成
1. 大模型回复的问题
时效性。最经济的解决方式就是利用 RAG,外挂知识库,让大模型基于检索到的知识来做回答。
长上下文理解。由于 RAG 通常冗余地注入知识,来保证知识的召回率,会使 token 数很多,对大模型上下文理解能力的要求就更高。
指令遵循。我们的场景下,为了保证用户的体验,期望回复简单,不要做信息的罗列。特别是当商品属性众多,需要明确哪些属性是用户关心的。通常是产品定义。大模型难以遵循指令只输出关键信息。
2. 大模型微调
知识总结。比如推荐一款手机,注入知识之后,要把用户关心的那个手机的一些参数给出来。
信息抽取。比如小米十四的像素是多少,我们希望大模型能够从我们注入的知识中,把小米十四的像素信息准确地提取出来。
复杂推理。比如推荐一个拍照好的手机,大模型需要理解这个拍照好对应的是相机的参数。再比如对比一下小米 14 和小米 14 pro 的差别,那大模型需要从注入的知识中,把这个小米 14 和小米 14 的 pro 的参数差异给出来。
多轮对话。多轮的时候经常会有缺省的部分,第一轮我说小米十四的价格,然后第二轮是像素是多少,那我当然希望他回答是小米十四的像素,而不是其他手机的像素。
兜底回复。因为会有一些知识缺失,或者是知识未检索到的情况,我们不希望大模型去杜撰。比如小米 17 什么时候发布,注入知识中肯定是没有小米 17 的,我们希望大模型能够具备抗干扰的能力。
最后为了保证大模型具备通用的问答能力,我们还会混入一些通用的能力。
第一步,优化单能力训练数据;这里,一个很重要的问题是如何评价。我们最终的模型评价是人工标注,但是人工标注成本太高且周期太长,在迭代过程中不适合。我们采用更好的大模型进行自动评价,例如 chatGPT,GPT4。前期评测,大模型评价与人工评价的一致性大概 80% 左右。 第二步,按比例混合训练数据,指令微调。这里最重要的是数据混合比例如何确定: 单个能力的数据到达一定的规模(1000->1500), 评测集合满足率(40%->81%)呈现大幅度提升,继续增加训练数据(1500->2000),满足率提升缓慢(81%->86%) 因此,训练数据混合时,我们找到不同能力的满足率大幅提升到平稳的临界点,以此作为调整的基础。一般来说,难度大的,训练数据会稍多。在合并数据过程中,我们会控制每个能力的数据上限。 第三步,构建偏好数据,对齐训练 DPO。数据构建格式是一个四元组<Query, Knowledge,Win_response,Lose_response>
3. 未来展望
分享嘉宾
INTRODUCTION
杜鑫
小米公司
高级算法工程师
2010.9-2013.3 北京邮电大学 硕士研究生
2013.4-2020.6 北京三星研究院,负责30+语种的联机手写识别,三星语音助手 Bixby 开发
2020.7-至今 小米公司 小爱同学 负责语音助手中的 NLP 相关算法开发。
往期推荐
生成式AI带来的冲击与改变,我们讨论得还远远不够
多模态在京东内容算法上的应用
LLM+RAG:大模型在金融场景的落地探索
智能电销新纪元:大模型技术的应用与未来趋势
Apache Hudi 从零到一:初识表服务:压缩、清理及索引(五)
小红书推荐系统迭代:AB测试架构的高效与稳定性策略
7倍性能提升|阿里云AnalyticDB Spark向量化能力解析
金融大模型数据治理与应用创新
面向大规模向量数据的云原生存储解决方案:Milvus 向量数据库的经验
点个在看你最好看
SPRING HAS ARRIVED