前言

此篇重点记录下小白在开发过程中可能产生的一些问题和疑问的解答(含代码~),部分内容如messages该如何组织适配agent应用因篇幅原因会在下一文联合上下文处理一起介绍。

what?——function call是什么?

这个问题在前一篇文章中有讲述过,简单说:Function Call就是让智能助手能调用外部工具的功能,比如查天气、订外卖、算数学题,让它从"只会说话"变成"会办实事"的全能帮手!

why?——为什么需要function call?

大模型本身的一些缺陷,例如:

1. 知识有时效性缺陷

比如你问 “2025 年 NBA 总冠军是谁?”(假设现在是 2025 年),模型如果没学过 2025 年的新数据,就答不上来。但用 Function Call 调用体育新闻 API,马上能拿到实时结果。

2. 不会做专业操作

模型懂医学知识,但不能直接帮你查医院排班;懂数学公式,但不会用 Excel 算工资表。而 Function Call 能喊医院系统、办公软件来干活,实现 “理论 + 实操” 结合。

how?——怎么做一个基于function call的应用?

整个系统框架可以如下图所示:

图片

基于function call的应用图解

1)用户发起请求(User→应用系统):用户向应用系统提交自然语言问题(如"查询上海天气")。

2)提示词编排(应用系统→LLM):应用系统将问题转化为结构化提示词,调用大模型并请求决策。

3)工具调用判断(LLM决策分支):

无需工具:LLM直接生成文本回复(如回答常识问题)。

需工具调用:LLM输出工具名称及参数(如WeatherAPI: {location: “上海”})。

4)安全审批(应用系统→Host系统):工具调用需经权限校验与风险审核,通过后触发执行确认。

5)函数执行(Host系统):Host系统按参数调用目标工具(如天气API),获取原始结果(如JSON数据)。

6-8)结果整合(逆向传递链):

工具结果经Host系统→应用系统→LLM逐层返回,LLM将数据转化为自然语言(如"上海今日多云,28°C")。

9)最终响应(应用系统→User):应用系统将LLM生成的友好回复返回给用户,流程终止。

why&how?——小白开发中可能有的几个核心疑问

怎么实现函数调度的功能?

整体其实就是提示词来激发模型选择工具的能力,目前开发过程中主要有两种实现方式:一种是直接使用大模型API提供方提供的利用tools和messages的组织方式(其实背后他们自己也是通过prompt来组建的一套能力,不过相比自己开发一套提示词工程而言,他们更了解底层模型如何做的,在通用化场景下的适配效果可能比自己研究要好很多。

图片

阿里云官网提供的函数调用的流程图解

阿里云官网提供的函数调用的流程图解

1)使用官方提供的服务+openai接口访问方式:快速使用推荐!

简版代码如下,但提前需准备好tools的定义(见下文tools的样式小节)和messages数组(见下文messages该如何组织部分,后续推文会有更详细的介绍)。

from openai import OpenAI
import os

client = OpenAI(
    # 若没有配置环境变量,请用提供商提供的api_key="sk-xxx",
    api_key=os.getenv("API_KEY"),
    base_url="BASE_URL",
)

deffunction_calling():
    completion = client.chat.completions.create(
        model="qwen-plus",  # 此处以qwen-plus为例
        messages=messages,
        tools=tools # 这里tools的结构体可以见下文tools的样式
    )
    print("返回对象:")
    print(completion.choices[0].message.model_dump_json())
    print("\n")
    return completion

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

2)prompt+系统自实现:完全小白不建议用这个哈,相对自适配能力更强,但很考验对底层模型的理解。

上图提供了函数调用流程的图解,实际自己用prompt开发流程与上图一致。用户提问的时候将工具内容和问题组织为一定的提示词给到大模型,然后写一段拆解函数拆解大模型返回内容里面携带的工具调用信息和其他文本内容。下面是一个简单的访问模型的例子,注意拆解工具调用函数部分并没有给出。

import os
from openai import OpenAI
import json

client = OpenAI(
    # 若没有配置环境变量,请用提供商提供的api_key="sk-xxx",
    api_key=os.getenv("API_KEY"),
    base_url="BASE_URL",
)

# 自定义 System prompt,可根据您的需求修改
custom_prompt = "你是一个智能助手,专门负责调用各种工具来帮助用户解决问题。你可以根据用户的需求选择合适的工具并正确调用它们。"

tools = [
    # 工具1 获取当前时刻的时间
    {
        "type": "function",
        "function": {
            "name": "get_current_time",
            "description": "当你想知道现在的时间时非常有用。",
            "parameters": {}
        }
    },  
    # 工具2 获取指定城市的天气
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "当你想查询指定城市的天气时非常有用。",
            "parameters": {  
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市或县区,比如北京市、杭州市、余杭区等。"
                    }
                },
                "required": ["location"]
            }
        }
    }
]

# 遍历tools列表,为每个工具构建描述
tools_descriptions = []
for tool in tools:
    tool_json = json.dumps(tool, ensure_ascii=False)
    tools_descriptions.append(tool_json)

# 将所有工具描述组合成一个字符串
tools_content = "\n".join(tools_descriptions)

system_prompt = f"""{custom_prompt}

# Tools

You may call one or more functions to assist with the user query.

You are provided with function signatures within <tools></tools> XML tags:
<tools>
{tools_content}
</tools>

For each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:
<tool_call>
{{"name": <function-name>, "arguments": <args-json-object>}}
</tool_call>"""

