基于OpenAI的多PDF加载与向量嵌入问题:索引仅保留最后文件
问题原因及解决方案
你的代码出现向量索引仅保留最后一个PDF的问题,核心原因有两个:
- 循环中每次执行
vectorstore = FAISS.from_documents(documents, embeddings)都会创建新的FAISS实例,直接覆盖之前的向量库,最终只保留最后一次循环生成的结果。 - 用
ab模式将多个独立的FAISS实例写入同一个pickle文件,这种方式无法实现向量库的合并,后续加载也无法直接使用完整的合并结果。
下面提供两种可行的修改方案:
方案一:先收集所有文档片段,再一次性创建向量库
适合文档数量不大的场景,先把所有PDF的文本片段收集起来,再统一生成向量库:
from langchain.text_splitter import CharacterTextSplitter from langchain.document_loaders import UnstructuredPDFLoader from langchain.vectorstores.faiss import FAISS from langchain.embeddings import OpenAIEmbeddings import pickle import os print("Loading data...") pdf_folder_path = "content/" print(os.listdir(pdf_folder_path)) # 加载所有PDF文件的加载器 loaders = [UnstructuredPDFLoader(os.path.join(pdf_folder_path, fn)) for fn in os.listdir(pdf_folder_path)] print(loaders) alldocument = [] for loader in loaders: print("Loading raw document..." + loader.file_path) raw_documents = loader.load() print("Splitting text...") text_splitter = CharacterTextSplitter( separator="\n\n", chunk_size=800, chunk_overlap=100, length_function=len, ) documents = text_splitter.split_documents(raw_documents) alldocument += documents # 累加所有文档的文本片段 # 基于全部文档创建向量库 print("Creating vectorstore from all documents...") embeddings = OpenAIEmbeddings() vectorstore = FAISS.from_documents(alldocument, embeddings) # 保存合并后的向量库 with open("vectorstore.pkl", "wb") as f: pickle.dump(vectorstore, f)
方案二:循环中逐步合并向量库
适合单文档体积较大的场景,避免一次性加载所有文档到内存:
from langchain.text_splitter import CharacterTextSplitter from langchain.document_loaders import UnstructuredPDFLoader from langchain.vectorstores.faiss import FAISS from langchain.embeddings import OpenAIEmbeddings import pickle import os print("Loading data...") pdf_folder_path = "content/" print(os.listdir(pdf_folder_path)) # 加载所有PDF文件的加载器 loaders = [UnstructuredPDFLoader(os.path.join(pdf_folder_path, fn)) for fn in os.listdir(pdf_folder_path)] print(loaders) vectorstore = None embeddings = OpenAIEmbeddings() # 提前初始化嵌入模型,避免重复创建 for loader in loaders: print("Loading raw document..." + loader.file_path) raw_documents = loader.load() print("Splitting text...") text_splitter = CharacterTextSplitter( separator="\n\n", chunk_size=800, chunk_overlap=100, length_function=len, ) documents = text_splitter.split_documents(raw_documents) print("Updating vectorstore...") if vectorstore is None: # 处理第一个文档,创建初始向量库 vectorstore = FAISS.from_documents(documents, embeddings) else: # 将后续文档的片段添加到已有向量库中 vectorstore.add_documents(documents) # 保存合并后的向量库 with open("vectorstore.pkl", "wb") as f: pickle.dump(vectorstore, f)
内容的提问来源于stack exchange,提问作者Soakland
相关产品推荐
相关产品推荐

