今年LLM的发展趋势之一,就是端侧LLM快速发展,超级APP入口之争异常激烈。不过,端侧LLM如何应用,不知道细节就很难理解。正好,《Octopus v2: On-device language model for super agent》这篇文章可以解惑。
对比部署在云上,端侧大模型的好处主要来说就是:成本低、增强隐私。创建更小的模型以部署在智能手机、汽车、VR 耳机和个人电脑等边缘设备,等等方面的应用,正在快速发展。增强数据隐私的优点好理解,对于降低成本,应该说也是不得已的要求,受限于终端的算力、电池电量等因素,必须要求模型小,同时又需要有足够的推理能力。
这篇文章的核心就是,如何根据用户要求,让语言模型能够正确的进行API函数调用。文章的方法,简单说,就是把各种API函数的函数名,作为functional token新增到词汇表,把函数查询变成一个基于语言模型的分类问题。同时,为了选择正确的functional token,语言模型必须理解与该token相关联的含义,通过将函数描述纳入训练数据集,让模型完成相关知识学习。
这里面两个要点,一方面是增加functional token到词汇表,前面学习了领域适配分词技术,不难理解。再一方面,将函数描述纳入数据集,与之对比的就是RAG技术,是通过RAG查询,还是将函数的功能作为知识注入语言模型,通过语言模型进行查询?前面关于RAG的文章,提到一个很有意思的话题:“Self-DC:何时检索,何时生成?”——“什么时候利用外部检索,什么时候促使大模型产生已知的知识,以回答当前的问题?”按照这篇文章的方法,针对具体应用,检索的范围有限并且很具体,应该还是让模型学习专业知识比较好。不过,我其实有个问题,智能手机上的APP是在不断增加的,模型如何实时更新以适应最新的APP?
文章的核心思想是在终端设备上部署一个高效的大型语言模型,以便直接调用设备上的API功能。这种方法旨在解决以下几个关键点:
-
减少对云模型的依赖:通过在本地设备上部署模型,可以减少对云计算资源的依赖,从而降低成本和提高隐私保护。
-
提高性能:通过优化模型结构和训练方法,文章提出的方法能够在保持高准确性的同时,显著降低模型的延迟,使得模型在终端设备上运行更加高效。
-
直接API调用:模型通过学习API的功能描述和使用方式,能够直接生成调用API所需的命令和参数,从而实现对设备功能的直接控制和自动化操作。
-
适应性:文章提出的方法不仅适用于一种设备或API集,还能够适应不同的设备和API,具有很好的通用性和扩展性。
通过这种方式,可以在用户的设备上实现更加快速和准确的AI代理功能,例如智能手机、汽车、智能家居设备等,为用户提供更加丰富和便捷的服务。同时,这种方法还有助于减少对云服务的依赖,降低数据传输的需求,从而减轻对网络连接的依赖,提高系统的稳定性和安全性。
API(应用程序编程接口)通常提供了一组预定义的接口,允许不同的软件应用程序或组件之间进行交互和通信。API的核心作用是作为软件组件之间交互的桥梁,使得开发者能够利用某个服务或应用程序提供的功能,而无需了解其内部实现细节。
在文章中提到的上下文中,API调用通常指的是以下几个方面:
-
系统级API:例如,在移动操作系统(如Android或iOS)中,系统级API允许应用程序执行各种系统任务,如访问文件系统、发送网络请求、处理用户输入等。
-
应用程序级API:这些API是由特定的应用程序提供的,允许其他应用程序或服务与其交互。例如,社交媒体平台可能提供API,允许开发者创建应用程序来发布消息、检索用户信息等。
-
第三方服务API:许多在线服务和云平台提供了丰富的API集,使得开发者可以将各种服务集成到自己的应用程序中。例如,支付服务、地图服务、数据分析服务等。
文章中提到的模型通过学习API的功能描述,能够生成正确的API调用命令,这意味着模型可以理解API的用途,并生成相应的代码或命令序列来实现特定的功能。这种方法使得AI代理能够更加智能地与设备上的API进行交互,实现自动化任务和提高用户体验。
图1的这个图片,就是显示,语言模型如何根据用户要求,生成正确的函数调用示例。
文章标题为《Octopus v2: On-device language model for super agent》,主要研究了在设备上部署语言模型以提高AI代理的性能,特别是在自动工作流程任务中。以下是对文章的主要内容进行的分析:
解决的主要问题:
-
云环境中大型语言模型的隐私和成本问题:虽然大型语言模型在云环境中表现出色,但它们通常与隐私和成本问题相关。
-
设备上模型的性能问题:当前的设备上模型在功能调用方面面临延迟和准确性的问题。
方法:
-
新方法的提出:文章提出了一种新的方法,使得一个运行在终端设备的具有20亿参数的模型在准确性和延迟方面超越了GPT-4,并减少了95%的上下文长度。
-
函数令牌化(Functional Tokenization):通过将核心函数的名称进行token化并使用functional token对模型进行微调,模型能够理解软件应用的功能,并学习将函数描述映射到特定的token上。
-
模型训练:使用Google Gemma-2B模型作为预训练模型框架,结合了全模型训练和LoRA模型训练两种方法。
贡献:
-
性能提升:与GPT-4相比,提出的方法在准确性和推理延迟方面取得了显著提升,并且在设备上部署时减少了上下文长度,提高了效率。
-
适用性:该方法降低了延迟,达到适合在生产环境中部署各种边缘设备的水平,符合实际应用的性能要求。
-
扩展性:通过在设备上部署Octopus 2B模型并通过量化,展示了该模型在移动设备上的出色性能。
遗留问题:
-
训练成本:尽管文章提出了一种高效的训练方法,但生成特定API的训练数据集仍然需要成本,这可能会影响新功能集的训练。
-
模型的通用性:虽然文章展示了模型在特定功能集上的性能,但在更广泛的应用场景中的通用性和适应性还需要进一步研究。
-
隐私和安全性:虽然设备上模型可以减少隐私问题,但文章没有详细讨论如何确保模型在本地部署时的安全性和隐私保护。
-
模型的可解释性:文章没有讨论模型的可解释性,这对于理解和信任AI代理的决策过程是重要的。
模型方法
文章的第三节阐述了核心方法,关于Octopus模型的主要方法论。
3 方法论
在本节中,文章详细描述了在文章的模型中实现的主要方法论,然后是对于微调这些模型至关重要的数据集收集过程。文章通过从Android API中提取的示例来说明这一点。随后,文章深入探讨了文章的模型训练方法的具体细节。
3.1 作为分类模型的因果语言模型
要成功调用一个函数,准确选择所有可用选项中的适当函数并生成正确的函数参数至关重要。这涉及一个两阶段过程:函数选择阶段和参数生成阶段。初始步骤涉及理解函数的描述及其参数,使用用户查询中的信息为可执行函数创建参数。一个直接的策略可能是将分类模型与因果语言模型结合起来。文章设想N个可用函数作为一个选择池,将选择挑战转化为softmax分类问题。
分类的一个直接方法可能是基于检索的文档选择,通过语义相似性识别与用户查询最匹配的函数。或者,文章可以使用分类模型将查询映射到特定的函数名称。另外,像GPT这样的自回归模型可以从用户查询中预测正确的函数名称,考虑到潜在函数的上下文。这两种方法基本上将任务分成两部分,可能需要两个模型,π1和π2:
其中q表示查询,f表示选定的函数名称,params表示所选函数的参数。
在多任务学习/元学习原则的驱动下,为了实现更快的推理速度和系统便利性,文章追求了一个统一的GPT模型策略,设置π1 = π2 = π。因此,文章重新定义了文章的目标为:
对于P(f|q; π),传统方法涉及检索相关函数并提供相关函数的上下文,以推断最佳函数名称。在大多数使用情况下,可能的函数名称集合是固定的。当使用语言模型制定函数名称时,必须生成多个token以形成一个函数名称,这可能导致不准确。为了减少这种错误,文章将函数指定为独特的functional token。例如,在N个可用函数的池中,文章分配从<nexa_0> to <nexa_N-1>的token名称来象征这些函数。这将函数名称预测任务转化为N个functional token中的单个token分类,提高了函数名称预测的准确性,同时减少了所需的token数量。为了实现这一点,文章将从<nexa_0> to <nexa_N-1>引入成为新的特殊token,并修改了预训练模型的架构,通过额外的N个单元扩展了语言头部。因此,对于函数名称预测,文章利用语言模型通过argmax概率选择来确定N个functional token中的正确函数。
为了选择正确的functional token,语言模型必须理解与该token相关联的含义。文章决定将函数描述纳入训练数据集,使模型能够学习这些特殊token的重要性。文章设计了一个提示模板,可以容纳三种不同的响应风格,促进并行和嵌套函数调用。
这种方法提供了一个额外的关键好处。在对模型进行微调以理解functional token的意义后,它可以通过使用添加的特殊token <next_end>作为早期停止标准来进行推理。该策略否定了从函数描述中分析token的必要性,取消了对相关函数的检索和对其描述的处理。因此,这大大减少了准确识别函数名称所需的token数量。传统的基于检索的方法和文章目前提出的模型之间的差异如下图所示。
图2:基于检索的函数调用过程与Octopus模型的函数调用过程的比较。
3.2 functional token
本文提出的关键创新是引入了functional token。借鉴自然语言的token化,文章提议将特定函数表示为functional token。文章为这些token引入了一种训练方法,灵感来自自然语言模型处理罕见词的技术。这种训练方法受到word2vec框架的启发,其中上下文词丰富了一个token的语义表示。例如,预训练的语言模型最初可能难以识别化学领域的专业术语。然而,这些模型可以通过因果语言建模学习这些术语,利用包含这些专业术语的语料库。类似地,functional token也可以使用类似的方法学习。文章的实验没有发现定义functional token的数量有任何限制,允许用户将任何特定函数映射到一个token。
通过纳入functional token,文章的目标是赋予functional token与其他语言token相同的重要性。与传统的语言token不同,文章的functional token没有固有的自然语言含义;相反,它代表模型内封装的特定动作。对于像Google Gemma 2B这样的小型模型,执行函数调用可能是具有挑战性的,尽管它们在典型的语言完成任务上表现出色。functional token使语言模型能够将功能性调用方法转化为标准完成任务。由于文章为语言模型定义了动作,文章也可以将文章的模型表征为一个小动作模型。functional token的整合允许模型专注于一组固定的动作,并在这些任务上有效执行。
3.3 数据集收集
本节概述了文章为训练、验证和测试阶段组装高质量数据集的方法论。它还描述了文章用于高效训练目的的组织过程。
API收集作为示例,文章从Android API开始。文章的选择标准包括可用性、使用频率和技术实现的复杂性。文章最终收集了20个Android API,并将它们分为三个不同的类别,确保每个函数都可以通过Android应用开发在设备上实际执行,前提是开发人员拥有必要的系统权限。此外,文章还编制了车辆中可用的API。
-
Android系统API 这一类包括对基本移动操作至关重要的系统级函数的API,例如打电话、发送短信、设置闹钟、修改屏幕亮度、创建日历条目、管理蓝牙、启用勿扰模式和拍照。文章排除了访问系统状态信息或更改辅助功能设置等高度敏感的任务。
-
Android应用API 文章的研究检查了Android设备上预装的Google应用的API,例如YouTube、Google Chrome、Gmail和Google Maps。文章探索了访问热门新闻、检索天气更新、搜索YouTube内容和地图导航等功能。
-
Android智能设备管理API 文章的关注范围扩展到了Google Home生态系统,该系统包括具有重要市场份额的广泛智能家居设备。文章的目标是通过API改进智能设备管理,涵盖调整Nest恒温器、管理Google Nest设备上的媒体播放和使用Google Home应用控制门锁等功能。
数据集生成 文章的方法在图(3)中展示,展示了组装数据集所涉及的步骤。数据集的创建涉及三个关键阶段:(1) 生成相关查询及其关联的函数调用参数;(2) 开发无关查询并附上适当的函数体;以及(3) 通过Google Gemini实现二进制验证支持。 -
Google Gemini生成的查询和函数调用:创建高质量数据集的关键在于制定明确定义的查询和准确的函数调用参数。文章的策略强调生成单个API可以解决的正面查询。有了查询和预定的API描述,文章使用随后的Google Gemini API调用来产生所需的函数调用参数。
-
负样本:为了增强模型的分析技能和实际应用,文章纳入了正面和负面数据集的例子。这些集合之间的平衡在图3中由比例M/N表示,这在文章的实验方法论中至关重要。具体来说,文章选择M和N相等,每个都分配值为1000。
数据集验证 尽管像OpenAI的GPT-4和Google的Gemini这样的大型语言模型具有先进的能力,但在生成函数调用参数方面仍然存在明显的错误率。这些错误可能表现为缺少参数、错误的参数类型或对预期查询的误解。为了缓解这些不足,文章引入了一种验证机制。该系统允许Google Gemini评估其生成的函数调用的完整性和准确性,如果输出被发现不足,它将启动一个再生过程。
3.4 模型开发和训练
文章在框架中使用Google Gemma-2B模型作为预训练模型。文章的方法是结合了两种不同的训练方法:全模型训练和LoRA模型训练。对于全模型训练,文章使用了一个设置为5e-5的学习率、10个预热步骤和线性学习率调度器的AdamW优化器。相同的优化器和学习率配置应用于LoRA训练。文章将LoRA的秩设置为16,并将LoRA应用于以下模块:q_proj、k_proj、v_proj、o_proj、up_proj、down_proj。LoRA alpha 参数设置为 32。对于两种训练方法(全模型训练和 LoRA),文章将 epoch 数设置为 3。
特殊token的加权损失函数
文章中的4.6节(Weighted loss function for special tokens)讨论了特殊token的加权损失函数。
文章方法的一个独特之处在于将众多特殊token纳入到分词器中,并扩展了语言模型的头部。损失函数定义方程(3)如下:
其中T代表序列长度,V表示词汇表大小。
鉴于引入了从<nexa_0> to <nexa_N-1>的特殊token,以及token <nexa_end>,这些在Gemma-2B预训练数据集中都是不存在的独特token ,文章在模型训练期间面临不平衡数据集的挑战。为了解决这个问题,文章采用了加权交叉熵损失作为替代损失,以改善收敛性:
在文章的配置中,非特殊token被赋予了1的权重,而特殊token则获得了更高的权重。早期训练实验表明,增加token权重可以加快收敛速度。文章发现,在训练过程的早期使用替代训练损失有助于收敛。然而,实验发现在微调后的模型中没有性能差异,因此,对于少量的functional token,推荐使用等权重token损失。在文章的基准测试中,评估的模型是使用等权重训练的。
文章通过引入特殊token和加权损失函数来优化模型对这些特殊token的学习,这些特殊token对于模型正确理解和执行函数调用至关重要。通过加权损失函数,模型能够更加关注这些特殊token,从而提高了模型在实际应用中的性能和准确性。
理解扩展语言模型的头部
这篇文章,作者引入了特殊标记(functional tokens)来表示不同的API调用。这些特殊标记被加入到模型的词汇表中,并且模型的输出层(通常称为“头”或“head”)被扩展以包含这些新标记的表示。这样做的目的是使模型能够识别和生成这些特殊标记,从而准确地调用相应的API。
例如,假设文章有一个模型,它的词汇表大小是1000,这意味着它可以表示1000个不同的标记。如果作者引入了5个新的功能标记来表示不同的API调用,他们需要将模型的词汇表大小增加到1005。相应地,模型的输出层(头)也需要扩展,以便能够生成这5个新的标记。
在实际操作中,这可能意味着以下步骤:
-
词汇表更新:在模型的词汇表中添加新的标记,如
<nexa_0>
,<nexa_1>
, …,<nexa_N-1>
。 -
模型架构调整:在模型的输出层,原本可能只有1000个神经元对应词汇表中的1000个标记。现在,需要增加到1005个神经元,以便能够输出这N个新的功能标记。
-
训练调整:在训练过程中,模型需要学习这些新标记的含义,以及如何在适当的上下文中使用它们。
-
损失函数加权:为了确保模型能够快速学习并准确生成这些新标记,作者可能还会在损失函数中对这些特殊标记赋予更高的权重。
通过这种方式,模型不仅能够理解自然语言输入,还能够识别和生成用于API调用的特殊标记,从而实现更复杂的功能,如自动执行软件中的特定任务。
实验部分
文章第四章(Experiments)对Octopus模型进行了全面的评估,主要关注点包括:
-
模型性能比较:将Octopus模型的准确性和响应时间与当前领域的主要模型进行比较,包括GPT-4和GPT-3.5。
-
RAG技术的效果:探索了RAG(Retrieval-Augmented Generation)技术的效率,该技术通过为语言模型提供潜在功能的简明选择来减少错误输出(hallucinations)和延迟。
-
训练数据集大小和训练方法的影响:分析了训练数据集的大小和模型训练方法对性能指标的影响。
-
Android函数调用:选择Android系统函数调用作为案例研究,重点关注函数调用生成的准确性和延迟。
-
扩展到其他功能集:除了Android函数调用,评估还扩展到了20个车辆功能调用,展示了算法对不同用例的适应性。
-
完整与部分训练数据集:讨论了在训练阶段为每个API采样1,000个数据点的Octopus模型的卓越性能,并考虑了生成训练数据集的成本效率。
-
全模型训练与LoRA训练:LoRA(Low-Rank Adaptation)在框架中扮演了重要角色,特别是在将Octopus模型整合到多个应用中以确保平滑计算时。
-
并行和嵌套函数调用:为了支持并行函数调用和嵌套函数调用,需要为每个API准备4,000个数据点,以便达到与单个函数调用相同的准确度水平。
-
特殊token的加权损失函数:介绍了将多个特殊token纳入token器和模型头部的方法,并定义了损失函数以处理这些特殊token。
-
模型部署:讨论了Octopus模型在设备上的部署,包括在移动设备上的量化部署,以及在不同硬件上的兼容性。
这些评估要点展示了Octopus模型在不同方面的性能,并与现有的技术进行了比较,证明了其在设备上部署的潜力和效果。
图4和图5提供了关于模型在Android函数调用任务上准确性和延迟的重要数据。以下是对这些评估结果的主要结论的总结:
-
准确性提升:Octopus模型在执行Android系统函数调用时展现出了高准确度。在图4所示的准确性对比图中,Octopus模型与GPT-4、GPT-3.5以及使用RAG技术的Llama-7B模型进行了比较。结果显示,Octopus模型在数据点数量和训练方法不同的情况下,都能达到与GPT-4相当的准确性水平,甚至在某些配置下超过了GPT-4。
-
延迟降低:图5展示了不同模型在函数调用任务中的延迟(推理时间)对比。Octopus模型在延迟方面表现出色,相比于Llama-7B模型,Octopus模型的延迟显著降低。特别是,Octopus模型在全模型训练和LoRA训练的不同配置下,都能实现快速响应。
-
训练方法的影响:实验表明,使用LoRA训练方法可以在保持准确性的同时减少模型大小,这对于在资源受限的设备上部署模型是有益的。LoRA训练的Octopus-1模型虽然在准确性上有轻微下降,但延迟得到了优化。
-
数据集大小对性能的影响:通过减少训练数据点的数量,Octopus-2和Octopus-3模型展示了即使在数据点数量较少的情况下,模型仍然能够维持较高的准确性。这表明在训练新功能时,可以采用较小的数据集来平衡成本和性能。
-
模型的可扩展性:Octopus模型不仅在Android API上表现良好,还在车辆、Yelp和DoorDash等其他功能集上展示了其算法的适应性和通用性。
-
特殊token的有效性:通过引入特殊token和加权损失函数,Octopus模型能够更有效地处理函数调用,同时减少了模型所需的token数量。
-
设备上的高效部署:Octopus模型在移动设备上的部署表现出了快速的响应时间,即使是在标准Android手机上,也能在1.1到1.7秒内完成对20到30个token的典型查询的函数调用。
综上所述,图4和图5的评估结果表明,Octopus模型在准确性和延迟方面都取得了显著的性能,特别是对于需要在设备上快速运行并处理大量函数调用的实时应用场景。此外,模型的训练成本较低,且具有良好的扩展性和适应性,使其成为一个有前景的AI代理解决方案。
(欢迎关注微信公众号:老无谈藏书票)