大模型如何调用外部工具:以Qwen为例的完整实践指南

October 28, 2025

在人工智能快速发展的今天,大语言模型(LLM)已经展现出强大的自然语言理解和生成能力。然而,纯粹的语言模型存在一些固有限制:知识更新滞后、无法进行实时计算、不能访问外部数据源。工具调用(Tool Calling / Function Calling)技术的出现,让大模型突破了这些限制,使其能够与外部世界交互,完成更复杂的任务。

本文将以阿里巴巴的Qwen(通义千问)模型为例,全面讲解大模型工具调用的原理和实践方法。

一、为什么大模型需要调用外部工具?

1.1 大语言模型的局限性

尽管大模型在文本理解和生成方面表现出色,但它们面临几个关键挑战:

知识截止问题:模型的训练数据有时间限制,无法获取最新信息。例如,如果你问"今天的天气如何?",模型无法直接回答。

计算能力限制:虽然模型擅长自然语言处理,但对于精确的数学计算、复杂的数据处理等任务,效率和准确性都不如专门的计算工具。

无法访问私有数据:模型无法访问企业内部数据库、API接口或用户个人数据。

幻觉问题:当模型不确定答案时,可能会生成看似合理但实际错误的内容。

1.2 工具调用的价值

通过引入工具调用机制,大模型可以:

  • 获取实时信息:调用天气API、新闻API等获取最新数据
  • 执行精确计算:使用计算器、数据库查询等工具
  • 与外部系统集成:操作数据库、发送邮件、创建订单等
  • 提高回答准确性:用实际数据代替推测,减少幻觉

二、工具调用的技术原理

2.1 核心机制

工具调用本质上是一个意图识别参数提取的过程,包含以下关键步骤:

  1. 工具定义:开发者定义可用工具的名称、描述、参数schema
  2. 意图识别:模型理解用户需求,判断是否需要调用工具
  3. 参数生成:模型提取所需参数,生成符合工具要求的调用请求
  4. 工具执行:应用程序执行实际的工具调用
  5. 结果整合:将工具返回的结果反馈给模型,生成最终回答

2.2 工作流程图

用户输入  大模型分析  需要工具?
                          ├─   直接生成回答
                          └─   生成工具调用请求
                                  
                          应用程序执行工具
                                  
                          返回执行结果
                                  
                          大模型整合结果  生成最终回答

2.3 技术实现方式

主流的实现方式主要有两种:

方式一:Prompt工程 通过精心设计的提示词,引导模型在需要时输出特定格式的工具调用指令。

方式二:模型微调 对模型进行专门的工具调用训练,使其原生支持工具调用能力。Qwen系列模型采用这种方式。

三、Qwen模型工具调用实践

接下来,我们将通过实际代码演示如何使用Qwen模型进行工具调用。

3.1 环境准备

首先安装必要的依赖包:

pip install dashscope openai

获取API密钥:访问阿里云百炼平台获取你的API Key。

3.2 定义工具

在Qwen中,工具通过JSON Schema格式定义。以天气查询为例:

import os
from openai import OpenAI

# 初始化客户端
client = OpenAI(
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 定义天气查询工具
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "获取指定城市的当前天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名称,例如:北京、上海"
                    },
                    "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "温度单位"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

工具定义说明

  • name: 工具的唯一标识符
  • description: 工具的功能描述,帮助模型理解何时使用
  • parameters: 参数schema,遵循JSON Schema规范
    • type: 参数类型(object, string, number等)
    • properties: 具体参数定义
    • required: 必需参数列表

3.3 实现工具函数

定义实际执行的工具函数:

def get_current_weather(location, unit="celsius"):
    """
    模拟天气查询API
    实际应用中,这里应该调用真实的天气API
    """
    # 模拟天气数据
    weather_data = {
        "北京": {"temperature": 15, "condition": "晴天", "humidity": 45},
        "上海": {"temperature": 20, "condition": "多云", "humidity": 65},
        "深圳": {"temperature": 25, "condition": "小雨", "humidity": 80},
    }
    
    weather = weather_data.get(location, {
        "temperature": 18,
        "condition": "未知",
        "humidity": 50
    })
    
    if unit == "fahrenheit":
        weather["temperature"] = weather["temperature"] * 9/5 + 32
        unit_str = "°F"
    else:
        unit_str = "°C"
    
    return {
        "location": location,
        "temperature": f"{weather['temperature']}{unit_str}",
        "condition": weather["condition"],
        "humidity": f"{weather['humidity']}%"
    }

