paper-qa

paper-qa

基于文档的智能问答系统 实现精准信息检索和回答生成

paper-qa是一款轻量级文档问答工具包,专门从PDF和文本文件中提取信息并生成回答。通过文档嵌入、向量搜索和摘要生成等技术,结合大型语言模型,paper-qa能够提供高质量且有据可依的回答。支持OpenAI、Anthropic等多种嵌入和语言模型,并可集成本地托管模型。工具提供异步API,支持自定义文档添加和引用格式推断,还可整合外部向量存储。这些特性使paper-qa成为科研和信息检索领域的实用解决方案。

PaperQA文献问答嵌入式向量LLM异步处理Github开源项目

PaperQA

GitHub tests PyPI version

这是一个用于对PDF或文本文件(可以是原始HTML)进行问答的简洁软件包。它致力于通过在文本中引用来源,提供非常优质的答案,避免产生幻觉。

默认情况下,它使用OpenAI Embeddings和一个简单的numpy向量数据库来嵌入和搜索文档。然而,通过langchain,你也可以使用开源模型或嵌入(详情见下文)。

paper-qa使用以下流程:

  1. 将文档嵌入为向量
  2. 将查询嵌入为向量
  3. 在文档中搜索前k个相关段落
  4. 为每个与查询相关的段落创建摘要
  5. 使用LLM重新评分并仅选择相关摘要
  6. 将摘要放入提示中
  7. 用提示生成答案

更多详情请参阅我们的论文:

