一、前言
每个模型都有自己的限制,有些情况下它们无法满足复杂的业务需求。但是,可以通过一个外置函数的方式,例如:"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
从魔搭下载:魔搭社区汇聚各领域最先进的机器学习模型,提供模型探索体验、推理、训练、部署和应用的一站式服务。https://www.modelscope.cn/models/ZhipuAI/chatglm3-6b/fileshttps://www.modelscope.cn/models/ZhipuAI/chatglm3-6b/files
3.3. 创建虚拟环境&安装依赖
conda create --name chatglm3 python=3.10
conda activate chatglm3
pip install protobuf transformers==4.30.2 cpm_kernels torch>=2.0 sentencepiece accelerate
四、技术实现
# -*- coding = utf-8 -*-
import tracebackfrom transformers import AutoTokenizer, AutoModelForCausalLMmodelPath = "/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 = hismessages.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 responseexcept Exception:traceback.print_exc()def loadTokenizer():tokenizer = AutoTokenizer.from_pretrained(modelPath, use_fast=False, trust_remote_code=True)return tokenizerdef loadModel():model = AutoModelForCausalLM.from_pretrained(modelPath, device_map="auto", trust_remote_code=True).cuda()model = model.eval()# print(model)return modeldef 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,让模型更准确返回我们所需要的格式
# 在本地函数中,去判断输入的语种,当输入是中文的时候,可以转化成拼音或英文