3.4 完整的对话流程

现在实现完整的工具调用流程:

import json

def chat_with_tools(user_message):
    """
    与支持工具调用的模型对话
    """
    messages = [
        {"role": "user", "content": user_message}
    ]
    
    # 第一次调用:让模型判断是否需要工具
    response = client.chat.completions.create(
        model="qwen-plus",
        messages=messages,
        tools=tools,
        tool_choice="auto"  # 让模型自动决定是否使用工具
    )
    
    response_message = response.choices[0].message
    
    # 检查模型是否想要调用工具
    if response_message.tool_calls:
        # 将模型的响应添加到消息历史
        messages.append(response_message)
        
        # 执行工具调用
        for tool_call in response_message.tool_calls:
            function_name = tool_call.function.name
            function_args = json.loads(tool_call.function.arguments)
            
            print(f"模型请求调用工具: {function_name}")
            print(f"参数: {function_args}")
            
            # 调用实际的工具函数
            if function_name == "get_current_weather":
                function_response = get_current_weather(**function_args)
            else:
                function_response = {"error": "未知工具"}
            
            print(f"工具返回结果: {function_response}\n")
            
            # 将工具执行结果添加到消息历史
            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": json.dumps(function_response, ensure_ascii=False)
            })
        
        # 第二次调用:让模型基于工具结果生成最终回答
        second_response = client.chat.completions.create(
            model="qwen-plus",
            messages=messages
        )
        
        return second_response.choices[0].message.content
    else:
        # 模型直接回答,不需要工具
        return response_message.content

# 测试工具调用
if __name__ == "__main__":
    user_input = "今天北京的天气怎么样?"
    print(f"用户: {user_input}")
    print("-" * 50)
    
    answer = chat_with_tools(user_input)
    print(f"助手: {answer}")

3.5 运行示例

运行上述代码,你会看到类似如下的输出:

用户: 今天北京的天气怎么样?
--------------------------------------------------
模型请求调用工具: get_current_weather
参数: {'location': '北京', 'unit': 'celsius'}
工具返回结果: {'location': '北京', 'temperature': '15°C', 'condition': '晴天', 'humidity': '45%'}

助手: 今天北京的天气是晴天,温度为15°C,湿度45%。天气不错,适合外出活动。

流程解析

  1. 用户询问北京天气
  2. 模型识别需要调用get_current_weather工具
  3. 模型提取参数:location="北京", unit="celsius"
  4. 应用程序执行工具函数,获取天气数据
  5. 模型接收工具返回结果
  6. 模型基于真实数据生成自然语言回答

四、进阶技巧:多工具场景

在实际应用中,我们通常需要定义多个工具。下面展示一个包含多个工具的示例:

# 定义多个工具
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "获取指定城市的当前天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "城市名称"}
                },
                "required": ["location"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "执行数学计算,支持基本算术运算",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "数学表达式,例如:'2 + 3 * 4'"
                    }
                },
                "required": ["expression"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_database",
            "description": "在数据库中搜索产品信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "搜索关键词"},
                    "category": {
                        "type": "string",
                        "enum": ["electronics", "books", "clothing"],
                        "description": "产品类别"
                    }
                },
                "required": ["query"]
            }
        }
    }
]

# 实现对应的工具函数
def calculate(expression):
    """安全的数学计算"""
    try:
        # 注意:实际应用中要使用更安全的计算方法
        result = eval(expression, {"__builtins__": {}})
        return {"result": result, "expression": expression}
    except Exception as e:
        return {"error": str(e)}

def search_database(query, category=None):
    """模拟数据库搜索"""
    # 这里应该连接实际数据库
    mock_results = [
        {"id": 1, "name": f"产品A - {query}", "price": 299},
        {"id": 2, "name": f"产品B - {query}", "price": 399}
    ]
    return {"results": mock_results, "count": len(mock_results)}

# 工具调度器
def execute_tool(function_name, function_args):
    """根据工具名称调用相应的函数"""
    tool_functions = {
        "get_current_weather": get_current_weather,
        "calculate": calculate,
        "search_database": search_database
    }
    
    if function_name in tool_functions:
        return tool_functions[function_name](**function_args)
    else:
        return {"error": f"未知工具: {function_name}"}

五、主流技术方案对比

5.1 不同模型的工具调用支持

