Tool&Function Calling

概述

Function Calling 是 OpenAI 最早提出的一项重要功能,旨在让大型语言模型(LLM)能够调用外部工具或服务,后续其他LLM厂商都逐渐支持这项功能。其实现方式是:通过定义一组标准化的 JSON 格式接口,使模型能够理解并生成对特定函数的调用请求。这些外部工具可以包括网页搜索、数据库查询、文件解析等通用服务,也可以是用户自定义的业务逻辑函数。

借助 Function Calling,LLM 可以将原本无法处理的任务“委托”给相应的工具执行,从而显著提升其实际应用能力和推理深度。这种机制不仅增强了模型的实用性,也为构建基于 LLM 的复杂系统提供了良好的扩展基础。

在后续的发展中,这一功能逐渐被更广泛地称为 Tool Calling,两者语义等价。

Function calling

对于 Function calling 的使用流程,通常可以划分为以下五个步骤:

  1. 定义可用工具:在向 LLM 发送请求前,需在请求参数中明确声明可供调用的工具及其功能描述,使模型了解它可以借助哪些外部能力来完成任务;
  2. LLM 生成工具调用指令:模型在理解用户问题后,结合已知的可用工具,决定是否需要调用某个或多个工具,并输出对应的工具名称及参数;
  3. 执行工具调用:根据模型返回的调用信息,系统实际调用相应的外部工具(如 API、数据库查询等),并传入指定参数以获取真实数据;
  4. 注入工具结果至上下文:将工具返回的结果整合进原始对话上下文中,作为新的输入再次传递给 LLM,供其进行进一步的理解和推理;
  5. LLM 生成最终自然语言响应:模型基于用户的原始提问和工具返回的数据,生成最终的自然语言回复,完成整个交互过程。

注意:一次完整的 Function calling 流程包含两次 LLM 推理调用:

  • 第一次调用:输入为用户提问 + 可用工具描述,输出为模型希望调用的工具及参数
  • 第二次调用:输入为用户提问 + 工具返回的实际结果,输出为最终面向用户的自然语言回答

这一流程构成了 Function calling 的完整交互闭环,使得语言模型能够在自身能力之外,借助外部工具动态接入实时、外部的数据与服务,从而实现更强大和实用的功能。

第一步,定义函数get_weather,输入精度和维度就可以获取该地区的气温,并且定义好该函数的调用格式

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
import requests

def get_weather(latitude, longitude):
response = requests.get(
f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&current=temperature_2m,wind_speed_10m&hourly=temperature_2m,relative_humidity_2m,wind_speed_10m")
data = response.json()
return data['current']['temperature_2m']

tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current temperature for provided coordinates in celsius.",
"parameters": {
"type": "object",
"properties": {
"latitude": {
"type": "number",
"description": "The latitude",
},
"longitude": {
"type": "number",
"description": "The longitude",
},
},
"required": ["latitude", "longitude"],
},
},
}
]

第二步:调用大模型,输入查询内容和可供调用工具

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
import litellm

messages = [
{
"role": "user",
"content": "What's the weather like in Paris today?"
}
]

response = litellm.completion(
model="openai/gpt-4.1",
messages=messages,
tools=tools,
tool_choice="auto", # auto is default, but we'll be explicit
)
print("\nFirst LLM Response:\n")
print(response.model_dump_json(indent=2))
# OUTPUT
First LLM Response:

{
"id": "chatcmpl-BksIxuE09LW7FhkuTf7vIH84r6EV5",
"created": 1750511535,
"model": "gpt-4.1-2025-04-14",
"object": "chat.completion",
"system_fingerprint": "fp_07e970ab25",
"choices": [
{
"finish_reason": "tool_calls",
"index": 0,
"message": {
"content": null,
"role": "assistant",
"tool_calls": [
{
"index": 0,
"function": {
"arguments": "{\"latitude\":48.8566,\"longitude\":2.3522}",
"name": "get_weather"
},
"id": "call_NiNlG5wjgIqikZmS608qWYAo",
"type": "function"
}
],
"function_call": null
}
}
],
"usage": {
"completion_tokens": 25,
"prompt_tokens": 66,
"total_tokens": 91,
"completion_tokens_details": {
"accepted_prediction_tokens": null,
"audio_tokens": null,
"reasoning_tokens": null,
"rejected_prediction_tokens": null
},
"prompt_tokens_details": {
"audio_tokens": null,
"cached_tokens": null
}
},
"service_tier": null
}

第三步:解析大模型输出的结果