@article{lala2023paperqa, title={PaperQA: Retrieval-Augmented Generative Agent for Scientific Research}, author={L{\'a}la, Jakub and O'Donoghue, Odhran and Shtedritski, Aleksandar and Cox, Sam and Rodriques, Samuel G and White, Andrew D}, journal={arXiv preprint arXiv:2312.07559}, year={2023} }

输出示例

问题:如何大规模制造碳纳米管?

碳纳米管可以使用电弧技术进行大规模制造(Journet6644)。这种技术涉及在氦气氛围的反应器中,在两个电极之间产生电弧,并在阳极中使用金属催化剂和石墨粉的混合物。这种方法可以获得80%的缠绕碳纤维产率,这些纤维由较小的对齐单壁碳纳米管(SWNTs)自组装成束状晶体(Journet6644)。此外,碳纳米管还可以通过各种方法合成和自组装,如DNA介导的自组装、纳米颗粒辅助对齐、化学自组装和电寻址功能化(Tulevski2007)。这些方法已被用于制造大面积纳米结构阵列、高密度集成和自立网络(Tulevski2007)。还可以使用98%的半导体碳纳米管网络溶液,该溶液通过密度梯度超离心方法从金属纳米管中分离出来(Chen2014)。将基板浸入溶液中,然后用去离子水冲洗并用N2气枪吹干,留下均匀的碳网络(Chen2014)。

参考文献

Journet6644: Journet, Catherine, et al. "Large-scale production of single-walled carbon nanotubes by the electric-arc technique." nature 388.6644 (1997): 756-758.

Tulevski2007: Tulevski, George S., et al. "Chemically assisted directed assembly of carbon nanotubes for the fabrication of large-scale device arrays." Journal of the American Chemical Society 129.39 (2007): 11964-11968.

Chen2014: Chen, Haitian, et al. "Large-scale complementary macroelectronics using hybrid integration of carbon nanotubes and IGZO thin-film transistors." Nature communications 5.1 (2014): 4097.

最新更新

版本4移除了langchain包,因为它不再支持序列化。这也简化了软件包,特别是提示部分。Langchain仍然可以使用,但不是必需的。你可以使用langchain中的任何LLMs,但需要使用LangchainLLMModel类来包装模型。

安装

使用pip安装:

pip install paper-qa

你需要有一个LLM来使用paper-qa。你可以使用OpenAI、llama.cpp(通过服务器)或langchain中的任何LLMs。只要你设置了OpenAI API密钥(export OPENAI_API_KEY=sk-...),OpenAI就可以直接使用。其他LLMs的使用说明见下文。

使用方法

要使用paper-qa,你需要有一个路径/文件/URL列表(有效扩展名包括:.pdf, .txt)。然后你可以使用Docs类来添加文档并进行查询。Docs会尝试从文件内容中猜测引用格式,但你也可以自己提供。

from paperqa import Docs my_docs = ... # 获取路径列表 docs = Docs() for d in my_docs: docs.add(d) answer = docs.query( "双特异性抗体制造面临哪些独特的挑战?" ) print(answer.formatted_answer)

answer对象具有以下属性:formatted_answeranswer(仅答案)、questioncontext(用于回答的段落摘要)。

异步

paper-qa被设计为异步使用。同步API只是异步的包装器。以下是方法及其异步等效项:

同步异步
Docs.addDocs.aadd
Docs.add_fileDocs.aadd_file
Docs.add_urlDocs.aadd_url
Docs.get_evidenceDocs.aget_evidence
Docs.queryDocs.aquery

同步版本只是在循环中调用异步版本。大多数现代Python环境原生支持异步(包括Jupyter笔记本!)。因此,你可以在Jupyter笔记本中这样做:

from paperqa import Docs my_docs = ... # 获取路径列表 docs = Docs() for d in my_docs: await docs.aadd(d) answer = await docs.aquery( "双特异性抗体制造面临哪些独特的挑战?" )

添加文档

add将从路径添加。你也可以使用add_file(需要一个文件对象)或add_url来处理其他来源。

选择模型

默认情况下,它使用OpenAI模型,结合了gpt-4o-mini(用于重新排序和摘要步骤,summary_llm参数)和gpt-4-turbo(用于回答步骤,llm参数)。你可以调整这个设置:

docs = Docs(llm="gpt-4o-mini", summary_llm="gpt-4o")

你可以通过指定Anthropic客户端来使用Anthropic模型:

from paperqa import Docs from anthropic import AsyncAnthropic docs = Docs( llm="claude-3-5-sonnet-20240620", summary_llm="claude-3-5-sonnet-20240620", client=AsyncAnthropic(), )

或者你可以使用langchain中可用的任何其他模型:

from paperqa import Docs from langchain_community.chat_models import ChatAnthropic docs = Docs(llm="langchain", client=ChatAnthropic())

注意,我们将模型分为包装器和client,这里的clientChatAnthropic。这是因为client存储了不可序列化的部分,而langchain LLMs有时只能序列化/序列化。paper-qa的Docs必须始终可序列化。因此,我们将模型分为两部分。

import pickle docs = Docs(llm="langchain", client=ChatAnthropic()) model_str = pickle.dumps(docs) docs = pickle.loads(model_str) # 但你必须在加载后设置客户端 docs.set_client(ChatAnthropic())

我们还支持使用Anyscale来利用托管的开源模型。要使用它,你只需设置ANYSCALE_API_KEYANYSCALE_BASE_URL环境变量,或使用从Anyscale初始化的OpenAI客户端,并提供api_keybase_url参数。

本地托管

你可以使用llama.cpp作为LLM。请注意,你应该使用相对较大的模型,因为paper-qa需要遵循很多指令。7B模型的性能不会很好。

最简单的设置方法是下载一个llama文件并用-cb -np 4 -a my-llm-model --embedding执行它,这将启用连续批处理和嵌入。

from paperqa import Docs, LlamaEmbeddingModel from openai import AsyncOpenAI # 启动llama.cpp客户端 local_client = AsyncOpenAI( base_url="http://localhost:8080/v1", api_key="sk-no-key-required" ) docs = Docs( client=local_client, docs_index=NumpyVectorStore(embedding_model=LlamaEmbeddingModel()), texts_index=NumpyVectorStore(embedding_model=LlamaEmbeddingModel()), llm_model=OpenAILLMModel( config=dict( model="my-llm-model", temperature=0.1, frequency_penalty=1.5, max_tokens=512 ) ), )

更改嵌入模型

paper-qa默认使用OpenAI(text-embedding-3-small)嵌入,但对向量存储和嵌入选择都有灵活的选项。更改嵌入的最简单方法是通过Docs对象构造函数的embedding参数:

from paperqa import Docs docs = Docs(embedding="text-embedding-3-large")

embedding接受:

  • 任何OpenAI嵌入模型名称
  • VoyageAI模型名称(如果安装了voyageai并设置了VOYAGE_API_KEY可用)
  • "sentence-transformers"使用Sentence Transformersmulti-qa-MiniLM-L6-cos-v1
  • "hybrid-<model_name>",例如"hybrid-text-embedding-3-small"使用混合稀疏关键词(基于令牌模数嵌入)和密集向量嵌入,任何OpenAI或VoyageAI模型都可以用作密集模型名称
  • "sparse"仅使用稀疏关键词嵌入

对于更深入的嵌入自定义,可以单独构建嵌入模型和向量存储,然后传递给Docs对象。嵌入模型用于创建paper-qa的文档引用嵌入向量索引(docs_index参数)以及全文嵌入向量(texts_index参数)。在创建新的Docs对象时,可以将它们都指定为参数。你可以使用任何实现paper-qa的EmbeddingModel类的嵌入模型。例如,使用text-embedding-3-large

from paperqa import Docs, NumpyVectorStore, OpenAIEmbeddingModel docs = Docs( docs_index=NumpyVectorStore( embedding_model=OpenAIEmbeddingModel(name="text-embedding-3-large") ), texts_index=NumpyVectorStore( embedding_model=OpenAIEmbeddingModel(name="text-embedding-3-large") ), )

请注意,嵌入模型被指定为paper-qa的VectorStore基类的属性。NumpyVectorStore是最好的起点,它是一个简单的内存存储,没有索引。如果需要大于内存的向量存储,你可以这样使用LangchainVectorStore

from langchain_community.vectorstores.faiss import FAISS from langchain_openai import OpenAIEmbeddings from paperqa import Docs, LangchainVectorStore docs = Docs( docs_index=LangchainVectorStore(cls=FAISS, embedding_model=OpenAIEmbeddings()), texts_index=LangchainVectorStore(cls=FAISS, embedding_model=OpenAIEmbeddings()), )

我们支持本地langchain嵌入模型和SentenceTransformer模型。例如:

from paperqa import Docs, SentenceTransformerEmbeddingModel from openai import AsyncOpenAI # 启动llama.cpp客户端 local_client = AsyncOpenAI( base_url="http://localhost:8080/v1", api_key="sk-no-key-required" ) docs = Docs( client=local_client, docs_index=NumpyVectorStore(embedding_model=SentenceTransformerEmbeddingModel()), texts_index=NumpyVectorStore(embedding_model=SentenceTransformerEmbeddingModel()), llm_model=OpenAILLMModel( config=dict( model="my-llm-model", temperature=0.1, frequency_penalty=1.5, max_tokens=512 ) ), )

我们还支持混合关键词(稀疏令牌模数向量)和密集嵌入向量。它们可以这样指定:

from paperqa import Docs, HybridEmbeddingModel, SparseEmbeddingModel, NumpyVectorStore model = HybridEmbeddingModel(models=[OpenAIEmbeddingModel(), SparseEmbeddingModel()]) docs = Docs( docs_index=NumpyVectorStore(embedding_model=model), texts_index=NumpyVectorStore(embedding_model=model), )

稀疏嵌入(关键词)模型默认有256个维度,但可以通过ndim参数指定。

调整源数量

你可以调整源(文本段落)的数量以减少令牌使用或添加更多上下文。k指的是最相关和多样化(可能来自不同源)的前k个段落。每个段落都会被发送给LLM进行总结,或确定是否无关。在此步骤之后,应用max_sources限制,以便最终答案能够适应LLM上下文窗口。因此,k > max_sources,而max_sources是最终答案中使用的源数量。

docs.query( "双特异性抗体特有的制造挑战是什么?", k=5, max_sources=2, )

使用代码或HTML

你不需要使用论文 - 你可以使用代码或原始HTML。请注意,这个工具专注于回答问题,所以它在编写代码方面表现不佳。需要注意的是,该工具无法从代码中推断引用,所以你需要自己提供它们。

import glob source_files = glob.glob("**/*.js") docs = Docs() for f in source_files: # 这假设代码中的文件名是唯一的 docs.add(f, citation="文件 " + os.path.name(f), docname=os.path.name(f)) answer = docs.query("页眉中的搜索栏在哪里定义?") print(answer)

使用外部数据库/向量数据库和缓存

你可能想在外部数据库或文件中缓存解析的文本和嵌入。然后你可以直接从这些构建Docs对象:

docs = Docs() for ... in my_docs: doc = Doc(docname=..., citation=..., dockey=..., citation=...) texts = [Text(text=..., name=..., doc=doc) for ... in my_texts] docs.add_texts(texts, doc)

如果你想使用外部向量存储,也可以通过langchain直接实现。例如,使用langchain的FAISS向量存储:

from paperqa import LangchainVectorStore, Docs from langchain_community.vector_store import FAISS from langchain_openai import OpenAIEmbeddings docs = Docs( texts_index=LangchainVectorStore(cls=FAISS, embedding_model=OpenAIEmbeddings()), docs_index=LangchainVectorStore(cls=FAISS, embedding_model=OpenAIEmbeddings()), )

我从哪里获取论文?

这是一个很好的问题!最好的方法可能是下载你认为有助于回答问题的论文的PDF,然后从那里开始。

Zotero

如果你使用Zotero来组织你的个人参考文献,你可以使用paperqa.contrib.ZoteroDB从你的库中查询论文,它依赖于pyzotero

安装pyzotero以使用此功能:

pip install pyzotero

首先,请注意paperqa解析论文的PDF以存储在数据库中,所以所有相关论文都应该在你的数据库中存储PDF。你可以让Zotero自动执行此操作,方法是高亮显示你想检索的参考文献,右键单击,然后选择"查找可用的PDF"。你也可以手动将PDF拖放到每个参考文献上。

要下载论文,你需要获取你账户的API密钥。

  1. 获取您的图书馆ID,并将其设置为环境变量 ZOTERO_USER_ID
    • 对于个人图书馆,该ID可在此处找到,位于"您在API调用中使用的userID为XXXXXX"部分。
    • 对于群组图书馆,请访问您的群组页面 https://www.zotero.org/groups/groupname,将鼠标悬停在设置链接上。ID是/groups/后的整数。(感谢pyzotero提供的提示!)
  2. 此处创建一个新的API密钥,并将其设置为环境变量 ZOTERO_API_KEY
    • 该密钥需要对图书馆有读取权限。

有了这些,我们就可以从我们的图书馆下载论文并将它们添加到 paperqa 中:

from paperqa.contrib import ZoteroDB docs = paperqa.Docs() zotero = ZoteroDB(library_type="user") # 如果是群组图书馆,则为"group" for item in zotero.iterate(limit=20): if item.num_pages > 30: continue # 跳过长篇论文 docs.add(item.pdf, docname=item.key)

这将下载Zotero数据库中的前20篇论文并将它们添加到 Docs 对象中。

我们还可以对Zotero图书馆进行特定查询并遍历结果:

for item in zotero.iterate( q="large language models", qmode="everything", sort="date", direction="desc", limit=100, ): print("正在添加", item.title) docs.add(item.pdf, docname=item.key)

您可以在IPython中输入 zotero.iterate? 以了解更多关于搜索语法的信息。

论文抓取器

如果您想搜索自己收藏之外的论文,我发现了一个名为paper-scraper的无关项目,看起来可能会有帮助。但请注意,该项目似乎使用了一些可能违反出版商权利或处于法律灰色地带的抓取工具。

keyword_search = "bispecific antibody manufacture" papers = paperscraper.search_papers(keyword_search) docs = paperqa.Docs() for path, data in papers.items(): try: docs.add(path) except ValueError as e: # 有时如果PDF未下载或无法读取会发生这种情况 print("无法读取", path, e) answer = docs.query( "双特异性抗体制造有哪些独特的挑战?" ) print(answer)

PDF阅读选项

默认情况下使用PyPDF,因为它是纯Python实现且易于安装。为了更快的PDF阅读,paper-qa会检测并使用PymuPDF (fitz)

pip install pymupdf

回调工厂

要在LLM完成的每个块上执行函数,您需要提供一个函数,该函数在被调用时会根据步骤名称生成要在每个块上执行的函数列表。例如,要获得完成内容的打字机视图,您可以这样做:

def make_typewriter(step_name): def typewriter(chunk): print(chunk, end="") return [typewriter] # <- 注意这是一个函数列表 ... docs.query( "双特异性抗体制造有哪些独特的挑战?", get_callbacks=make_typewriter, )

缓存嵌入

通常,无论您使用什么向量存储,当您pickle一个 Docs 时,嵌入都会被缓存。有关更明确管理它们的详细信息,请参见上文。

自定义提示

您可以使用 PromptCollection 类自定义任何提示。例如,如果您想更改问题的提示,可以这样做:

from paperqa import Docs, Answer, PromptCollection my_qaprompt = ( "回答问题'{question}' " "如果有帮助,请使用下面的上下文。" "您可以使用键来引用上下文 " "例如(Example2012)。" "如果上下文不足,请写一首诗 " "描述您无法回答的情况。\n\n" "上下文:{context}\n\n" ) prompts = PromptCollection(qa=my_qaprompt) docs = Docs(prompts=prompts)

前置和后置提示

按照上面的语法,您还可以包含在查询之前和之后执行的提示。例如,您可以使用它来对答案进行评论。

常见问题

这与LlamaIndex有何不同?

它并没有太大的不同!这类似于LlamaIndex中的树响应方法。我只是包含了一些我认为有用的提示,能提供页码/行号的阅读器,并专注于一个任务 - 用引用源回答技术问题。

这与LangChain有何不同?

LangChain在检索器方面做了一些很棒的工作,你可以说这是一个基于LLM重新排序和上下文摘要的检索器的例子。

我可以保存或加载吗?

Docs 类可以被pickle和unpickle。如果您想保存文档的嵌入,然后稍后加载它们,这会很有用。

import pickle # 保存 with open("my_docs.pkl", "wb") as f: pickle.dump(docs, f) # 加载 with open("my_docs.pkl", "rb") as f: docs = pickle.load(f) docs.set_client() # 默认使用OpenAI

编辑推荐精选

Trae

Trae

字节跳动发布的AI编程神器IDE

Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。

AI工具TraeAI IDE协作生产力转型热门
问小白

问小白

全能AI智能助手,随时解答生活与工作的多样问题

问小白,由元石科技研发的AI智能助手,快速准确地解答各种生活和工作问题,包括但不限于搜索、规划和社交互动,帮助用户在日常生活中提高效率,轻松管理个人事务。

热门AI助手AI对话AI工具聊天机器人
Transly

Transly

实时语音翻译/同声传译工具

Transly是一个多场景的AI大语言模型驱动的同声传译、专业翻译助手,它拥有超精准的音频识别翻译能力,几乎零延迟的使用体验和支持多国语言可以让你带它走遍全球,无论你是留学生、商务人士、韩剧美剧爱好者,还是出国游玩、多国会议、跨国追星等等,都可以满足你所有需要同传的场景需求,线上线下通用,扫除语言障碍,让全世界的语言交流不再有国界。

讯飞智文

讯飞智文

一键生成PPT和Word,让学习生活更轻松

讯飞智文是一个利用 AI 技术的项目,能够帮助用户生成 PPT 以及各类文档。无论是商业领域的市场分析报告、年度目标制定,还是学生群体的职业生涯规划、实习避坑指南,亦或是活动策划、旅游攻略等内容,它都能提供支持,帮助用户精准表达,轻松呈现各种信息。

AI办公办公工具AI工具讯飞智文AI在线生成PPTAI撰写助手多语种文档生成AI自动配图热门
讯飞星火

讯飞星火

深度推理能力全新升级,全面对标OpenAI o1

科大讯飞的星火大模型,支持语言理解、知识问答和文本创作等多功能,适用于多种文件和业务场景,提升办公和日常生活的效率。讯飞星火是一个提供丰富智能服务的平台,涵盖科技资讯、图像创作、写作辅助、编程解答、科研文献解读等功能,能为不同需求的用户提供便捷高效的帮助,助力用户轻松获取信息、解决问题,满足多样化使用场景。

热门AI开发模型训练AI工具讯飞星火大模型智能问答内容创作多语种支持智慧生活
Spark-TTS

Spark-TTS

一种基于大语言模型的高效单流解耦语音令牌文本到语音合成模型

Spark-TTS 是一个基于 PyTorch 的开源文本到语音合成项目,由多个知名机构联合参与。该项目提供了高效的 LLM(大语言模型)驱动的语音合成方案,支持语音克隆和语音创建功能,可通过命令行界面(CLI)和 Web UI 两种方式使用。用户可以根据需求调整语音的性别、音高、速度等参数,生成高质量的语音。该项目适用于多种场景,如有声读物制作、智能语音助手开发等。

咔片PPT

咔片PPT

AI助力,做PPT更简单!

咔片是一款轻量化在线演示设计工具,借助 AI 技术,实现从内容生成到智能设计的一站式 PPT 制作服务。支持多种文档格式导入生成 PPT,提供海量模板、智能美化、素材替换等功能,适用于销售、教师、学生等各类人群,能高效制作出高品质 PPT,满足不同场景演示需求。

讯飞绘文

讯飞绘文

选题、配图、成文,一站式创作,让内容运营更高效

讯飞绘文,一个AI集成平台,支持写作、选题、配图、排版和发布。高效生成适用于各类媒体的定制内容,加速品牌传播,提升内容营销效果。

热门AI辅助写作AI工具讯飞绘文内容运营AI创作个性化文章多平台分发AI助手
材料星

材料星

专业的AI公文写作平台,公文写作神器

AI 材料星,专业的 AI 公文写作辅助平台,为体制内工作人员提供高效的公文写作解决方案。拥有海量公文文库、9 大核心 AI 功能,支持 30 + 文稿类型生成,助力快速完成领导讲话、工作总结、述职报告等材料,提升办公效率,是体制打工人的得力写作神器。

openai-agents-python

openai-agents-python

OpenAI Agents SDK,助力开发者便捷使用 OpenAI 相关功能。

openai-agents-python 是 OpenAI 推出的一款强大 Python SDK,它为开发者提供了与 OpenAI 模型交互的高效工具,支持工具调用、结果处理、追踪等功能,涵盖多种应用场景,如研究助手、财务研究等,能显著提升开发效率,让开发者更轻松地利用 OpenAI 的技术优势。

下拉加载更多