【AI大模型第9集】Function Calling,让AI大模型连接外部世界

文章目录

  • 一、大模型为什么要连接外部世界?
  • [二、Function Calling 是什么?](#二、Function Calling 是什么?)
  • [三、为什么需要 Function Calling ?](#三、为什么需要 Function Calling ?)
  • [四、Function Calling 的工作原理](#四、Function Calling 的工作原理)
  • [五、Function Calling 代码实战](#五、Function Calling 代码实战)
    • [1. 大模型调用单个方法](#1. 大模型调用单个方法)
    • [2. 大模型调用个多方法](#2. 大模型调用个多方法)
    • [3. 大模型生成sql查询数据库](#3. 大模型生成sql查询数据库)
  • [六、Function Calling 的注意事项](#六、Function Calling 的注意事项)
  • [七、Function Calling 解决的问题](#七、Function Calling 解决的问题)

Function Calling 是 OpenAI 最先引入的一项技术,允许开发者将大语言模型(如 GPT-4)与外部函数或工具集成。通过 Function Calling,模型可以理解用户请求并生成调用外部函数所需的参数,从而实现更复杂、更动态的任务处理。下面我们一起来详细了解 Function Calling 技术吧。

一、大模型为什么要连接外部世界?

大模型连接外部世界,不是为了更"聪明",而是为了更"可靠、可用、可控"。

  • 大模型知识有限 :大模型的知识来源于训练数据,一旦训练完成,知识就停止更新。
    • 不知道最新新闻、政策变化、股价、天气。
    • 不知道某个网站是否已经下线。
    • 不知道你刚刚发生了什么事。
  • 大模型没有真逻辑 :大模型表现出得逻辑、推理是训练文本的统计规律,它擅长语言概率预测,而不是事实验证,所以存在幻觉。
    • 可能虚构不存在的论文、法律条文、产品。
    • 对不确定问题给出"自信但错误"的答案。
  • 会说话不等于真正有用:如果不能连接外部世界,大模型只能聊天、写文章、做理论推理,但实际需求是调用搜索引擎、访问数据库、访问第三方系统、执行程序等。
  • 增强感知和行动能力:现实世界是一直在变动的,大模型需要连接外部世界,不断读取外部数据,感知外界变化,基于外部数据,给出正确的行动能力。

二、Function Calling 是什么?

Function Calling 技术是一种让大模型连接外部世界的桥梁技术。通过Function Calling,大模型可以与外部系统、实时数据库、历史数据等进行交互,并以结构化方式传递参数。

它的核心作用是让大模型负责"想清楚要做什么",再由函数负责"真的去做"。


三、为什么需要 Function Calling ?

  1. 让模型"能做事":没有 Function Calling,模型只能输出文本。有了它,模型可以:

    • 查数据库。
    • 调用 API。
    • 执行业务逻辑。
    • 操作系统或服务。
  2. 减少胡编乱造:让大模型不自己编结果,而是:

    • 明确调用函数。
    • 用真实返回值回答。
    • 大幅降低幻觉问题。
  3. 更安全、可控:控制大模型的行为能力,只允许他做规定的事,让行为更加可控、正确。

    • 大模型不能随便执行代码。
    • 只能调用你事先定义好的函数。
    • 参数结构清晰、可校验、可审计。

四、Function Calling 的工作原理

Function Calling 的工作流程如下图:

  1. 当用户请求后,应用程序提取propmt信息后调用大模型,给出场景提示词和函数定义。
  2. 大模型通过上下文判断给出结构化输出,应用程序调用结构化输出对应的函数。
  3. 将执行结果作为输入给到大模型,大模型转换成自然语言将结果返回。

大模型可以根据上下文判断调用哪个函数,大模型通过循环调用应用程序函数可以实现复杂场景。


五、Function Calling 代码实战

1. 大模型调用单个方法

模拟大模型调用单个方法。

python 复制代码
# 导入依赖库
import os
import json
from openai import OpenAI
from math import *

# 定义一个辅助函数,用来打印日志
def print_json(data):
    """
        如果参数是有结构的(如字典或列表),则以 JSON 形式打印,否则直接打印。
    """
    if hasattr(data, 'model_dump_json'):
        data = json.loads(data.model_dump_json())
    
    if (isinstance(data, (list))):
        for item in data:
            print_json(item)
    elif (isinstance(data, (list, dict))):
        print(json.dumps(data, indent=4, ensure_ascii=False))
    else:
        print(data)

# 初始化 OpenAI 客户端
client = OpenAI(
    # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",

)

# 定义一个函数
def get_completion(prompt, response_format="text", model="qwen3-max-preview"):
    print_json(prompt)
    
    response = client.chat.completions.create(
        model=model,
        messages=prompt,
        temperature=0.6,  # 取值范围: [0, 2),temperature越高,生成的文本更多样,反之,生成的文本更确定。
        response_format={"type": response_format}, # 返回消息的格式
        tools=[{
            "type": "function",
            "function": {
                "name": "calc",
                "description": "数鸭子,计算一共有几只鸭子",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "numbers": {
                            "type": "array",
                            "items": {
                                "type": "number"
                            }
                        }
                    }
                }
            }
        }]
    )
    return response.choices[0].message

# 请求提示词
prompt="河里有1个人,2条船,3只白鸭子,4条红鲤鱼,5只黑天鹅,6只黑鸭子,7只白鹭,8只乌龟,一共有几只鸭子?"

messages=[
    {"role": "system", "content": "你是一个天才数学家"},
    {"role": "user", "content": prompt}
]

print("===== 第一次调用大模型 =====")
response=get_completion(messages)

# 把大模型返回加入上下文中
messages.append(response)
print(response.content)

if(response.tool_calls is not None):
    tool_call=response.tool_calls[0]
    if(tool_call.function.name == "calc"):
        args=json.loads(tool_call.function.arguments)
        result=sum(args["numbers"])

        messages.append({
            "role": "tool",
            "content": str(result),
            "tool_call_id": tool_call.id,
            "name": "calc"
        })

        print("===== 第二次调用大模型 =====")
        response=get_completion(messages)
        messages.append(response)
        print("===== 大模型最终回复结果 =====")
        print_json(response.content)

返回结果:

复制代码
===== 第一次调用大模型 =====
{
    "role": "system",
    "content": "你是一个天才数学家"
}
{
    "role": "user",
    "content": "河里有1个人,2条船,3只白鸭子,4条红鲤鱼,5只黑天鹅,6只黑鸭子,7只白鹭,8只乌龟,一共有几只鸭子?"
}

===== 第二次调用大模型 =====
{
    "role": "system",
    "content": "你是一个天才数学家"
}
{
    "role": "user",
    "content": "河里有1个人,2条船,3只白鸭子,4条红鲤鱼,5只黑天鹅,6只黑鸭子,7只白鹭,8只乌龟,一共有几只鸭子?"
}
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_40e59c608e9f4e6cb359ca",
            "function": {
                "arguments": "{\"numbers\": [3, 6]}",
                "name": "calc"
            },
            "type": "function",
            "index": 0
        }
    ]
}
{
    "role": "tool",
    "content": "9",
    "tool_call_id": "call_40e59c608e9f4e6cb359ca",
    "name": "calc"
}
===== 大模型最终回复结果 =====
河里一共有9只鸭子(3只白鸭子 + 6只黑鸭子)。

2. 大模型调用个多方法

模拟大模型循环调用多个方法。

python 复制代码
# 导入依赖库
import os
import json
from openai import OpenAI
from math import *

# 定义一个辅助函数,用来打印日志
def print_json(data):
    """
        如果参数是有结构的(如字典或列表),则以 JSON 形式打印,否则直接打印。
    """
    if hasattr(data, 'model_dump_json'):
        data = json.loads(data.model_dump_json())
    
    if (isinstance(data, (list))):
        for item in data:
            print_json(item)
    elif (isinstance(data, (list, dict))):
        print(json.dumps(data, indent=4, ensure_ascii=False))
    else:
        print(data)

# 初始化 OpenAI 客户端
client = OpenAI(
    # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",

)

# 定义一个函数
def get_completion(prompt, response_format="text", model="qwen3-max-preview"):
    print_json(prompt)
    
    response = client.chat.completions.create(
        model=model,
        messages=prompt,
        temperature=0,  # 取值范围: [0, 2),temperature越高,生成的文本更多样,反之,生成的文本更确定。
        seed=1024, # 随机种子保持不变,当temperature和prompt不变时,输出结果不变。
        response_format={"type": response_format}, # 返回消息的格式
        tools=[{
            "type": "function",
            "function": {
                "name": "get_landmark",
                "description": "通过城市编号city_no,获取对应城市的热门旅游景点",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "city_no": {
                            "type": "string",
                            "description": "城市编号,比如:BJ"
                        }
                    }
                }
            }
        },
        {
            "type": "function",
            "function": {
                "name": "get_city_no",
                "description": "通过城市名称获取城市编号",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "city_name": {
                            "type": "string",
                            "description": "城市名称,比如:北京"
                        }
                    }
                }
            }
        }]
    )
    return response.choices[0].message

