三、OpenAI之Function Calling实战

黑8决心将对 OpenAI API 的学习应用到更多实际场景中,以展示新时代技术的巨大潜力。在接下来的日子里,他不断探索和尝试,将 API 中的各种功能融入到不同的生活场景中,取得了一系列令人瞩目的成果。

首先,他将 OpenAI API 中的文本生成功能应用到了日常写作中。通过简单的 function calling,他可以请求 API 生成文章大纲、段落或完整的文章。例如,在准备一个关于项目的解决方案时,他使用 API 生成了一份生动而具有说服力的文章,引起了人们的关注和共鸣。

接着,他将 API 中的图像识别功能应用到了家庭生活中。通过 function calling,他可以上传家里的照片并请求 API 分析其中的内容。比如,当他的女儿画了一幅画作时,他使用 API 对画作进行分析,并得到了有关主题、色彩和风格的反馈,从而为女儿提供更专业的指导和建议。

此外,他还将 API 中的语言理解功能应用到了教育领域。通过 function calling,他可以向 API 提出问题并获得详细的解答,帮助孩子们更好地理解学习内容。比如,当他的儿子遇到数学难题时,他可以使用 API 进行智能辅导,为儿子提供个性化的学习支持。

随着时间的推移,黑8不断完善和拓展自己的应用案例,将 OpenAI API 的功能发挥到了极致。他的努力和成就得到了革委会的认可和赞赏,成为了新时代技术应用的典范。通过 function calling,他不仅改变了自己的生活方式,还为身边的人们带来了更多便利和惊喜,展示了科技的力量和魅力。

1. 接口(Interface)

两种常用接口:

  • 人机交互接口,User Interface(UI)
  • 应用程序编程接口,Application Programming Interface(API)

2. 接口的进化(Interface evolution)

UI进化的趋势:越来越适应人的习惯,越来越自然

  • 命令行:Command Line Interface(CLI) Dos,Unix/Linux shell,Windows Power Shell
  • 图形界面:Graphical User Interface(GUI)Windows,MacOS,IOS,Android
  • 语言界面:Conversational User Interface(CUL) Natural Language User Interface(NLUI)
  • 脑机接口:Brain Computer Interface(BCI)
    在这里插入图片描述
    API:
  • 从本地到远程,从同步到异步,媒介发生很多变化,但本质一直没有变:程序员的约定
  • 现在开始进化为自然语言接口,Natural Language Interface(NLI)

3. 自然语言接口(Natural Language Interface)

最自然的接口就是自然语言接口:
以前因为计算机处理不好自然语言,所以才有了那么多编程语言、接口、协议、界面风格。而且每一次进化,都是为了“更自然”,现在自然的终极时刻到来,大模型赋予计算机以“人类灵魂”,能和我们进行友好的沟通。

为什么要大模型连接外部世界?
大模型有两大缺陷:

  1. 并非知晓一切
    • 训练数据不可能什么都有。垂直、非公开数据欠缺
    • 不知道最新信息。大模型训练周期较长,且更新一次耗资巨大,还有越训练越傻的风险。中间会有延时、空档期。GPT-3.5 ,GPT-4 发布日期分别为:2022.1 和 2023.4
  2. 没有“真逻辑”
    表现出来的逻辑、推理,是文本的统计概率,而不是真正的逻辑

所以:大模型需要连接真实世界,对接真逻辑系统。

比如计算加法:

  • 把100以内的所有加法算式都训练给大模型,它就能回答100以内的加法
  • 如果超出100的加法,就不一定能算对了
  • 大模型并不懂加法,只是记住了100以内的加法算式的统计概率
  • 它是用字面意义做加法

4. OpenAI-Actions 接外部世界

第一次尝试用Plugins连接真实世界,产品不成功,原因:

  • 不在“场景”中,不能提供端到端的服务
  • 缺少“强Agetn”调度,只能手工选择3个plugin,使用成本太高
    第二次尝试升级为Actions,内置到GPTs中,解决了落地场景问题
    Actions工作流程:
    在这里插入图片描述

4.1 开发一个Action步骤

  • 创建一个应用的API接口
  • 以OpenAPI YAML或JSON格式记录API
  • 在ChatGPT UI中将schema传给GPT
    示例:
openapi: 3.0.1
info:title: TODO Actiondescription: An action that allows the user to create and manage a TODO list using a GPT.version: 'v1'
servers:- url: https://example.com
paths:/todos:get:operationId: getTodossummary: Get the list of todosresponses:"200":description: OKcontent:application/json:schema:$ref: '#/components/schemas/getTodosResponse'
components:schemas:getTodosResponse:type: objectproperties:todos:type: arrayitems:type: stringdescription: The list of todos.