| 模型/平台 | 支持程度 | 特点 | |----------|---------|------| | OpenAI GPT-4/GPT-3.5 | ✅ 原生支持 | 最早推出Function Calling,API设计成熟 | | Qwen系列 | ✅ 原生支持 | 完全兼容OpenAI API格式,中文支持优秀 | | Claude | ✅ 原生支持 | Anthropic的工具调用实现 | | 开源模型(如Llama) | ⚠️ 部分支持 | 需要微调或使用特定prompt工程 |

5.2 实现架构对比

方案一:ReAct框架

Reasoning (推理)  Action (行动)  Observation (观察)  循环

模型通过链式思维,逐步推理并执行工具调用。

方案二:原生Function Calling

单次推理  工具调用请求  执行  结果整合

Qwen和GPT采用这种方式,效率更高。

方案三:Agent框架(LangChain/LlamaIndex)

高级封装  自动化工具管理  多轮对话  记忆管理

提供更高层次的抽象,但增加了复杂度。

六、精确调用的最佳实践

6.1 工具描述优化

清晰的工具描述能显著提高调用准确率:

#  不好的描述
"description": "查天气"

#  好的描述
"description": "获取指定城市的实时天气信息,包括温度、天气状况和湿度"

6.2 参数Schema设计

#  详细的参数说明
"parameters": {
    "type": "object",
    "properties": {
        "location": {
            "type": "string",
            "description": "城市名称,需要提供完整的城市名,如'北京''上海''深圳'"
        },
        "unit": {
            "type": "string",
            "enum": ["celsius", "fahrenheit"],
            "description": "温度单位,celsius表示摄氏度,fahrenheit表示华氏度",
            "default": "celsius"
        }
    },
    "required": ["location"]
}

6.3 错误处理

def chat_with_tools_robust(user_message):
    """带有错误处理的工具调用"""
    try:
        messages = [{"role": "user", "content": user_message}]
        response = client.chat.completions.create(
            model="qwen-plus",
            messages=messages,
            tools=tools,
            tool_choice="auto"
        )
        
        response_message = response.choices[0].message
        
        if response_message.tool_calls:
            messages.append(response_message)
            
            for tool_call in response_message.tool_calls:
                try:
                    function_name = tool_call.function.name
                    function_args = json.loads(tool_call.function.arguments)
                    
                    # 执行工具
                    function_response = execute_tool(function_name, function_args)
                    
                    # 检查工具执行是否成功
                    if "error" in function_response:
                        print(f"工具执行出错: {function_response['error']}")
                    
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": json.dumps(function_response, ensure_ascii=False)
                    })
                    
                except json.JSONDecodeError as e:
                    print(f"参数解析失败: {e}")
                    messages.append({
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "content": json.dumps({"error": "参数格式错误"})
                    })
            
            second_response = client.chat.completions.create(
                model="qwen-plus",
                messages=messages
            )
            return second_response.choices[0].message.content
        else:
            return response_message.content
            
    except Exception as e:
        return f"发生错误: {str(e)}"

七、扩展应用场景

7.1 智能客服系统

# 客服场景工具集
customer_service_tools = [
    {
        "type": "function",
        "function": {
            "name": "query_order_status",
            "description": "查询订单状态",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string", "description": "订单号"}
                },
                "required": ["order_id"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "initiate_refund",
            "description": "发起退款申请",
            "parameters": {
                "type": "object",
                "properties": {
                    "order_id": {"type": "string", "description": "订单号"},
                    "reason": {"type": "string", "description": "退款原因"}
                },
                "required": ["order_id", "reason"]
            }
        }
    }
]

应用价值

  • 自动处理常见查询
  • 减少人工客服压力
  • 24/7全天候服务

7.2 数据分析助手

