AI大模型探索之路-实战篇8:多轮对话与Function Calling技术应用

news2024/11/15 8:33:39

系列篇章💥

AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研
AI大模型探索之路-实战篇5:探索Open Interpreter开放代码解释器调研
AI大模型探索之路-实战篇6:掌握Function Calling的详细流程
AI大模型探索之路-实战篇7:Function Calling技术实战自动生成函数


目录

  • 系列篇章💥
  • 一、前言
  • 二、封装调用2轮response的函数
    • 1、输出函数列表
    • 2、function函数调用封装
    • 3、定义参数数据
    • 4、测试函数tangseng_function
    • 5、测试函数sunwukong_function
    • 6、测试函数(描述中不指明信息)
  • 三、增加多轮对话的效果
    • 1、创建OpenAI客户端
    • 2、定义工具函数
    • 3、定义函数生成器
    • 4、封装大模型2次API调用
    • 5、多轮对话函数定义
    • 6、函数列表定义
    • 7、对话调用测试
  • 四、结语


一、前言

继前文深入探讨了Function Calling的操作流程并成功实验自动生成function函数之后,本文将进一步深化我们的研究,具体考察OpenAI的Function Calling技术在现实应用中的表现。此次研究的重点在于封装一个能够调用两轮response的函数,并在此基础上执行多轮对话的测试,从而全面评估该技术在实际应用中的效率和效果。

通过精心设计的实验,我们将探索这项技术的潜力及其在智能数据分析平台上的应用前景。我们的目标是为平台的顺利实施构建一个稳固且高效的技术基础。这不仅涉及到技术层面的优化,也关系到如何在实际应用中提供更流畅的用户体验和更准确的数据处理能力。

在本文中,我们将详细阐述这一过程的每个步骤,从技术选型到功能实现,再到最终的效果评估。我们希望通过对OpenAI的Function Calling技术的深入分析和应用展示,为未来相关技术的发展和应用场景的拓展提供有益的参考和启示。

二、封装调用2轮response的函数

在实现function call的过程中,我们通常需要进行两次关键的调用。
1)第一次调用:目的是让强大的大型模型协助我们识别并选择恰当的工具函数。这就像在进行一场棋局,首先需要确定使用哪个棋子。一旦选定,接下来的步骤便是实际调用该工具函数,执行具体的任务。
2)第二次调用:这一次,我们再次借助大模型的强大能力,其任务是将工具函数处理后的结果进行整合和优化,以最清晰、最易于理解的形式呈现最终输出。这可以比喻为将散落的珠子串成一串光彩夺目的项链,使其更具有观赏价值和实用价值。

在本章节中,我们将重点介绍如何将这两阶段的调用过程进行有效的封装,使其成为一个独立、可复用的模块。这种封装不仅简化了操作流程,还提高代码的可维护性和扩展性,为未来的功能拓展或技术升级提供了便利。

1、输出函数列表

继上文中,我们定义了2个工具函数

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())

#在定义一个工具函数,一起测试
def tangseng_function(data):
    """
    唐僧算法函数,该函数定义了数据集计算过程
    :param data: 必要参数,表示带入计算的数据表,用字符串进行表示
    :return:tangseng_function函数计算后的结果,返回结果为表示为JSON格式的Dataframe类型对象
    """
    data = io.StringIO(data)
    df_new = pd.read_csv(data, sep='\s+', index_col=0)
    res = df_new * 1000000
    return json.dumps(res.to_string())
    
# 将2个函数放入函数列表
functions_list=[sunwukong_function,tangseng_function]

输出函数列表:

functions_list

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

2、function函数调用封装

