AI大模型探索之路-实战篇6: Function Calling技术调研之详细流程剖析

news2024/11/16 19:48:38

系列篇章💥

AI大模型探索之路-实战篇4:DB-GPT数据应用开发框架调研实践
AI大模型探索之路-实战篇5: Open Interpreter开放代码解释器调研实践


目录

  • 系列篇章💥
  • 一、前言
  • 二、Function Calling详细流程剖析
    • 1、创建OpenAI客户端
    • 2、定义函数
    • 3、创建数据参数对象
    • 4、对象转化
    • 5、函数调用测试
    • 6、定义工具函数
    • 7、发送OpenAI 对话请求测试
    • 8、指定工具函数进行调用
    • 9、存储返回的结果信息
    • 10、查看函数名称和参数
    • 11、调用工具函数
    • 12、将第一次返回的结果合并到消息列表
    • 13、将functiona的信息合并到消息列表
    • 14、第二次OpenAI API调用
  • 三、Function Calling完整样例
  • 四、结语


一、前言

继之前对DB-GPT和Open Interpreter技术的深入调研,本文将转向对OpenAI的Function Calling技术进行回顾与探讨。此次分析的目的旨在为即将到来的智能数据分析平台的顺利落地做好充分的技术储备。通过对Function Calling技术的深度剖析,我们希望建立更加坚实的理论基础,并在此基础上探索其在实际应用中的潜在价值和实施路径。这将不仅有助于我们更好地理解语言模型如何与程序代码交互,而且为未来的开发工作提供指导和灵感。

二、Function Calling详细流程剖析

本章节旨在深入剖析从OpenAI客户端的创建到数据参数的定义,再到函数的定义、调用以及最终结果的整理输出的完整过程。这一详尽的解析将帮助我们深入理解Function Calling技术的每一个细节和实际应用中的操作流程。

1、创建OpenAI客户端

首先,我们需要创建一个有效的OpenAI客户端。这包括获取必要的API密钥和配置环境参数。通过这个过程,我们可以确保在后续步骤中顺畅地与OpenAI的服务器进行通信。

import openai
import os
import numpy as np
import pandas as pd
import json
import io
from openai import OpenAI
import inspect

# 从环境变量中获取OpenAI API密钥
openai.api_key = os.getenv("OPENAI_API_KEY")

# 使用API密钥创建OpenAI客户端实例
client = OpenAI(api_key=openai.api_key)

2、定义函数

定义了一个名为sunwukong_function的函数,该函数接受一个字符串类型的数据集作为参数,并将其转换为pandas DataFrame对象。然后,它将DataFrame中的每个元素乘以10,并将结果转换为JSON格式的字符串返回。

def sunwukong_function(data):
    """
    孙悟空算法函数,该函数定义了数据集计算过程
    :param data: 必要参数,表示带入计算的数据表,用字符串进行表示
    :return:sunwukong_function函数计算后的结果,返回结果为表示为JSON格式的Dataframe类型对象
    """
    data = io.StringIO(data)
    df_new = pd.read_csv(data, sep='\s+', index_col=0)
    res = df_new * 10
    return json.dumps(res.to_string())

3、创建数据参数对象

接下来,我们需要定义数据参数。这些参数将作为输入传递给Function Call函数,以生成相应的输出结果。在本例中,我们将使用一个简单的数学计算任务作为示例。

#创建了一个名为df的DataFrame对象,其中包含两列数据x1和x2。
df = pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]})
df

输出
在这里插入图片描述

4、对象转化

#将df对象转换为字符串类型。

df_str = df.to_string()
df_str

输出
在这里插入图片描述

5、函数调用测试

#将df字符串传递给sunwukong_function函数进行计算。最后,它将计算结果打印出来。

result_json=sunwukong_function(df_str)
result_json

在这里插入图片描述

6、定义工具函数

# 定义一个工具函数
sunwukong={
        "type": "function",
        "function": {"name": "sunwukong_function",
                      "description": "用于执行孙悟空算法函数,定义了一种特殊的数据集计算过程",
                      "parameters": {"type": "object",
                                     "properties": {"data": {"type": "string",
                                                             "description": "执行孙悟空算法的数据集"},
                                                   },
                                     "required": ["data"],
                                    },
                     }
    }
# 放入工具列表
tools = [sunwukong]

7、发送OpenAI 对话请求测试

我们通过大模型的对话请求API进行确认,大模型是否能能正确找到对应的函数工具。

# 这段代码定义了一个名为messages的列表,其中包含两个字典对象。第一个字典对象表示系统角色,其内容为数据集data的描述信息;第二个字典对象表示用户角色,其内容为执行孙悟空算法的请求。
messages=[
    {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
    {"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]
# 使用OpenAI API中的chat.completions.create方法来生成响应。该方法接受两个参数:model和messages。model参数指定要使用的模型版本,这里使用的是gpt-3.5-turbo模型;messages参数是要发送给API的消息列表,这里传入的是前面定义的messages列表。

response =  client.chat.completions.create(
  model="gpt-3.5-turbo",
  messages=messages
)
# 从响应中提取出第一个选择的消息,并将其打印出来。这个消息应该是由API根据输入的数据集和请求生成的孙悟空算法的结果。
response.choices[0].message

输出:

ChatCompletionMessage(content='抱歉,我不清楚您指的“孙悟空算法”是什么意思。请问您能提供更多关于该算法的背景或者说明吗?这样我才能帮助您更好地实现您的目标。', role='assistant', function_call=None, tool_calls=None)

当前对话中没有设置工具函数,因此大模型并没有找到自定义的工具函数

8、指定工具函数进行调用

我们再次进行大模型API调用,这一次我们指定功能工具函数tools,设置为自动选择(tool_choice=“auto”,)让模型自己检查判断是否需要调用工具函数。

messages=[
    {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
    {"role": "user", "content": "请在数据集data上执行孙悟空算法"}
]
# 重新初始化消息列表后,设置tools参数和tool_choice,让大模型自己选择是否使用工具
# 不会直接执行function_call函数。这段代码是调用OpenAI API的chat.completions.create方法,用于生成聊天机器人的回答。其中,model参数指定了使用的模型版本,messages参数传入了要发送给API的消息列表,tools参数传入了工具列表,tool_choice参数指定了选择工具的方式。
response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
        tools=tools,
        tool_choice="auto",  
    )
# 查看消息结果,返回内容为空,但是找到返回了工具函数
response.choices[0].message

输出:

ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1  x2\\n0   1   3\\n1   2   4"}', name='sunwukong_function'), type='function')])

从输出结果可以看到,工具配置生效,大模型已经找到了工具函数

9、存储返回的结果信息

将结果信息存储到first_response

# 打印出消息,可以看到消息中已经找到了函数sunwukong_function
first_response = response.choices[0].message
first_response

输出:

ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1  x2\\n0   1   3\\n1   2   4"}', name='sunwukong_function'), type='function')])

查看结果信息中的工具信息

response.choices[0].message.tool_calls

输出:

[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1  x2\\n0   1   3\\n1   2   4"}', name='sunwukong_function'), type='function')]

10、查看函数名称和参数

将工具函数放入到字典中,再循环获取到工具列表中的每一个函数的名称,参数

#定义了一个名为available_tools的字典,其中包含了可用的工具函数
available_tools =  {
    "sunwukong_function": sunwukong_function,
}
#从API返回的回答中提取出工具调用信息,并遍历每个工具调用。对于每个工具调用,获取函数名、函数参数,并使用这些信息调用相应的工具函数。
tool_calls = response.choices[0].message.tool_calls
 
for tool_call in tool_calls:
    function_name = tool_call.function.name
    function_to_call = available_tools[function_name]
    function_args = json.loads(tool_call.function.arguments)
    function_response = function_to_call(**function_args)
 
# 打印出函数名、函数参数和函数响应。
print(function_name)
print(function_args)
print(function_response)

输出:
在这里插入图片描述

11、调用工具函数

#调用工具函数并获取其响应。它首先使用工具函数名和参数调用相应的工具函数,并将返回值存储在名为function_response的变量中。然后打印出这个响应
function_response = function_to_call(**function_args)
function_response

输出:
在这里插入图片描述

12、将第一次返回的结果合并到消息列表

# 追加第一次模型返回结果消息
messages.append(first_response)  
messages

输出:

[{'role': 'system',
  'content': '数据集data:   x1  x2\n0   1   3\n1   2   4,数据集以字符串形式呈现'},
 {'role': 'user', 'content': '请在数据集data上执行孙悟空算法'},
 ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1  x2\\n0   1   3\\n1   2   4"}', name='sunwukong_function'), type='function')])]

13、将functiona的信息合并到消息列表

# 追加function返回消息
messages.append(
        {
            "tool_call_id": tool_call.id,
            "role": "tool",
            "name": function_name,
            "content": function_response,
        }
)
messages

输出:

[{'role': 'system',
  'content': '数据集data:   x1  x2\n0   1   3\n1   2   4,数据集以字符串形式呈现'},
 {'role': 'user', 'content': '请在数据集data上执行孙悟空算法'},
 ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_z16cI8SX4FkoW71SNV95hjIL', function=Function(arguments='{"data":"x1  x2\\n0   1   3\\n1   2   4"}', name='sunwukong_function'), type='function')]),
 {'tool_call_id': 'call_z16cI8SX4FkoW71SNV95hjIL',
  'role': 'tool',
  'name': 'sunwukong_function',
  'content': '"   x1  x2\\n0  10  30\\n1  20  40"'}]

14、第二次OpenAI API调用

第二次调用大模型API,让大模型帮忙整理响应信息

# 再次调用,由大模型重新整理工具函数返回的结果信息(主要是将结果信息整理的更加方便可视化)
second_response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=messages,
)
 

print(second_response.choices[0].message.content)

在这里插入图片描述

三、Function Calling完整样例

完整的Function Calling函数使用代码如下

from openai import OpenAI
import json

openai.api_key = os.getenv("OPENAI_API_KEY")

client = OpenAI(api_key=openai.api_key)

# Example dummy function hard coded to return the same weather
# In production, this could be your backend API or an external API
def sunwukong_function(data):
    """
    孙悟空算法函数,该函数定义了数据集计算过程
    :param data: 必要参数,表示带入计算的数据表,用字符串进行表示
    :return:sunwukong_function函数计算后的结果,返回结果为表示为JSON格式的Dataframe类型对象
    """
    data = io.StringIO(data)
    df_new = pd.read_csv(data, sep='\s+', index_col=0)
    res = df_new['x1'] * 10
    return json.dumps(res.to_string())


df_str=pd.DataFrame({'x1':[1, 2], 'x2':[3, 4]}).to_string

def run_conversation():
    # 步骤1:将对话和可用函数发送给模型
    messages=[
    {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
    {"role": "user", "content": "请在数据集data上执行孙悟空算法"}  
        ]
    tools = [
    {
        "type": "function",
        "function": {"name": "sunwukong_function",
                      "description": "用于执行孙悟空算法函数,定义了一种特殊的数据集计算过程",
                      "parameters": {"type": "object",
                                     "properties": {"data": {"type": "string",
                                                             "description": "执行孙悟空算法的数据集"},
                                                   },
                                     "required": ["data"],
                                    },
                     }
    }]

    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
        tools=tools,
        tool_choice="auto",  # auto is default, but we'll be explicit
    )
    response_message = response.choices[0].message
    tool_calls = response_message.tool_calls
    # 步骤2:检查模型是否想要调用函数
    if tool_calls:
        # 步骤3:调用函数
        # 注意:JSON响应可能不总是有效的;确保处理错误
        available_functions = {
            "sunwukong_function": sunwukong_function,
        }  # 这个例子中只有一个函数,但您可以有多个函数
        messages.append(response_message)  # 将助手的回复扩展到对话中
        # 步骤4:将每个函数调用和函数响应的信息发送给模型
        for tool_call in tool_calls:
            function_name = tool_call.function.name
            function_to_call = available_functions[function_name]
            function_args = json.loads(tool_call.function.arguments)
            function_response = function_to_call(**function_args)
            messages.append(
                {
                    "tool_call_id": tool_call.id,
                    "role": "tool",
                    "name": function_name,
                    "content": function_response,
                }
            )  # 将函数响应扩展到对话中
        second_response = client.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=messages,
        )  # 从模型获取新的响应,其中可以看到函数响应
        return second_response
result=run_conversation()
result.choices[0].message.content

输出:
在这里插入图片描述

# 使用StringIO将字符串转换为文件对象
df_str='\\n    x1\\n0  10\\n1  20\\n.'
data = io.StringIO(df_str)

# 使用read_csv()函数读取数据,并设置第一列为索引
df_new = pd.read_csv(data, sep='\s+', index_col=0)
df_new

输出:
在这里插入图片描述

四、结语

本文深入探讨了函数调用的全过程,详细阐述了其每一个细节步骤。在回顾函数调用的实践应用中,我们不仅加深了对其运作机制的理解,还体会到了其在编程实践中的强大功能和灵活性。通过逐步剖析与实际操作的结合,本文档旨在为读者提供一个全面而实用的指南,以促进对函数调用概念的掌握及其在实际编程中的应用。希望读者能够借此更好地利用函数调用,优化代码结构,提升开发效率。

在这里插入图片描述

🎯🔖更多专栏系列文章:AIGC-AI大模型探索之路

如果文章内容对您有所触动,别忘了点赞、⭐关注,收藏!加入我,让我们携手同行AI的探索之旅,一起开启智能时代的大门!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1693130.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

infoq读书笔记-Davide Taibi博士-花8年转型微服务却得不到回报,问题出在哪 儿?

InfoQ:您的论文“On the Definition of Microservice Bad Smells”涉及非常多的微服务不良做法,但如果要用几个大类别来列举危害性比较大的微服务反模式,您认为会是哪几类?另外,您能再大概分析说明下造成这个几个反模式…

《计算机网络微课堂》1-2:因特网概述

1-2:因特网概述 网络、互连网(互联网)和因特网因特网发展的三个阶段因特网的标准化工作因特网的组成 ‍ 网络、互连网(互联网)和因特网 我们首先介绍网络、互联网(互连网)因特网的基本概念&a…

c语言——宏offsetof

1.介绍 !!! offsetof 是一个宏 2.使用举例 结构体章节的计算结构体占多少字节需要先掌握(本人博客结构体篇章中已经讲解过) 计算结构体中某变量相对于首地址的偏移,并给出说明 首先,结构体首个…

MyBatis常见报错:org.apache.ibatis.binding.BindingException

哈喽,大家好,我是木头左! 异常现象描述 当开发者在使用MyBatis进行数据库操作时,可能会遇到org.apache.ibatis.binding.BindingException: Parameter appId not found这样的错误提示。这个错误通常会让程序无法正常运行&#xff…

如何在华为手机上恢复已删除的视频[4种解决方案]

概括 在数字媒体时代,智能手机已成为我们的个人金库,存储以视频形式捕捉的珍贵记忆。然而,意外删除这些珍贵的文件可能会是一次令人心痛的经历。对于华为手机用户来说,由于删除或其他意外导致视频丢失尤其令人痛苦。但不用担心&a…

cadence23---PCB Editer 学习笔记

1.交互式布局 在Orcad中点击图标N生成第一网表: 在PCB Editer中导入第一网表, 之后点击移动命令并在右侧属性框中勾选Symbol选项卡: 设置--应用模式--点击常规编辑: 之后就可以进行交互式选择了。 绿色图标为打开全部飞线&#…

【Spring Security + OAuth2】OAuth2

Spring Security OAuth2 第一章 Spring Security 快速入门 第二章 Spring Security 自定义配置 第三章 Spring Security 前后端分离配置 第四章 Spring Security 身份认证 第五章 Spring Security 授权 第六章 OAuth2 文章目录 Spring Security OAuth21、OAuth2简介1.1、OAu…

力扣:92. 反转链表 II(Java)

目录 题目描述&#xff1a;示例 1&#xff1a;示例 2&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的…

刷代码随想录有感(78):回溯算法——关于树枝/树层去重的思考(涉及break/continue的使用)

在复原IP地址中&#xff0c;剪枝操作我们使用的是break: if(isvalid(s, start, i)){s.insert(s.begin() i 1, .);pointNum;backtracking(s, i 2, pointNum);s.erase(s.begin() i 1);pointNum--; }else break;在其他情况&#xff0c;举个例子&#xff0c;在含有重复元素求…

WiFi蓝牙模块开发配置过程中需要注意的细节

在很多产品的应用场景中&#xff0c;WIFI网络会给我们提供很多便捷&#xff0c;MCU开发中大多使用串口WIFI蓝牙模块来实现产品接入WIFI网络中。   具体的使用模型如下图所示&#xff1a;整个系统涉及到WIFI网络、手机、服务器平台以及我们设计的产品&#xff0c;一个完整的生…

第十一课,end关键字、简单while循环嵌套、初识for循环

一&#xff0c;end关键字 end关键字用于在print输出的内容后面声明结束的字符&#xff0c;我们之前学过并且十分了解print是默认输出内容之后跟着换行的&#xff0c;如果我们不希望换行而希望使用其它字符来代替换行&#xff0c;就可以用end关键字来实现 特殊的&#xff0c;en…

使用elementUI的form表单校验时,错误提示位置异常解决方法

问题 最近在做项目时遇到一个问题&#xff0c;使用elementUI的Descriptions 描述列表与form表单校验时&#xff0c;遇到校验信息显示的位置不对&#xff0c;效果如图&#xff1a; 期望显示在表格中。 效果 代码 html <el-form :model"form":rules"rules…

原始字面常量(C++11)

原始字面常量&#xff08;C11&#xff09; 文章目录 原始字面常量&#xff08;C11&#xff09;前言一、原始字面量二、代码示例总结 前言 字面量一般是指数值&#xff08;12、454等&#xff09;和字符串&#xff08;“Hw”、“h\t”&#xff09;&#xff0c;但是有时候我们想表…

用栈实现队列(C语言)

目录 题目题目分析 代码栈的实现结构体。栈的初始化栈的销毁 入栈删除查找顶部数据判空 答案结构体初始化插入数据删除数据获取队列开头元素判空销毁栈 题目 题目分析 链接: 题目 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;push、po…

MyBatis 学习笔记(一)

MyBatis 封装 JDBC :连接、访问、操作数据库中的数据 MyBatis 是一个持久层框架。 MyBatis 提供的持久层框架包括 SQLMaps 和 Data Access Objects&#xff08;DAO&#xff09; SQLMaps&#xff1a;数据库中的数据和 Java数据的一个映射关系 封装 JDBC 的过程Data Access Ob…

使用xxl-job-executor-go 接入xxl-job实现定时任务调度

定时任务是软件开发中很常见的一种处理业务的机制&#xff0c;xxl-job是近些年比较火的定时任务调用组件&#xff0c;其采用java 实现&#xff0c;是一个高可用&#xff0c;分布式调用的组件&#xff0c;还支持多种定时任务有关的特性&#xff0c;不仅能轻易的用java 客户端接入…

ChatGPT可以开车吗?分享大型语言模型在自动驾驶方面的应用案例

自动驾驶边缘案例需要复杂的、类似人类的推理&#xff0c;远远超出传统的算法和人工智能模型。而大型语言模型正在致力实现这一目标。 人工智能技术如今正在快速发展和应用&#xff0c;人工智能模型也是如此。拥有100亿个参数的通用模型的性能正在碾压拥有5000万个参数的任务特…

Pytorch-01 框架简介

智能框架概述 人工智能框架是一种软件工具&#xff0c;用于帮助开发人员构建和训练人工智能模型。这些框架提供了各种功能&#xff0c;如定义神经网络结构、优化算法、自动求导等&#xff0c;使得开发人员可以更轻松地实现各种人工智能任务。通过使用人工智能框架&#xff0c;…

【云原生】用 Helm 来简化 K8s 应用管理

用 Helm 来简化 K8s 应用管理 1.诞生背景2.主要功能3.相关概念4.工作原理5.架构演变6.Helm 常用命令7.推荐仓库8.Charts8.1 目录结构8.2 构建一个无状态应用模版 charts Helm 对于 Kubernetes 来说就相当于 Yum 对于 Centos 来说&#xff0c;如果没有 Yum 的话&#xff0c;我们…