函数调用(function calling)

目录

入门例子

openai调用function calling

LangChain调用function calling

OpenAI Assistant API支持function calling

LangChain Assistant API支持function calling

网页Assistant支持function calling


函数调用(Function Calling)是OpenAI在今年6月13日对外发布的新能力。根据OpenAI官方博客描述,函数调用能力可以让大模型输出一个请求调用函数的消息,其中包含所需调用的函数信息、以及调用函数时所携带的参数信息。这是一种将大模型(LLM)能力与外部工具/API连接起来的新方式。

比如用户输入:

What’s the weather like in Tokyo?

使用function calling,可实现函数执行get_current_weather(location: string),从而获取函数输出,即得到对应地理位置的天气情况。这其中,location这个参数及其取值是借助大模型能力从用户输入中抽取出来的,同时,大模型判断得到调用的函数为get_current_weather

开发人员可以使用大模型的function calling能力实现:

  • • 在进行自然语言交流时,通过调用外部工具回答问题(类似于ChatGPT插件);

  • • 将自然语言转换为调用API调用,或数据库查询语句;

  • • 从文本中抽取结构化数据

  • • 其它

那么,在OpenAI发布的模型中,是如何实现function calling的呢?

本文中,使用的第三方模块信息如下:

openai==1.3.2
langchain==0.0.339

入门例子

我们以函数get_weather_info为例,其实现逻辑(模拟实现世界中的API调用,获取对应城市的天气状况)如下:

def get_weather_info(city: str):
    weather_info = {"Shanghai": "Rainy", "Beijing": "Snow"}
    return weather_info.get(city, "Sunny")

该函数只有一个参数:字符串变量city,即城市名称。为了实现function calling功能,需配置函数描述(类似JSON化的API描述),代码如下:

functions = [
    {
        "name": "get_weather_info",
        "description": "Get the weather information of a city",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "The name of the city, e.g. Shanghai",
                },
            },
            "required": ["city"],
        }
    }
]

对于一般的用户输入(query),大模型回复结果如下:

import json
from openai import OpenAI

client = OpenAI(api_key="sk-xxx")

query = "What is the capital of france?"
response = client.chat.completions.create(
        model="gpt-3.5-turbo-0613",
        messages=[{"role": "user", "content": query}],
        functions=functions
    )
message = response.dict()["choices"][0]["message"]
print(message)

>>> {'content': 'The capital of France is Paris.', 'role': 'assistant', 'function_call': None, 'tool_calls': None}

此时function_call为None,即大模型判断不需要function calling.

对于查询天气的query,大模型输出结果如下:

import json
from openai import OpenAI

client = OpenAI(api_key="sk-xxx")

query = "What is the weather like in Beijing?"
response = client.chat.completions.create(
        model="gpt-3.5-turbo-0613",
        messages=[{"role": "user", "content": query}],
        functions=functions
    )
message = response.dict()["choices"][0]["message"]
print(message)

>>> {'content': None, 'role': 'assistant', 'function_call': {'arguments': '{\n  "city": "Beijing"\n}', 'name': 'get_weather_info'}, 'tool_calls': None}

此时我们看到了令人吃惊的输出,大模型的输出内容为空,而判断需要function calling, 函数名称为get_weather_info,参数为{'arguments': '{\n "city": "Beijing"\n}

下一步,我们可以调用该函数,传入参数,得到函数输出,并再次调用大模型得到答案回复。

func_name = message["function_call"]["name"]
func_args = json.loads(message["function_call"]["arguments"])
print("func name and args: ", func_name, func_args)
func_response = get_weather_info(**func_args)

final_response = client.chat.completions.create(
                model="gpt-3.5-turbo-0613",
                messages=[
                    {"role": "user", "content": query},
                    {"role": "assistant", "content": None, "function_call": message["function_call"]},
                    {
                        "role": "function",
                        "name": func_name,
                        "content": func_response
                    },
                ],
            )
print("answer: ", final_response.dict()["choices"][0]["message"]["content"])

输出结果如下:

func name and args:  get_weather_info {'city': 'Beijing'}
answer:  The weather in Bei
### 如何在 DeepSeek 中调用外部函数 为了理解如何在 DeepSeek 中调用外部函数,可以借鉴其他平台和工具链中的实现方式。通常情况下,在集成不同编程环境的功能时,主要依赖于特定的语言绑定或接口机制。 #### 利用语言互操作性特性 对于像 C 和 C++ 这样的低级语言,可以通过 `extern "C"` 来确保名称不会被修饰,从而允许从其他模块访问这些函数[^1]。这同样适用于任何支持此特性的高级框架或库,包括可能用于构建 DeepSeek 的组件。 当涉及到更复杂的场景,比如将 Python 或 JavaScript 函数封装到另一个环境中执行时,则需考虑使用相应的桥接技术或是 API 接口来完成跨语言调用。例如,在 Flutter 应用程序中利用 Firebase Cloud Functions 调用 OpenAI API 就是一个很好的例子[^3]。 #### 创建适配层 如果目标是在 DeepSeek 内部调用来自另一种语言编写的外部功能,那么创建一个中间件可能是必要的解决方案之一。这个中间件负责处理两种运行时之间的通信协议转换工作,并提供简单易用的方法给开发者去间接地调用那些原本不属于当前系统的资源和服务。 具体来说: - 对于静态链接库形式存在的 C/C++ 代码片段,可以直接引入并声明其原型定义; - 如果是动态加载类型的共享对象文件 (.so),则可通过 dlopen() 系列函数获取句柄进而定位所需符号地址; - 面向 WebAssembly (Wasm) 输出的目标产物,可借助 WASI 标准或其他类似的沙盒化方案来进行交互操作。 ```cpp // 假设有一个名为 'my_function' 的 C 函数存在于某个 .so 文件里 void* handle = dlopen("./libexample.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "%s\n", dlerror()); exit(EXIT_FAILURE); } typedef void (*func_ptr)(); *(func_ptr*)(&my_function) = dlsym(handle, "my_function"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } (*my_function)(); dlclose(handle); ``` 上述代码展示了如何在一个 POSIX 兼容的操作系统上打开一个已编译好的动态链接库,并从中提取指定名字的过程入口点以便后续调用[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值