使用HuggingFace与Pinecone嵌入PDF摘要时向量无效的解决方案咨询
问题与解决方案
问题描述
处理一批已摘要的PDF文件,使用HuggingFace模型生成嵌入向量后,以原文档名称作为namespace存入Pinecone数据库时,始终触发ValueError(提示向量无效)。
错误原因分析
- 向量格式错误:Pinecone的
upsert方法要求vectors参数为二维列表(每个子列表对应一个向量),但原代码直接传入了单个一维向量。 - namespace参数使用错误:
upsert方法没有namespaces参数,正确指定namespace的方式是用单个字符串的namespace参数。 - ID类型错误:Pinecone要求
ids的元素为字符串类型,原代码传入的整数i不符合要求。 - 重复初始化索引:循环内每次都创建
pinecone.Index实例,属于冗余操作,影响效率。
修复后的完整代码
import os from langchain.document_loaders import DirectoryLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings import HuggingFaceEmbeddings import pinecone class Embedding: def __init__(self): self.embeddings = HuggingFaceEmbeddings(model_name="paraphrase-MiniLM-L6-v2") # 提前初始化Pinecone索引,避免循环内重复创建 self.initialize_pinecone() self.index = pinecone.Index("lecture-index") def initialize_pinecone(self): pinecone.init( api_key="apikey", environment="environment", ) def load_documents(self, folder_path): document_loader = DirectoryLoader(path=folder_path) documents = document_loader.load() return documents def split_documents(self, documents, chunk_size=1000, chunk_overlap=100): text_splitter = RecursiveCharacterTextSplitter( chunk_size=chunk_size, chunk_overlap=chunk_overlap ) split_docs = text_splitter.split_documents(documents) return split_docs def embed(self): print("\n-------EMBEDDING-------") summarizedTextsPath = os.path.join(os.path.dirname(__file__), "summarizedTexts") summarizedDocs = self.load_documents(summarizedTextsPath) summarizedDocsSplit = self.split_documents(summarizedDocs) # 批量处理优化,避免单次upsert效率低下 batch_size = 100 for batch_start in range(0, len(summarizedDocsSplit), batch_size): batch_end = min(batch_start + batch_size, len(summarizedDocsSplit)) batch_docs = summarizedDocsSplit[batch_start:batch_end] ids = [] vectors = [] namespace_map = {} for idx, doc in enumerate(batch_docs, start=batch_start): text = doc.page_content # 跳过空文本,避免生成无效向量 if not text.strip(): continue vector = self.embeddings.embed_query(text) doc_name = os.path.splitext(os.path.basename(doc.metadata["source"]))[0] # ID转为字符串类型 doc_id = str(idx) ids.append(doc_id) vectors.append(vector) namespace_map[doc_id] = doc_name # 按namespace分组批量插入,同一namespace的向量一起upsert for ns in set(namespace_map.values()): ns_ids = [id for id in ids if namespace_map[id] == ns] ns_vectors = [vec for id, vec in zip(ids, vectors) if namespace_map[id] == ns] self.index.upsert(ids=ns_ids, vectors=ns_vectors, namespace=ns) print("Database access successful.")
关键注意事项
- 索引维度匹配:确保Pinecone创建的索引维度与
paraphrase-MiniLM-L6-v2的输出维度一致(该模型输出384维向量),否则会触发维度不匹配错误。 - 空文本处理:添加空文本检查,避免生成无效的空向量。
- 批量插入优化:采用批量插入替代循环单次插入,大幅提升数据写入效率。
- namespace命名规则:Pinecone的namespace名称不能包含特殊字符,需确保文档名称符合要求。
内容的提问来源于stack exchange,提问作者lucasgoddamn
相关产品推荐
相关产品推荐

