本文的前两个部分最早是属于此旧文的《学术论文GPT的源码解读与微调:从ChatPaper到七月论文审稿GPT第1版》,但为了每一篇文章各自的内容更好的呈现,于是我今天做了以下三个改动
- 原来属于mamba第五部分的「Mamba近似工作之线性Transformer:从TransnormerLLM到RWKV」,改放到此文中:学术论文GPT的源码解读与微调:从ChatPaper到七月论文审稿GPT第1版
- 把旧文「学术论文GPT的源码解读与微调」中关于chatpaper相关的部分独立抽取出来成本文:学术论文GPT的源码解读与二次开发:从ChatPaper到gpt_academic
- 故旧文「学术论文GPT的源码解读与微调」的标题就改成了:七月论文审稿GPT第1版:通过3万多篇paper和10多万的review数据微调RWKV
如此,mamba那篇解读可以专注mamba的解读,不把过多篇幅放在mamba之外的RWKV上,且原来论文审稿第一版本身微调的RWKV,故刚好需要介绍下RWKV
且对于学术论文GPT的源码解读与微调本来就还得解读下gpt_academic,故把ChatPaper和gpt_academic这两个开源系统独立成本文,也更好
本文
- 第一部分 解读chatpaper:GitHub - kaixindelele/ChatPaper: Use ChatGPT to summarize the arXiv papers. 全流程加速科研,利用chatgpt进行论文全文总结+专业翻译+润色+审稿+审稿回复,1.4和1.5节和我司杜老师共创
第二部分 解读gpt_academic:GitHub - binary-husky/gpt_academic: 为GPT/GLM等LLM大语言模型提供实用化交互接口,特别优化论文阅读/润色/写作体验,模块化设计,支持自定义快捷按钮&函数插件,支持Python和C++等项目剖析&自译解功能,PDF/LaTex论文翻译&总结功能,支持并行问询多种LLM模型,支持chatglm3等本地模型。接入通义千问, deepseekcoder, 讯飞星火, 文心一言, llama2, rwkv, claude2, moss等。
ChatPaper的自身定位是全流程加速科研:论文总结+专业级翻译+润色+审稿+审稿回复,因为论文更多是PDF的格式,故针对PDF的对话、总结、翻译,便不可避免的涉及到PDF的解析
1.1.1 对PDF的解析:ChatReviewerAndResponse/get_paper.py
1.1.2 论文审查:ChatReviewerAndResponse/chat_reviewer.py
使用OpenAI的GPT模型进行论文审查的脚本。它首先定义了一个Reviewer类来处理审查工作,然后在if __name__ == '__main__':语句下使用argparse处理命令行参数,并调用chat_reviewer_main函数来开始审查过程
- 导入模块:比如jieba、tenacity等
- 命名元组定义:用于保存与论文审稿相关的参数
- 判断文本中是否包含中文:
- 插入句子到文本
主要功能是在给定文本的每隔一定数量的单词或中文字符后插入一个指定的句子。如果文本行包含中文字符,则使用jieba分词工具来切分中文,否则使用空格来切分: - 论文审稿类:定义了一个Reviewer类,包含以下功能:
第一阶段审稿:先是基于论文标题和摘要,选择要审稿的部分 然后分别实现两个函数
一个stage_1,主要功能是为了与GPT-3模型进行对话,获取模型对于文章的两个最关键部分的选择意见 一个chat_review,主要功能是调用GPT-3模型进行论文审稿,对输入的文章文本进行审查,并按照预定格式生成审稿意见 使用ChatGPT进行审稿,且有tenacity重试机制和更多的功能,其中review_by_chatgpt 调用了上面所示的两个函数,一个stage_1,一个chat_review - 主程序部分:
定义了一个chat_reviewer_main 函数,该函数创建了一个Reviewer对象,并对指定路径中的PDF文件进行审稿 主程序中定义了命令行参数解析,并调用了chat_reviewer_main 函数
在主程序中增加了审稿时间的计算功能
当然,这个项目的论文审稿部分更多是用的ChatGPT的API审稿,我司在API的基础上进一步做了微调的工作,比如如何通过论文审阅语料微调出一个论文审稿GPT(甚至通过10万量级的paper+review语料微调/训练),详见本文的第三部分或我司的「大模型项目开发线下营」
通过这个项目文件:ChatPaper/scipdf_parser-master/scipdf/pdf/parse_pdf.py可以看到以下内容
1.2.1 必要的库、常量、PDF路径
- 导入必要的库
re: 正则表达式库,用于匹配和处理字符串
os 和 os.path: 操作文件和路径的库
glob: 搜索文件的库
urllib: 用于处理和获取 URL
subprocess: 执行外部命令和程序的库
requests: 用于发送 HTTP 请求的库
BeautifulSoup 和 NavigableString: 从 bs4 导入,用于解析和操作 XML/HTML 内容
tqdm 和 tqdm_notebook: 提供进度条功能 - 定义常量
GROBID_URL: GROBID 是一个开源软件,可以从 PDF 文件中提取和解析学术出版物的结构化信息
PDF_FIGURES_JAR_PATH: 这是指向某个 jar 文件的路径,但这段代码中并没有用到这个常量 - 函数 list_pdf_paths: 返回给定文件夹中所有 PDF 文件的路径
- 函数 validate_url: 通过正则表达式验证给定的路径是否为有效的 URL
1.2.2 parse_pdf:对PDF的解析
这是代码中的核心功能,用 GROBID 服务从 PDF 文档中解析 XML 或 BeautifulSoup 格式的信息
如果 fulltext 参数为 True,则解析整篇文章;否则,只解析标题
可以从本地或云端的 GROBID 服务中获取数据
1.2.3 提取作者信息/parse_authors、出版日期/parse_date、摘要/parse_abstract、段落/parse_sections
- 函数parse_authors从 BeautifulSoup 文章对象中提取作者信息
- 下面这个parse_date函数是提取初版日期,从 BeautifulSoup 文章对象中提取出版日期
- 而parse_abstract这个函数则是提取摘要,即从 BeautifulSoup 文章对象中提取摘要
- 而parse_sections则是提取段落,从 BeautifulSoup 文章对象中提取文章的各个部分或段落,且它还计算每个部分中的引用数量
1.2.4 计算引用与解析文献引用/parse_references(article)
- calculate_number_of_references:计算给定部分中的引用数量
- parse_references(article):解析文献引用
功能:从给定的BeautifulSoup对象中解析文献引用列表
主要步骤:
寻找包含引用的部分
对于每个引用,提取文章标题、期刊、发布日期和作者信息
返回包含所有引用信息的列表
1.2.5 解析图形和表格、公式
- parse_figure_caption(article)
功能:从给定的BeautifulSoup对象中解析图形和表格
主要步骤:
搜索所有图形
对于每个图形或表格,提取标签、类型、ID、标题和数据
返回包含所有图形/表格信息的列表
- parse_figures(...):
功能:使用pdffigures2工具从给定的科学PDF中解析图形
主要步骤:
检查输出文件夹是否存在,如果不存在则创建它
在输出文件夹中创建子文件夹来保存数据和图形
使用Java运行pdffigures2工具解析图形
打印完成消息 - parse_formulas(article):解析公式
功能:从给定的BeautifulSoup对象中解析公式
主要步骤:
搜索所有公式
提取公式的ID、文本和坐标
返回包含所有公式信息的列表
1.2.6 把标题/作者/摘要/图形/公式等转换为JSON格式的字典
- convert_article_soup_to_dict(article, as_list=False):
功能:将BeautifulSoup对象转换为JSON格式的字典,类似于某些开源项目的输出
主要步骤:
提取文章的标题、作者、发布日期、摘要、部分、引用、图形和公式
返回一个包含所有这些信息的字典 - parse_pdf_to_dict(...)
功能:解析给定的PDF并返回解析后的文章的字典
主要步骤:
使用外部工具或服务(如GROBID)解析PDF
将解析后的BeautifulSoup对象转换为字典格式
返回该字典 这个函数的目的是解析给定的PDF文件,并将其转换为一个结构化的字典。首先,它使用parse_pdf函数来解析PDF,然后使用convert_article_soup_to_dict函数将解析后的BeautifulSoup对象转换为字典
具体包含如下功能(这个基于GPT4的文献总结工具的项目auto-draft也提供类似的功能)
- 自动搜索相关文献, 提供真实有出处的引用
- 自动生成LaTeX格式,markdown格式的调研结果
1.3.1 /utils/knowledge_databases/ml_textbook_test
1.3.2 /utils/embeddings.py
1.3.3 /utils/gpt_interaction.py
1.3.4 /utils/knowledge.py
定义了一个Knowledge类,该类使用关键词字典从数据库中搜索相关内容,并可以将这些内容转化为提示文本或JSON格式
1.3.5 /utils/references.py
这个代码文件主要注意实现了以下功能
1.3.5.1 第一部分: 类之外
-
Reference类的说明
- 从给定的文件中读取论文,并用方法填充缺失的摘要
- 根据一些关键词使用Semantic Scholar API查找相关论文
- 从所选论文中生成Bibtex引用格式
- 从所选论文中生成提示(prompts)。示例提示格式为:。
-
待完成的任务(todo)
- 加载预定义的论文;
- 使用Semantic Scholar API查找所有相关作品;
- 将所有引文添加到;
- 将所有被引文添加到;
- 使用Semantic Scholar查找它们的嵌入;
- 将引文分组以减少tokens的数量
-
一些基本的工具
- evaluate_cosine_similarity:计算两个向量的余弦相似性
- chunks 将一个较长的列表分割为较小的批次,以便于处理;
- embed 通过向Semantic Scholar的API发送请求,为一组论文计算嵌入(即将论文映射到一个向量空间中)
- get_embeddings 为给定的论文标题和描述获取嵌入
- get_top_k 获取与给定论文最相关的篇论文
具体而言,从提供的papers_dict 中找到与给定的paper_title和paper_description最相似的前k篇论文,并返回。至于相似性是通过计算两篇论文嵌入向量的余弦相似度来确定的 - remove_newlines 去除摘要中的换行符,减少提示的长度
-
从.bib文件加载论文信息
- 读取.bib文件,并将其解析为一个python对象;
- 通过load_papers_from_bibtex 函数遍历这个对象,从中提取论文的各种属性(如ID、标题、期刊、年份、作者、摘要等);
- 对于缺失摘要的论文,使用函数查询摘要
-
计算文本的tokens数量
- 使用对象来计算给定文本的tokens的数量
-
使用Semantic Scholar (SS) API搜索论文
- 使用Semantic Scholar API搜索指定关键词的论文;
- 从API返回的数据中提取论文的各种属性
-
函数
这部分主要关于从搜索结果中提取学术论文的相关信息:
该函数的目的是对传入的搜索结果进行解析,并将其转换为一个论文信息列表。- 首先检查传入的搜索结果是否为空。
- 逐个解析每篇论文的内容,包括作者信息、年份、标题等。
- 对某些字段进行特殊处理,如将日志名中的替换为。
- 如果存在摘要的“tldr”(即“过长不读”)版本,它会被优先使用,否则会使用原始摘要。
- 最后,所有提取出的信息将被组合成一个字典并添加到结果列表中
且函数下方的代码调用了一个假设的方法,然后使用上述函数处理这些搜索结果
1.3.5.2 第二部分: 类
该类用于管理论文引用:
- 初始化方法:当创建一个References对象时,可以选择为其提供标题、论文列表、关键词以及描述
- load_papers 方法:加载给定BibTeX格式的论文到引用类中
- generate_keywords_dict 方法:生成一个关键词字典,其中每个关键词都关联一个论文数量
- collect_papers 方法:使用给定的关键词字典收集尽可能多的论文。这个方法尝试收集给定关键词的相关论文,并添加到类的内部存储中
- to_bibtex 方法:将保存的论文列表转换为BibTeX格式的文件
- _get_papers 方法:一个内部方法,用于从内部存储中获取论文列表
- to_prompts 方法:将引用转换为提示格式,这可能是为了后续使用某种机器学习模型
- to_json 方法:将论文列表转换为JSON格式
- 代码的最后部分(在if __name__ == "__main__":之后)是一个简单的测试部分,用于测试上述代码的功能
chat_paper.py,包含一个Paper类、Reader类和chat_paper_mian函数。该程序功能为根据读者输入的搜索查询和感兴趣的关键词,从Arxiv数据库中获取文章,并对文章进行摘要和总结。程序使用了OpenAI的GPT-3模型生成文本摘要,使用了arxiv包获取Arxiv数据库中的文章。程序会将摘要和总结以markdown文件的形式保存下来。
1.4.1 Paper类
- Paper 类代表了一篇论文,它可以从 PDF 文件中解析出论文的元信息和内容,并提供了一些函数用于获取论文信息,如获取文章标题,获取章节名称及内容等。主要方法有:
- parse_pdf:解析PDF文件
其中的self._get_all_page_index() 和self._get_all_page() 这两个方法 下文很快会定义 - get_all_page_index:各个部分与页码的对应字典
- get_all_page:各个部分与内容对应的字典
- get_paper_info:获取论文的摘要信息
首先尝试从self.section_text_dict 字典中获取摘要,如果没有,则使用self.abs。最后,它从标题页的文本中移除摘要的内容并返回 - get_chapter_names:根据字体大小,识别每个章节名称,并返回一个列表
- get_title:获取论文标题
1.4.2 Reader类
Reader类包含了下载文章、筛选文章以及使用OpenAI的GPT-3模型生成文本摘要和总结的方法。主要方法有:
- get_arxiv(): 使用Arxiv的API获取搜索结果
- filter_arxiv(): 筛选文章,并返回筛选后的结果
- download_pdf(): 从Arxiv下载筛选后的文章
- summary_with_chat(): 对每一篇下载下来的文章进行文本摘要和总结,并将结果以markdown文件的形式保存
该函数的实现主要分为三个部分
首先,第一步:用title,abs和introduction进行总结 其次,第二步:总结方法 最后,第三步:总结全文并打分 - chat_summary():第一次提取title,abs,和introduction,设定prompt通过调用API的方式得到对应的总结
- chat_method():提取上面chat_summary()得到的结果,加上method或approach部分的内容,设定prompt通过调用API的方式得到对应的总结
- chat_conclusion():提取上面两部分:chat_summary()和chat_method()得到的结果(API给的回复),加上conclusion部分的内容,设定prompt通过调用API的方式得到对应的总结
1.4.3 chat_paper_main
chatpaper代码运行后得到的部分结果 输出:标题、作者、单位、 关键词、相关链接及 Summary。其中
- Summary为总结 得到的摘要
- method_result:对论文方法(method或approach)的总结
- Conclusion_result:对论文全文的总结(包含工作意义及创新点等)