最近业务上多了长文本的需求,因为要在prompt里面塞进比较多的rag内容,以供决策,且这些召回的内容,都有可能用到。这非常考验大模型的长文本能力,技术选型上都要着重考察这部分。
正巧,上次清影试用后,约了跟智谱的哥们吃饭聊天,吐槽说:“超长文本,有可能还要微调,这可咋办啊?”
“你还别说,我还真搞过。”
说完,甩给我一个链接。
“链接对应的地址是bigmodel模型中心的GLM-4-long
。支持支持高达1M (约150-200万字) 的上下文长度,大约相当于2本红楼梦或者125篇论文。”
然后跟我说,你先试试,我再跟你讲讲其中的几个技术关键点,说不定能用到你的场景呢。
“你先别吹牛,我用我的究极大模型长文测试方法看看”。
我准备的这个测试要比大海捞针更难。
大海捞针,比较出名了,也是一个被大家已经刷爆了的指标。就是在长文本里按设定的策略,分散插入一些语言片段来推理,考察大模型的能力。
但大海捞针有两个问题:
一、很多测试题目只需要聚焦在一句话上就能得到答案,不需要考虑全部的插入文本。
二、很多题目在训练阶段都见过了,不管你说多长的文本,什么内容,其实也都能答出来。
这也是为啥现在的大海捞针测试,长文本大模型基本都是满分了,这个测试已经没有区分度了。
大家看到也都是上面这张全绿的图,其实我们只要稍微改下。
一、推理需要考虑到每个地方插入的地方,不能遗漏任何一个。
二、是大模型没有学过的信息。
那这个中国队拿了几枚金牌的测试太合适了。
我用红楼梦的原文,把中国队伦敦奥运会拿金牌的信息分散插入,让模型把这些信息找出来,并整理给我。
这就算是个进阶版本的大海捞针测试了。
我试了下市面上的大模型,别说答对了,到1M上下文的都屈指可数。
测试脚本如下:
def read_txt(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
return content
def write_txt(file_path, content):
with open(file_path, 'w', encoding='utf-8') as file:
file.write(content)
def generate_insert_positions(content_length, num_inserts):
"""
生成插入位置,使得句子均匀分布在文本中。
"""
step = content_length // (num_inserts + 1)
positions = [(i + 1) * step for i in range(num_inserts)]
return positions
def main(file_path, gold_list, silver_list, bronze_list):
# Read the content of the original file
original_content = read_txt(file_path)[:1024*(1024-2)]
# Generate the sentence list
sentences = []
max_length = max(len(gold_list), len(silver_list), len(bronze_list))
for i in range(max_length):
if i < len(gold_list):
sentences.append(f"中国队获得了 金牌 {gold_list[i]} 枚。")
if i < len(silver_list):
sentences.append(f"中国队获得了 银牌 {silver_list[i]} 枚。")
if i < len(bronze_list):
sentences.append(f"中国队获得了 铜牌 {bronze_list[i]} 枚。")
# Calculate the insert positions
num_inserts = len(sentences)
positions = generate_insert_positions(len(original_content), num_inserts)
# Insert sentences into the original content at calculated positions
updated_content_parts = []
last_position = 0
for i, pos in enumerate(positions):
updated_content_parts.append(original_content[last_position:pos])
updated_content_parts.append("\n" + sentences[i] + "\n")
last_position = pos
updated_content_parts.append(original_content[last_position:])
updated_content = "".join(updated_content_parts)
# Write the combined content back to the file
return updated_content
if __name__ == "__main__":
file_path = "The_Story_of_the_Stone.txt" # 文件路径
gold_list = [3, 2, 1] # 金牌数
silver_list = [2, 8, 9] # 银牌数
bronze_list = [7, 10, 13] # 铜牌数
prompt = "请你根据如下文本,整理中国队获得的金银铜牌数。格式: {\"金牌数\":[x,x,x,...],\"银牌数\":[x,x,x,...],\"铜牌数\":[x,x,x,...]}[x,x,x,...]中对应的奖牌数,仅以JSON格式输出结果,不需要输出任何解释。下面是文本:\n"
counting = main(file_path, gold_list, silver_list, bronze_list)
print(len(counting))
from zhipuai import ZhipuAI
client = ZhipuAI(api_key="XXX") # 请填写您自己的APIKey
response = client.chat.completions.create(
model="glm-4-long", # 填写需要调用的模型名称
messages=[
{
"role": "user",
"content": prompt + counting
}
],
)
print(response.choices[0].message.content)
红楼梦整本长度为887276个字符,88万汉字,对应的token其实还不够1M,不得不说,GLM-4-long
的1M有点恐怖了,吃两本半红楼梦的书,可谓是「一目十K行」了。
那我们用这个脚本就测一下这个GLM4-long,输出结果为:
{"金牌数":[3,2,1],"银牌数":[2,8,9],"铜牌数":[7,10,13]}
完全答对了。
感兴趣的同学可以试试,并且可以拓展下测试的插入颗粒度,长度和对应的效果,画一个对应类似大海捞针的二维可视化效果图。
另外,我准备了一稍微复杂的长文本推理场景,具体任务是输入苹果公司的Q3的财报进行问答。具体的方法为把苹果公司财报pdf使用mathpix转为大模型处理的文本格式,然后设计QA对进行问答。
以这页的信息为例,使用的prompt和得到的答案分别为:
prompt:你是一个专业的财报分析助手,请根据以下财报内容 {finance_content}
,回答问题{question}
。请直接说出答案,不需要解释。
问题一:苹果公司2024年Q3的研发成本有多少?
content:xxx
question:苹果公司2024年Q3的研发成本有多少?
answer:80亿美元。
问题二:苹果公司2024年Q3的销售额比2023年Q3的销售额增长多少美元?
content:xxx
question:苹果公司2024年Q3的销售额比2023年Q3的销售额增长多少?
answer:39.8亿美元。
问题三:苹果公司2024年Q3的销售额比2023年Q3的销售额增长多少美元?
content:xxx
question:苹果公司2024年Q3的销售额比2023年Q3的毛利增长百分之多少?
answer:8.97%。
我也就好奇了,效果不错的长文本模型,到底是咋弄出来的呢?
哥们跟我说了四个字,「拾级而上」。
“你在这谜语人呢。”
“我们都知道,rope中的base参数能调整大模型上下文感知的分辨率,很多技术报告里都提到了这个。但具体怎么训练好调整后分辨率的模型,闭口不谈。”
其实只要让大模型一步一步适应不同的上下文长度就可以了,比如先训4096,再训8k,逐步扩展到128k,1M。
当然这个过程里面还有一些细节的技巧,比如长文本要是packing的话,太浪费资源了,怎么提高训练的吞吐量。特别长的指令数据怎么弄。
“怎么弄?”
“第一个,就是你之前bert时候打比赛中常用的,batch sort方法,让一个batch中的样本尽量对齐,这样需要packing的空间就很少了,提高资源利用率。
第二个,用一个小模型,针对不同的片断,做一些指令合成数据合成。然后用来训大模型。
另外,还需要很强的infra大佬做基建的保障,不过你们微调的话,可能这方面也还好。
对了,我刚刚给你说的那些,之前开源的技术报告里都有。你回去对着使劲儿琢磨琢磨吧,就算是垂直模型自己训练的话,问题应该问题不大
我们有个9b版本的权重开源了。”
https://huggingface.co/THUDM/glm-4-9b-chat-1m
智谱果然是国产大模型开源事业的排头兵,如果把国产化大模型看成一个整体的话,开源确实会继续整个群体的智力水平和互相交流不断进步,把整个行业的蛋糕越做越大,最终使整个群体收益。
降低入行的门槛,吸引更多潜在的人才加入这个游戏。
从而提高整个社会的运转效率。这个过程往往没有制造内卷,反而制造了大量全新的工作岗位。
不说了,赶紧去试试哥们传授的大模型长文本实践。