当前位置:   article > 正文

AI系列:大语言模型的function calling(上)

AI系列:大语言模型的function calling(上)

语言模型(LLM) 的function calling

大语言模型(LLM)可以使用自然语言与人类对话。但在使用它完成某项复杂工作时,很多时候必须依赖其他外部工具,这包括但不限于:

  • 训练的知识库和提示词以外的知识。包括某些垂直细分领域以及非公开的数据。
  • 计算任务。相信我,即使它给出的结果看起来很像样,你也不能相信它在计算方面的能力;它无法保证100%的准确性。
  • 实时数据。需要外部工具提供。

能识别需要使用的外部工具,能根据其结果数据完成对话的功能叫做function calling。

实验:OpenAI之function calling

OpenAI的GPT作为LLM的代表作,我们将给它提出如下问题:

问题:一共有3个人,每个人有15个苹果,10个鸭梨,一共有多少苹果?
注: 这个简单的逻辑和算数题只作为实验用途;实际应用中可以扩展到复杂的计算。

我们将给GPT提供两个function/tool。一个是乘法,一个是加法。
注: 其中加法用来迷惑GPT。

我们期待的结果:GPT能判断使用乘法及其参数,并使用乘法function calling给出的结果数据,最终返回正确答案:
三个人一共有45个苹果。

序列图:function calling如何工作

我们的代码和GPT将怎样完成这个过程呢?这里将整个过程描绘在下面的时序图中:

代码 大模型LLM 1. 调用对话接口,告诉LLM提示词+可使用的functions/tools定义 2. 需要调用的functions/tools及调用参数 3. 将步骤2中LLM的回复加入对话 4. 循环执行function calling,并将结果加入对话 5. 调用对话接口,需要以上所有对话信息 6. 最终回答 alt [分支:需要function calling] [分支:不需要function calling] 代码 大模型LLM

详情: 对话内容

以下内容是真实的对话历史,程序和GPT配合按照我们的预想完成了整个过程,并最终给出了正确答案。
注:以下用到的UserMessage, AIMessage, FunctionMessage都是LangChain中的概念;它比较贴切的抽象了不同role的对话项。


步骤1中的对话项:HumanMessage | 向GPT输入对话提示词。

#提示词
{
    "role": "user",
    "content": "一共有3个人,每个人有15个苹果,10个鸭梨,一共有多少苹果?"
}
  • 1
  • 2
  • 3
  • 4
  • 5

另外,在调用GPT接口时,定义了2个function type tools:乘法multiply和加法add。内容参见下一部分的代码部分。


步骤2中的对话项:AIMessage | GPT返回需要调用的functions/tools及其调用参数。

#这里GPT没有给出最终答案,它识别出了需要调用乘法multiply,参数一first_int为3个人,参数二second_int为15个苹果/每人。
{
    "content": null,
    "role": "assistant",
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_ZMbo4SiA2iaZUSLJMyX8ZzkP",
            "function": {
                "arguments": "{\"first_int\":3,\"second_int\":15}",
                "name": "multiply"
            },
            "type": "function"
        }
    ]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

步骤4中的对话项:FunctionMessage |function calling的调用结果数据。
tool_call_id对应步骤2中的tool_calls元素中的id。content为程序调用function/tool后的结果数据。

#将function calling的结果为3*15=45,设定role为tool,将其加入对话中。
{
    "tool_call_id": "call_ZMbo4SiA2iaZUSLJMyX8ZzkP",
    "role": "tool",
    "name": "multiply",
    "content": "45"
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

步骤6中的对话项:AIMessage | 程序将以上所有对话项发送给GPT,GPT用自然语言返回最终结论。

#最终结果为:三个人一共有45个苹果。
{
    "content": "三个人一共有45个苹果。",
    "role": "assistant",
    "function_call": null,
    "tool_calls": null
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

参考代码

function calling的实现代码如下:

__author__ = 'liyane'

import json

# 初始化环境和OpenAI
from openai import OpenAI
from dotenv import load_dotenv, find_dotenv
_ = load_dotenv(find_dotenv())
client = OpenAI()

#调用GPT大模型
def get_completion(messages, tools, model="gpt-3.5-turbo"):
    response = client.chat.completions.create(
        model=model,
        messages=messages,
        # tool_choice支持设置 "auto"(由模型决定是否调用tool) 或者 "none" (不调用tool)作为value。 有tools定义时默认由模型决定。
        # 也可以强制要求必须调用指定的函数,如下所示
        # tool_choice= {"type": "function", "function": {"name": "multiply"}} ,  
        tools=tools
    )
    return response.choices[0].message

#定义function/tool 1: multiply
def multiply(first_int: int, second_int: int) -> int:
    """两个整数相乘"""
    return first_int * second_int

#定义function/tool 2: add
def add(first_add: int, second_add: int) -> int:
    """两个整数相加"""
    return first_add + second_add

#将function calling的schema格式告诉大模型
tools=[{
    "type": "function",
    "function": {
        "name": "multiply",
        "description": "两个整数相乘",
        "parameters": {
            "type": "object",
            "properties": {
                "first_int": {
                    "type": "integer",
                    "description": "第一个乘数",
                },
                "second_int": {
                    "type": "integer",
                    "description": "第二个乘数",
                }
            },
            "required": ["first_int", "second_int"],
        }
    }
    },
    {
    "type": "function",
    "function": {
        "name": "add",
        "description": "两个整数相加",
        "parameters": {
            "type": "object",
            "properties": {
                "first_add": {
                    "type": "integer",
                    "description": "第一个加数",
                },
                "second_add": {
                    "type": "integer",
                    "description": "第二个加数",
                }
            },
            "required": ["first_add", "second_add"],
        }
    }
}]

# 调用LLM接口,将LLM回复加入对话上下文
prompt = "一共有3个人,每个人有15个苹果,10个鸭梨,一共有多少苹果?"
messages = [
    {"role": "user", "content": prompt}
]
response = get_completion(messages, tools)
messages.append(response)  

# 如果LLM需要function calling,调用相应的函数,并将函数结果数据加入对话上下文,继续调用LLM。
while (response.tool_calls is not None):
    for tool_call in response.tool_calls:
        selected_tool = {"add": add, "multiply": multiply}[tool_call.function.name]
        args = json.loads(tool_call.function.arguments)
        tool_output = selected_tool(**args)

        messages.append({
            "tool_call_id": tool_call.id,  # 用于标识函数调用的 ID
            "role": "tool",
            "name": tool_call.function.name,
            "content": str(tool_output)  # 数值result 必须转成字符串
        })

    response = get_completion(messages, tools)
    messages.append(response)  

print("=====最终回复=====")
print(response.content)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

后续: 使用LangChain实现function calling

后续更新AI系列:大语言模型的function calling(下)- 使用LangChain:如何使用LangChain实现function calling,LangChain对比原生调用能提供哪些便利。

参考

OpenAI / function calling
LangChain / Tool/function calling

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/450571
推荐阅读
相关标签
  

闽ICP备14008679号