赞
踩
目录
前言
本章节旨在深入探索ChatGLM3所提供的丰富API接口,不仅覆盖GLM特有的代码风格API开发实践,还包括遵循OpenAI风格的API开发方式。我们将通过具体的操作步骤和实际案例,详细阐述如何利用核心工具Function Call来扩展模型功能,以及如何将这种强大的功能直接应用于实际应用中。随着内容的展开,读者将逐步掌握如何灵活使用ChatGLM3-6B的强大功能,开发出智能化的解决方案,满足不断变化的业务需求。
引入与GLM模型交互所需的Python库。这通常包括用于模型推理的特定库以及通用的数据处理库。AutoTokenizer 是一个分词器 ;AutoModel是基础模型
from transformers import AutoTokenizer, AutoModel
Tokenizer是用于将文本转换为模型可理解的数字序列的工具。由于其需要从远程服务器加载预训练的词汇表,首次运行时可能会消耗较长时间。
使用 AutoTokenizer.from_pretrained 方法,加载预训练的tokenizer "THUDM/chatglm3-6b" 。trust_remote_code=True 表示信任远程代码。
tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b",trust_remote_code=True)
使用 AutoModel.from_pretrained 方法,加载预训练的模型 "THUDM/chatglm3-6b" 到CUDA设备上。 trust_remote_code=True 表示信任远程代码(如果有), device='cuda' 表示将模型加载到CUDA设备上以便使用GPU加速。
要注意的是,根据显卡显存的不同,需要考虑加载不同精度的模型。13GB显存以上的显卡可以直接按照上述代码加载全精度的模型。
1)非量化(默认FP16)
model = AutoModel.from_pretrained("THUDM/chatglm3-6b",trust_remote_code=True,device='cuda')
使用非量化加载,目前权重相关的文件被维护人员修改了,导致量化加载时会报错,问题暂未修复
2)量化处理加载模型(量化为int8)
model = AutoModel.from_pretrained("THUDM/chatglm3-6b",trust_remote_code=True).quantize(8).cuda()
3)量化处理加载模型(量化为int4)
model = AutoModel.from_pretrained("THUDM/chatglm3-6b",trust_remote_code=True).quantize(4).cuda()
4) 多GPU情况
如果有多张 GPU,但是每张 GPU 的显存大小都不足以容纳完整的模型,那么可以将模型切分在多张GPU上。首先安装 accelerate:
pip install accelerate
然后通过如下方法加载模型:
- from utils import load_model_on_gpus
- #如果存在2个GPU
- model = load_model_on_gpus("THUDM/chatglm3-6b", num_gpus=2)
备注:这里默认会直接使用Hugging Face的模型库中开源的预训练模型进行开发测试;我们可以将Hugging Face上的"THUDM/chatglm3-6b"的相关模型文件全部下载到本地,然后将代码中地址换为本地的目录。
接下来则需要对模型进行实例化操作,并且设置为评估模式:
model = model.eval()
一旦模型被成功实例化,我们就可以向其提供输入并获取输出结果了。此步骤是实际进行模型推理的地方,也是API服务的核心功能之一。
response, history = model.chat(tokenizer, "你好", history=[])
#打印查看响应内容
print(response)
#打印查看历史记录
print(history)
安装依赖:# pip install openai
pip install openai
OpenAI风格代码调用时,不需要自己加载分词器和模型,但需要先 启动一个OpenAI api服务(用来对外提供openai风格接口时,在内部GLM会将openai的代码风格转化为自己的代码风格,在ChatGLM3/openai_api_demo目录下有一个api_server.py文件)
api服务启动:python api_server.py
备注说明:api_server.py源码中会进行拉取huggingface上的模型,进行加载,运行到本地服务器的GPU上。
通过curl命令,我们可以在终端中直接发送HTTP请求来测试API的响应情况。
- curl -X POST "http://127.0.0.1:8000/v1/chat/completions" \
-
- -H "Content-Type: application/json" \
-
- -d "{\"model\": \"chatglm3-6b\", \"messages\": [{\"role\": \"system\", \"content\": \"You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the user's instructions carefully. Respond using markdown.\"}, {\"role\": \"user\", \"content\": \"你好,给我讲一个故事,大概100字\"}], \"stream\": false, \"max_tokens\": 100, \"temperature\": 0.8, \"top_p\": 0.8}"
执行结果:
除了curl外,我们还可以使用Python编写脚本,通过POST请求的方式向API发送数据,并获取返回结果。
导入依赖,封装POST请求
- import requests
- import json
-
- base_url = "http://127.0.0.1:8000" # 前面本地启动的API服务地址
- def create_chat_completion(model, messages):
- data = {
- "model": model, # 模型名称
- "messages": messages, # 会话历史
- "max_tokens": 100, # 最多生成字数
- "temperature": 0.8, # 温度
- "top_p": 0.8, # 采样概率
- }
- response = requests.post(f"{base_url}/v1/chat/completions", json=data)
- decoded_line = response.json()
- content = decoded_line.get("choices", [{}])[0].get("message", "").get("content", "")
- return content
代码调用
- chat_messages = [
- {
- "role": "system",
- "content": "You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the user's instructions carefully. Respond using markdown.",
- },
- {
- "role": "user",
- "content": "你好,给我讲一个故事,大概100字"
- }
- ]
- content = create_chat_completion("chatglm3-6b", chat_messages)
- print(content)
输出结果:
- 从前有个美丽的小村庄,村子里的居民过着和谐的生活。村子里有一位聪明的老爷爷,他总是能给出最好的建议。有一天,村里发生了一件大事,一个恶龙来到了村子里,偷走了人们的宝藏。
-
- 村子里的人都很害怕,不知道该如何解决这个问题。但是,老爷爷却很镇定,他决定带领村民们一起打倒恶龙。经过艰苦的努力,他们最终成功地击败了恶龙,夺回了失去的宝藏。
GLM模型还支持以对话的形式进行交互,这使得我们可以像与人交谈一样与模型进行对话。
- from openai import OpenAI
-
- base_url = "http://127.0.0.1:8000/v1/"
- client = OpenAI(api_key="EMPTY", base_url=base_url)
-
- def simple_chat(use_stream=True):
- messages = [
- {
- "role": "system",
- "content": "You are ChatGLM3, a large language model trained by Zhipu.AI. Follow the user's "
- "instructions carefully. Respond using markdown.",
- },
- {
- "role": "user",
- "content": "你好,请你用生动的话语给我讲一个小故事吧"
- }
- ]
-
- response = client.chat.completions.create(
- model="chatglm3-6b", # 模型名称
- messages=messages, # 会话历史
- stream=use_stream,# 指定是否使用流式传输模式,如果设置为True,则返回一个生成器对象,可以逐个获取生成的文本片段;如果设置为False,则一次性返回完整的生成结果。
- max_tokens=256, # 最多生成字数
- temperature=0.8, # 温度
- presence_penalty=1.1,#控制生成回答时对已出现词汇的惩罚强度,较高的值会减少重复词汇的出现
- top_p=0.8) # 采样概率
- if response:
- if use_stream:
- for chunk in response:
- print(chunk.choices[0].delta.content)
- else:
- content = response.choices[0].message.content
- print(content)
- else:
- print("Error:", response.status_code)
-
- if __name__ == "__main__":
-
- simple_chat(use_stream=False)
- #simple_chat(use_stream=True)
-
输出:
- 从前,在一个遥远的国度里,有一个美丽的小村庄。村子里的人们过着和谐的生活,每天都充满欢声笑语。在这个小村庄里,有一位聪明、善良的少年,名叫小明。
-
- 有一天,村子里来了一个神秘的旅行者。他带着一颗魔法石,说这颗石子可以实现一个人最真诚的愿望。村民们为了寻求幸福和美好,都纷纷向旅行者许愿。可是, after 每个人完成愿望后,旅行者却离开了村子,没有兑换他的承诺。
-
- 于是,小明决定站出来,为了村子的和平与幸福,他追踪旅行者,希望能把魔法石带回来,让每个人都有机会实现自己的梦想。在旅途中,他经历了种种困难和挑战,但都凭借着自己的勇敢和智慧克服了它们。最终,他找到了旅行者,成功地将魔法石带回村子。
-
- 回到村子后,小明将魔法石交给村长。村长将这颗神奇的石头放在了村子的中心广场上,希望它能给村子带来幸福和繁荣。从此,村子变得更加美好,人们的生活也变得越来越幸福。而小明,则成为了这个故事中最勇敢、善良的英雄,被村民们传颂千古。
GLM中还提供了嵌入模型bge-large-zh-1.5
- from openai import OpenAI
-
- base_url = "http://127.0.0.1:8000/v1/"
- client = OpenAI(api_key="EMPTY", base_url=base_url)
-
- def embedding():
- response = client.embeddings.create(
- model="bge-large-zh-1.5",
- input=["你好,给我讲一个故事,大概100字"],
- )
- embeddings = response.data[0].embedding
- print("嵌入完成,维度:", len(embeddings))
-
- if __name__ == "__main__":
- embedding()
输出:
嵌入完成,维度: 1024
- from openai import OpenAI
-
- base_url = "http://127.0.0.1:8000/v1/"
- client = OpenAI(api_key="EMPTY", base_url=base_url)
定义一些工具函数,用于辅助完成特定的任务,例如查询天气信息
- tools = [
- {
- "type": "function",
- "function": {
- "name": "get_current_weather",
- "description": "Get the current weather in a given location",
- "parameters": {
- "type": "object",
- "properties": {
- "location": {
- "type": "string",
- "description": "The city and state, e.g. San Francisco, CA",
- },
- "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
- },
- "required": ["location"],
- },
- },
- }
- ]
最后,我们可以调用这些工具函数,并观察模型的响应结果,以验证功能是否正常工作。
- messages = [{"role": "user", "content": "What's the weather like in BeiJing?"}]
- response = client.chat.completions.create(
- model="chatglm3-6b",
- messages=messages,
- tools=tools,
- tool_choice="auto",
- )
- content = response.choices[0].message.content
- content
输出
"get_current_weather\n ```python\ntool_call(location='Beijing')\n```"
在实际应用中,我们可能需要将GLM模型与其他外部API进行结合。例如,获取实时天气信息通常需要调用专门的天气API。
提前申请API KEY: open_weather_key = "c6748580ef08742adf7bd05d79dd8e5d"
- import json
- import requests
-
- def get_weather(loc):
- """
- 查询即时天气函数
- :param loc: 必要参数,字符串类型,用于表示查询天气的具体城市名称,\
- 注意,中国的城市需要用对应城市的英文名称代替,例如如果需要查询北京市天气,则loc参数需要输入'Beijing';
- :return:OpenWeather API查询即时天气的结果,具体URL请求地址为:https://api.openweathermap.org/data/2.5/weather\
- 返回结果对象类型为解析之后的JSON格式对象,并用字符串形式进行表示,其中包含了全部重要的天气信息
- """
- # Step 1.构建请求
- url = "https://api.openweathermap.org/data/2.5/weather"
-
- # Step 2.设置查询参数
- params = {
- "q": loc,
- "appid": open_weather_key, # 输入API key
- "units": "metric", # 使用摄氏度而不是华氏度
- "lang":"zh_cn" # 输出语言为简体中文
- }
-
- # Step 3.发送GET请求
- response = requests.get(url, params=params)
-
- # Step 4.解析响应
- data = response.json()
- return json.dumps(data)
-
- #调用打印结果
- data=get_weather("BeiJing")
- data
返回结果
'{"coord": {"lon": 116.3972, "lat": 39.9075}, "weather": [{"id": 801, "main": "Clouds", "description": "\\u6674\\uff0c\\u5c11\\u4e91", "icon": "02d"}], "base": "stations", "main": {"temp": 15.94, "feels_like": 14.09, "temp_min": 15.94, "temp_max": 15.94, "pressure": 1011, "humidity": 19, "sea_level": 1011, "grnd_level": 1005}, "visibility": 10000, "wind": {"speed": 4.98, "deg": 299, "gust": 8.94}, "clouds": {"all": 12}, "dt": 1700633608, "sys": {"type": 1, "id": 9609, "country": "CN", "sunrise": 1700607993, "sunset": 1700643269}, "timezone": 28800, "id": 1816670, "name": "Beijing", "cod": 200}'
直接询问GLM大模型的天气情况,看他怎么返回结果
- ##测试模型
- from transformers import AutoTokenizer, AutoModel
- tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm3-6b",trust_remote_code=True)
- model = AutoModel.from_pretrained("THUDM/chatglm3-6b",trust_remote_code=True).quantize(8).cuda()
- model = model.eval()
-
- ## 测试模型调用
- response, history = model.chat(tokenizer, "你好,北京天气怎么样?", history=[])
- print(response)
返回结果:
你好!作为一个人工智能助手,我无法实时获取北京的最新天气信息。但你可以查看天气预报或使用天气应用来了解当前的北京天气。
- def run_conv_glm(query,tokenizer, history, model,functions_list=None, functions=None, return_function_call=True):
-
- """
- 能够自动执行外部函数调用的Chat对话模型
- :param messages: 必要参数,输入到Chat模型的messages参数对象
- :param functions_list: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象
- :param model: Chat模型,可选参数,默认模型为chatglm3-6b
- :return:Chat模型输出结果
- """
-
- # 如果没有外部函数库,则执行普通的对话任务
- if functions_list == None:
- response, history = model.chat(tokenizer, query, history=history)
- final_response = response
-
- # 若存在外部函数库,则需要灵活选取外部函数并进行回答
- else:
- # 创建调用外部函数的system_message
- system_info = {
- "role": "system",
- "content": "Answer the following questions as best as you can. You have access to the following tools:",
- "tools": functions,
- }
-
- # 创建外部函数库字典
- available_functions = {func.__name__: func for func in functions_list}
- history=[system_info]
-
- ## 第一次调用,目的是获取函数信息
- response,history = model.chat(tokenizer, query, history=history)
- # 需要调用外部函数
- function_call = response
-
- # 获取函数名
- function_name = function_call["name"]
-
- # 获取函数对象
- fuction_to_call = available_functions[function_name]
-
- # 获取函数参数
- function_args = function_call['parameters']
-
- # 将函数参数输入到函数中,获取函数计算结果
- function_response = fuction_to_call(**function_args)
-
- ## 第二次调用,带入进去函数
- # role="observation" 表示输入的是工具调用的返回值而不是用户输入
- # role:user,system,assistant,observation
- print(function_response)
- history=[]
- history.append(
- {
- "role": "observation",#设置观察着角色
- "name": function_name,
- "content": function_response,#将函数调用返回的结果再次给到大模型,由模型进行整理后再给出更加易用理解,可读性更强的答案,否则返回的就是天气API直接返回的内容。
- }
- )
- response, history = model.chat(tokenizer, query, history=history)
- final_response=response
-
- return final_response,history
最终,我们进行函数调用测试,查看整个流程的稳定性和准确性。
- query = "请帮我查询一下北京的天气"
- history=[]
- functions_list = [get_weather]
- functions=weather_api_spec
-
- response,history = run_conv_glm(query=query,functions=functions,model=model,functions_list=functions_list,history=history,tokenizer=tokenizer)
- print(response)
返回结果
- {"coord": {"lon": 116.3972, "lat": 39.9075}, "weather": [{"id": 801, "main": "Clouds", "description": "\u6674\uff0c\u5c11\u4e91", "icon": "02d"}], "base": "stations", "main": {"temp": 15.94, "feels_like": 14.09, "temp_min": 15.94, "temp_max": 15.94, "pressure": 1011, "humidity": 19, "sea_level": 1011, "grnd_level": 1005}, "visibility": 10000, "wind": {"speed": 4.98, "deg": 299, "gust": 8.94}, "clouds": {"all": 12}, "dt": 1700634535, "sys": {"type": 1, "id": 9609, "country": "CN", "sunrise": 1700607993, "sunset": 1700643269}, "timezone": 28800, "id": 1816670, "name": "Beijing", "cod": 200}
-
- 北京现在的天气是:Clouds,温度为15.94℃,湿度为19%。
本文详细介绍了通过API调用方式实践开发基于ChatGLM3-6B的应用程序。从基本的模型加载和实例化,到功能调用和外部API集成,我们一步步展示了GLM大模型的强大功能和灵活性。通过这些实践案例,开发者可以更加深入地理解如何在真实场景中利用GLM大模型,推动各类智能应用的发展。
文章若有瑕疵,恳请不吝赐教;若有所触动或助益,还望各位老铁多多关注并给予支持。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。