前言:不同的模型的输出结构不同,所以用了不同的API方式。不同在调用时,具体的输出结果是不同的。

1、加载API-KEY

方式一:从.env文件导入(.env文件应当被加入.gitignore以避免敏感信息泄露。)

需要创建.env文件并添加以下内容(确保文件在项目根目录):

# .env

DEEPSEEK_API_KEY =sk-
from dotenv  import load_dotenv
import  os
load_dotenv()
api_key = os.getenv('DEEPSEEK_API_KEY')

方式二: 添加环境变量

import os

os.environ["DEEPSEEK_API_KEY"]="sk-"

2、加载模型

2.1 langchain.chat_models

  1. 多模型支持:封装了 OpenAI、Anthropic、Cohere 等主流聊天模型的 API。
  2. 标准化输入输出:统一处理消息格式(如 HumanMessageAIMessage),简化开发流程。
  3. 上下文管理:支持对话历史记录,实现多轮对话的连贯性。
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(
    model='deepseek-chat', 
    openai_api_key=api_key, 
    openai_api_base='https://api.deepseek.com',
    max_tokens=1024
)

2.2 langchain_openai

 langchain_openai 是其与 OpenAI 模型集成的官方库。它简化了调用 OpenAI API(如 GPT-3.5、GPT-4)的过程,并支持链式调用、记忆管理、工具集成等高级功能,适用于聊天机器人、自动化流程、数据分析等场景。

from langchain_openai import ChatOpenAI
llm2 = ChatOpenAI(
    model='deepseek-chat', 
    base_url='https://api.deepseek.com',
    api_key=api_key, 
)

2.3  langchain_deepseek

DeepSeek 聊天模型集成,用于访问 DeepSeek API 中托管的模型。

from  langchain_deepseek import ChatDeepSeek

llm = ChatDeepSeek(
    model="deepseek-chat", 
    api_key=api_key)

2.4 openai

from openai import OpenAI

client = OpenAI(
    
    base_url="https://api.deepseek.com", 
    api_key=api_key,
)

response = client.chat.completions.create(
    model="deepseek-chat", 
    messages=[{"role": "user", "content": "Hello!"}]
)

3、llm.bind和llm.bind_tools

llm.bind_tool 是一种用于将外部工具或功能绑定到大型语言模型(LLM)的方法。通过这种绑定,LLM 可以调用外部工具(如 API、数据库、计算引擎等)来扩展其能力,从而实现更复杂的任务处理。

在 LangChain 中,llm.bind() 是一个用于将额外参数(如 functions 或 tools)绑定到语言模型的方法,以便在调用模型时自动传递这些参数。它通常用于 OpenAI 风格的函数调用(Function Calling) 或 工具绑定(Tool Binding)

3.1 直接构建工具
from langchain_core.tools import tool

@tool
def search(city: str) -> str:
    """查询城市天气"""
    return "30°C"


from langchain_openai import ChatOpenAI
llm2 = ChatOpenAI(
    model='qwen-turbo', 
    base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
    api_key='sk-0', 
)
llm2.bind_tools(tools=[search,get_current_temperature])
3.2 使用 function_call 的格式
from langchain_core.tools import tool

tools = [{
    "name": "get_weather", 
    "description": "查询城市天气",
    "parameters": {
        "type": "object",
        "properties": {
            "city": {"type": "string", "description": "城市名称"}
        },
        "required": ["city"]
    }
}]
from langchain_openai import ChatOpenAI
llm2 = ChatOpenAI(
    model='qwen-turbo', 
    base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
    api_key='sk-0', 
)
llm2.bind_tools(tools=tools)
3.3 使用convert_to_openai_function函数

from langchain.chat_models import ChatOpenAI
from pydantic import BaseModel, Field
from langchain_core.utils.function_calling import convert_to_openai_function
class add(BaseModel):
    """Add two integers."""

    a: int = Field(..., description="First integer")
    b: int = Field(..., description="Second integer")


# Initialize the LLM with DashScope configuration
llm = ChatOpenAI(
    model='qwen-turbo', 
    base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
    api_key='sk-0',
)
functions = [
  convert_to_openai_function(f)  for f  in [add]
]
llm_with_tools = llm.bind(functions=functions)
response = llm_with_tools.invoke("What's 1+2")
print(response)

或者

from langchain_core.utils.function_calling import convert_to_openai_function
from langchain.chat_models import ChatOpenAI
from langchain_core.tools import tool

@tool
def get_weather(city: str) -> str:
    """查询城市天气"""
    return f"Weather in {city}: 30°C"

llm = ChatOpenAI(
    model='qwen-turbo', 
    base_url='https://dashscope.aliyuncs.com/compatible-mode/v1',
    api_key='sk-0',
)

functions = [
  convert_to_openai_function(f)  for f  in [get_weather]
]
llm_with_tools = llm.bind(functions=functions)
response = llm_with_tools.invoke("What's the weather in Beijing?")
print(response)