def get_city_no(city_name: str) -> str:
    if city_name == "北京":
        city_no="BJ"
    elif city_name == "上海":
        city_no="SH"
    elif city_name == "广州":
        city_no="GZ"
    elif city_name == "深圳":
        city_no="SZ"
    
    return city_no

def get_landmark(city_no: str) -> str:

    if city_no == "BJ":
        ans="""
        城市:北京
        城市编号:BJ
        热门景点:北京是我们中国的首都,他有很多著名的旅游景点,比如:天安门、故宫、天坛、圆明园、颐和园、八达岭长城等。
        """
    elif city_no == "SH":
        ans="""
        城市:上海
        城市编号:SH
        热门景点:上海是我国的国际化大都市,它有很多著名的旅游景点,比如:东方明珠广播电视塔、外滩、豫园、上海野生动物园、上海科技馆、广富林遗址等。
        """
    elif city_no == "GZ":
        ans="""
        城市:广州
        城市编号:GZ
        热门景点:广州是我国广东省的省会,它有很多著名的旅游景点,比如:广州塔(小蛮腰)、白云山、陈家祠、沙面岛、圣心大教堂、珠江夜游等。
        """
    elif city_no == "SZ":
        ans="""
        城市:深圳
        城市编号:SZ
        热门景点:深圳是我国的经济特区,它有很多著名的旅游景点,比如:世界之窗、深圳欢乐谷、东部华侨城、深圳湾公园、南头古城、较场尾等。
        """
    
    return ans


