附1 ChatGPT与ChatGLM对比¶
国产大模型有很多,比如文心一言、通义千问、星火、 MOSS 和 ChatGLM 等等,但现在明确可以部署在本地并且开放 api 的只有 MOSS 和 ChatGLM 。MOSS 由于需要的GPU显存过大(不量化的情况下需要 80GB ,多轮对话还是会爆显存),但 ChatGLM 可以在笔记本电脑部署( int4 版本只需要 6GB 显存即可)。所以本文采用 ChatGLM 与 ChatGPT 做对比,看看国产模型的优点和缺点。
本文会选取本教程的各个方面进行对比,最后会总结 ChatGPT 与ChatGLM各自的优缺点。另外本文也适用于没有 OpenAI api key 的读者,部署好 ChatGLM-6B 之后,使用后续介绍的函数也可以学完整个课程。
一、环境配置¶
1.1 ChatGLM环境配置¶
ChatGLM环境配置可以参考DataWhale的这篇文章:ChatGLM-6B 本地部署指南!
部署好了之后,运行项目中的api.py文件即可。下面是使用ChatGLM的api封装的类似 ChatGPT 一样的get_completion函数,只需要传进去prompt参数即可。
import requests
import json
如果你没有 OpenAI 的 key 的话,部署好 ChatGLM -6B 之后,使用此函数也可以学完整个课程,加油~
def get_completion(prompt):
headers = {'Content-Type': 'application/json'}
data = {"prompt": prompt, "history": []}
response = requests.post(url='http://127.0.0.1:8000', headers=headers, data=json.dumps(data))
return response.json()['response']
get_completion("你好")
'你好👋!我是人工智能助手 ChatGLM-6B,很高兴见到你,欢迎问我任何问题。'
def get_completion_glm(prompt):
headers = {'Content-Type': 'application/json'}
data = {"prompt": prompt, "history": []}
response = requests.post(url='http://127.0.0.1:8000', headers=headers, data=json.dumps(data))
return response.json()['response']
get_completion_glm("你好")
'你好👋!我是人工智能助手 ChatGLM-6B,很高兴见到你,欢迎问我任何问题。'
1.2 ChatGPT环境配置¶
引入 OpenAI 包,加载 API 密钥,定义 getCompletion 函数。
pip install openai
import openai
# 导入第三方库
openai.api_key = "sk-..."
# 设置 API_KEY, 请替换成您自己的 API_KEY
def get_completion_gpt(prompt, model="gpt-3.5-turbo", temperature=0):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=temperature, # 值越低则输出文本随机性越低
)
return response.choices[0].message["content"]
get_completion_gpt('你好')
'你好!有什么我可以帮助你的吗?'
二、文本理解¶
2.1 文本总结与条件检测¶
2.1.1 有步骤的文本(满足输入条件)¶
# 有步骤的文本
text_1 = f"""
泡一杯茶很容易。首先,需要把水烧开。\
在等待期间,拿一个杯子并把茶包放进去。\
一旦水足够热,就把它倒在茶包上。\
等待一会儿,让茶叶浸泡。几分钟后,取出茶包。\
如果你愿意,可以加一些糖或牛奶调味。\
就这样,你可以享受一杯美味的茶了。
"""
prompt = f"""
您将获得由三个引号括起来的文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - …
…
第N步 - …
如果文本中不包含一系列的指令,则直接写“未提供步骤”。"
\"\"\"{text_1}\"\"\"
"""
response = get_completion_glm(prompt)
print(response)
第一步: 把水烧开 第二步: 把茶包放入杯子中 第三步: 等待水足够热 第四步: 倒在茶包上 第五步: 等待茶叶浸泡 第六步: 取出茶包 第七步: 如果喜欢,可以加一些糖或牛奶 第八步: 搅拌均匀 第九步: 享用美味的茶 未提供步骤
response = get_completion_gpt(prompt)
print(response)
第一步 - 把水烧开。 第二步 - 拿一个杯子并把茶包放进去。 第三步 - 把热水倒在茶包上。 第四步 - 等待几分钟,让茶叶浸泡。 第五步 - 取出茶包。 第六步 - 如果你愿意,可以加一些糖或牛奶调味。 第七步 - 就这样,你可以享受一杯美味的茶了。
注:这里可以看出,提供的文本是有步骤的文本。 ChatGLM 给出了步骤,但在最后说了未提供步骤。但 ChatGPT 给出步骤,而且步骤要比 ChatGLM 的完整,而且回答正确。
2.1.2 无步骤的文本(不满足输入条件)¶
# 无步骤的文本
text_2 = f"""
今天阳光明媚,鸟儿在歌唱。\
这是一个去公园散步的美好日子。\
鲜花盛开,树枝在微风中轻轻摇曳。\
人们外出享受着这美好的天气,有些人在野餐,有些人在玩游戏或者在草地上放松。\
这是一个完美的日子,可以在户外度过并欣赏大自然的美景。
"""
prompt = f"""
您将获得由三个引号括起来的文本。\
如果它包含一系列的指令,则需要按照以下格式重新编写这些指令:
第一步 - ...
第二步 - …
…
第N步 - …
如果文本中不包含一系列的指令,则直接写“未提供步骤”。"
\"\"\"{text_2}\"\"\"
"""
response = get_completion_glm(prompt)
print(response)
第一步: 去公园散步 第二步: 欣赏鲜花和树枝 第三步: 感受微风 第四步: 放松身心 第五步: 野餐或玩游戏 第六步: 感受大自然的美丽 未提供步骤。
response = get_completion_gpt(prompt)
print(response)
未提供步骤。
注: 提供的是一个无步骤文本,但 ChatGLM 回答了一个步骤,在最后说了无步骤,这跟上面的有步骤文本回答几乎一样。 ChatCPT 则是直接给出未提供步骤的回答。
2.2 提供少量示例的文本续写(Few-shot)¶
prompt = f"""
你的任务是以一致的风格回答问题。
<孩子>: 教我耐心。
<祖父母>: 挖出最深峡谷的河流源于一处不起眼的泉眼;最宏伟的交响乐从单一的音符开始;最复杂的挂毯以一根孤独的线开始编织。
<孩子>: 教我韧性。
"""
response = get_completion_glm(prompt)
print(response)
韧性是一种强大的品质,可以帮助人们在挑战中保持冷静和坚韧。以下是一些培养韧性的方法: 1. 接受挑战并做好准备:韧性需要面对挑战并克服困难。要培养韧性,需要先准备好接受挑战,并采取必要的措施来解决问题。 2. 学会放松:当我们感到紧张和焦虑时,可能会失去韧性。学会放松自己,可以帮助缓解压力和焦虑,从而提高韧性。 3. 培养自我意识:韧性需要了解自己的弱点和优点,并积极改善自己。学会关注自己的情绪和行为,并努力改善自己的韧性。 4. 学习沟通技巧:沟通是影响韧性的重要因素。学习有效的沟通技巧,可以帮助更好地表达自己的意见和想法,同时也可以帮助更好地理解他人的观点。 5. 坚持锻炼和健康饮食:锻炼和健康饮食可以帮助保持身体健康和精神健康,从而提高韧性。 希望这些方法可以帮助培养韧性。
response = get_completion_gpt(prompt)
print(response)
<祖父母>: 韧性就像是一棵树,它需要经历风吹雨打、日晒风干,才能成长得更加坚强。所以,当你遇到挫折和困难时,不要轻易放弃,要坚持下去,相信自己的能力和潜力,最终你会成为一棵茁壮成长的大树。
注: 让你模仿,没让你超越啊!可以看出 ChatGLM 的回答与提供的少量示例文本几乎毫无关系,而 ChatGPT 则是按照提供的示例模型续写。 ChatGPT 薄纱 ChatGLM 。
2.3 关注点侧重¶
prod_review_zh = """
这个熊猫公仔是我给女儿的生日礼物,她很喜欢,去哪都带着。
公仔很软,超级可爱,面部表情也很和善。但是相比于价钱来说,
它有点小,我感觉在别的地方用同样的价钱能买到更大的。
快递比预期提前了一天到货,所以在送给女儿之前,我自己玩了会。
"""
# 侧重运输
prompt = f"""
你的任务是从电子商务网站上生成一个产品评论的简短摘要。
请对三个反引号之间的评论文本进行概括,最多30个词汇,并且聚焦在产品运输上。
评论: ```{prod_review_zh}```
"""
response = get_completion_glm(prompt)
print(response)
评论: 熊猫公仔送给女儿生日礼物,她很喜欢。公仔软、可爱,面部表情和善。但小,感觉在其他地方用同样的价钱能买到更大。快递比预期提前了一天到货,自己玩了会。
response = get_completion_gpt(prompt)
print(response)
快递提前一天到货,熊猫公仔很软可爱,但有点小,价钱不太划算。
注: 让它侧重运输, ChatGLM 甚至把运输的内容放在了回答的最后, ChatGPT 倒是把运输的部分放到了最前,表示侧重。
2.4 关键信息提取¶
prompt = f"""
你的任务是从电子商务网站上的产品评论中提取相关信息。
请从以下三个反引号之间的评论文本中提取产品运输相关的信息,最多30个词汇。
评论: ```{prod_review_zh}```
"""
response = get_completion_glm(prompt)
print(response)
运输时间:快递比预期提前了一天到货,熊猫公仔小巧,快递过程安全顺利。
response = get_completion_gpt(prompt)
print(response)
快递比预期提前了一天到货。
注: 不错,不错, ChatGLM 和 ChatGPT 都把运输信息提取出来了, ChatGLM 甚至还多说了点。
2.5 总结¶
文本理解方面, ChatGLM 与 ChatGPT 的差距有点大。首先是步骤文本,无论提供的文本是否有步骤, ChatGLM 都给出了步骤。而 ChatGPT 则是有步骤给步骤,没步骤就不给。
示例文本续写方面, ChatGLM 本着模仿就要超越的原则,直接舍弃提供的少量示例,放飞自我。 ChatGPT 则是按照提供的少量示例给出了答案。
关键信息提取, ChatGLM 表现差强人意,不太行。 ChatGPT 倒是符合我的要求。
三、结构化输出¶
3.1 示例1¶
text = f"""
在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。\
他们一边唱着欢乐的歌,一边往上爬,\
然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。\
虽然略有些摔伤,但他们还是回到了温馨的家中。\
尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。
"""
# example
prompt = f"""
1-用一句话概括下面用<>括起来的文本。
2-将摘要翻译成英语。
3-在英语摘要中列出每个名称。
4-输出一个 JSON 对象,其中包含以下键:English_summary,num_names。
请使用以下格式:
文本:<要总结的文本>
摘要:<摘要>
翻译:<摘要的翻译>
名称:<英语摘要中的名称列表>
输出 JSON:<带有 English_summary 和 num_names 的 JSON>
Text: <{text}>
"""
response = get_completion_glm(prompt)
print(response)
摘要: 在一个迷人的村庄里,兄妹杰克和吉尔出发去一个山顶井里打水。他们一边唱着欢乐的歌,一边往上爬,然而不幸降临——杰克绊了一块石头,从山上滚了下来,吉尔紧随其后。虽然略有些摔伤,但他们还是回到了温馨的家中。尽管出了这样的意外,他们的冒险精神依然没有减弱,继续充满愉悦地探索。 翻译: In a charming village,兄妹杰克 and吉尔 went to a山顶 well to fetch water. They were singing joyfully as they reached the top, but something went wrong -杰克 stumbled and fell from the mountain, while吉尔 followed closely. Although they were slightly injured, they returned home feeling brave and愉悦. Although they encountered such an unexpected situation, their spirit of adventure did not dim, and they continued to explore with joy. 名称: The names in the English summary are: Jack,吉尔, and their mother.
response = get_completion_gpt(prompt)
print(response)
摘要:兄妹杰克和吉尔在迷人的村庄里冒险,不幸摔伤后回到家中,但仍然充满冒险精神。
翻译:In a charming village, siblings Jack and Jill set out to fetch water from a mountaintop well. While climbing and singing, Jack trips on a stone and tumbles down the mountain, with Jill following closely behind. Despite some bruises, they make it back home safely. Their adventurous spirit remains undiminished as they continue to explore with joy.
名称:Jack,Jill
输出 JSON:{"English_summary": "In a charming village, siblings Jack and Jill set out to fetch water from a mountaintop well. While climbing and singing, Jack trips on a stone and tumbles down the mountain, with Jill following closely behind. Despite some bruises, they make it back home safely. Their adventurous spirit remains undiminished as they continue to explore with joy.", "num_names": 2}
注: 可以看出, ChatGLM 完全忽略了 Prompt 中的输出json对象, 而且这个输出的摘要像是重新说了一遍,翻译也有些中文没有完全翻译。 ChatGPT 的回答是符合要求的。
3.2 从客户的评论中提取结构化信息¶
# 中文
lamp_review_zh = """
我需要一盏漂亮的卧室灯,这款灯具有额外的储物功能,价格也不算太高。\
我很快就收到了它。在运输过程中,我们的灯绳断了,但是公司很乐意寄送了一个新的。\
几天后就收到了。这款灯很容易组装。我发现少了一个零件,于是联系了他们的客服,他们很快就给我寄来了缺失的零件!\
在我看来,Lumina 是一家非常关心顾客和产品的优秀公司!
"""
# 中文
prompt = f"""
从评论文本中识别以下项目:
- 评论者购买的物品
- 制造该物品的公司
评论文本用三个反引号分隔。将你的响应格式化为以 “物品” 和 “品牌” 为键的 JSON 对象。
如果信息不存在,请使用 “未知” 作为值。
让你的回应尽可能简短。
评论文本: ```{lamp_review_zh}```
"""
response = get_completion_glm(prompt)
print(response)
物品:卧室灯 品牌:Lumina
response = get_completion_gpt(prompt)
print(response)
{
"物品": "卧室灯",
"品牌": "Lumina"
}
注: ChatGLM 提取信息成功!口头表扬一次,但是并没有按照json对象输出,口头批评一次。 ChatGPT 做的很好,表扬一次。
3.3 一次提取多条信息¶
# 中文
prompt = f"""
从评论文本中识别以下项目:
- 情绪(正面或负面)
- 审稿人是否表达了愤怒?(是或否)
- 评论者购买的物品
- 制造该物品的公司
评论用三个反引号分隔。将您的响应格式化为 JSON 对象,以 “Sentiment”、“Anger”、“Item” 和 “Brand” 作为键。
如果信息不存在,请使用 “未知” 作为值。
让你的回应尽可能简短。
将 Anger 值格式化为布尔值。
评论文本: ```{lamp_review_zh}```
"""
response = get_completion_glm(prompt)
print(response)
Sentiment: 正面 Anger: 否 Item: 卧室灯 Brand:mina
response = get_completion_gpt(prompt)
print(response)
{
"Sentiment": "正面",
"Anger": false,
"Item": "卧室灯",
"Brand": "Lumina"
}
注: ChatGLM 提取信息确实是提取的没问题,但是吧,还是没有转化为json对象输出。并且Anger没有给出布尔值,扣分项。
3.4 总结¶
提取信息+结构化输出, ChatGLM 基本只能做到提取信息,并没有实现输出json对象。能力有待加强,不知道 ChatGLM -130B的版本如何?希望能更好些,加油~
四、翻译与转换¶
4.1 多语种翻译¶
prompt = f"""
请将以下文本分别翻译成中文、英文、法语和西班牙语:
```I want to order a basketball.```
"""
response = get_completion_glm(prompt)
print(response)
```我想订购一把篮球。``` 中文:我想订购一把篮球。 英文:I want to order a basketball. 法语:Je veux orderir un basketball. 西班牙语:Vuelgo a intentar orderar un basketball.
response = get_completion_gpt(prompt)
print(response)
中文:我想订购一个篮球。 英文:I want to order a basketball. 法语:Je veux commander un ballon de basket. 西班牙语:Quiero pedir una pelota de baloncesto.
注: 本人知识浅薄,法语和西班牙语翻译是用有道翻译检验的。 ChatGLM 和 ChatGPT 的翻译都正确。大胜利!
4.2 翻译+正式语气¶
prompt = f"""
请将以下文本翻译成中文,分别展示成正式与非正式两种语气:
```Would you like to order a pillow?```
"""
response = get_completion_glm(prompt)
print(response)
``` Would you like to order a pillow?``` 正式语气: 我想订购一张枕头。 非正式语气: 嘿,你想预订一张枕头吗?
response = get_completion_gpt(prompt)
print(response)
正式语气:请问您需要订购枕头吗? 非正式语气:你要不要订一个枕头?
注: 两种语气, ChatGLM 和 ChatGPT 都回答的不错,都加分。
4.3 总结¶
在翻译这块, ChatGLM 做的和 ChatGPT 相差无几,甚至可以说有些超越。换个角度想想,本地部署一个 ChatGLM -int4专门用来翻译也不错啊,起码本地部署的api不收费!
五、逻辑推理¶
prompt = f"""
请判断学生的解决方案是否正确,请通过如下步骤解决这个问题:
步骤:
首先,自己解决问题。
然后将你的解决方案与学生的解决方案进行比较,并评估学生的解决方案是否正确。在自己完成问题之前,请勿决定学生的解决方案是否正确。
使用以下格式:
问题:问题文本
学生的解决方案:学生的解决方案文本
实际解决方案和步骤:实际解决方案和步骤文本
学生的解决方案和实际解决方案是否相同:是或否
学生的成绩:正确或不正确
问题:
我正在建造一个太阳能发电站,需要帮助计算财务。
- 土地费用为每平方英尺100美元
- 我可以以每平方英尺250美元的价格购买太阳能电池板
- 我已经谈判好了维护合同,每年需要支付固定的10万美元,并额外支付每平方英尺10美元
作为平方英尺数的函数,首年运营的总费用是多少。
学生的解决方案:
设x为发电站的大小,单位为平方英尺。
费用:
1. 土地费用:100x
2. 太阳能电池板费用:250x
3. 维护费用:100,000+100x
总费用:100x+250x+100,000+100x=450x+100,000
实际解决方案和步骤:
"""
response = get_completion_glm(prompt)
print(response)
实际解决方案和步骤与学生的解决方案相同。 学生的解决方案可以简化为: 总费用 = 土地费用 + 太阳能电池板费用 + 维护费用 根据题目中的数据,土地费用为每平方英尺100美元,太阳能电池板费用为每平方英尺250美元,维护费用为每年10万美元和每平方英尺10美元,因此: 总费用 = 100x + 250x + 100,000 + 10x 将x的表达式代入总费用公式中,得到: 总费用 = 100x + 250x + 100,000 + 10x = 450x + 100,000 因此,学生的解决方案和实际解决方案相同。
response = get_completion_gpt(prompt)
print(response)
正确的解决方案和步骤:
1. 计算土地费用:100美元/平方英尺 * x平方英尺 = 100x美元
2. 计算太阳能电池板费用:250美元/平方英尺 * x平方英尺 = 250x美元
3. 计算维护费用:10万美元 + 10美元/平方英尺 * x平方英尺 = 10万美元 + 10x美元
4. 计算总费用:100x美元 + 250x美元 + 10万美元 + 10x美元 = 360x + 10万美元
学生的解决方案和实际解决方案是否相同:否
学生的成绩:不正确
注: 实际上学生的解决方案是不正确的,维护费用每平方英尺是10美元,在学生的解答中错误的将其写成了100美元, ChatGLM 发现这个错误,但它没有指出学生解答中的错误。相反 ChatGPT 发现了错误,并给出了正确解法。