在使用langchain_openai时,并没有注意到bind和bind_tools的具体区别。无论是普通格式的tool还是function_call格式的tool在代码编译时都没有报错。

在使用langchain.chat_models 时,使用bind_tools时开始报错。才开始注意两者的不同。

在使用openai 时,会有明确的定义。 在使用tool时,会有对应的tool_id 进行对应。

 completion = client.chat.completions.create(
        model="qwen-plus",  # 此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
        messages=messages,
        # tools=tools
        # functions=functions
    )
3.4 tool 和function_call 的具体区别

在网络上简单搜索后,没有找到具体的文章来表述两者的具体区别。很多文章都是在表示function_call的用法。

1、https://zhuanlan.zhihu.com/p/707459943

在这篇文章中作者对比了不同模型的function_call。

2、https://juejin.cn/post/7490784514841673778 

在这篇文章中说到”Function 这个术语实际上已经废弃了,取而代之的是 Tool。Tool 泛指指一切 LLM 能够调用的外部工具。Tool 相比 function 要更加广义,只不过目前的 tool 只有 function calling 这一种形式,因此为了文章方便理解,就这里认为 function 与 tool 是等价的。“

3、LangChain 官网

LangChain Tools contain a description of the tool (to pass to the language model) as well as the implementation of the function to call.(Tools包含工具的描述(传递给语言模型)以及要调用的函数的实现)

4、大模型FunctionCall-知识整理_function call-CSDN博客

Function Callingl(Tool_Calls)并不是通过对话让大模型执行函数,而是通过大模型与用户对话获取到函数所需的参数。Function Calling是获取函数参数用的,不是执行函数用的。

5、如何使用 Function Calling 功能_大模型服务平台百炼(Model Studio)-阿里云帮助中心

 从上述文章可以简单的看出,function_call 主要是为了获取用户回答的参数,也就是简单的用户意图识别。在Function calling中,参数是连接模型和外部函数的关键。参数的解释和定义需要非常精确,以确保模型能够正确理解用户的意图,并生成符合函数要求的参数值。

3.5 具体案例实践(来源于百炼平台的Function Calling案例)
3.5.1 定义tool

定义工具函数

import random
from datetime import datetime


def get_current_weather(location: str) -> str:
    """获取当前天气情况。输入地点,如'上海'"""
    weather_conditions = ["晴天", "多云", "雨天"]
    random_weather = random.choice(weather_conditions)
    return f"{location}今天是{random_weather}。"

# 查询当前时间的工具
def get_current_time() -> str:
    """获取当前时间"""
    current_datetime = datetime.now()
    formatted_time = current_datetime.strftime('%Y-%m-%d %H:%M:%S')
    return f"当前时间:{formatted_time}。"

创建tool列表

请根据以下的 JSON 格式提供工具信息。

  • type字段固定为"function"

  • function字段为 Object 类型;

    • name字段为自定义的工具函数名称,建议使用与函数相同的名称,如get_current_weatherget_current_time

    • description字段是对工具函数功能的描述,大模型会参考该字段来选择是否使用该工具函数。

    • parameters字段是对工具函数入参的描述,类型是 Object ,大模型会参考该字段来进行入参的提取。如果工具函数不需要输入参数,则无需指定parameters参数。

      • type字段固定为"object"

      • properties字段描述了入参的名称、数据类型与描述,为 Object 类型,Key 值为入参的名称,Value 值为入参的数据类型与描述;

      • required字段指定哪些参数为必填项,为 Array 类型。

{
    "type": "function",
    "function": {
        "name": "get_current_weather",
        "description": "当你想查询指定城市的天气时非常有用。",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "城市或县区,比如北京市、杭州市、余杭区等。",
                }
            },
            "required": ["location"]
        }
    }
}

具体代码:

# 请将以下代码粘贴到步骤1代码后

## 步骤2:创建 tools 数组

tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "当你想知道现在的时间时非常有用。",
        }
    },
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "当你想查询指定城市的天气时非常有用。",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市或县区,比如北京市、杭州市、余杭区等。",
                    }
                },
                "required": ["location"]
            }
        }
    }
]
tool_name = [tool["function"]["name"] for tool in tools]
print(f"创建了{len(tools)}个工具,为:{tool_name}\n")
 2.5.2 创建messages(类似于prompt)

一般分为System Message 和 User Message

System Message

你是一个很有帮助的助手。如果用户提问关于天气的问题,请调用 ‘get_current_weather’ 函数;
如果用户提问关于时间的问题,请调用‘get_current_time’函数。
请以友好的语气回答问题。

 User Message

User Message 用于传入用户提问的问题。假设用户提问“上海天气”,