# 请求提示词
prompt="我想去北京和深圳玩,你可以给我推荐一些景点吗?"

messages=[
    {"role": "system", "content": "你是一个导游,你非常清楚全国城市都有哪些著名的旅游景点。"},
    {"role": "user", "content": prompt}
]

count=1
response=get_completion(messages)

# 把大模型返回加入上下文中
messages.append(response)
print("===== 第 "+str(count)+" 次大模型调用 =====")
print(response.content)

while(response.tool_calls is not None):
    for tool_call in response.tool_calls:
        args=json.loads(tool_call.function.arguments)
        print_json(args)        

        # 函数路由
        if(tool_call.function.name == "get_city_no"):
            print("===== 开始执行方法:get_city_no() =====")
            result=get_city_no(**args)
        elif(tool_call.function.name == "get_landmark"):
            print("===== 开始执行方法:get_landmark() =====")
            result=get_landmark(**args)

        print_json("===== 方法执行完成,返回结果 =====")
        print_json(result)

        messages.append({
            "role": "tool",
            "content": str(result),
            "tool_call_id": tool_call.id,
            "name": tool_call.function.name
        })

    count=count+1
    response=get_completion(messages)
    print("===== 第 "+str(count)+" 次大模型调用 =====")
    print_json(response)
    messages.append(response)

print("===== 大模型最终回复结果 =====")
print_json(response.content)
# print("===== 大模型全部对话上下文 =====")
# print_json(messages)

返回结果:

复制代码
{
    "role": "system",
    "content": "你是一个导游,你非常清楚全国城市都有哪些著名的旅游景点。"
}
{
    "role": "user",
    "content": "我想去北京和深圳玩,你可以给我推荐一些景点吗?"
}
===== 第 1 次大模型调用 =====

