【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框架,模型可以将复杂任务拆分为多个子任务,逐步调用函数。
相关推荐
手揽回忆怎么睡2 小时前
Streamlit学习实战教程级,一个交互式的机器学习实验平台!
人工智能·学习·机器学习
‿hhh2 小时前
综合交通运行协调与应急指挥平台项目说明
java·ajax·npm·json·需求分析·个人开发·规格说明书
小徐Chao努力2 小时前
【Langchain4j-Java AI开发】06-工具与函数调用
java·人工智能·python
无心水2 小时前
【神经风格迁移:全链路压测】33、全链路监控与性能优化最佳实践:Java+Python+AI系统稳定性保障的终极武器
java·python·性能优化
db_murphy2 小时前
时事篇 | Manus收购
人工智能
萧曵 丶2 小时前
Synchronized 详解及 JDK 版本优化
java·多线程·synchronized
攻城狮7号2 小时前
阶跃星辰开源NextStep-1.1图像模型:告别“鬼影”与“马赛克”?
人工智能·ai图像生成·nextstep-1.1·阶跃星辰开源模型·图像模型
_codemonster2 小时前
BERT中的padding操作
人工智能·深度学习·bert
夏幻灵2 小时前
JAVA基础:基本数据类型和引用数据类型
java·开发语言