基于千帆(ERNIE-Functions-8K)Function Calling的简单使用

1.Function Calling是什么?

1.1 概念

Function calling是一种将LLM(大语言模型Large language model)连接外部工具的能力,LLM经过微调后,可以检测出何时需要调用函数以及需要调用函数的方法名及参数,并返回给调用方以便调用外部函数,然后把调用外部函数的结果再传给LLM,最后LLM给出用户问题的最终响应。

1.2 流程图

下面是一张Function Calling工作的流程图,重点有3个:

  1. LLM会告诉我们需要调用什么工具函数以及调用工具函数的具体参数
  2. 调用函数发生在我们的系统里(一般使用反射实现),并把函数的执行情况加入到与LLM交互的历史会话中
  3. 会有多次跟LLM的交互过程
    在这里插入图片描述

2. Function Calling的作用?

序号 作用 内容 应用场景
1 扩展能力 能允许LLM与外部函数或者服务交互,极大地扩展了LLM的能力 数据库查询、数学计算、第三方API
2 实时性与动态性 可以使LLM获取实时的数据,突破LLM的训练数据静态知识的限制 股票信息、天气预报
3 任务自动化 能实现任务的自动编排 智能家具系统中灯光、温度、湿度等设备的自动调节
4 自然语言到标准化的转化 能识别出需要用到的外部函数和参数,完成自然语言到函数和参数的转换 我想知道上海的天气? -> {‘name’: ‘get_city_weather’, ‘arguments’: ‘{“city”: “上海市”}’}
5 业务逻辑集成 能让LLM的智能处理能力与企业的业务逻辑紧密结合 一家客服公司基于现有的知识沉淀来做智能客服

基于Function Calling的上述作用,能极大地推进AI在产品形态上的落地,以往我们总希望AI是无所不能的,期望能给它很少的输入,能完成很复杂的事情,但结果往往事与愿违,这样很难得到我们想要的结果。其实应该把复杂的任务拆得足够简单,每次给到AI清晰的prompt,完成单次的任务,最后所有任务完成了再给出最终的响应,这其实就是Function Call的工作机制,而LLM在其中扮演了任务拆分的重要工作。

特别是在已有系统的基础上,利用已有系统的API作为外部函数,让LLM来实现任务拆分和编排,就能很快地让AI为我们业务赋能。

3. Function Calling怎么用?

很多大模型都在微调之后支持了Function Calling,下面是基于百度千帆的ERNIE-Functions-8K的具体实现

注意:ERNIE-Functions-8K的function calling的能力只有python版本的SDK,没有其他语言的。如果python基础好的,可以直接看官方文档,不过官方文档里没有给出调用函数的过程。

3.1 单函数调用

接下来,我们用Python代码看如何实现用户的问题:“请帮我查询一下数据库中用python撰写的代码文件数量”

3.1.1 首先定义函数get_file_num

如下所示,主要就是通过指定语言获取文件数量,这个函数主要是在LLM给予我们返回参数后调用的

def get_file_num(params: dict) -> str:
    """获取数据库中指定语言的代码文件数量"""
    language_low = params.get('language', '').lower()
    language_map = {
   
   
        "c/c++": 35,
        "java": 10,
        "javascript": 25,
        "python": 35,
        "go": 32,
    }
    return str(language_map.get(language_low, 0))

3.1.2 定义函数Schema

为了让LLM知道什么时候需要调用函数,以及调用函数名及参数,我们需要定义函数的schema传给LLM

# 定义函数schema
func_list = [{
   
   
    "name": "get_file_num",  # 函数名称
    "description": "获取内部数据库中以某一编程语言编写的文件数量",  # 函数描述
    "parameters": {
   
   
        "type": "object",
        "properties": {
   
     # 参数schema,如果参数为空,设为空字典即可
            "language": {
   
     # 参数名称
                "type": "string",  # 参数类型
                "description": "代码所运用的编程语言,例如:python、c/c++、go、java"  # 参数描述
            }
        },
        "required": ["language"]  # 必填参数(无默认值)
    }
}]

3.1.3 第一次调用LLM接口