{
    "city_name": "北京"
}
===== 开始执行方法:get_city_no() =====
===== 方法执行完成,返回结果 =====
BJ
{
    "city_name": "深圳"
}
===== 开始执行方法:get_city_no() =====
===== 方法执行完成,返回结果 =====
SZ
{
    "role": "system",
    "content": "你是一个导游,你非常清楚全国城市都有哪些著名的旅游景点。"
}
{
    "role": "user",
    "content": "我想去北京和深圳玩,你可以给我推荐一些景点吗?"
}
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_892a88c2045c48a1b34f44",
            "function": {
                "arguments": "{\"city_name\": \"北京\"}",
                "name": "get_city_no"
            },
            "type": "function",
            "index": 0
        },
        {
            "id": "call_b0e6821ebaec4f8691a08a",
            "function": {
                "arguments": "{\"city_name\": \"深圳\"}",
                "name": "get_city_no"
            },
            "type": "function",
            "index": 1
        }
    ]
}
{
    "role": "tool",
    "content": "BJ",
    "tool_call_id": "call_892a88c2045c48a1b34f44",
    "name": "get_city_no"
}
{
    "role": "tool",
    "content": "SZ",
    "tool_call_id": "call_b0e6821ebaec4f8691a08a",
    "name": "get_city_no"
}
===== 第 2 次大模型调用 =====
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_7d3800976adc4418a501dd",
            "function": {
                "arguments": "{\"city_no\": \"BJ\"}",
                "name": "get_landmark"
            },
            "type": "function",
            "index": 0
        },
        {
            "id": "call_cc6927249062467f83e2f3",
            "function": {
                "arguments": "{\"city_no\": \"SZ\"}",
                "name": "get_landmark"
            },
            "type": "function",
            "index": 1
        }
    ]
}
{
    "city_no": "BJ"
}
===== 开始执行方法:get_landmark() =====
===== 方法执行完成,返回结果 =====

        城市:北京
        城市编号:BJ
        热门景点:北京是我们中国的首都,他有很多著名的旅游景点,比如:天安门、故宫、天坛、圆明园、颐和园、八达岭长城等。
        
{
    "city_no": "SZ"
}
===== 开始执行方法:get_landmark() =====
===== 方法执行完成,返回结果 =====

        城市:深圳
        城市编号:SZ
        热门景点:深圳是我国的经济特区,它有很多著名的旅游景点,比如:世界之窗、深圳欢乐谷、东部华侨城、深圳湾公园、南头古城、较场尾等。
        
{
    "role": "system",
    "content": "你是一个导游,你非常清楚全国城市都有哪些著名的旅游景点。"
}
{
    "role": "user",
    "content": "我想去北京和深圳玩,你可以给我推荐一些景点吗?"
}
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_892a88c2045c48a1b34f44",
            "function": {
                "arguments": "{\"city_name\": \"北京\"}",
                "name": "get_city_no"
            },
            "type": "function",
            "index": 0
        },
        {
            "id": "call_b0e6821ebaec4f8691a08a",
            "function": {
                "arguments": "{\"city_name\": \"深圳\"}",
                "name": "get_city_no"
            },
            "type": "function",
            "index": 1
        }
    ]
}
{
    "role": "tool",
    "content": "BJ",
    "tool_call_id": "call_892a88c2045c48a1b34f44",
    "name": "get_city_no"
}
{
    "role": "tool",
    "content": "SZ",
    "tool_call_id": "call_b0e6821ebaec4f8691a08a",
    "name": "get_city_no"
}
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_7d3800976adc4418a501dd",
            "function": {
                "arguments": "{\"city_no\": \"BJ\"}",
                "name": "get_landmark"
            },
            "type": "function",
            "index": 0
        },
        {
            "id": "call_cc6927249062467f83e2f3",
            "function": {
                "arguments": "{\"city_no\": \"SZ\"}",
                "name": "get_landmark"
            },
            "type": "function",
            "index": 1
        }
    ]
}
{
    "role": "tool",
    "content": "\n        城市:北京\n        城市编号:BJ\n        热门景点:北京是我们中国的首都,他有很多著名的旅游景点,比如:天安门、故宫、天坛、圆明园、颐和园、八达岭长城等。\n        ",
    "tool_call_id": "call_7d3800976adc4418a501dd",
    "name": "get_landmark"
}
{
    "role": "tool",
    "content": "\n        城市:深圳\n        城市编号:SZ\n        热门景点:深圳是我国的经济特区,它有很多著名的旅游景点,比如:世界之窗、深圳欢乐谷、东部华侨城、深圳湾公园、南头古城、较场尾等。\n        ",
    "tool_call_id": "call_cc6927249062467f83e2f3",
    "name": "get_landmark"
}
===== 第 3 次大模型调用 =====
{
    "content": "当然可以!以下是为您推荐的北京和深圳的热门旅游景点:\n\n### 北京\n北京是中国的首都,拥有丰富的历史文化和名胜古迹,推荐景点包括:\n- **天安门**:中国的象征性建筑之一。\n- **故宫**:明清两代的皇家宫殿,世界文化遗产。\n- **天坛**:古代皇帝祭天祈福的地方。\n- **圆明园**:昔日皇家园林,充满历史韵味。\n- **颐和园**:中国现存规模最大、保存最完整的皇家园林。\n- **八达岭长城**:举世闻名的万里长城精华段。\n\n### 深圳\n深圳是中国的经济特区,现代化与自然风光兼具,推荐景点包括:\n- **世界之窗**:微缩世界著名景观的主题公园。\n- **深圳欢乐谷**:适合家庭游玩的大型主题乐园。\n- **东部华侨城**:集生态旅游、休闲度假为一体的综合景区。\n- **深圳湾公园**:沿海风景优美的城市公园。\n- **南头古城**:感受岭南文化与历史的好去处。\n- **较场尾**:被称为"深圳鼓浪屿",文艺小清新的海滨小镇。\n\n希望这些推荐能为您的旅行提供帮助,祝您旅途愉快!",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": null
}
===== 大模型最终回复结果 =====
当然可以!以下是为您推荐的北京和深圳的热门旅游景点:

### 北京
北京是中国的首都,拥有丰富的历史文化和名胜古迹,推荐景点包括:
- **天安门**:中国的象征性建筑之一。
- **故宫**:明清两代的皇家宫殿,世界文化遗产。
- **天坛**:古代皇帝祭天祈福的地方。
- **圆明园**:昔日皇家园林,充满历史韵味。
- **颐和园**:中国现存规模最大、保存最完整的皇家园林。
- **八达岭长城**:举世闻名的万里长城精华段。

### 深圳
深圳是中国的经济特区,现代化与自然风光兼具,推荐景点包括:
- **世界之窗**:微缩世界著名景观的主题公园。
- **深圳欢乐谷**:适合家庭游玩的大型主题乐园。
- **东部华侨城**:集生态旅游、休闲度假为一体的综合景区。
- **深圳湾公园**:沿海风景优美的城市公园。
- **南头古城**:感受岭南文化与历史的好去处。
- **较场尾**:被称为"深圳鼓浪屿",文艺小清新的海滨小镇。

希望这些推荐能为您的旅行提供帮助,祝您旅途愉快!

3. 大模型生成sql查询数据库

通过提示词和function定义,让大模型自动生成sql返回我们想要的结果。

python 复制代码
# 导入依赖库
import os
import json
import sqlite3
from openai import OpenAI
from math import *

# 模拟数据库数据准备
database_schema_string="""
    CREATE TABLE orders(
        id INT PRIMARY KEY NOT NULL, -- 主键,不允许为空
        customer_id INT NOT NULL, -- 客户ID,不允许为空
        product_id STR NOT NULL, -- 产品ID,不允许为空
        price DECIMAL(10,2) NOT NULL, -- 价格,不允许为空
        status INT NOT NULL, -- 订单状态,整数类型,不允许为空。0代表待支付,1代表已支付,2代表已退款
        create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 订单创建时间,默认为当前系统时间
        pay_time TIMESTAMP -- 订单支付时间,可以为空
    );
"""

conn=sqlite3.connect(':memory:')
cursor=conn.cursor()
cursor.execute(database_schema_string)
mock_data=[
    (1,101,'xiaomi',998.00,0,'2025-09-11 10:00:00',None),
    (2,101,'xiaomi_plus',1998.00,1,'2025-09-18 16:00:00','2025-09-18 17:00:00'),
    (3,102,'huawei',9998.00,2,'2025-10-11 10:00:00','2025-10-11 10:10:00'),
    (4,103,'huawei',9998.00,1,'2025-10-11 13:00:00','2025-10-11 14:00:00'),
    (5,103,'iphone_19',6998.00,1,'2025-10-15 13:00:00','2025-10-15 15:00:00'),
    (6,102,'iphone_18',4998.00,0,'2025-12-16 10:00:00',None),
]

