Function Calling 原理与实战:从零构建智能工具调用系统摘要:Function Calling 是大语言模型(LLM)与外部世界交互的核心机制。本文深入解析 Function Calling 的工作原理、实现细节和最佳实践,通过完整的实战案例演示如何构建可靠的工具调用系统,帮助开发者掌握这一关键技术。一、Function Calling 核心概念1.1 什么是 Function Calling?Function Calling 允许 LLM 在对话过程中调用预定义的函数,获取实时信息或执行操作:┌─────────────────────────────────────────────────────────┐ │ Function Calling 工作流程 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 用户: "北京今天天气怎么样?" │ │ │ │ │ ▼ │ │ ┌─────────┐ │ │ │ LLM │ 分析用户意图,决定调用哪个函数 │ │ └────┬────┘ │ │ │ │ │ │ function_call: { │ │ │ name: "get_weather", │ │ │ arguments: {"city": "北京"} │ │ │ } │ │ ▼ │ │ ┌─────────┐ │ │ │ 函数 │ 执行天气 API 调用 │ │ └────┬────┘ │ │ │ │ │ │ result: "北京今天晴,25°C" │ │ ▼ │ │ ┌─────────┐ │ │ │ LLM │ 整合结果,生成自然语言回复 │ │ └────┬────┘ │ │ │ │ │ ▼ │ │ AI: "北京今天天气晴朗,气温25°C,很适合出行~" │ │ │ └─────────────────────────────────────────────────────────┘1.2 Function Calling vs 传统 API 调用# 传统方式:硬编码逻辑判断deftraditional_chat(user_input):if"天气"inuser_input:# 提取城市名city=extract_city(user_input)# 调用天气 APIweather=get_weather(city)# 格式化回复returnf"{city}天气:{weather}"elif"翻译"inuser_input:# 另一套逻辑...pass# 需要为每种意图编写判断逻辑,难以扩展# Function Calling 方式:LLM 自动决策asyncdeffunction_calling_chat(user_input,tools):# LLM 根据工具描述自动选择合适的函数response=awaitllm.chat(messages=[{"role":"user","content":user_input}],tools=tools# 工具定义列表)ifresponse.tool_calls:# LLM 决定调用某个工具tool_call=response.tool_calls[0]result=awaitexecute_tool(tool_call)# 将结果返回给 LLM 生成最终回复returnawaitgenerate_response_with_result(result)returnresponse.content二、主流平台 Function Calling 实现2.1 OpenAI Function Calling# OpenAI Function Calling 实现fromopenaiimportOpenAIimportjson client=OpenAI()# 定义工具tools=[{"type":"function","function":{"name":"get_weather","description":"获取指定城市的当前天气信息","parameters":{"type":"object","properties":{"city":{"type":"string","description":"城市名称"},"unit":{"type":"string","enum":["celsius","fahrenheit"],"description":"温度单位"}},"required":["city"]}}}]# 工具实现defget_weather(city:str,unit:str="celsius")-str:# 实际实现中调用天气 APIreturnjson.dumps({"city":city,"temperature":25,"unit":unit,"condition":"晴"})# 发起对话defchat_with_tools(user_message):messages=[{"role":"user","content":user_message}]response=client.chat.completions.create(model="gpt-4",messages=messages,tools=tools,tool_choice="auto"# 自动决定是否调用工具)assistant_message=response.choices[0].message# 检查是否有工具调用ifassistant_message.tool_calls:# 执行工具调用fortool_callinassistant_message.tool_calls:function_name=tool_call.function.name arguments=json.loads(tool_call.function.arguments)iffunction_name=="get_weather":result=get_weather(**arguments)# 将工具结果添加到消息历史messages.append({"role":"tool","tool_call_id":tool_call.id,"content":result})# 再次调用 LLM 生成最终回复final_response=client.chat.completions.create(model="gpt-4",messages=messages)returnfinal_response.choices[0].message.contentreturnassistant_message.content2.2 Anthropic Claude Tool Use# Anthropic Claude Tool Use 实现importanthropic client=anthropic.Anthropic()# 定义工具tools=[{"name":"get_weather","description":"获取指定城市的当前天气信息","input_schema":{"type":"object","properties":{"city":{"type":"string","description":"城市名称"}},"required":["city"]}}]defchat_with_claude(user_message):messages=[{"role":"user","content":user_message}]response=client.messages.create(model="claude-3-opus-20240229",max_tokens=1024,tools=tools,messages=messages)# 检查是否有工具使用ifresponse.stop_reason=="tool_use":# 提取工具调用tool_use=next(blockforblockinresponse.contentifblock.type=="tool_use")# 执行工具result=get_weather(**tool_use.input)# 发送工具结果messages.append({"role":"assistant","content":response.content})messages.append({"role":"user","content":[{"type":"tool_result","tool_use_id":tool_use.id,"content":result}]})# 获取最终回复final_response=client.messages.create(model="claude-3-opus-20240229",max_tokens=1024,tools=tools,messages=messages)returnfinal_response.content[0].textreturnresponse.content[0].text2.3 Google Gemini Function Calling# Google Gemini Function Calling 实现importgoogle.generativeaiasgenai genai.configure(api_key="your-api-key")# 定义函数defget_weather(city:str)-dict:"""获取天气信息"""return{"city":city,"temperature":25,"condition":"晴"}# 创建模型model=genai.GenerativeModel(model_name="gemini-pro",tools=[get_weather]# 直接传递函数)defchat_with_gemini(user_message):chat=model.start_chat()response=chat.send_message(user_message)# 检查是否有函数调用ifresponse.candidates[0].content.parts:forpartinresponse.candidates[0].content.parts: