Agent来了0x01:Function Calling

0 阅读3分钟

前言

前面学习了 什么是AI Agent,更早也在 Langhcain-Tool 中学习了 Langchain 中怎么使用工具,其中也谈到了Function Calling技术。但是我们当时并没有细究 Langchain 的@tool或者tool()到底是怎么让 LLM 识别并精准调用的。这次就来研究研究这个。

定义

Function Calling(函数调用) :这是模型在推理过程中生成的一个结构化输出。当模型决定要使用某个工具时,它不会直接执行代码,而是返回一个 JSON 对象,其中包含了要调用的工具名称(name)和具体的参数(arguments)。这是模型“思考”的结果。

  • 核心:赋予大语言模型调用外部 API的能力,也成为 AI Agent 的核心技能。

  • 流程:

    1. 额外挂载某些具备特定功能的函数库(api)。
    2. LLM 收到用户提问,判断是否需要外挂”帮助“。如果需要,返回这个结构化输出
    3. 调用外部函数并获取函数运行结果后,大模型再基于函数结果进行回答。

借用 openAI官网 的描述:

function_calling.png

实现

image.png

交互格式

Function Calling 是 openAI 在 2023 年 6 月率先提出的,所以 Function 和 LLM 的数据交互格式最开始也是 openAI 定义的。

image.png

# 定义工具
tools = [{
    "type": "function", # 固定写法
    "function": {
        "name": "calculate_total_age_from_split_json", #告诉大模型函数的名字
        "description": "计算年龄总和的函数,会从给定的JSON格式字符串中解析出DataFrame,计算所有人的年龄总和,并以JSON格式返回结果。",
        "parameters": {
            "type": "object",# 固定写法
            "properties": {
                "input_json": {
                    "type": "string",
                    "description": "包含待计算年龄总和的数据集",
                },
            },
        "required": ["input_json"],
        }
    }
}]

函数编写

这里就是普通的函数编写。因为是原生的 LLM,不借助 Langchain等框架,所以不需要 @tool 这样的装饰器。我们只需要按照上面要求的交互格式 和 LLM 交互即可。

# 编写函数功能
def calculate_total_age_from_split_json(input_json):
    """
    从给定的JSON格式字符串(按'split'方向排列)中解析出DataFrame,计算所有人的年龄总和,并以JSON格式返回结果。
    参数:
    input_json (str): 包含个体数据的JSON格式字符串。
    返回:
    str: 所有人的年龄总和,以JSON格式返回。
    """
    print("函数calculate_total_age_from_split_json被调用")
    # 将JSON字符串转换为DataFrame
    df = pd.read_json(StringIO(input_json), orient='split')
    # 计算所有人的年龄总和
    total_age = df['Age'].sum()
    # 将结果转换为字符串形式,然后使用json.dumps()转换为JSON格式
    return json.dumps({"total_age": str(total_age)})

Calling

response = client.chat.completions.create(
    model=ALI_TONGYI_PLUS_MODEL,
    messages=messages,
    tools=tools,  # 编写JSON Schema描述
    tool_choice="auto"
)

response = client.chat.completions.create(
    model=ALI_TONGYI_PLUS_MODEL,
    messages=messages,
    tools=tools,  # 编写JSON Schema描述
    tool_choice="auto"
)

思考

前面我们在 Langchain 中使用工具获取答案时,LLM 的返回结构是这样的:

image.png

那么,我们现在知道 tool 调用的本质需要依赖 Function Calling。我们不管是使用 @tool 还是 tool() 都并没有定义 openAI 要求的这种固定的交互格式。那么为什么 LLM 能调用到这些 function 呢?

其实,LangChain会自动将工具定义(args_schemadescription转换成底层模型(openAI)所要求的 Function Calling 交互格式。这就是 Agent 框架的好处,他会为我们封装好很多底层的功能,供我们更方便快捷地调用。

源码

github