for record in mock_data:
    cursor.execute('''
        INSERT INTO orders(id,customer_id,product_id,price,status,create_time,pay_time) VALUES(?,?,?,?,?,?,?)
    ''', record)

conn.commit

def select_database(query):
    cursor.execute(query)
    records=cursor.fetchall()
    return records

# 定义一个辅助函数,用来打印日志
def print_json(data):
    """
        如果参数是有结构的(如字典或列表),则以 JSON 形式打印,否则直接打印。
    """
    if hasattr(data, 'model_dump_json'):
        data = json.loads(data.model_dump_json())
    
    if (isinstance(data, (list))):
        for item in data:
            print_json(item)
    elif (isinstance(data, (list, dict))):
        print(json.dumps(data, indent=4, ensure_ascii=False))
    else:
        print(data)

# 初始化 OpenAI 客户端
client = OpenAI(
    # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",

)

# 定义一个函数
def get_completion(prompt, response_format="text", model="qwen3-max-preview"):
    print_json(prompt)
    
    response = client.chat.completions.create(
        model=model,
        messages=prompt,
        temperature=0,  # 取值范围: [0, 2),temperature越高,生成的文本更多样,反之,生成的文本更确定。
        response_format={"type": response_format}, # 返回消息的格式
        tools=[{
            "type": "function",
            "function": {
                "name": "select_database",
                "description": "Use this function to answer users questions about business. Output should be a fully formed SQL query.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {
                            "type": "string",
                            "description": f"""
                                SQL query extracting info to answer the user's question.
                                SQL should be written using this database schema:
                                {database_schema_string}
                                The query should be returned in plain text, not in JSON.
                                The query should only contain grammars supported by SQLite.
                            """
                        }
                    },
                    "required": ["query"]
                }
            }
        }]
    )
    return response.choices[0].message

# 请求提示词
prompt="2025年10月份的总销售额是多少?"

messages=[
    {"role": "system", "content": "你是一个数据分析师,基于数据库的数据来回答问题"},
    {"role": "user", "content": prompt}
]

print("===== 第一次调用大模型 =====")
response=get_completion(messages)

# 把大模型返回加入上下文中
messages.append(response)
print(response.content)

if(response.tool_calls is not None):
    tool_call=response.tool_calls[0]
    if(tool_call.function.name == "select_database"):
        args=json.loads(tool_call.function.arguments)
        print("===== query SQL =====")
        print(args["query"])
        result=select_database(args["query"])
        print("===== execute SQL return =====")
        print(result)

        messages.append({
            "role": "tool",
            "content": str(result),
            "tool_call_id": tool_call.id,
            "name": "calc"
        })

        response=get_completion(messages)
        messages.append(response)
        print("===== 大模型最终回复结果 =====")
        print_json(response.content)

返回结果:

复制代码
===== 第一次调用大模型 =====
{
    "role": "system",
    "content": "你是一个数据分析师,基于数据库的数据来回答问题"
}
{
    "role": "user",
    "content": "2025年10月份的总销售额是多少?"
}

===== query SQL =====
SELECT SUM(price) AS total_sales FROM orders WHERE strftime('%Y-%m', create_time) = '2025-10';
===== execute SQL return =====
[(26994,)]
{
    "role": "system",
    "content": "你是一个数据分析师,基于数据库的数据来回答问题"
}
{
    "role": "user",
    "content": "2025年10月份的总销售额是多少?"
}
{
    "content": "",
    "refusal": null,
    "role": "assistant",
    "annotations": null,
    "audio": null,
    "function_call": null,
    "tool_calls": [
        {
            "id": "call_db4011b2bd7e4ecf9210d5",
            "function": {
                "arguments": "{\"query\": \"SELECT SUM(price) AS total_sales FROM orders WHERE strftime('%Y-%m', create_time) = '2025-10';\"}",
                "name": "select_database"
            },
            "type": "function",
            "index": 0
        }
    ]
}
{
    "role": "tool",
    "content": "[(26994,)]",
    "tool_call_id": "call_db4011b2bd7e4ecf9210d5",
    "name": "calc"
}
===== 大模型最终回复结果 =====
2025年10月份的总销售额为 **26,994** 元。