# 步骤3:创建messages数组
# 请将以下代码粘贴到步骤2 代码后
messages = [
    {
        "role": "system",
        "content": """你是一个很有帮助的助手。如果用户提问关于天气的问题,请调用 ‘get_current_weather’ 函数;
     如果用户提问关于时间的问题,请调用‘get_current_time’函数。
     请以友好的语气回答问题。""",
    },
    {
        "role": "user",
        "content": "上海天气"
    }
]
3. 发起 Function Calling
from openai import OpenAI
import os

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 function_calling():
    completion = client.chat.completions.create(
        model="qwen-plus",  # 此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
        messages=messages,
        tools=tools
    )
    print("返回对象:")
    print(completion.choices[0].message.model_dump_json())
    print("\n")
    return completion

print("正在发起function calling...")
completion = function_calling()

 出现以下信息,说明成功:

正在发起function calling...
返回对象:
{"content":"","refusal":null,"role":"assistant","annotations":null,"audio":null,"function_call":null,"tool_calls":[{"id":"call_b17c9629164343388d9719","function":{"arguments":"{\"location\": \"上海\"}","name":"get_current_weather"},"type":"function","index":0}]}

此时输出结果为tool_call。

3.5.简单改编:使用convert_to_openai_function
from langchain_core.utils.function_calling import convert_to_openai_function
functions = [
  convert_to_openai_function(f)  for f  in [get_current_weather,get_current_time]
]
functions

 functions的输出

[{'name': 'get_current_weather',
  'description': "获取当前天气情况。输入地点,如'上海'",
  'parameters': {'properties': {'location': {'type': 'string'}},
   'required': ['location'],
   'type': 'object'}},
 {'name': 'get_current_time',
  'description': '获取当前时间',
  'parameters': {'properties': {}, 'type': 'object'}}]
调用function_call
# 步骤4:发起 function calling
from openai import OpenAI


import os

client = OpenAI(

    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)

def function_calling():
    # messages = [{"role": "user", "content": "北京现在的天气怎么样?"}]
    completion = client.chat.completions.create(
        model="qwen-plus",  # 此处以qwen-plus为例,可按需更换模型名称。模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
        messages=messages,
        # tools=tools
        functions=functions
    )
    print("返回对象:")
    print(completion.choices[0].message.model_dump_json())
    print("\n")
    return completion

print("正在发起function calling...")
completion = function_calling()

此时的输出为 function_call

正在发起function calling...
返回对象:
{"content":"","refusal":null,"role":"assistant","annotations":null,"audio":null,"function_call":{"arguments":"{}","name":"get_current_time"},"tool_calls":null}

 

Function calling的第一次响应是指模型在接收到用户的自然语言输入后,生成的包含函数调用请求的响应。在这个阶段,模型会首先解析用户的意图,判断是否需要调用外部函数来完成任务。如果需要调用函数,模型会生成一个结构化的函数调用请求,包括函数名和参数,并将其作为响应的一部分返回。

Function calling的第二次响应是指在外部函数执行完成后,模型根据函数的执行结果生成的最终回复。在这个阶段,模型会将外部函数返回的结果整合到自然语言回复中,以向用户提供完整的信息。

测试代码如下:

from openai import OpenAI
from datetime import datetime
import json
import os
import random

client = 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/models
        messages=messages,
        tools=tools,
    )
    return completion


def call_with_messages():
    print("\n")
    messages = [
        {
            "content": input(
                "请输入:"
            ),  # 提问示例:"现在几点了?" "一个小时后几点" "北京天气如何?"
            "role": "user",
        }
    ]
    print("-" * 60)
    # 模型的第一轮调用
    i = 1
    first_response = get_response(messages)
    assistant_output = first_response.choices[0].message
    print(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].message
        if assistant_output.content is None:
            assistant_output.content = ""
        messages.append(assistant_output)
        i += 1
        print(f"第{i}轮大模型输出信息:{assistant_output}\n")
    print(f"最终答案:{assistant_output.content}")


if __name__ == "__main__":
    call_with_messages()
------------------------------------------------------------

第1轮大模型输出信息:ChatCompletion(id='chatcmpl-f9311047-dda8-9c7a-afbf-d45b7465ec3e', choices=[Choice(finish_reason='tool_calls', index=0, logprobs=None, message=ChatCompletionMessage(content='', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_834f5ecaed4d4d95b70735', function=Function(arguments='{}', name='get_current_time'), type='function', index=0)]))], created=1748793647, model='qwen-plus', object='chat.completion', service_tier=None, system_fingerprint=None, usage=CompletionUsage(completion_tokens=13, prompt_tokens=223, total_tokens=236, completion_tokens_details=None, prompt_tokens_details=PromptTokensDetails(audio_tokens=None, cached_tokens=0)))

工具输出信息:当前时间:2025-06-02 00:00:48。

------------------------------------------------------------
第2轮大模型输出信息:ChatCompletionMessage(content='现在的时间是2025年6月2日的00:00:48。', refusal=None, role='assistant', annotations=None, audio=None, function_call=None, tool_calls=None)

最终答案:现在的时间是2025年6月2日的00:00:48。

在不同的API中,有不同的用法,大家根据自己的习惯即可。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