前言
之前写了两篇文章,介绍如何用阿里云免费GPU搭建论文阅读助手,并且通过命令行方式进行使用。感兴趣的可以去看之前的文章:无需langchian,5分钟搭建专属论文阅读助手 以及 命令行快速启动论文阅读助手与交互。但是使用下来发现仍存在问题,一个是通过命令行调取存在较高使用门槛,对于完全不懂命令行的小伙伴可能不太友好;另一个是对于不同尺寸的论文需要调整分割的页面中心阈值,可能需要多次尝试,比较麻烦。经过最近一段时间的研究后,这两个问题都能解决了,并且还把输出方式修改为流式输出,减少等待时间,下面将一一展示这些进展。
效果可以看:B站视频
网页方式调用
这里采用了Gradio用于搭建阅读助手交互网页,对于非前端同学来说,无需掌握HTML、CSS、JAVASCRIPTS也能快速搭建基于网页的应用,非常适合机器学习应用的demo展示。著名的Stable DIffusion WebUi也是基于Gradio搭建的,可想而知它的易用性和受众面了。
def build_app():
import gradio as gr
with gr.Blocks(title="AsktoPDF:基于大模型的论文阅读助手") as app:
with gr.Row():
pdf_render = gr.HTML("请点击右侧上传论文进行预览")
with gr.Column(scale=1):
upload = gr.File(file_types=["pdf"], label="上传文档")
content = gr.Textbox(lines=2, label="论文解析", max_lines=2, visible=False)
chatbot = gr.Chatbot(
label="论文阅读助手",
value=None,
height=500
)
instruction = gr.Textbox(lines=2, label="请输入您的问题", placeholder="在这里输入问题...", max_lines=2)
with gr.Row():
submit = gr.Button("提交", size="sm", interactive=False)
clean = gr.Button("清除", size="sm")
upload.upload(fn=render_pdf, inputs=upload, outputs=pdf_render, queue=False).then(fn=extract_content, inputs=upload, outputs=[content,submit], queue=False)
submit.click(fn=start_ask, inputs=[instruction, chatbot, content], outputs=[instruction, chatbot], queue=True)
clean.click(fn=lambda: None, inputs=None, outputs=chatbot, queue=False)
return app
代码如上,只需通过简单几行代码就能搭建一个网页应用,Amazing!逻辑也不复杂,比如上面的代码就只是声明了4个组件:论文上传、论文展示、对话栏和问题输入框,2个按钮:提问按钮和清空按钮。已经做了注释,这里不进行深入说明了,感兴趣可以自行查看官方项目:Gradio
论文提取方法
之前的论文版面分析与文字提取使用了pdfplumber这个模块,它比较灵活,提供了许多底层的方法,因此可以根据自身需求设计复杂的策略。但是最近研究发现了一个更加简单的模块pymupdf,一个方法就能提取论文中的文字并保持顺序不变,真是太适合小白了
def extract_content(pdf_file):
pdf_document = fitz.open(pdf_file.name)
# 获取总页数
total_pages = pdf_document.page_count
# 提取整个文档的文本
full_text = ""
for page_num in range(total_pages):
page = pdf_document.load_page(page_num)
full_text += page.get_text("text")
return full_text, gr.Button.update(interactive=True)
读者可以对比以下之前那些繁琐冗余的代码,会发现这个实在是太好用了,太优雅了。。
模型流式输出
chatglm3提供了stream_chat的方法,可以实现像打字机一样的输出效果,减少普通数据漫长的等待时间。需要注意返回的response是一串不断变长的字符串,如果普通的print的话是会有很多行,并且每一行越来越长;可以加入flush=True这个属性以刷新显示区,实现打字机的效果。
past_key_values, history = None, []
prompt = "你是谁?介绍以下你自己的情况"
cur_len = 0
for response, history, past_key_values in model.stream_chat(tokenizer,
prompt,
history=history,
temperature=1,
past_key_values=past_key_values,
return_past_key_values=True):
print(response[cur_len:], end="", flush=True)
cur_len = len(response)
总结
这篇文章的工作在之前的基础上,改进点如下:
- 更简单的交互方式
- 更简单的论文提取方法
- 更快的响应
如果觉得这篇文章对您有些许帮助,那将是我的荣幸~
如感兴趣请查看项目地址:Ask-PDF