1
2
3
4
5
6
7
response_message = response.choices[0].message
print(response_message)
tool_calls = response.choices[0].message.tool_calls
print(tool_calls)
# OUTPUT
Message(content=None, role='assistant', tool_calls=[ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"latitude":48.8566,"longitude":2.3522}', name='get_weather'), id='call_8h7sJ2Yxn6E0cMAgs7yaxv7W', type='function')], function_call=None, provider_specific_fields={'refusal': None})
[ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"latitude":48.8566,"longitude":2.3522}', name='get_weather'), id='call_8h7sJ2Yxn6E0cMAgs7yaxv7W', type='function')]

根据解析结果,调用相应的外部工具

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
import json

# Check if the model wants to call a function
if tool_calls:
# Execute the functions and prepare responses
available_functions = {
"get_weather": get_weather,
}

messages.append(response_message) # Extend conversation with assistant's reply

for tool_call in tool_calls:
print(f"\nExecuting tool call\n{tool_call}")
function_name = tool_call.function.name
function_to_call = available_functions[function_name]
function_args = json.loads(tool_call.function.arguments)
# calling the get_current_weather() function
function_response = function_to_call(
latitude=function_args.get("latitude"),
longitude=function_args.get("longitude"),
)
print(f"Result from tool call\n{function_response}\n")

# Extend conversation with function response
messages.append(
{
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": str(function_response),
}
)
# OUTPUT
Executing tool call
ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"latitude":48.8566,"longitude":2.3522}', name='get_weather'), id='call_8h7sJ2Yxn6E0cMAgs7yaxv7W', type='function')
Result from tool call
33.6

第四步/第五步:输入提问结合外部工具获取的结果,进行第二次大模型计算,生成最终结果

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
second_response = litellm.completion(
model="openai/gpt-4.1",
messages=messages,
)
print("Second Response\n", second_response.model_dump_json(indent=2))
message = second_response.choices[0].message.content
print(f"Message: {message}")
# OUTPUT
Second Response
{
"id": "chatcmpl-Bkskgv18D7JiQWLDeOPtRHJFQbplo",
"created": 1750513254,
"model": "gpt-4.1-2025-04-14",
"object": "chat.completion",
"system_fingerprint": "fp_07e970ab25",
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "Today in Paris, the temperature is currently around 33.6°C. It's quite a hot day, so if you're heading outside, remember to stay hydrated and wear sun protection! If you need more details on weather conditions, let me know.",
"role": "assistant",
"tool_calls": null,
"function_call": null
}
}
],
"usage": {
"completion_tokens": 50,
"prompt_tokens": 50,
"total_tokens": 100,
"completion_tokens_details": {
"accepted_prediction_tokens": null,
"audio_tokens": null,
"reasoning_tokens": null,
"rejected_prediction_tokens": null
},
"prompt_tokens_details": {
"audio_tokens": null,
"cached_tokens": null
}
},
"service_tier": null
}
Message: Today in Paris, the temperature is currently around 33.6°C. It's quite a hot day, so if you're heading outside, remember to stay hydrated and wear sun protection! If you need more details on weather conditions, let me know.

Parallel function calling

在某些高级应用场景中,大型语言模型(LLM)可以在一次推理过程中并行地调用多个工具函数。传统上,模型在处理需要外部数据的任务时,会按顺序依次调用函数,这可能导致较高的延迟。而LLM接口(如 OpenAI 的 tool_call 机制)支持在单次响应中返回多个函数调用指令,从而实现并行执行,显著缩短整体响应时间。

考虑以下用户输入:

“今天旧金山、东京和巴黎的天气分别怎么样?”

这是一个典型的多目标查询,要求模型获取三个不同城市的实时天气信息。为了高效完成该请求,LLM 可以在单次回复中并行调用三次 get_weather 函数,每个调用对应一个城市的位置参数。

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
# INPUT MESSAGES
messages = [
{
"role": "user",
# "content": "What's the weather like in Paris today?"
"content": "What's the weather like in San Francisco, Tokyo, and Paris today?"
}
]
# Tool Calls
tool_calls = response.choices[0].message.tool_calls
pprint.pprint(tool_calls)
# OUTPUT
[ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"latitude": 37.7749, "longitude": -122.4194}', name='get_weather'), id='call_BBuG4wEfDvmZ61eFdihdinDR', type='function'),
ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"latitude": 35.6895, "longitude": 139.6917}', name='get_weather'), id='call_O606wPtT2qMlqUtIBNVIrrwD', type='function'),
ChatCompletionMessageToolCall(index=0, function=Function(arguments='{"latitude": 48.8566, "longitude": 2.3522}', name='get_weather'), id='call_nEqcSa7pZt9Jklni57JnReCi', type='function')]
# Second LLM
second_response = litellm.completion(
model="openai/gpt-4.1",
messages=messages,
base_url=base_url,
)
message = second_response.choices[0].message.content
print(f"Message: {message}")
# OUTPUT
Message: Today's weather:

- San Francisco: Around 14°C, cool and typically foggy or breezy for this time of year.
- Tokyo: Around 30°C, warm and possibly humid.
- Paris: Around 23°C, mild and likely pleasant.

Let me know if you need more detailed weather info or forecasts!

相关阅读