利用ChatGLM-6B批量总结计算机英文学术论文
概要
为了节省搜索和阅读无关主题论文的时间,博主想写一段简单的程序利用本地部署语言大模型对已经下载或网络上开放获取地论文进行批量地总结提炼。代码可以在 gitcode-link 下载。
整体流程
程序分为三段,分别是是获取论文(pdf文件),提取文件内容并使用LLM总结和整理并存入CSV文件。流程图如下所示。
软件和模型列表
软件或模型 | 用处 |
---|---|
python | 程序语言 |
ChatGLM-6B | LLM,用于翻译、提取论文中的内容和主题等 |
PyPDF2 | python第三方库,用于提取pdf文件中的文字内容 |
modelscope | python第三方库,用于下载LLM权重和使用LLM |
re | python库,用于匹配文本内容 |
bs4 | python库,用于解析HTML网页元素(同时也需要安装lxml这个python库) |
requests 和 io | python库,二者配合根据url下载并保存pdf文件 |
time 和 random | python库,二者配合控制论文下载请求时间间隔,以防被认为是恶意访问 |
代码文件
论文PDF文件批量下载
这里以CVPR2023年的论文网址为例(PS:因为CVPR的网页很整洁,所以相对来说简单一些)。首先拿到CVPR2023的网页HTML文件(直接使用python程序抓取或直接用浏览器打开网页保存都行,本博文用的方式是后者)。之后提取HTML元素中的pdf文件下载链接和论文题目,最后根据url下载pdf文件并保存到本地就好了。注意:申请下载的频率不易过快,我这里用的睡眠间隔用的是0~15内的随机数(秒)
'''
文件名称 download_cvpr_pdf.py
'''
from bs4 import BeautifulSoup as bs
import re, io, requests
from time import sleep
from random import random
# 一次 pdf文件下载
def download_pdf(save_path, pdf_url, pdf_name=None):
# 申请信息
send_headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36",
"Connection": "keep-alive",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.8"}
# 申请获取pdf
response = requests.get(url=pdf_url, headers=send_headers)
# 将返回的 pdf文件信息截取(二进制)
bytes_io = io.BytesIO(response.content)
pdf_name = pdf_url.replace('https://openaccess.thecvf.com/content/CVPR2023/papers/', '')
# 保存为本地 pdf文件
with open(f'{save_path}/{pdf_name}', mode='wb') as f:
f.write(bytes_io.getvalue())
print(f'Finish :: {pdf_url}')
##### 获取 CVPR 2023 的HTML文件内容
html_page = open('./CVPR 2023 Open Access Repository.html', 'r', encoding='utf-8').read()
##### 解析 HTML文件
soup = bs(html_page, 'lxml')
##### 发现pdf文件url和文件名等信息一一对应,并且 HTML元素标签为 <a>
title_pdfs = soup.find_all('a')
##### 提取并筛选,只留下 pdf文件的url和论文名称
title_pdfs = [p for p in title_pdfs if 'paper' in str(p) or 'html' in str(p)]
##### 提取论文名称和 pdf文件 url
paper_pair = []
pattern = re.compile('href="([\s\S]+?)">')
for i in range(0, len(title_pdfs), 2):
paper_title = title_pdfs[i].contents[0]
pdf_url = re.findall(pattern, str(title_pdfs[i+1]))[0]
pair = (paper_title,pdf_url)
paper_pair.append(pair)
##### 根据提取到的url一一申请下载,申请失败的pdf文件信息被计入csv文件中
f = open('fail_download.csv', 'w+', encoding='utf-8')
for i, pair in enumerate(paper_pair):
try:
download_pdf('papers', pair[1])
except:
print('Fail to download. url= ', pair[1])
f.write(f'{pair[0]};{pair[1]}')
print(f'{i}/{len(paper_pair)} sleeping now, and downloading will start within 5 s')
sleep(random()*15)
f.close()
使用 ChatGLM-6B 对文章进行简单的总结
该阶段,首先使用 PyPDF2 提取 pdf 文件中的文章文本内容。为了简单,这里以提取摘要为例。
之后,载入LLM,通过调用方法根据摘要内容(或其他提取到的内容)进行总结,具体方式其实就是聊天[doge]。最后将返回的内容整理并写入CSV文件中。需要注意的是:1. 模型和数据张量都是半精度浮点数类型,显存占比至少 12GB。如果显存不足,需要转换为INT8,甚至INT4,请参考 ChatGLM 的官方 github 中的样例修改。2. 提取的信息存入CSV文件时使用的分隔符为 “\t”,可以换为一些更不宜出现的符号组合。
'''
文件名称:extract_summary_ChatGLM6B.py
'''
import PyPDF2 as pdf2
import re
from bs4 import BeautifulSoup as bs
def extract_abstract(pdf_path):
# 打开 pdf文件
fhandle = open(pdf_path, 'rb')
pdfreader = pdf2.PdfReader(fhandle)
# 找到第一页
page1 = pdfreader.pages[0]
# 提取文本
cont = page1.extract_text()
# 通过字符匹配找到 摘要部分
pattern = re.compile('Abstract([\s\S]+?)Introduction')
abstr = re.findall(pattern, cont)
abstr = abstr[0] if abstr != [] else abstr
# 清洗,得到完整的一段摘要
abstract = abstr.strip('\n').replace('-\n', '').replace('\n', ' ')
return abstract
### 加载 ChatGLM-6B,第一次会自动下载权重和模型结构
from modelscope import AutoTokenizer, AutoModel, snapshot_download
model_dir = snapshot_download("ZhipuAI/chatglm3-6b", revision = "v1.0.0")
tokenizer = AutoTokenizer.from_pretrained(model_dir, trust_remote_code=True)
model = AutoModel.from_pretrained(model_dir, trust_remote_code=True).half().cuda() ## 半精度推理
model = model.eval()
html_page = open('./CVPR 2023 Open Access Repository.html', 'r', encoding='utf-8').read()
soup = bs(html_page, 'lxml')
title_pdfs = soup.find_all('a')
title_pdfs = [p for p in title_pdfs if 'paper' in str(p) or 'html' in str(p)]
# 提取论文名称和 pdf文件 url
paper_pair = []
pattern = re.compile('href="([\s\S]+?)">')
for i in range(0, len(title_pdfs), 2):
paper_title = title_pdfs[i].contents[0]
pdf_url = re.findall(pattern, str(title_pdfs[i+1]))[0]
pair = (paper_title,pdf_url.replace('https://openaccess.thecvf.com/content/CVPR2023/', ''))
paper_pair.append(pair)
title_prompt = '请将该论文题目翻译为中文:'
abstract_prompt = '请使用中文简化该摘要内容:'
f = open('./cvpr2023_info_chatglm.csv', 'w+', encoding='utf-8')
f.write('论文题目(英文)\t论文题目(中文)\t摘要(英文)\t摘要简述(中文)\t主题词\t数据集\t文件链接(本地)\n')
fail_list = []
for i, pair in enumerate(paper_pair):
try:
abstr = extract_abstract(pair[1])
# print(abstr)
# 调用 chat 方法得到LLM的回复
title_zh, _ = model.chat(tokenizer, title_prompt+pair[0], history=[])
# print(title_zh)
abstr_bf, history = model.chat(tokenizer, abstract_prompt+abstr, history=[])
# print(abstr_bf)
themes, history = model.chat(tokenizer, '根据该摘要能够总结出的主题词是什么?', history=history)
# print(themes)
dataset, history = model.chat(tokenizer, '该摘要中有提到数据集吗?有的话请给出数据集名称,要求仅使用一句话。', history=history)
# print(dataset)
f.write(f'{pair[0]}\t{title_zh}\t{abstr}\t{abstr_bf}\t{themes}\t{dataset}\t{pair[1]}\n')
print(f'{i}/{len(paper_pair)} finish {pair[1]}')
# if i > 4:
# break
except:
print(pair, 'fail to extract abstract')
fail_list.append(pair)
f.close()
### 出错的 pdf 文件信息保存
f = open('fail_summary.txt', 'a+', encoding='utf-8')
f.write(str(fail_list))
f.close()
小结
最后使用 Excel 导入 CSV文件中的数据,查看已经整理好的论文信息。效果如下图所示。
声明:ChatGLM-6B 总结的信息并不是十分准确,只是大部分说得过去。整理的内容只能帮助初步了解一篇论文大体的方向,具体内容还是需要人来看的。