4.2 Function Calling扩展

OpenAI GPTs

  1. 无需编程,就能定制个性对话机器人的平台
  2. 可以放入自己的知识库,实现 RAG(后面会讲)
  3. 可以通过 actions 对接专有数据和功能
  4. 内置 DALL·E 3 文生图和 Code Interpreter 能力
  5. 只有 ChatGPT Plus 会员可以使用

字节跳动 Coze

  1. 免费使用 GPT-4 等 OpenAI 的服务
  2. 只有英文界面,但其实对中文更友好
  3. Prompt 优化功能更简单直接

Dify

  1. 开源,中国公司开发
  2. 功能最丰富
  3. 可以本地部署,支持非常多的大模型
  4. 有 GUI,也有 API

有这类无需开发的工具,为什么还要学大模型开发技术呢?

  • 它们都无法针对业务需求做极致调优
  • 它们和其它业务系统的集成不是特别方便

Function Calling 技术可以把自己开发的大模型应用和其它业务系统连接。

4.3 Function Calling 的机制

在这里插入图片描述
注意: 接口里叫 tools,是从 functions 改的

4.3 Function Calling示例

调用本地函数

# 初始化
from openai import OpenAI
from dotenv import load_dotenv, find_dotenv
import os
import json_ = load_dotenv(find_dotenv())client = OpenAI()# 定义一个函数
def get_completion(messages, model="gpt-3.5-turbo"):response = client.chat.completions.create(model=model,messages=messages,temperature=0.7,  # 模型输出的随机性,0 表示随机性最小tools=[{  # 用 JSON 描述函数。可以定义多个。由大模型决定调用谁。也可能都不调用"type": "function","function": {"name": "sum","description": "加法器,计算一组数的和","parameters": {"type": "object","properties": {"numbers": {"type": "array","items": {"type": "number"}}}}}}],)return response.choices[0].message
from math import *prompt = "1+2+3...+99+100"messages = [{"role": "system", "content": "你是一个超级计算器"},{"role": "user", "content": prompt}
]
response = get_completion(messages)# 把大模型的回复加入到对话历史中
print(response)
messages.append(response)print('=====GPT回复=====', response)# 如果返回的是函数调用结果,则打印出来
if (response.tool_calls is not None):# 是否要调用 sumtool_call = response.tool_calls[0]print("=====函数调用=====", tool_call)if (tool_call.function.name == "sum"):# 调用 sumargs = json.loads(tool_call.function.arguments)result = sum(args["numbers"])# 打印函数调用结果print("=====函数返回=====", result)# 把函数调用结果加入到对话历史中messages.append({"tool_call_id": tool_call.id,  # 用于标识函数调用的 ID"role": "tool","name": "sum","content": str(result)  # 数值 result 必须转成字符串})# 再次调用大模型print("=====最终回复=====")print(get_completion(messages).content)

在这里插入图片描述
逻辑:

  • 定义调用OpenAI gpt-3.5-turbo模型的函数,增加tools参数,tools参数为JSON数组,JSON内容:type:function和function的JSON对象,function:描述name、description、parameters等
  • 定义提示词,第一次将提示词传给大模型gpt-3.5-turbo,模型根据提示词判断是否调用函数并做出响应
  • 如果需要调用函数,返回数据将含有重要参数:tool_calls,包含 ID和function描述,function中包含:arguments(参数)、name(参数名称)、type(类型function)
  • 将上步返回的结果:ID和调用参数的结果(result),追加到历史会话中,作为新的提示词。
  • 第二次传给大模型gpt-3.5-turbo
  • 大模型gpt-3.5-turbo根据历史提示词和调用函数的结果,给出新响应
注意:
  1. Function Calling 中的函数与参数的描述也是一种 Prompt
  2. 这种 Prompt 也需要调优,否则会影响函数的调用、参数的准确性,甚至让 GPT 产生幻觉

调用多个函数

定义返回奇、偶数函数,模型本身也具有区分能力,这里为了演示多函数调用,所以定义了两个具体函数

# 定义一个函数
def get_completion(messages, model="gpt-3.5-turbo"):response = client.chat.completions.create(model=model,messages=messages,temperature=0.7,  # 模型输出的随机性,0 表示随机性最小tools=[{  # 用 JSON 描述函数。可以定义多个。由大模型决定调用谁。也可能都不调用"type": "function","function": {"name": "getEvenNumber","description": "获得所有的偶数","parameters": {"type": "object","properties": {"numbers": {"type": "array","items": {"type": "number"}}}}}}, {"type": "function","function": {"name": "getOddNumber","description": "获得所有的奇数","parameters": {"type": "object","properties": {"numbers": {"type": "array","items": {"type": "number"}}}}}}],)return response.choices[0].message
# 返回所有偶数
def getEvenNumber(nums):if 0 == len(nums):return []new_nums = []for n in nums:if n % 2 == 0:new_nums.append(n)return new_nums# 返回所有奇数
def getOddNumber(nums):if 0 == len(nums):return []new_nums = []for n in nums:if n % 2 != 0:new_nums.append(n)return new_nums            
prompt = "1,2,3,4,5,6,7,8,9,10"messages = [{"role": "system", "content": "你是一个超级数学家,返回所有偶数"},{"role": "user", "content": prompt}
]
response = get_completion(messages)# 把大模型的回复加入到对话历史中
messages.append(response)print('=====GPT回复=====')
print(response)# 如果返回的是函数调用结果,则打印出来
while response.tool_calls is not None:for tool_call in response.tool_calls:# 是否要调用 函数args = json.loads(tool_call.function.arguments)result = Nonefunction_name = ""if tool_call.function.name == "getEvenNumber":# 调用 getEvenNumber        result = getEvenNumber(args["numbers"])function_name = "getEvenNumber"# 打印函数调用结果print("=====函数返回=====", result)elif tool_call.function.name == "getOddNumber":# 调用 getOddNumberresult = getOddNumber(args["numbers"])function_name = "getOddNumber"print("=====函数返回=====", result)# 把函数调用结果加入到对话历史中messages.append({"tool_call_id": tool_call.id,  # 用于标识函数调用的 ID"role": "tool","name": function_name,"content": str(result)  # 数值 result 必须转成字符串})response = get_completion(messages)messages.append(response)  # 把大模型的回复加入到对话中print("=====最终回复=====")
print(response.content)

返回偶数结果:
在这里插入图片描述

返回奇数结果:
在这里插入图片描述

Function Calling 获取JSON

def get_completion(messages, model="gpt-3.5-turbo"):response = client.chat.completions.create(model=model,messages=messages,temperature=0,  # 模型输出的随机性,0 表示随机性最小tools=[{"type": "function","function": {"name": "splitEvenAndOdd","description": "区分奇、偶数","parameters": {"type": "object","properties": {"even": {"type": "string","description": "奇数"},"odd": {"type": "string","description": "偶数"}}}}}],)return response.choices[0].messageprompt = "1,3,2,5,4,6,7,9,8,10"
messages = [{"role": "system", "content": "你是一个数学老师"},{"role": "user", "content": prompt}
]
response = get_completion(messages)
print("====GPT回复====")
print(response)
args = json.loads(response.tool_calls[0].function.arguments)
print("====函数参数====")
print(args)

在这里插入图片描述

查询数据库

从SQLite数据库获得数据
在这里插入图片描述

def get_table_names(conn):"""返回所有表名."""table_names = []tables = conn.execute("SELECT name FROM sqlite_master WHERE type='table';")for table in tables.fetchall():table_names.append(table[0])return table_namesdef get_column_names(conn, table_name):"""返回所有列名."""column_names = []columns = conn.execute(f"PRAGMA table_info('{table_name}');").fetchall()for col in columns:column_names.append(col[1])return column_namesdef get_database_info(conn):"""返回一个包含数据库中每个表的名字和列的字典列表。"""table_dicts = []for table_name in get_table_names(conn):columns_names = get_column_names(conn, table_name)table_dicts.append({"table_name": table_name, "column_names": columns_names})return table_dictsdatabase_schema_dict = get_database_info(conn)
database_schema_string = "\n".join([f"Table: {table['table_name']}\nColumns: {', '.join(table['column_names'])}"for table in database_schema_dict # 构造表名和列名字符数组]
)

和之前一样,我们为函数调用定义一个函数规范,让模型API生成参数。请注意:我们要插入数据库的模型到函数规范中。让模型知道这一点很重要:

tools = [{"type": "function","function": {"name": "ask_database","description": "使用这个函数回答用户关于音乐的问题. 输入为格式化好的SQL语句.","parameters": {"type": "object","properties": {"query": {"type": "string","description": f"""通过SQL查询提取用户问题的答案。SQL语句应该使用这个数据库模式:{database_schema_string}查询结果应该以纯文本形式返回,而不是JSON格式。""",}},"required": ["query"],},}}
]

执行SQL查询

messages = []
messages.append({"role": "system", "content": "通过chinook音乐数据库生成SQL查询来回答用户问题"})
messages.append({"role": "user", "content": "谁是按曲目数量排名前五的艺术家?"})
# 传入prompt及tools
chat_response = chat_completion_request(messages, tools)
assistant_message = chat_response.choices[0].message
assistant_message.content = str(assistant_message.tool_calls[0].function)
messages.append({"role": assistant_message.role, "content": assistant_message.content})
if assistant_message.tool_calls:results = execute_function_call(assistant_message)messages.append({"role": "function", "tool_call_id": assistant_message.tool_calls[0].id, "name": assistant_message.tool_calls[0].function.name, "content": results})
pretty_print_conversation(messages)

在这里插入图片描述

messages.append({"role": "user", "content": "歌曲最多的专辑叫什么名字?"})
chat_response = chat_completion_request(messages, tools)
assistant_message = chat_response.choices[0].message
assistant_message.content = str(assistant_message.tool_calls[0].function)
messages.append({"role": assistant_message.role, "content": assistant_message.content})
if assistant_message.tool_calls:results = execute_function_call(assistant_message)messages.append({"role": "function", "tool_call_id": assistant_message.tool_calls[0].id, "name": assistant_message.tool_calls[0].function.name, "content": results})
pretty_print_conversation(messages)

在这里插入图片描述

4.5. Function Calling 注意事项

  1. gpt-3.5-turbogpt-3.5-turbo-1106 的别名
  2. gpt-4gpt-4-1106-preview 是两个不同的模型
  3. OpenAI 针对 Function Calling 做了 fine-tuning,以尽可能保证函数调用参数的正确
  4. 函数声明是消耗 token 的。要在功能覆盖、节约上下文tokens之间找到平衡点
  5. Function Calling 不仅可以调用读函数,也能调用写函数。但官方强烈建议,在写之前,一定要有人做确认

5. NLP 算法工程师视角

  1. 模型砍大面,规则修细节
  2. 一个模型搞不定的问题,拆成多个解决
  3. 评估算法的准确率(所以要先有测试集,否则别问「能不能做」)
  4. 评估 bad case 的影响面
  5. 算法的结果永远不是100%正确的,建立在这个假设基础上推敲产品的可行性

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

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

相关文章

三维模型轻量化、格式转换、可视化、数字孪生综合服务平台

老子云概述 老子云3D可视化快速开发平台,集云压缩、云烘焙、云存储云展示于一体,使3D模型资源自动输出至移动端PC端、Web端,能在多设备、全平台进行展示和交互,是全球领先、自主可控的自动化3D云引擎。 平台架构 平台特性 基于 …

在那静谧的冬天你飘落我荒凉心园

北风 - 刘蓝溪/梁弘志 --女--在那静谧的冬天你飘落我荒凉心园恰似北风一袭吹去秋意无限带来几片相思带来往日笑靥只见北风又起撒落枯叶片片--男--在那静谧的冬天你走进我冷漠心田恰似北风一袭吹去秋意无限北风婵媛白云白云本是轻烟只见北风又见带来白云片片--合--喔喔喔 海角…

【Pytorch深度学习开发实践学习】B站刘二大人课程笔记整理lecture11 Advanced_CNN 实现GoogleNet和ResNet

【Pytorch深度学习开发实践学习】B站刘二大人课程笔记整理lecture11 Advanced_CNN 代码: Pytorch实现GoogleNet import torch from torchvision import datasets, transforms from torch.utils.data import DataLoader import torch.nn as nn import torch.nn.fun…

遥感、航拍、影像等用于深度学习的数据集集合

遥感图像的纹理特征异常繁杂,地貌类型多变,人工提取往往存在特征提取困难和特征提取不准确的问题,同时,在这个过程中还会耗费海量的人力物力。随着计算力的突破、数据洪流的暴发和算法的不断创新,在具有鲜明“大数据”…

ArcgisForJS如何使用ArcGIS Server发布的GP服务?

文章目录 0.引言1.ArcGIS创建GP服务2.ArcGIS Server发布GP服务3.ArcgisForJS使用ArcGIS Server发布的GP服务 0.引言 ArcGIS for JavaScript(或简称AGJS)是一个强大的工具,它允许开发者使用JavaScript在Web浏览器中创建和运行ArcGIS应用程序。…

前端工程化面试题 | 18.精选前端工程化高频面试题

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

Leetcode刷题笔记题解(C++):6. Z 字形变换

思路:遍历时候需要更新步进长度 到达0行的时候步进长度为1;到达最后一行numRows-1行的时候步进长度为-1;代码如下所示: class Solution { public:string convert(string s, int numRows) {//如果字符串长度为1或者所给行数为1 …

Linux安装jdktomcatMySQl一战完成

一、jdk安装具体步骤 1、查询是否有jdk java -version 2、进入opt目录 cd /opt/ 连接服务器工具 进入opt目录,把压缩文件上传 查询是否查询成功 进入解压到的目录 cd /usr/local/创建新文件夹 mkdir java 再回到opt目录进行解压 cd /opt 解压到刚刚创建的文…

孙艺洲驾考再传捷报,科目二通过。

♥ 为方便您进行讨论和分享,同时也为能带给您不一样的参与感。请您在阅读本文之前,点击一下“关注”,非常感谢您的支持! 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 在《飞驰人生2》的首映礼盛大举行的日子里,猴哥意…

深入浅出:探究过完备字典矩阵

在数学和信号处理的世界里,我们总是在寻找表达数据的最佳方式。在这篇博文中,我们将探讨一种特殊的矩阵——过完备字典矩阵,这是线性代数和信号处理中一个非常有趣且实用的概念。 什么是过完备字典矩阵? 首先,我们先…

警用装备柜|单警装备柜系统功能强大

警用装备是警察执法的基本保障。近年来,基层的警用装备得到了极大的改善,老旧警用装备得以更新换代,新配警用装备性能也越来越好,科技含量也越来越高。但随着品种繁多的警用装备在如此短的时间内大量配备,警用装备管理…

Nodejs+vue图书阅读评分个性化推荐系统

此系统设计主要采用的是nodejs语言来进行开发,采用 vue框架技术,对于各个模块设计制作有一定的安全性;数据库方面主要采用的是MySQL来进行开发,其特点是稳定性好,数据库存储容量大,处理能力快等优势&#x…

编曲学习:高叠和弦 挂留和弦 和弦实战应用

高叠和弦 挂留和弦 和弦实战应用小鹅通-专注内容付费的技术服务商https://app8epdhy0u9502.pc.xiaoe-tech.com/live_pc/l_65d4826fe4b04c10a1310517?course_id=course_2XLKtQnQx9GrQHac7OPmHD9tqbv 七和弦 以三和弦举例,三和弦上面叠一个三度的音,就变成了七和弦。 从下到…

用6点结构标定5点结构的顺序

( A, B )---6*30*2---( 1, 0 )( 0, 1 ) 让网络的输入只有6个节点,AB训练集各由6张二值化的图片组成,A的6张图片共有5个点,B全是0.收敛误差7e-4,收敛199次,统计迭代次数平均值并排序。 如果使行和列自由变换&#xff0…

博途PLC PID仿真(单容水箱液位高度控制含变积分变增益测试)

单容水箱和双荣水箱的微分方程和数值求解,可以参考下面文章链接: https://rxxw-control.blog.csdn.net/article/details/131139432https://rxxw-control.blog.csdn.net/article/details/131139432这篇博客我们利用欧拉求解器在PLC里完成单容水箱的数学建模。PLC也可以和MATL…

【分布式事务 XA模式】MySQL XA模式详解

MYSQL中的XA事务 写在前面1. XA事务的基本原理2. MySQL XA事务操作 写在前面 MySQL 的 5.0.3 版本开始支持XA分布式事务,并且只有innoDB存储引擎支持XA事务。 1. XA事务的基本原理 XA事务本质上是一种基于两阶段提交的分布式事务,分布式事务可以理解成…

【递归版】归并排序算法(1)

目录 MergeSort归并排序 整体思想 图解分析 代码实现 时间复杂度 递归&归并排序VS快速排序 MergeSort归并排序 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer&a…

【Web】CTFSHOW 常用姿势刷题记录(全)

目录 web801 web802 web803 web804 web805 web806 web807 法一:反弹shell 法二:vps外带 web808 web809 web810 web811 web812 web813 web814 web815 web816 web817 web818 web819 web820 web821 web822 web823 web824 web825…

神经网络系列---计算图基本原理

文章目录 计算图符号微分符号微分的步骤示例符号微分在计算图中的使用总结 数值微分前向差分法中心差分法数值微分的使用注意事项总结 自动微分1. 基本原理2. 主要类型3. 计算图4. 应用5. 工具和库6. 优点和缺点 计算图1. **计算图的建立**2. **前向传播**3. **反向传播**4. **…

【广度优先搜索】【网格】【割点】1263. 推箱子

作者推荐 视频算法专题 涉及知识点 广度优先搜索 网格 割点 并集查找 LeetCode:1263. 推箱子 「推箱子」是一款风靡全球的益智小游戏,玩家需要将箱子推到仓库中的目标位置。 游戏地图用大小为 m x n 的网格 grid 表示,其中每个元素可以是墙、地板或…