到这里各位小伙伴应该就清楚了什么是Function Calling吧?

我们通过定义函数,然后让大模型自己内部控制选择调用某些函数,上面案例中的方法体if else内可以换成调用外系统、查数据库等等操作,来控制返回我们需要给大模型的信息。我们还可以通过添加某个格式化输出的函数,控制大模型最终的输出格式,以满足我们的业务需求,让大模型更靠谱。


六、Function Calling 的注意事项

使用Function Calling时需要注意以下问题:

  • 函数职责要单一,最好一个函数只做一件事,有利于模型正确选择要调用的函数。
  • 函数命名要清晰、可读,模型会根据函数名称猜他的用途。
  • 函数与参数的描述,也是一种prompt,会影响模型调用函数的准确性,需要调优。
  • 参数定义要明确、可约束,比如参数类型、枚举类型等,约束越强,模型越不容易搞错参数。
  • 不要认为模型一定会调用某些函数,我们需要对模型返回结果进行校验。
  • 函数返回结果要精简、结构化,避免返回无关数据和非结构化数据。
  • 避免出现无限循环调用函数情况,比如函数返回结果不确定后又重新调用函数,或者返回结果很模糊,模型又需要继续调用函数,应设置最大调用次数。
  • 避免将关键操作直接交给模型,比如数据更新删除、支付转账等。
  • 需要对模型参数进行校验,避免出现prompt注入漏洞。
  • 避免函数过多,导致模型选择困难,应将函数按场景拆分、按阶段加载。
  • 记录模型调用跟踪日志,方便对模型查错和调优。

七、Function Calling 解决的问题

  • 解决知识滞后问题:大语言模型的训练数据存在截止日期,无法获取此后更新的信息。Function Calling通过调用外部API获取实时数据,有效解决了这一问题。
  • 解决计算能力不足问题:大语言模型在处理高精度数学计算、复杂逻辑推理等方面存在局限。Function Calling允许模型将计算任务委托给专业的计算工具或代码,如调用计算器函数计算复杂数学表达式,或调用数据分析函数处理用户上传的Excel表格。
  • 解决系统交互限制:传统模型无法直接操作数据库、发送邮件或控制硬件设备等。Function Calling通过预定义的函数接口,使模型能够与外部系统交互。
  • 参数校验与纠错:模型可以在函数调用过程中检测潜在错误,并提出修正意见,确保函数能够安全、正确的执行。
  • 提升自动化能力:Function Calling支持任务分解和工具链集成,是智能体和自动化流程的底座能力。通过Chain-of-Thought或ReAct框架,模型可以将复杂任务拆分为多个子任务,逐步调用函数。
相关推荐
@小匠1 小时前
Read Frog:一款开源的 AI 驱动浏览器语言学习扩展
人工智能·学习
一灯架构3 小时前
90%的人答错!一文带你彻底搞懂ArrayList
java·后端
网教盟人才服务平台4 小时前
“方班预备班盾立方人才培养计划”正式启动!
大数据·人工智能
Y4090014 小时前
【多线程】线程安全(1)
java·开发语言·jvm
芯智工坊4 小时前
第15章 Mosquitto生产环境部署实践
人工智能·mqtt·开源
菜菜艾4 小时前
基于llama.cpp部署私有大模型
linux·运维·服务器·人工智能·ai·云计算·ai编程
TDengine (老段)4 小时前
TDengine IDMP 可视化 —— 分享
大数据·数据库·人工智能·时序数据库·tdengine·涛思数据·时序数据
小真zzz4 小时前
搜极星:第三方多平台中立GEO洞察专家全面解析
人工智能·搜索引擎·seo·geo·中立·第三方平台
布局呆星5 小时前
SpringBoot 基础入门
java·spring boot·spring
风吹迎面入袖凉5 小时前
【Redis】Redisson的可重入锁原理
java·redis