可以看到,我们把用户的问题(msgs)和函数schema(funclist)传给了LLM

    chat_comp = qianfan.Function()
    msgs = qianfan.QfMessages()
    msgs.append(query, role='user')
    resp = chat_comp.do(
        messages=msgs,
        functions=func_list
    )

上述是千帆的SDK,实际调用LLM的Prompt如下:

        {
   
   
            "role": "user",
            "content": "接下来的所有对话中,你可以使用外部的工具来回答问题。\n你必须按照规定的格式来使用工具,当你使用工具时,我会在下一轮对话给你工具调用结果,然后你应该根据实际结果判断是否需要进一步使用工具,或给出你的回答。\n工具可能有多个,每个工具由名称、描述、参数组成,参数符合标准的json schema。\n\n下面是工具列表:\n名称:get_file_num\n描述:获取内部数据库中以某一编程语言编写的文件数量\n参数:{\"type\": \"object\", \"properties\": {\"language\": {\"type\": \"string\", \"description\": \"代码所运用的编程语言,例如:python、c/c++、go、java\"}}, \"required\": [\"language\"]}\n\n\n如果你需要使用外部工具,那么你的输出必须按照如下格式,只包含2行,不需要输出任何解释或其他无关内容:\nAction: 使用的工具名称\nAction Input: 使用工具的参数,json格式\n\n如果你不需要使用外部工具,不需要输出Action和Action Input,请输出你的回答。\n你的问题:请帮我查询一下数据库中用python撰写的代码文件数量"
        }

可以看出,整体是由:千帆system_prompt + 函数schema + 用户问题

3.1.4 解析第一次调用结果

第一次调用LLM,LLM发现要解决用户的问题,需要调用函数,则会返回如下的格式:

 {
   
   
    "id": "as-09dj7y7hzz",
    "object": "chat.completion",
    "created": 1736684991,
    "result": "",
    "is_truncated": false,
    "need_clear_history": false,
    "finish_reason": "normal",
    "usage": {
   
   
        "prompt_tokens": 226,
        "completion_tokens": 17,
        "total_tokens": 243
    },
    "function_call": {
   
   
        "name": "get_file_num",
        "arguments": "{\"language\": \"python\"}"
    }
}

千帆会把需要调用的函数和参数放到function_call中返回,所以我们用如下代码获得函数及调用的参数:

func_call_result = resp['body'].get('function_call')

3.1.5 调用函数获得结果

