一、前言
每个模型都有自己的限制,有些情况下它们无法满足复杂的业务需求。但是,可以通过一个外置函数的方式,例如:"Function Call",让开发者能够更加灵活地利用大型语言模型,帮助开发者在特定场景下解决问题。
二、术语
2.1、Function Call
Function Call 是一项强大的功能,它允许开发者向模型提供不同的函数来执行特定的任务,根据用户的输入和要求。这些函数可以接受输入参数,并根据当前的任务提供相关的输出。
三、前置条件
3.1. windows or linux操作系统均可
3.2. 下载chatglm3-6b模型
从huggingface下载:https://huggingface.co/THUDM/chatglm3-6b/tree/main
3.3. 创建虚拟环境&安装依赖
conda create --name chatglm3 python=3.10
conda activate chatglm3
pip install protobuf transformers==4.39.3 cpm_kernels torch>=2.0 sentencepiece accelerate
四、技术实现
# -*- coding = utf-8 -*-
import traceback
from transformers import AutoTokenizer, AutoModelForCausalLM
modelPath = "/model/chatglm3-6b"
def get_weather(region):
low_region = region.lower()
if 'guangzhou' == low_region:
return '21 ~ 28℃ 多云 无持续风向<3级'
elif 'shenzhen' == low_region:
return '22 ~ 28℃ 晴 西南风3级'
else:
return '6 ~ 18℃ 晴 北风4级'
funcList = {
"weather": get_weather
}
def chat(model, tokenizer, message, history, system):
messages = []
if system is not None:
messages.append(system)
if history is not None:
for his in history:
user, assistant = his
messages.append({"role": "user", "content": user})
messages.append({"role": "assistant", 'metadata': '', "content": assistant})
print(messages)
try:
response = model.chat(tokenizer, message, messages, max_length=2048, top_p=0.9, temperature=0.45, repetition_penalty=1.1, do_sample=True)
return response
except Exception:
traceback.print_exc()
def loadTokenizer():
tokenizer = AutoTokenizer.from_pretrained(modelPath, use_fast=False, trust_remote_code=True)
return tokenizer
def loadModel():
model = AutoModelForCausalLM.from_pretrained(modelPath, device_map="auto", trust_remote_code=True).cuda()
model = model.eval()
# print(model)
return model
def main():
model = loadModel()
tokenizer = loadTokenizer()
message = "广州今天的天气如何?"
history = []
tools = [
{'name': 'weather', 'description': '获取指定地区实时天气',
'parameters':
{
'type': 'object',
'properties':
{'region':
{
'description': '待查询天气的区域'
}
},
'required': []
}
}
]
system = {
"role": "system",
"content": "Answer the following questions as best as you can. You have access to the following tools:",
"tools": tools
}
response,_ = chat(model, tokenizer, message, history, system)
print(response)
if 'name' not in response:
print('本地方法名称没返回!')
if 'parameters' not in response:
print('本地方法参数没返回!')
func_name = response['name']
parameters = response['parameters']
if 'region' not in parameters:
print('地区参数没返回!')
region = parameters['region']
print(fun, region)
if func_name in funcList:
func = funcList[func_name]
result = func(region)
print(result)
else:
print(f'{func_name}方法不存在!')
if __name__ == "__main__":
main()
调用结果:
五、附带说明
5.1. 流程说明
1. 设置本地函数(实际业务可以是调第三方的API、查询数据库、查询缓存等逻辑)
def get_weather(region):
low_region = region.lower()
if 'guangzhou' == low_region:
return '21 ~ 28℃ 多云 无持续风向<3级'
elif 'shenzhen' == low_region:
return '22 ~ 28℃ 晴 西南风3级'
else:
return '6 ~ 18℃ 晴 北风4级'
2. 设置本地函数列表
funcList = {
"weather": get_weather
}
示例只有一个本地函数,实际可以有N个
3. 设置本地函数的描述
tools = [
{'name': 'weather', 'description': '获取指定地区实时天气',
'parameters':
{
'type': 'object',
'properties':
{'region':
{
'description': '待查询天气的区域'
}
},
'required': []
}
}
]
4. 在System Prompt中,指定可使用的本地函数库
system = {
"role": "system",
"content": "Answer the following questions as best as you can. You have access to the following tools:",
"tools": tools
}
5. 模型调用,获取本地函数的方法名和参数列表
response,_ = chat(model, tokenizer, message, history, system)
print(response)
if 'name' not in response:
print('本地方法名称没返回!')
if 'parameters' not in response:
print('本地方法参数没返回!')
func_name = response['name']
parameters = response['parameters']
if 'region' not in parameters:
print('地区参数没返回!')
region = parameters['region']
6. 本地函数调用
if func_name in funcList:
func = funcList[func_name]
result = func(region)
print(result)
else:
print(f'{func_name}方法不存在!')
7. 再次调用模型,对本地调用结果进行汇总加工处理(此处代码省略)
5.2. 优化地方
1. ChatGLM3推理返回的本地函数参数是“Guangzhou”,而Prompt提示语是:“广州今天的天气如何?”。两者之间是存在信息差,为此,可以优化的地方是:
# 修改模型参数和System Prompt,让模型更准确返回我们所需要的格式
# 在本地函数中,去判断输入的语种,当输入是中文的时候,可以转化成拼音或英文