大模型 Function Call 的實現步驟及示例詳解
- 一、Function Call的核心流程拆解
- 二、結合代碼詳解Function Call實現
- 步驟1:定義工具(對應代碼中的`tools`列表)
- 步驟2:實現工具函數(對應代碼中的`get_current_weather`和`get_current_time`)
- 步驟3:模型交互與工具調用判斷(對應`call_with_messages`函數)
- 子步驟3.1:初始化對話消息
- 子步驟3.2:首次調用模型,判斷是否需要調用工具
- 子步驟3.3:解析工具調用指令并執行工具
- 子步驟3.4:多輪調用模型,整合工具結果生成最終回答
- 三、總結:代碼如何實現Function Call的核心邏輯
Function Call(函數調用)是大模型與外部工具/函數交互的核心機制,其核心邏輯是:讓大模型根據用戶需求判斷是否需要調用預設工具,若需要則生成標準化的調用指令(包含工具名、參數等),執行工具后將結果返回給模型,最終由模型整合結果生成自然語言回答。
一、Function Call的核心流程拆解
Function Call的完整流程可分為5個關鍵步驟,每個步驟對應具體的邏輯和目標:
-
定義工具(Tool Definition)
提前告訴大模型“有哪些工具可用”“工具的功能是什么”“需要傳入哪些參數”,通常以結構化格式(如JSON Schema)描述,確保模型能精準理解工具的調用規則。 -
用戶提問與初始判斷
接收用戶輸入后,大模型結合問題和工具定義,判斷“是否需要調用工具”:- 若問題可直接回答(如“1+1等于幾”),則直接返回結果;
- 若問題需要外部信息(如“現在幾點了”“北京天氣如何”),則生成工具調用指令。
-
生成工具調用指令
若需要調用工具,大模型會生成標準化的調用指令(包含工具名、參數等),格式需嚴格匹配工具定義,確保后續能被正確解析執行。 -
執行工具并返回結果
解析模型生成的調用指令,調用對應的工具函數,執行邏輯(如查詢數據庫、API調用等),并將結果以固定格式(如“tool角色”消息)返回給模型。 -
整合結果生成最終回答
大模型接收工具返回的結果后,結合問題和結果,生成自然語言回答,完成交互。
二、結合代碼詳解Function Call實現
下面結合完整的代碼,逐步驟解析每個環節的具體實現,示例代碼來自大模型服務平臺百煉 Function Calling:
點擊展開代碼from openai import OpenAI
from datetime import datetime
import json
import os
import randomclient = OpenAI(# 若沒有配置環境變量,請用百煉API Key將下行替換為:api_key="sk-xxx",api_key=os.getenv("DASHSCOPE_API_KEY"),base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", # 填寫DashScope SDK的base_url
)# 定義工具列表,模型在選擇使用哪個工具時會參考工具的name和description
tools = [# 工具1 獲取當前時刻的時間{"type": "function","function": {"name": "get_current_time","description": "當你想知道現在的時間時非常有用。",# 因為獲取當前時間無需輸入參數,因此parameters為空字典"parameters": {},},},# 工具2 獲取指定城市的天氣{"type": "function","function": {"name": "get_current_weather","description": "當你想查詢指定城市的天氣時非常有用。","parameters": {"type": "object","properties": {# 查詢天氣時需要提供位置,因此參數設置為location"location": {"type": "string","description": "城市或縣區,比如北京市、杭州市、余杭區等。",}},"required": ["location"],},},},
]# 模擬天氣查詢工具。返回結果示例:“北京今天是雨天。”
def get_current_weather(arguments):# 定義備選的天氣條件列表weather_conditions = ["晴天", "多云", "雨天"]# 隨機選擇一個天氣條件random_weather = random.choice(weather_conditions)# 從 JSON 中提取位置信息location = arguments["location"]# 返回格式化的天氣信息return f"{location}今天是{random_weather}。"# 查詢當前時間的工具。返回結果示例:“當前時間:2024-04-15 17:15:18。“
def get_current_time():# 獲取當前日期和時間current_datetime = datetime.now()# 格式化當前日期和時間formatted_time = current_datetime.strftime("%Y-%m-%d %H:%M:%S")# 返回格式化后的當前時間return f"當前時間:{formatted_time}。"# 封裝模型響應函數
def get_response(messages):completion = client.chat.completions.create(model="qwen-plus", # 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/modelsmessages=messages,tools=tools,)return completiondef call_with_messages():print("\n")messages = [{"content": input("請輸入:"), # 提問示例:"現在幾點了?" "一個小時后幾點" "北京天氣如何?""role": "user",}]print("-" * 60)# 模型的第一輪調用i = 1first_response = get_response(messages)assistant_output = first_response.choices[0].messageprint(f"\n第{i}輪大模型輸出信息:{first_response}\n")if assistant_output.content is None:assistant_output.content = ""messages.append(assistant_output)# 如果不需要調用工具,則直接返回最終答案if (assistant_output.tool_calls == None): # 如果模型判斷無需調用工具,則將assistant的回復直接打印出來,無需進行模型的第二輪調用print(f"無需調用工具,我可以直接回復:{assistant_output.content}")return# 如果需要調用工具,則進行模型的多輪調用,直到模型判斷無需調用工具while assistant_output.tool_calls != None:# 如果判斷需要調用查詢天氣工具,則運行查詢天氣工具tool_info = {"content": "","role": "tool","tool_call_id": assistant_output.tool_calls[0].id,}if assistant_output.tool_calls[0].function.name == "get_current_weather":# 提取位置參數信息argumens = json.loads(assistant_output.tool_calls[0].function.arguments)tool_info["content"] = get_current_weather(argumens)# 如果判斷需要調用查詢時間工具,則運行查詢時間工具elif assistant_output.tool_calls[0].function.name == "get_current_time":tool_info["content"] = get_current_time()tool_output = tool_info["content"]print(f"工具輸出信息:{tool_output}\n")print("-" * 60)messages.append(tool_info)assistant_output = get_response(messages).choices[0].messageif assistant_output.content is None:assistant_output.content = ""messages.append(assistant_output)i += 1print(f"第{i}輪大模型輸出信息:{assistant_output}\n")print(f"最終答案:{assistant_output.content}")if __name__ == "__main__":call_with_messages()
步驟1:定義工具(對應代碼中的tools
列表)
代碼中通過tools
列表定義了兩個工具,這是大模型判斷“是否調用工具”和“如何調用”的依據。每個工具的定義包含3個核心要素:
name
:工具函數的唯一標識(需與實際函數名一致,如get_current_weather
);description
:工具的功能描述(幫助模型判斷何時該用這個工具,如“查詢指定城市的天氣時使用”);parameters
:工具所需參數的結構化定義(包含參數名、類型、描述、是否必填等,確保模型傳入正確參數)。
示例解析:
tools = [# 工具1:獲取當前時間(無參數){"type": "function","function": {"name": "get_current_time","description": "當你想知道現在的時間時非常有用。","parameters": {} # 無參數,因此為空字典},},# 工具2:獲取指定城市天氣(需location參數){"type": "function","function": {"name": "get_current_weather","description": "當你想查詢指定城市的天氣時非常有用。","parameters": {"type": "object","properties": {"location": { # 參數名:location"type": "string", # 參數類型:字符串"description": "城市或縣區,比如北京市、杭州市" # 參數描述}},"required": ["location"] # 該參數為必填項}},}
]
作用:大模型會讀取tools
中的信息,例如當用戶問“北京天氣如何”時,模型會匹配到get_current_weather
的description
,并根據parameters
知道需要傳入location="北京"
。
步驟2:實現工具函數(對應代碼中的get_current_weather
和get_current_time
)
工具函數是實際執行邏輯的“執行者”,接收模型傳入的參數,返回具體結果。代碼中這兩個函數是模擬實現(實際場景可能是調用天氣API、時間接口等)。
get_current_time
:無參數,返回當前格式化時間(如“2025-07-19 15:30:00”);get_current_weather
:接收location
參數,隨機返回天氣結果(如“北京今天是晴天”)。
示例解析:
def get_current_weather(arguments):weather_conditions = ["晴天", "多云", "雨天"]random_weather = random.choice(weather_conditions)location = arguments["location"] # 從參數中提取城市return f"{location}今天是{random_weather}。" # 返回工具結果
步驟3:模型交互與工具調用判斷(對應call_with_messages
函數)
這是Function Call的核心流程,負責協調用戶輸入、模型判斷、工具執行和結果整合,具體分為以下子步驟:
子步驟3.1:初始化對話消息
用戶輸入作為初始消息(role="user"
),存入messages
列表,用于傳遞給模型。
messages = [{"content": input("請輸入:"), # 例如用戶輸入“杭州天氣如何?”"role": "user",}
]
子步驟3.2:首次調用模型,判斷是否需要調用工具
通過get_response
函數調用大模型(這里對接的是阿里云DashScope的千問模型),傳入messages
(用戶問題)和tools
(工具列表),模型會返回判斷結果:
- 若無需調用工具:
assistant_output.tool_calls
為None
,直接返回回答; - 若需要調用工具:
assistant_output.tool_calls
包含調用指令(工具名、參數等)。
示例解析:
first_response = get_response(messages) # 調用模型
assistant_output = first_response.choices[0].message # 獲取模型輸出
if assistant_output.tool_calls is None: # 無需調用工具print(f"無需調用工具,我可以直接回復:{assistant_output.content}")return
子步驟3.3:解析工具調用指令并執行工具
若模型返回tool_calls
,則需解析指令并執行對應工具:
- 從
tool_calls
中提取工具名(function.name
)和參數(function.arguments
); - 調用對應的工具函數(如
get_current_weather
),傳入參數,獲取工具返回結果; - 將工具結果以
role="tool"
的格式存入messages
,并關聯tool_call_id
(確保模型知道結果對應哪個調用)。
示例解析:
# 循環處理工具調用(可能多輪,直到模型無需調用)
while assistant_output.tool_calls is not None:tool_call = assistant_output.tool_calls[0] # 獲取第一個工具調用指令tool_info = {"role": "tool","tool_call_id": tool_call.id, # 關聯調用ID"content": "" # 存儲工具返回結果}# 若調用的是天氣工具if tool_call.function.name == "get_current_weather":arguments = json.loads(tool_call.function.arguments) # 解析參數(如{"location":"杭州"})tool_info["content"] = get_current_weather(arguments) # 執行工具,獲取結果# 若調用的是時間工具elif tool_call.function.name == "get_current_time":tool_info["content"] = get_current_time() # 執行工具messages.append(tool_info) # 將工具結果加入對話歷史
子步驟3.4:多輪調用模型,整合工具結果生成最終回答
工具結果存入messages
后,再次調用模型,模型會基于“用戶問題+工具結果”生成最終回答。若仍需進一步調用工具(如參數缺失),則重復“解析→執行→返回”流程,直到模型判斷無需調用工具,輸出最終結果。
示例解析:
# 再次調用模型,傳入工具結果
assistant_output = get_response(messages).choices[0].message
messages.append(assistant_output) # 更新對話歷史# 直到模型不再返回tool_calls,輸出最終結果
print(f"最終答案:{assistant_output.content}") # 例如“杭州今天是晴天。”
三、總結:代碼如何實現Function Call的核心邏輯
- 工具定義:通過
tools
列表讓模型“認識”可用工具及調用規則; - 模型判斷:大模型結合用戶問題和工具定義,決定是否調用工具;
- 指令解析與執行:解析模型生成的
tool_calls
,調用對應工具函數并獲取結果; - 多輪交互:將工具結果反饋給模型,反復迭代直到生成最終回答。
這種機制讓大模型突破“僅依賴內部知識”的限制,能通過外部工具獲取實時信息(如時間、天氣)、執行復雜計算等,極大擴展了應用場景。