赞
踩
写过程序的人可能都懂接口是什么,这里再简述一下接口的形式。
目前常见的接口形式:
AI时代的接口形式:用户通过自然语言与软件或系统交互,不用再点击按钮,按标准流程操作软件
未来的接口形式:
以前的接口调用,我们需要给定明确的接口名称和精确的参数。大模型时代的接口调用,我们只需要给出自然语言任务,大模型自动解析出参数和调用哪个接口。
没有Function Calling的架构:
加入Function calling之后的架构:
其实大模型也不是万能的,它有三大缺陷:
比如算加法:
- 把 100 以内所有加法算式都训练给大模型,它就能回答 100 以内的加法算式
- 如果问它更大数字的加法,就不一定对了 因为它并不懂「加法」,只是记住了 100 以内的加法算式的统计规律
所以:大模型需要连接真实世界,并对接真逻辑系统,以此来控制大模型输出的不确定性和幻觉,达到我们想要的结果。
以Python内置的sum函数为例,假设我们想让大模型使用这个函数。
sum函数介绍,接收一个列表、元组或集合:
def get_completion(messages, model="gpt-3.5-turbo-1106"): response = openai.chat.completions.create( model=model, messages=messages, temperature=0, max_tokens=1024, tools=[ { # 用 JSON 描述函数。可以定义多个。由大模型决定调用谁 "type": "function", "function": { "name": "sum", "description": "计算一组数的和", "parameters": { "type": "object", "properties": { "numbers": { "type": "array", "items": { "type": "number" } } } } } }, ] ) return response.choices[0].message
代码解释:
openai.chat.completions.create
接口,这次我们需要使用的是tools
参数tools
参数中注意:Function Calling 中的函数与参数的描述
description
也是一种 Prompt。这种 Prompt 也需要调优,否则会影响函数的召回、参数的准确性,甚至让 GPT 产生幻觉
我们用自然语言给一个做加法的需求:
prompt = "桌上有 2 个苹果,四个桃子和 3 本书,一共有几个水果?"
messages = [
{"role": "system", "content": "你是一个数学家,你可以计算任何算式。"},
{"role": "user", "content": prompt}
]
response = get_completion(messages)
messages.append(response) # 注意这一句,必须加入到上下文中,否则报错
print("=====GPT回复=====")
print(response)
运行看下这时候大模型的返回: 可以看到返回了函数的名称和函数的参数。
当大模型返回了需要调用的名称和参数之后,我们可以通过本地代码解析出来,然后再去调用相应函数。
if (response.tool_calls is not None):
for tool_call in response.tool_calls:
print(response.tool_calls)
print(f"调用 {tool_call.function.name} 函数,参数是 {tool_call.function.arguments}")
if tool_call.function.name == "sum":
# 调用 sum 函数(本地函数或库函数,非chatgpt),打印结果
args = json.loads(tool_call.function.arguments)
result = sum(args["numbers"])
print("=====函数返回=====")
print(result)
本地函数执行完得到结果后,再将这个结果给大模型,让大模型用自然语言组织起最终答案。
这里需要怎么给大模型呢?需要将函数调用结果,tool_call_id,role,name等一起加入到prompt中。
# 把函数调用结果加入到对话历史中
messages.append(
{
"tool_call_id": tool_call.id, # 用于标识函数调用的 ID
"role": "tool",
"name": "sum",
"content": str(result) # 数值result 必须转成字符串
}
)
# 再次调用大模型
print("=====最终回复=====")
print(get_completion(messages).content)
经测试,tool_call_id和role是必须参数,name可以不要,但最好也加上。
import json import os from math import * import openai # 加载 .env 到环境变量 from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) def get_completion(messages, model="gpt-3.5-turbo-1106"): response = openai.chat.completions.create( model=model, messages=messages, temperature=0, max_tokens=1024, tools=[ { # 用 JSON 描述函数。可以定义多个。由大模型决定调用谁 "type": "function", "function": { "name": "sum", "description": "计算一组数的和", "parameters": { "type": "object", "properties": { "numbers": { "type": "array", "items": { "type": "number" } } } } } }, ] ) return response.choices[0].message prompt = "桌上有 2 个苹果,四个桃子和 3 本书,一共有几个水果?" messages = [ {"role": "system", "content": "你是一个数学家,你可以计算任何算式。"}, {"role": "user", "content": prompt} ] response = get_completion(messages) # 把大模型的回复加入到对话历史中 messages.append(response) # 注意这一句,必须加入到上下文中,否则报错 print("=====GPT回复=====") print(response) # 如果返回的是函数调用结果,则打印出来 if (response.tool_calls is not None): for tool_call in response.tool_calls: print(response.tool_calls) print(f"调用 {tool_call.function.name} 函数,参数是 {tool_call.function.arguments}") if tool_call.function.name == "sum": # 调用 sum 函数(本地函数或库函数,非chatgpt),打印结果 args = json.loads(tool_call.function.arguments) result = sum(args["numbers"]) print("=====函数返回=====") 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)
这里以一个查询某个地点附近某些信息的需求为例。
这里我们需要定义自己的本地函数,不再使用Python的库函数了。
下面的代码,我们定义了两个函数。
def get_location_coordinate(location, city="北京"): url = f"https://restapi.amap.com/v5/place/text?key={amap_key}&keywords={location}®ion={city}" print(url) r = requests.get(url) result = r.json() if "pois" in result and result["pois"]: return result["pois"][0] return None def search_nearby_pois(longitude, latitude, keyword): url = f"https://restapi.amap.com/v5/place/around?key={amap_key}&keywords={keyword}&location={longitude},{latitude}" print(url) r = requests.get(url) result = r.json() ans = "" if "pois" in result and result["pois"]: for i in range(min(3, len(result["pois"]))): name = result["pois"][i]["name"] address = result["pois"][i]["address"] distance = result["pois"][i]["distance"] ans += f"{name}\n{address}\n距离:{distance}米\n\n" return ans
这是用的高德地图的开放接口,在使用本例之前,你需要先去高德地图开放接口的官网申请一个key,免费的。这里就不过多介绍了。
def get_completion(messages, model="gpt-3.5-turbo-1106"): response = openai.chat.completions.create( model=model, messages=messages, temperature=0, max_tokens=1024, tools=[{ "type": "function", "function": { "name": "get_location_coordinate", "description": "根据POI名称,获得POI的经纬度坐标", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "POI名称,必须是中文", }, "city": { "type": "string", "description": "POI所在的城市名,必须是中文", } }, "required": ["location", "city"], } } }, { "type": "function", "function": { "name": "search_nearby_pois", "description": "搜索给定坐标附近的poi", "parameters": { "type": "object", "properties": { "longitude": { "type": "string", "description": "中心点的经度", }, "latitude": { "type": "string", "description": "中心点的纬度", }, "keyword": { "type": "string", "description": "目标poi的关键字", } }, "required": ["longitude", "latitude", "keyword"], } } }] ) return response.choices[0].message
prompt = "北京三里屯附近的咖啡" messages = [ {"role": "system", "content": "你是一个地图通,你可以找到任何地址。"}, {"role": "user", "content": prompt} ] response = get_completion(messages) if (response.content is None): # 解决 OpenAI 的一个 400 bug response.content = "" messages.append(response) # 把大模型的回复加入到对话中 print("=====GPT回复=====") print(response) # 如果返回的是函数调用结果,则打印出来 while (response.tool_calls is not None): # 1106 版新模型支持一次返回多个函数调用请求 for tool_call in response.tool_calls: args = json.loads(tool_call.function.arguments) print(args) if (tool_call.function.name == "get_location_coordinate"): print("Call: get_location_coordinate") result = get_location_coordinate(**args) elif (tool_call.function.name == "search_nearby_pois"): print("Call: search_nearby_pois") result = search_nearby_pois(**args) print("=====函数返回=====") print(result) messages.append({ "tool_call_id": tool_call.id, # 用于标识函数调用的 ID "role": "tool", "name": tool_call.function.name, "content": str(result) # 数值result 必须转成字符串 }) response = get_completion(messages) if (response.content is None): # 解决 OpenAI 的一个 400 bug response.content = "" messages.append(response) # 把大模型的回复加入到对话中 print("=====最终回复=====") print(response.content)
看下执行过程和结果:
(1)首先大模型识别到应该先调用get_location_coordinate函数获取经纬度。
(2)get_location_coordinate执行结果给到大模型,大模型识别到下一步应该调用search_nearby_pois
(3)search_nearby_pois执行结果给到大模型,大模型识别到不需要调用其它函数,用自然语言组织了最终答案。
import json import os import openai import requests # 加载 .env 到环境变量 from dotenv import load_dotenv, find_dotenv _ = load_dotenv(find_dotenv()) amap_key = os.getenv('AMAP_KEY') def get_completion(messages, model="gpt-3.5-turbo-1106"): response = openai.chat.completions.create( model=model, messages=messages, temperature=0, max_tokens=1024, tools=[{ "type": "function", "function": { "name": "get_location_coordinate", "description": "根据POI名称,获得POI的经纬度坐标", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "POI名称,必须是中文", }, "city": { "type": "string", "description": "POI所在的城市名,必须是中文", } }, "required": ["location", "city"], } } }, { "type": "function", "function": { "name": "search_nearby_pois", "description": "搜索给定坐标附近的poi", "parameters": { "type": "object", "properties": { "longitude": { "type": "string", "description": "中心点的经度", }, "latitude": { "type": "string", "description": "中心点的纬度", }, "keyword": { "type": "string", "description": "目标poi的关键字", } }, "required": ["longitude", "latitude", "keyword"], } } }] ) return response.choices[0].message def get_location_coordinate(location, city="北京"): url = f"https://restapi.amap.com/v5/place/text?key={amap_key}&keywords={location}®ion={city}" print(url) r = requests.get(url) result = r.json() if "pois" in result and result["pois"]: return result["pois"][0] return None def search_nearby_pois(longitude, latitude, keyword): url = f"https://restapi.amap.com/v5/place/around?key={amap_key}&keywords={keyword}&location={longitude},{latitude}" print(url) r = requests.get(url) result = r.json() ans = "" if "pois" in result and result["pois"]: for i in range(min(3, len(result["pois"]))): name = result["pois"][i]["name"] address = result["pois"][i]["address"] distance = result["pois"][i]["distance"] ans += f"{name}\n{address}\n距离:{distance}米\n\n" return ans prompt = "北京三里屯附近的咖啡" messages = [ {"role": "system", "content": "你是一个地图通,你可以找到任何地址。"}, {"role": "user", "content": prompt} ] response = get_completion(messages) if (response.content is None): # 解决 OpenAI 的一个 400 bug response.content = "" messages.append(response) # 把大模型的回复加入到对话中 print("=====GPT回复=====") print(response) # 如果返回的是函数调用结果,则打印出来 while (response.tool_calls is not None): # 1106 版新模型支持一次返回多个函数调用请求 for tool_call in response.tool_calls: args = json.loads(tool_call.function.arguments) print("参数:", args) if (tool_call.function.name == "get_location_coordinate"): print("Call: get_location_coordinate") result = get_location_coordinate(**args) elif (tool_call.function.name == "search_nearby_pois"): print("Call: search_nearby_pois") result = search_nearby_pois(**args) print("=====函数返回=====") print(result) messages.append({ "tool_call_id": tool_call.id, # 用于标识函数调用的 ID "role": "tool", "name": tool_call.function.name, "content": str(result) # 数值result 必须转成字符串 }) response = get_completion(messages) if (response.content is None): # 解决 OpenAI 的一个 400 bug response.content = "" print("=====GPT回复2=====") print(response) messages.append(response) # 把大模型的回复加入到对话中 print("=====最终回复=====") print(response.content)
通过本文的两个实战示例,是否已经对Function calling有了一个初步的认识?
学习AI大模型是一个系统的过程,需要从基础开始,逐步深入到更高级的技术。
这里给大家精心整理了一份全面的AI大模型学习资源,包括:AI大模型全套学习路线图(从入门到实战)、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频,免费分享!
L1级别:AI大模型时代的华丽登场
L2级别:AI大模型API应用开发工程
L3级别:大模型应用架构进阶实践
L4级别:大模型微调与私有化部署
达到L4级别也就意味着你具备了在大多数技术岗位上胜任的能力,想要达到顶尖水平,可能还需要更多的专业技能和实战经验。
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。
作为普通人在大模型时代,需要不断提升自己的技术和认知水平,同时还需要具备责任感和伦理意识,为人工智能的健康发展贡献力量。
有需要全套的AI大模型学习资源的小伙伴,可以微信扫描下方CSDN官方认证二维码,免费领取【保证100%免费
】
如有侵权,请联系删除。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。