# 数据分析工具
data_analysis_tools = [
    {
        "type": "function",
        "function": {
            "name": "query_database",
            "description": "执行SQL查询获取数据",
            "parameters": {
                "type": "object",
                "properties": {
                    "sql": {"type": "string", "description": "SQL查询语句"},
                    "database": {"type": "string", "description": "数据库名称"}
                },
                "required": ["sql"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "generate_chart",
            "description": "生成数据可视化图表",
            "parameters": {
                "type": "object",
                "properties": {
                    "data": {"type": "array", "description": "图表数据"},
                    "chart_type": {
                        "type": "string",
                        "enum": ["bar", "line", "pie"],
                        "description": "图表类型"
                    }
                },
                "required": ["data", "chart_type"]
            }
        }
    }
]

应用价值

  • 自然语言转SQL
  • 自动生成报表
  • 降低数据分析门槛

7.3 个人助理应用

# 个人助理工具集
personal_assistant_tools = [
    {
        "type": "function",
        "function": {
            "name": "create_calendar_event",
            "description": "创建日历事件",
            "parameters": {
                "type": "object",
                "properties": {
                    "title": {"type": "string", "description": "事件标题"},
                    "start_time": {"type": "string", "description": "开始时间"},
                    "duration": {"type": "number", "description": "持续时长(分钟)"}
                },
                "required": ["title", "start_time"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "send_email",
            "description": "发送邮件",
            "parameters": {
                "type": "object",
                "properties": {
                    "to": {"type": "string", "description": "收件人邮箱"},
                    "subject": {"type": "string", "description": "邮件主题"},
                    "body": {"type": "string", "description": "邮件正文"}
                },
                "required": ["to", "subject", "body"]
            }
        }
    }
]

应用价值

  • 日程管理自动化
  • 邮件处理智能化
  • 提高工作效率

7.4 开发辅助工具

# 开发辅助工具
dev_tools = [
    {
        "type": "function",
        "function": {
            "name": "execute_code",
            "description": "在安全沙箱中执行代码",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "要执行的代码"},
                    "language": {
                        "type": "string",
                        "enum": ["python", "javascript", "bash"],
                        "description": "编程语言"
                    }
                },
                "required": ["code", "language"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "search_documentation",
            "description": "搜索API文档",
            "parameters": {
                "type": "object",
                "properties": {
                    "query": {"type": "string", "description": "搜索关键词"},
                    "library": {"type": "string", "description": "库名称"}
                },
                "required": ["query"]
            }
        }
    }
]

应用价值

  • 代码实时验证
  • 快速查找文档
  • 辅助调试问题

八、实战演练:构建天气查询机器人

现在让我们完整实现一个实用的天气查询机器人:

import os
import json
from openai import OpenAI

class WeatherBot:
    def __init__(self, api_key=None):
        """初始化天气机器人"""
        self.client = OpenAI(
            api_key=api_key or os.getenv("DASHSCOPE_API_KEY"),
            base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
        )
        
        self.tools = [
            {
                "type": "function",
                "function": {
                    "name": "get_current_weather",
                    "description": "获取指定城市的当前天气信息",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "location": {
                                "type": "string",
                                "description": "城市名称,例如:北京、上海、深圳"
                            }
                        },
                        "required": ["location"]
                    }
                }
            },
            {
                "type": "function",
                "function": {
                    "name": "get_weather_forecast",
                    "description": "获取未来几天的天气预报",
                    "parameters": {
                        "type": "object",
                        "properties": {
                            "location": {"type": "string", "description": "城市名称"},
                            "days": {
                                "type": "number",
                                "description": "预报天数(1-7天)",
                                "minimum": 1,
                                "maximum": 7
                            }
                        },
                        "required": ["location", "days"]
                    }
                }
            }
        ]
        
        self.conversation_history = []
    
    def get_current_weather(self, location):
        """获取当前天气(模拟)"""
        weather_db = {
            "北京": {"temp": 15, "condition": "", "wind": "北风3级"},
            "上海": {"temp": 20, "condition": "多云", "wind": "东风2级"},
            "深圳": {"temp": 25, "condition": "小雨", "wind": "南风4级"},
            "广州": {"temp": 24, "condition": "", "wind": "无风"}
        }
        
        weather = weather_db.get(location, {
            "temp": 18, "condition": "未知", "wind": "未知"
        })
        
        return {
            "location": location,
            "temperature": f"{weather['temp']}°C",
            "condition": weather["condition"],
            "wind": weather["wind"]
        }
    
    def get_weather_forecast(self, location, days):
        """获取天气预报(模拟)"""
        forecast = []
        for i in range(int(days)):
            forecast.append({
                "day": f"第{i+1}天",
                "temperature": f"{15 + i*2}°C",
                "condition": ["", "多云", "", "小雨"][i % 4]
            })
        
        return {
            "location": location,
            "forecast": forecast
        }
    
    def execute_tool(self, function_name, function_args):
        """执行工具调用"""
        if function_name == "get_current_weather":
            return self.get_current_weather(**function_args)
        elif function_name == "get_weather_forecast":
            return self.get_weather_forecast(**function_args)
        else:
            return {"error": "未知工具"}
    
    def chat(self, user_message):
        """处理用户消息"""
        # 添加用户消息到历史
        self.conversation_history.append({
            "role": "user",
            "content": user_message
        })
        
        # 调用模型
        response = self.client.chat.completions.create(
            model="qwen-plus",
            messages=self.conversation_history,
            tools=self.tools,
            tool_choice="auto"
        )
        
        response_message = response.choices[0].message
        
        # 处理工具调用
        if response_message.tool_calls:
            # 添加助手响应到历史
            self.conversation_history.append(response_message)
            
            # 执行所有工具调用
            for tool_call in response_message.tool_calls:
                function_name = tool_call.function.name
                function_args = json.loads(tool_call.function.arguments)
                
                print(f"🔧 调用工具: {function_name}")
                print(f"📝 参数: {function_args}")
                
                # 执行工具
                result = self.execute_tool(function_name, function_args)
                print(f"✅ 结果: {result}\n")
                
                # 添加工具结果到历史
                self.conversation_history.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "content": json.dumps(result, ensure_ascii=False)
                })
            
            # 再次调用模型生成最终回答
            final_response = self.client.chat.completions.create(
                model="qwen-plus",
                messages=self.conversation_history
            )
            
            final_message = final_response.choices[0].message
            self.conversation_history.append(final_message)
            
            return final_message.content
        else:
            # 直接回答
            self.conversation_history.append(response_message)
            return response_message.content
    
    def reset(self):
        """重置对话历史"""
        self.conversation_history = []