messages = [
    {"role": "system", "content": system_prompt},
    {"role": "user", "content": "几点了"}
]

completion = client.chat.completions.create(
    model="qwen-plus",
    messages=messages,
)
print(completion.model_dump_json())

tools的样式是什么样的?怎么准备tools?

OpenAI协议中,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")

其中,

  • • type字段固定为"function";

  • • function字段为 Object 类型;

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

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

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

      • • type字段固定为"object";
      • • properties字段描述了入参的名称、数据类型与描述,为 Object 类型,Key 值为入参的名称,Value 值为入参的数据类型与描述;
      • • required字段指定哪些参数为必填项,为 Array 类型。

messages该如何组织?

message数组样例如下,具体role有 system、user、tool、assistant。

  • • system:对话的全局导演,设定模型的行为框架和初始规则。交互框架的 “设计者” 与 “规则制定者”。
  • • user:交互的 “需求发起者” 与 “信息输入方”。
  • • tool:交互中的 “功能执行者” 与 “数据提供者”。
  • • assistant:交互的 “问题解决者” 与 “内容整合者”。
messages = [
    {
        "role": "system",
        "content": """你是一个很有帮助的助手。如果用户提问关于天气的问题,请调用 ‘get_current_weather’ 函数;
     如果用户提问关于时间的问题,请调用‘get_current_time’函数。
     请以友好的语气回答问题。""",
    },
    {
        "role": "user",
        "content": "深圳天气"
    }
]
print("messages 数组创建完成\n")

怎么进行函数的并行调度?

部分问题可能需要同时调用多个工具,比如问北京和上海的天气如何?这个问题可能需要调用两次天气函数分别查询北京和上海的天气情况。

def function_calling():
    completion = client.chat.completions.create(
        model="qwen-plus",# 此处以 qwen-plus 为例,可按需更换模型名称
        messages=messages,
        tools=tools,
# 新增参数
        parallel_tool_calls=True
    )
    print("返回对象:")
    print(completion.choices[0].message.model_dump_json())
    print("\n")
    return completion

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

怎么强制使用或者不使用工具?

tool_choice可以选择:auto,none,required(必须调用至少一个工具)或者指定要调用的函数

# 强制使用某个工具
deffunction_calling():
    completion = client.chat.completions.create(
        model="qwen-plus",
        messages=messages,
        tools=tools,
        tool_choice={"type": "function", "function": {"name": "get_current_weather"}}
    )
    print(completion.model_dump_json())

function_calling()

# 强制不使用工具:tool_choice设置为none
deffunction_calling():
    completion = client.chat.completions.create(
        model="gpt-4",
        messages=messages,
        tools=tools,
        tool_choice="none"
    )
    print(completion.model_dump_json())

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"],
            },
        },
    },
]

# 模拟天气查询工具。返回结果示例:“北京今天是雨天。”
defget_current_weather(arguments):
    # 定义备选的天气条件列表
    weather_conditions = ["晴天", "多云", "雨天"]
    # 随机选择一个天气条件
    random_weather = random.choice(weather_conditions)
    # 从 JSON 中提取位置信息
    location = arguments["location"]
    # 返回格式化的天气信息
    returnf"{location}今天是{random_weather}。"

# 查询当前时间的工具。返回结果示例:“当前时间:2024-04-15 17:15:18。“
defget_current_time():
    # 获取当前日期和时间
    current_datetime = datetime.now()
    # 格式化当前日期和时间
    formatted_time = current_datetime.strftime("%Y-%m-%d %H:%M:%S")
    # 返回格式化后的当前时间
    returnf"当前时间:{formatted_time}。"

# 封装模型响应函数
defget_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

defcall_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 isNone:
        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 isNone:
            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()

最后

感谢你们的阅读和喜欢,作为一位在一线互联网行业奋斗多年的老兵,我深知在这个瞬息万变的技术领域中,持续学习和进步的重要性。

为了帮助更多热爱技术、渴望成长的朋友,我特别整理了一份涵盖大模型领域的宝贵资料集。

这些资料不仅是我多年积累的心血结晶,也是我在行业一线实战经验的总结。

这些学习资料不仅深入浅出,而且非常实用,让大家系统而高效地掌握AI大模型的各个知识点。如果你愿意花时间沉下心来学习,相信它们一定能为你提供实质性的帮助。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

AI大模型系统学习路线

在面对AI大模型开发领域的复杂与深入,精准学习显得尤为重要。一份系统的技术路线图,不仅能够帮助开发者清晰地了解从入门到精通所需掌握的知识点,还能提供一条高效、有序的学习路径。

img

但知道是一回事,做又是另一回事,初学者最常遇到的问题主要是理论知识缺乏、资源和工具的限制、模型理解和调试的复杂性,在这基础上,找到高质量的学习资源,不浪费时间、不走弯路,又是重中之重。

AI大模型入门到实战的视频教程+项目包

看视频学习是一种高效、直观、灵活且富有吸引力的学习方式,可以更直观地展示过程,能有效提升学习兴趣和理解力,是现在获取知识的重要途径

在这里插入图片描述
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
在这里插入图片描述

海量AI大模型必读的经典书籍(PDF)

阅读AI大模型经典书籍可以帮助读者提高技术水平,开拓视野,掌握核心技术,提高解决问题的能力,同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说,阅读经典书籍是非常有必要的。
在这里插入图片描述

600+AI大模型报告(实时更新)

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
在这里插入图片描述

AI大模型面试真题+答案解析

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下
在这里插入图片描述

在这里插入图片描述

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多推荐