def run_conversation(messages, functions_list=None, model="gpt-3.5-turbo"):
    """
    能够自动执行外部函数调用的对话模型
    :param messages: 必要参数,字典类型,输入到Chat模型的messages参数对象
    :param functions_list: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象
    :param model: Chat模型,可选参数,默认模型为gpt-3.5-turbo
    :return:Chat模型输出结果
    """
    # 如果没有外部函数库,则执行普通的对话任务
    if functions_list == None:
        response = client.chat.completions.create(
                        model=model,
                        messages=messages,
                        )
        response_message = response.choices[0].message
        final_response = response_message.content
        
    # 若存在外部函数库,则需要灵活选取外部函数并进行回答
    else:
        # 创建functions对象
        tools = auto_functions(functions_list)

        # 创建外部函数库字典
        available_functions = {func.__name__: func for func in functions_list}

        # 第一次调用大模型,寻找工具函数
        response = client.chat.completions.create(
                        model=model,
                        messages=messages,
                        tools=tools,
                        tool_choice="auto", )
        response_message = response.choices[0].message


        tool_calls = response_message.tool_calls

        if tool_calls:

            messages.append(response_message) 
            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=model,
                messages=messages,
            ) 
            # 获取最终结果
            final_response = second_response.choices[0].message.content
        else:
            final_response = response_message.content
                
    return final_response

3、定义参数数据

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

在这里插入图片描述

4、测试函数tangseng_function

