提升大模型 Function Calling 准确性
提升大模型 Function Calling 准确性
无论是LLM还是Agent,发挥胜寒里的核心点是「工具调用」或者说「函数调用」,但是目前来看说通用的模型,函数调用的性能还不能很好满足我们的需求。本文探讨如何提升函数调用准确性的一些方案。
先提个醒,论文内容并不一定(大多时候不)适合我们的场景,而且论文提出的方法也并不是创新性的,而是工程实验性的。大家核心关注作者们怎么发现问题、实验以及解决问题的思路。这个思路是我们大多数应用设计开发中经常面对的。
这部分内容主要来自下面论文:《Robust Function-Calling for On-Device Language Models via Function Masking》:
函数调用的过程
函数调用的过程
我们先介绍一个典型的函数调用过程,如上图所示。在这个过程中,
- 每个候选函数都包含几个部分,包括函数名、参数名、默认值和描述。
- 模型的目标是输出完整、准确的函数调用代码,以实现用户的意图,或者输出一个空列表,表示给定的候选函数都不能满足用户的要求。
- 实现这一目标取决于模型能否准确地将用户的意图与候选函数的功能相匹配,即选择合适的函数,以及模型能否理解每个参数的用法,即用正确的参数填充函数。
发现的问题
在实践中观察到了一些反复出现的问题:
- 函数名称和参数名称的误导
- 过度关注命名的影响
函数名称和参数名称的误导
函数的定义通常包括函数名称、参数名称和描述。函数和参数名称的格式通常非常紧凑,例如cal_sum
或max_value
,并且受设计者的个人风格和偏好的影响。当模型试图仅从函数名称推断函数的用途时,这种紧凑性可能会导致歧义,从而误导模型的选择,尤其是在存在复杂功能的情况下。
例如,名为parse_data
的函数可能用于解析JSON数据,但同一名称可能指在不同上下文中解析CSV文件,从而导致潜在的误解。同样,在根据参数名称推断参数用法时,模型可能会受到训练数据集中类似名称参数的历史用法的误导。更具体地说,这些误导场景可以分为几种情况。
函数名称误导。当用户意图与训练标签中存在的函数名称高度一致时,模型可能会在测试期间错误地将该函数从候选列表中优先考虑,即使其功能与预期操作有很大差异。例如,如果训练对中包含一个名为fetch_data
的函数用于从数据库检索用户数据,但在测试集中,同名函数从外部API检索数据,则模型可能会错误地仅根据名称选择它。
参数名称误导。在测试环境中,当参数的功能和描述发生变化时,模型经常会坚持其原始的参数使用模式,从而导致错误的函数调用。例如,如果函数的参数超时在一个上下文中应为表示秒的整数,但 在另一个上下文中,它被定义为“10s”格式的字符串,则模型对原始整数格式的依赖可能会导致错误调用。
命名偏好带来的困扰。当测试环境中函数或参数的命名约定与训练数据集中的命名约定不同时,模型的稳健性可能会降低。诸如CamelCase
和snake_case
之间的差异等变化可能会降低模型的置信度,因为设备上的轻量级模型可能难以在不同的命名风格中进行推广。
过度关注命名的影响
下面看看我们在测试集中屏蔽了函数和参数名称,即用随机字符串替换它们,并观察模型性能的变化。受测试模型的性能大幅下降。Hammer模型在相同设置下的性能,性能下降要小得多,证明了它在面对任意函数和参数命名模式时具有很强的适应性。下面看如何实现。
方法
函数屏蔽
缓解上述问题的直接方法是尽量减少函数名称和参数名称的干扰,同时强制模型根据候选函数的描述理解其功能和用法。描述的优点:
- 描述提供了更灵活的自然语言解释,通常封装了函数和参数名称想要传达的信息。
- 虽然描述在某种程度上也能反映设计者的个人风格,但它们往往更准确、更详细,从而降低了出现歧义或误导的可能性。
下图展示了函数屏蔽的过程:
函数屏蔽
论文结果肯定是好的,看下测试结果:
Hammer2.0
Hammer2.0已经在HuggingFace上发布,最小的仅为0.5B,最大的为7B,大家可以在自己的环境或者MaaS平台部署测试。
Hammer2.0
注意
最后大家在注意一下,论文中的函数屏蔽方案可能大多数时候并不使用与我们自己的场景。我接触的客户多是基于API调用,其函数数量也不会太多,所以性能而本身更依赖函数Schema的定义,以及基础模型本身和的性能。大规模函数调用当函数数量到达一定数量级的时候,我们可以使用RAG+Func Template的方式实现,可以参考我之前讲Chat SQL的相关文章。