# 使用示例
if __name__ == "__main__":
    bot = WeatherBot()
    
    print("🤖 天气机器人已启动!输入'退出'结束对话。\n")
    
    while True:
        user_input = input("👤 您: ")
        if user_input.lower() in ["退出", "exit", "quit"]:
            print("👋 再见!")
            break
        
        if not user_input.strip():
            continue
        
        print()
        response = bot.chat(user_input)
        print(f"🤖 助手: {response}\n")
        print("-" * 60 + "\n")

运行机器人

python weather_bot.py

交互示例

🤖 天气机器人已启动!输入'退出'结束对话。

👤 : 北京今天天气怎么样?

🔧 调用工具: get_current_weather
📝 参数: {'location': '北京'}
 结果: {'location': '北京', 'temperature': '15°C', 'condition': '', 'wind': '北风3级'}

🤖 助手: 北京今天天气晴朗,温度15°C,北风3级。天气不错,适合外出活动!

------------------------------------------------------------

👤 : 深圳未来3天天气如何?

🔧 调用工具: get_weather_forecast
📝 参数: {'location': '深圳', 'days': 3}
 结果: {'location': '深圳', 'forecast': [{'day': '第1天', 'temperature': '15°C', 'condition': ''}, ...]}

🤖 助手: 深圳未来3天天气预报:
- 第1天:晴,15°C
- 第2天:多云,17°C
- 第3天:阴,19°C

------------------------------------------------------------

九、常见问题与解决方案

9.1 工具调用失败

问题:模型没有调用工具 解决方案

  • 检查工具描述是否清晰
  • 确认用户问题确实需要工具
  • 尝试调整tool_choice参数

9.2 参数提取错误

问题:模型提取的参数不正确 解决方案

  • 优化参数description,提供更多示例
  • 使用enum限制参数取值范围
  • 添加参数验证逻辑

9.3 性能优化

问题:响应速度慢 解决方案

  • 减少工具数量,只保留必要工具
  • 使用更快的模型(如qwen-turbo)
  • 实现工具结果缓存

9.4 成本控制

问题:API调用成本高 解决方案

  • 合理使用对话历史,避免重复上下文
  • 选择性价比高的模型
  • 实现本地缓存机制

十、总结与展望

通过本文,我们全面了解了大模型工具调用的:

核心价值:突破模型局限,实现实时交互 ✅ 技术原理:意图识别、参数提取、结果整合 ✅ 实现方法:Qwen模型的完整实践流程 ✅ 最佳实践:工具定义、错误处理、性能优化 ✅ 应用场景:客服、数据分析、个人助理、开发工具

未来趋势

  1. 多模态工具调用:支持图像、音频等多模态输入输出
  2. 自主Agent:模型自主规划和执行复杂任务
  3. 工具生态:标准化的工具市场和共享平台
  4. 安全增强:更完善的权限控制和审计机制

继续学习资源

现在,你已经掌握了大模型工具调用的核心知识!开始动手实践,构建你自己的AI应用吧!🚀


相关阅读推荐

  • 如何优化大模型提示词工程
  • LangChain框架深度解析
  • 构建企业级AI Agent系统