# 定义消息列表
messages = [
        {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
        {"role": "user", "content": '请在data上执行唐僧算法函数'}]


# API调用测试
run_conversation(messages = messages, functions_list = functions_list)

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

5、测试函数sunwukong_function

# 定义消息列表
messages = [
        {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
        {"role": "user", "content": '请在data上执行孙悟空算法函数'}]

# API调用测试
run_conversation(messages = messages, functions_list = functions_list)

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

6、测试函数(描述中不指明信息)

# 定义消息列表
messages = [
        {"role": "system", "content": "数据集data:%s,数据集以字符串形式呈现" % df_str},
        {"role": "user", "content": '请解释一下data数据集'}]

# API调用测试
run_conversation(messages = messages, functions_list = functions_list)

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

根据结果可以看出,大模型并没有成功调用工具函数

三、增加多轮对话的效果

在实现function call技术的过程中,我们不仅需要关注单次调用的优化,还需要注重多轮对话的效果。本章节将介绍如何通过引入两个工具函数,来测试大型模型在面对涉及工具函数的问题时,是否能准确识别并调用相应的工具。

1、创建OpenAI客户端

import openai
import os
import numpy as np
import pandas as pd
import json
import io
from openai import OpenAI
import inspect
# 定义api key
openai.api_key = os.getenv("OPENAI_API_KEY")

#创建OpenAI客户端
client = OpenAI(api_key=openai.api_key )

2、定义工具函数

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

3、定义函数生成器

def auto_functions(functions_list):
    """
    Chat模型的functions参数编写函数
    :param functions_list: 包含一个或者多个函数对象的列表;
    :return:满足Chat模型functions参数要求的functions对象
    """
    def functions_generate(functions_list):
        # 创建空列表,用于保存每个函数的描述字典
        functions = []
        # 对每个外部函数进行循环
        for function in functions_list:
            # 读取函数对象的函数说明
            function_description = inspect.getdoc(function)
            # 读取函数的函数名字符串
            function_name = function.__name__

            system_prompt = '以下是某的函数说明:%s' % function_description
            user_prompt = '根据这个函数的函数说明,请帮我创建一个JSON格式的字典,这个字典有如下5点要求:\
                           1.字典总共有三个键值对;\
                           2.第一个键值对的Key是字符串name,value是该函数的名字:%s,也是字符串;\
                           3.第二个键值对的Key是字符串description,value是该函数的函数的功能说明,也是字符串;\
                           4.第三个键值对的Key是字符串parameters,value是一个JSON Schema对象,用于说明该函数的参数输入规范。\
                           5.输出结果必须是一个JSON格式的字典,只输出这个字典即可,前后不需要任何前后修饰或说明的语句' % function_name

            response = client.chat.completions.create(
                              model="gpt-3.5-turbo",
                              messages=[
                                {"role": "system", "content": system_prompt},
                                {"role": "user", "content": user_prompt}
                              ]
                            )
            json_function_description=json.loads(response.choices[0].message.content.replace("```","").replace("json",""))
            json_str={"type": "function","function":json_function_description}
            functions.append(json_str)
        return functions
    ## 最大可以尝试4次
    max_attempts = 4
    attempts = 0

    while attempts < max_attempts:
        try:
            functions = functions_generate(functions_list)
            break  # 如果代码成功执行,跳出循环
        except Exception as e:
            attempts += 1  # 增加尝试次数
            print("发生错误:", e)
            if attempts == max_attempts:
                print("已达到最大尝试次数,程序终止。")
                raise  # 重新引发最后一个异常
            else:
                print("正在重新运行...")
    return functions

4、封装大模型2次API调用

def run_conversation(messages, functions_list=None, model="gpt-3.5-turbo"):
    """
    能够自动执行外部函数调用的对话模型
    :param messages: 必要参数,字典类型,输入到Chat模型的messages参数对象
    :param functions_list: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象
    :param model: Chat模型,可选参数,默认模型为gpt-3.5-turbo
    :return:Chat模型输出结果
    """
    # 如果没有外部函数库,则执行普通的对话任务
    if functions_list == None:
        response = client.chat.completions.create(
                        model=model,
                        messages=messages,
                        )
        response_message = response.choices[0].message
        final_response = response_message.content
        
    # 若存在外部函数库,则需要灵活选取外部函数并进行回答
    else:
        # 创建functions对象
        tools = auto_functions(functions_list)

        # 创建外部函数库字典
        available_functions = {func.__name__: func for func in functions_list}

        # 第一次调用大模型
        response = client.chat.completions.create(
                        model=model,
                        messages=messages,
                        tools=tools,
                        tool_choice="auto", )
        response_message = response.choices[0].message


        tool_calls = response_message.tool_calls

        if tool_calls:

            messages.append(response_message) 
            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=model,
                messages=messages,
            ) 
            # 获取最终结果
            final_response = second_response.choices[0].message.content
        else:
            final_response = response_message.content
                
    return final_response

5、多轮对话函数定义

def chat_with_model(functions_list=None, 
                    prompt="你好", 
                    model="gpt-3.5-turbo", 
                    system_message=[{"role": "system", "content": "你是小智助手。"}]):
    
    messages = system_message
    messages.append({"role": "user", "content": prompt})
    
    while True:           
        answer = run_conversation(messages=messages, 
                                    functions_list=functions_list, 
                                    model=model)
        
        print(f"智能助手回答: {answer}")
        
        
        # 询问用户是否还有其他问题
        user_input = input("您还有其他问题吗?(输入退出以结束对话): ")
        if user_input == "退出":
            break

        # 记录用户回答
        messages.append({"role": "user", "content": user_input})

6、函数列表定义

functions_list=[sunwukong_function,tangseng_function]

7、对话调用测试

chat_with_model(functions_list,prompt="你好")

gpt3.5生成json schema还是会不太稳定,经常会生成失败,如下:
在这里插入图片描述

调用成功效果如下:
在这里插入图片描述
以下是我测试的对话过程
问题1:你好
问题2:1+2
问题3:什么是孙悟空函数
问题4:数据集data以字符串形式呈现如下:’ x1 x2\n0 1 3\n1 2 4’,请在数据集data上执行孙悟空算法

智能助手回复结果如下:
在这里插入图片描述

四、结语

在本文中,我们深入探讨了function call技术中对大型模型API进行两次调用的进一步封装方法,并实践了这一方法以实现多轮对话的效果。通过精心设计的技术策略和实验,我们不仅优化了API调用流程,还成功地将这些技术应用于实际的对话场景中,使得交互更加流畅和自然。这一成果不仅展示了function call技术的高级应用,也为未来更复杂的应用场景提供了可能。

在这里插入图片描述

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

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

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

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

相关文章

一次编辑00

题目链接 一次编辑 题目描述 注意点 只能进行一次(或者零次)编辑 解答思路 首先判断两个字符串的长度&#xff0c;如果长度相差大于1&#xff0c;说明一次编辑无法通过一次编辑变换而来通过两个指针idx1和idx2指向first和second&#xff0c;初始idx1和idx2指向的都是同一个…

Android 系统日志(Log) JNI实现流程源码分析

1、JNI概述 Java Native Interface (JNI) 是一种编程框架&#xff0c;使得Java代码能够与用其他编程语言&#xff08;如C和C&#xff09;编写的本地代码进行交互。JNI允许Java代码调用本地代码的函数&#xff0c;也允许本地代码调用Java代码的函数。下面是对JNI机制的详细概述…

无人机助力光伏项目测绘建模

随着全球对可再生能源需求的不断增长&#xff0c;光伏项目作为其中的重要一环&#xff0c;其建设规模和速度都在不断提高。在这一背景下&#xff0c;如何高效、准确地完成光伏项目的测绘与建模工作&#xff0c;成为了行业发展的重要课题。近年来&#xff0c;无人机技术的快速发…

帝国CMS如何修改时间格式,变成几分钟,几小时教程

该插件已经在帝国cms6.6上测试通过&#xff0c;至于其他版本&#xff0c;请自行测试。 目前支持&#xff1a;标签模板&#xff0c;列表模板&#xff0c;内容模板 安装说明&#xff1a; 把以下的内容复制到 /e/class/userfun.php 文件里&#xff08;放在<?php和?>之间…

亚马逊云科技专家分享 | OPENAIGC开发者大赛能量加油站6月5日场预约开启~

由联想拯救者、AIGC开放社区、英特尔联合主办的“AI生成未来第二届拯救者杯OPENAIGC开发者大赛”自上线以来&#xff0c;吸引了广大开发者的热情参与。 为了向技术开发者、业务人员、高校学生、以及个体创业人员等参赛者们提供更充分的帮助与支持&#xff0c;AIGC开放社区特别…

eNSP华为模拟器-DHCP配置

拓扑图 要求 PC1通过DHCP获取192.168.1.1地址PC2和PC3通过DHCP接口地址池方式获取IP地址配置静态路由使其ping通 配置 配置主机名及接口IP地址 # AR1 <Huawei>sys Enter system view, return user view with CtrlZ. [Huawei]sys AR1 [AR1]int g0/0/0 [AR1-Gigabit…

『ZJUBCA Weekly Feed 07』MEV | AO超并行计算机 | Eigen layer AVS生态

一文读懂MEV&#xff1a;区块链的黑暗森林法则 01 &#x1f4a1;TL;DR 这篇文章介绍了区块链中的最大可提取价值&#xff08;MEV&#xff09;概念&#xff0c;MEV 让矿工和验证者通过抢先交易、尾随交易和三明治攻击等手段获利&#xff0c;但也导致网络拥堵和交易费用增加。为了…

微信小程序进阶(1)--自定义组件

自定义组件 1.1 什么是自定义组件 开发文档&#xff1a;https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/ 小程序中常常会有些通用的交互模块&#xff0c;比如&#xff1a;下拉选择列表、搜索框、日期选择器等&#xff1b;这些界面交互模块可…

c语言--结构体

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 结构体概念简介 c语言数组是一些相同类型的数据的集合。 这个结构体就是一些可以是不同类型的集合。 比如描述班里的一个人&#xff0c;他可能需要名字(字符串),也需要年龄(整数)。 这种情况就需要用结构体。 …

苹果手机备忘录共享到微信,为何显示不支持的类型

作为一名苹果手机用户&#xff0c;我深知其系统的流畅与便捷。然而&#xff0c;在日常使用中&#xff0c;我发现了一个令人不解的问题&#xff1a;为何苹果手机的原生备忘录无法直接分享到微信&#xff1f;每次当我尝试将备忘录里的内容共享给微信好友时&#xff0c;总会遇到“…

六西格玛培训的讲师应该具备哪些能力?

六西格玛培训的讲师作为专业知识的传授者和实践经验的分享者&#xff0c;其能力水平的高低直接决定了培训效果的好坏。那么&#xff0c;一个优秀的六西格玛培训讲师应该具备哪些能力呢&#xff1f;深圳天行健企业管理咨询公司解析如下&#xff1a; 首先&#xff0c;六西格玛培训…

AIGC行业的发展前景与市场需求

简介&#xff1a;探讨当前时机是否适合进入AIGC行业&#xff0c;考虑行业发展阶段和市场需求。 方向一&#xff1a;行业前景 AIGC&#xff08;人工智能生成内容&#xff09;行业是近年来随着人工智能技术的快速发展而兴起的一个新兴领域&#xff0c;它涉及到使用人工智能技术来…

R实验 随机变量及其分布

实验目的&#xff1a; 掌握常见几种离散性随机变量及其分布在R语言中对应的函数用法&#xff1b;掌握常见几种连续性随机变量及其分布在R语言中对应的函数用法&#xff1b;掌握统计量的定义及统计三大抽样分布在R语言中对应的函数用法。 实验内容&#xff1a; &#xff08;习题…

PyTorch的数据处理

&#x1f4a5;今天看一下 PyTorch数据通常的处理方法~ 一般我们会将dataset用来封装自己的数据集&#xff0c;dataloader用于读取数据 Dataset格式说明 &#x1f4ac;dataset定义了这个数据集的总长度&#xff0c;以及会返回哪些参数&#xff0c;模板&#xff1a; from tor…

element ui 的el-input输入一个字后失去焦点,需重新点击输入框才能再次输入!

解决方案&#xff1a; 我是form表单嵌套表格&#xff0c;里面的el-input输入框&#xff0c;输入第一个值的时候会突然失去焦点&#xff0c;需要再次点击输入框才能正常输入&#xff0c;原因是table的key值&#xff0c;需要改成正常的index即可&#xff0c;如果你是循环的&…

进化计算引领深度学习新纪元

《进化深度学习》介绍了进化计算(EC)&#xff0c;并为你提供了一套实用的技术工具&#xff0c;你可以在整个深度学习过程中应用这些技术。本书提供了遗传算法和进化计算方法在网络拓扑、生成模型、强化学习等方面的应用。通过交互式的Colab notebook使你有机会在探索过程中进行…

day15

第一题 1419. 数青蛙 本题主要是采用模拟的解题思路&#xff0c;用一个croak来模拟青蛙的叫声&#xff0c;在一堆字符串中来找到几个croak&#xff0c;并判断这是由几个青蛙叫的&#xff1b; 首先我们使用数组来模拟hash表&#xff0c;其次我们使用hash表来映射青蛙叫的字符中…

smart-link + STP的vlan映射 + monitor-link实现二层链路的负载均衡+主备切换

一、适用场景 1、保护原有投资&#xff0c;不浪费原有网络设备及链路的投资&#xff1b; 2、对高可靠、高可用要求的业务&#xff0c;链路中的设备、接头、线路故障时&#xff0c;毫秒级切换&#xff0c;不影响业务的运行&#xff1b; 3、使用华为、华三智能管理型的交换设备&…

香橙派 AIpro评测

一. 香橙派AIpro开箱 官网外观&#xff1a; ​ ​ 外观实测&#xff1a;做工精致&#xff0c;散热片有精致的金属感 ​ ​ 反面&#xff1a;由于加装了wifi蓝牙模块&#xff0c;如果需要做外壳&#xff0c;需要注意保护天线贴片。在树莓派pi5的前面一版&#xff0c;增加了wifi…

MedSegDiff: Medical Image Segmentation with Diffusion Probabilistic Model 论文总结

题目&#xff1a;MedSegDiff: Medical Image Segmentation&#xff08;图像分割&#xff09;with Diffusion Probabilistic Model&#xff08;扩散概率模型&#xff09; 论文&#xff08;MIDL会议&#xff09;&#xff1a;MedSegDiff: Medical Image Segmentation with Diffusi…