如下所示,我们获取需要调用的函数和参数,然后使用globals()反射的方式使用"{“language”: “python”}"作为参数调用函数get_file_num函数得到结果func_resp

    if func_call_result:
        # 获取函数名称、入参
        func_name = func_call_result["name"]
        func_param = json.loads(func_call_result["arguments"])
        func_resp = None
        # 使用 globals() 动态调用函数
        if func_name in globals() and callable(globals()[func_name]):
            func_resp = globals()[func_name](func_param)
            print("函数" + func_name + "执行结果:"+
<think>好的,我现在需要帮助用户了解如何使用ERNIE-4.0-8K模型的API接口。用户已经提供了三个相关的引用内容,我需要仔细阅读这些引用,从中提取关键信息,并按照用户的要求结构化回答。 首先,根据引用[1],用户需要创建应用并获取API Key和Secret Key,然后在代码中进行替换。引用[3]提到需要开通接口付费,并且给出了调用示例。引用[2]则说明虽然主要是关于开发板接入,但可能涉及API调用方式,但可能参考价值较低,主要还是看引用[1]和[3]。 接下来,我需要按照用户的要求,分步骤说明使用方法,包括申请步骤、调用步骤、示例代码、注意事项等。同时要确保使用正确的LaTeX格式,比如行内公式用$...$,独立公式用$$...$$。不过在这个问题中可能数学公式较少,但如果有需要的话需要注意格式。 用户还要求生成相关问题,我需要根据ERNIE-4.0-8K的API使用场景,提出几个相关的问题,比如如何鉴权、错误处理、计费方式等。 需要检查是否所有行内数学表达式正确使用$...$,独立公式单独成段。这里可能不太涉及数学公式,但要注意代码块的使用,如Python示例需要用```python包裹。 另外,回答中引用的段落末尾要自然地添加引用标识,例如[^1],所以需要确保每个引用的地方都正确标注。 现在开始组织回答结构: 1. 申请步骤:创建应用,获取API Key和Secret Key,开通服务付费(引用[1]和[3])。 2. 调用步骤:鉴权获取access_token,发送HTTP请求(引用[1]示例代码)。 3. 代码示例:提供Python代码,替换API Key和Secret Key(引用[1]和[3])。 4. 注意事项:计费方式、模型特点、错误处理(引用[3]和[1])。 5. 相关问题:生成三个相关问题,围绕接口使用、鉴权、计费等。 需要确保每个步骤都引用正确的来源,比如申请步骤引用[1]和[3],调用步骤引用[1]和[3],代码示例来自引用[1]和[3]。 检查是否存在可能的错误,比如代码中的占位符是否正确,是否需要更多的参数,比如在引用[3]中提到的模型名称可能需要指定为"ERNIE-Bot-4",但用户问的是ERNIE-4.0-8K,可能需要确认模型名称是否正确。但根据引用[1],示例中的模型是ERNIE-4.0-8K,所以代码中的模型参数可能需要调整。 例如,在引用[1]的示例中,使用的是ERNIE-4.0-8K,而引用[3]中的是ERNIE-Bot-4。用户现在想调用的是ERNIE-4.0-8K,所以需要确认模型名称是否正确。可能需要在请求体中指定model参数为"ERNIE-4.0-8K"。 因此,在代码示例中,发送POST请求的URL可能需要包含模型名称,或者在请求参数中指定。例如,引用[1]的示例代码中的URL可能已经包含模型名称,需要用户替换正确的endpoint。 需要提醒用户查阅官方文档确认模型名称和接口地址是否正确,避免错误。 另外,在鉴权部分,需要说明如何获取access_token,可能需要向特定的token_url发送请求,如引用[1]中的示例代码所示。 最后,确保回答使用中文,结构清晰,分步骤说明,并正确引用来源。</think>### ERNIE-4.0-8K模型API接口使用指南 #### 1. 申请与准备 - **创建应用**:登录百度AI开放平台,进入「控制台」→「应用列表」创建新应用,获取`API Key`和`Secret Key`。 - **开通付费服务**:在「ModelBuilder」中选择ERNIE-4.0-8K模型,完成接口付费开通(当前价格约0.12元/tokens)[^3]。 #### 2. 调用步骤 1. **鉴权获取Token** 使用`API Key`和`Secret Key`向百度鉴权接口发送请求,获取`access_token`(有效期为30天)[^1]: ```python import requests API_KEY = "your_api_key" SECRET_KEY = "your_secret_key" token_url = "https://aip.baidubce.com/oauth/2.0/token" params = { "grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY } response = requests.get(token_url, params=params).json() access_token = response["access_token"] ``` 2. **发送请求** 通过HTTP POST调用接口,需将`access_token`加入请求URL,并在请求体中传入对话内容[^3]: ```python endpoint = "https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions" headers = {"Content-Type": "application/json"} payload = { "messages": [ {"role": "user", "content": "你好,请介绍ERNIE-4.0的功能"} ], # "model": "ERNIE-4.0-8K" # 根据接口文档确认是否需要显式声明模型 } response = requests.post( f"{endpoint}?access_token={access_token}", headers=headers, json=payload ).json() print(response['result']) ``` #### 3. 注意事项 - **计费方式**:按token数量计费,需关注输入与输出的总token消耗[^3]。 - **性能优化**:可通过`max_output_tokens`参数限制生成文本长度以控制成本。 - **错误处理**:检查响应中的`error_code`字段,常见错误如`110`(鉴权失败)或`336003`(输入敏感词)。 #### 4. 接口文档参考 建议访问[百度AI开放平台](https://ai.baidu.com/)获取最新文档,重点关注: - 支持的输入格式(如多轮对话结构) - 可调节参数(温度值、重复惩罚等) - 模型限制(如最大上下文长度8K tokens)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值