LangChain RAG实战——数据预处理篇:从文档加载到嵌入向量化
LangChain RAG实战——数据预处理篇从文档加载到嵌入向量化平台LangChain 阿里云百炼Qwen ChromaDB本篇介绍RAG系统的数据预处理环节涵盖文档加载、文本分割、嵌入模型三大核心模块。目录RAG技术概述环境安装与依赖文档加载器文本分割策略嵌入模型与向量化一、RAG技术概述1.1 为什么需要RAG大语言模型LLM虽然具备强大的生成能力但也存在固有的局限性问题说明RAG解决方案知识截止日期模型训练数据有时效限制实时检索最新文档幻觉问题可能生成看似合理但错误的内容基于真实文档内容生成领域知识缺乏通用模型缺乏垂直领域知识注入领域文档作为上下文信息无法更新无法动态更新模型知识直接更新向量数据库1.2 RAG核心原理RAGRetrieval-Augmented Generation检索增强生成通过以下流程解决上述问题用户查询 → 向量化检索 → 相关文档匹配 → 上下文组装 → LLM生成 → 回答核心思想将检索系统获取的相关信息作为上下文帮助LLM生成更准确、更可靠的答案。1.3 RAG系统架构RAG系统主要分为两个阶段索引构建阶段Indexing文档加载 → 文本分割 → 嵌入向量化 → 存储至向量数据库检索生成阶段RAG用户查询向量化 → 相似度检索 → 上下文组装 → LLM增强生成二、环境安装与依赖2.1 基础依赖安装pipinstalllangchain langchain-openai langchain-core langchain-community pipinstallopenai chromadb pipinstallpypdf python-docx tenacity pipinstalltiktoken包名说明langchain核心框架langchain-community第三方集成ChromaDB等chromadb向量数据库pypdfPDF文档解析python-docxWord文档解析tiktokenToken计数工具2.2 环境变量配置importos# 阿里云百炼 API 配置os.environ[DASHSCOPE_API_KEY]sk-xxxxxxxxxxxxxxxx# OpenAI兼容接口配置OPENAI_API_BASEhttps://dashscope.aliyuncs.com/compatible-mode/v1三、文档加载器3.1 LangChain文档加载器概述LangChain提供了丰富的文档加载器支持多种格式加载器支持格式适用场景PyPDFLoaderPDF论文、技术文档Docx2txtLoaderWord (.docx)办公文档TextLoaderTXT纯文本UnstructuredHTMLLoaderHTML网页内容CSVLoaderCSV表格数据3.2 PDF文档加载# 01_document_loader.pyfromlangchain_community.document_loadersimportPyPDFLoaderfromlangchain.schemaimportDocument# 加载单个PDF文件loaderPyPDFLoader(document/sample.pdf)pagesloader.load()# 加载多个PDF文件fromlangchain_community.document_loadersimportDirectoryLoader loaderDirectoryLoader(pathdocuments/,glob*.pdf,loader_clsPyPDFLoader)documentsloader.load()# 查看文档内容forpageinpages:print(f页码:{page.metadata[page]})print(f内容:{page.page_content[:200]}...)print(-*50)3.3 Word文档加载# 01_document_loader.pyfromlangchain_community.document_loadersimportDocx2txtLoader loaderDocx2txtLoader(document/report.docx)documentsloader.load()fordocindocuments:print(doc.page_content)3.4 文本文件加载# 01_document_loader.pyfromlangchain_community.document_loadersimportTextLoader loaderTextLoader(document/readme.txt,encodingutf-8)documentsloader.load()3.5 加载结果格式LangChain的文档加载器返回Document对象列表每个文档包含classDocument:page_content:str# 文档内容文本metadata:dict# 元数据来源、页码等# 示例documentDocument(page_content这是文档的文本内容...,metadata{source:document/sample.pdf,page:0,total_pages:10})四、文本分割策略4.1 为什么需要文本分割LLM有token数量限制且完整文档太长无法全部放入上下文检索效率小块文档更易于精确匹配语义完整性适当的分块保持语义连贯4.2 分割策略对比策略原理优点缺点递归字符分割按字符递归切分通用性强可能切断语义按段落分割按自然段落边界保持完整语义块大小不均匀滑动窗口重叠切分减少边界丢失冗余信息多Token分割按token数切分精确控制大小中途切断词4.3 RecursiveCharacterTextSplitterLangChain推荐使用递归字符分割器# 02_text_splitter.pyfromlangchain.text_splitterimportRecursiveCharacterTextSplitter# 创建分割器text_splitterRecursiveCharacterTextSplitter(chunk_size500,# 块大小字符数chunk_overlap50,# 重叠大小减少边界丢失length_functionlen,# 长度计算函数separators[\n\n,\n,。,, ,]# 分割符优先级)# 分割文档textstext_splitter.split_documents(documents)print(f原始文档数:{len(documents)})print(f分割后块数:{len(texts)})# 查看分割结果fori,chunkinenumerate(texts[:3]):print(f\n--- Chunk{i1}---)print(f内容:{chunk.page_content[:100]}...)print(f元数据:{chunk.metadata})4.4 按段落分割# 02_text_splitter.pyfromlangchain.text_splitterimportNLTKTextSplitter text_splitterNLTKTextSplitter(separator\n\n,# 按双换行分割段落chunk_size1000,chunk_overlap100)textstext_splitter.split_text(long_text)4.5 Token感知分割# 02_text_splitter.pyfromlangchain.text_splitterimportTokenTextSplitter text_splitterTokenTextSplitter(chunk_size500,# 块大小token数chunk_overlap50,# 重叠token数encoding_namecl100k_base# OpenAI编码)textstext_splitter.split_text(text)4.6 自定义分割器# 02_text_splitter.pyfromlangchain.text_splitterimportTextSplitterclassChineseTextSplitter(TextSplitter):中文文本分割器def__init__(self,**kwargs):super().__init__(**kwargs)defsplit_text(self,text:str)-list[str]:# 按中文标点和换行分割importre paragraphsre.split(r[\n。\n],text)chunks[]forparainparagraphs:ifpara.strip():iflen(para)self._chunk_size:chunks.append(para)else:# 进一步分割sub_chunksself._split_long_text(para)chunks.extend(sub_chunks)returnchunksdef_split_long_text(self,text:str)-list[str]:chunks[]start0whilestartlen(text):endstartself._chunk_size chunktext[start:end]chunks.append(chunk)startend-self._chunk_overlapreturnchunks五、嵌入模型与向量化5.1 嵌入模型原理嵌入Embedding将文本转换为稠密向量使语义相似的文本在向量空间中距离更近文本 → 嵌入模型 → 向量 [0.12, -0.34, 0.56, ..., 0.89]5.2 常用嵌入模型模型提供商维度特点text-embedding-ada-002OpenAI1536通用性强text-embedding-3-smallOpenAI1536/256高效轻量text-embedding-3-largeOpenAI3072高精度m3e-baseMokaAI768中文优化bge-base-zhBAAI768中英文双语5.3 OpenAI嵌入# 03_embedding.pyfromlangchain_openaiimportOpenAIEmbeddings embeddingsOpenAIEmbeddings(modeltext-embedding-3-small,openai_api_keyos.getenv(DASHSCOPE_API_KEY),openai_api_basehttps://dashscope.aliyuncs.com/compatible-mode/v1)# 单文本嵌入query什么是人工智能vectorembeddings.embed_query(query)print(f向量维度:{len(vector)})print(f向量前5位:{vector[:5]})# 多文本嵌入texts[文本1,文本2,文本3]vectorsembeddings.embed_documents(texts)print(f嵌入数量:{len(vectors)})5.4 本地嵌入模型中文优化# 03_embedding.pyfromlangchain_community.embeddingsimportHuggingFaceBgeEmbeddings# BAAI BGE中文嵌入模型embeddingsHuggingFaceBgeEmbeddings(model_nameBAAI/bge-base-zh-v1.5,model_kwargs{device:cpu},encode_kwargs{normalize_embeddings:True})# 使用本地模型进行嵌入query人工智能的应用领域vectorembeddings.embed_query(query)print(f向量维度:{len(vector)})5.5 向量相似度计算# 03_embedding.pyimportnumpyasnpfromsklearn.metrics.pairwiseimportcosine_similaritydefcalculate_similarity(vec1,vec2):计算余弦相似度returncosine_similarity([vec1],[vec2])[0][0]defeuclidean_distance(vec1,vec2):计算欧氏距离returnnp.linalg.norm(np.array(vec1)-np.array(vec2))# 示例vec_a[0.1,0.2,0.3,0.4]vec_b[0.11,0.21,0.31,0.41]vec_c[0.9,0.8,0.7,0.6]print(fA vs B 相似度:{calculate_similarity(vec_a,vec_b):.4f})# 高相似print(fA vs C 相似度:{calculate_similarity(vec_a,vec_c):.4f})# 低相似本篇总结本篇介绍了RAG系统的数据预处理三大模块模块核心组件作用文档加载PyPDFLoader、Docx2txtLoader解析多种格式文档文本分割RecursiveCharacterTextSplitter智能分块保持语义嵌入向量化OpenAI Embeddings、BGE文本转稠密向量下篇预告《LangChain RAG实战——向量存储与检索篇》将介绍向量数据库选择、语义检索实现、RAG Chain构建等核心内容。