向量计算-第10章-实战1-搭建一个“私有知识库问答助手”(RAG)_第1页
向量计算-第10章-实战1-搭建一个“私有知识库问答助手”(RAG)_第2页
向量计算-第10章-实战1-搭建一个“私有知识库问答助手”(RAG)_第3页
向量计算-第10章-实战1-搭建一个“私有知识库问答助手”(RAG)_第4页
向量计算-第10章-实战1-搭建一个“私有知识库问答助手”(RAG)_第5页
已阅读5页,还剩38页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

清华大学出版社《向量计算》配套课件·课堂讲义第10章实战1:搭建一个“私有知识库问答助手”(RAG)换个角度学AI,打通任督二脉刘鹏著·清华大学出版社从零搭建企业私有知识库:解析→切块→向量化→存库→检索生成《向量计算》配套课件第10章实战1:搭建一个“私有知识库问答助手”(RAG)第10章实战1:搭建一个“私有知识库问答助手”(RAG)2/43教学目标1掌握PDF等异构文档的解析流程与四类清洗目标2熟练使用固定/递归/Markdown三种切分器并能为切片丰富元数据3掌握Embedding模型选型依据与批量、缓存、GPU三类性能优化4能在Chroma与Milvus中建库、写入、检索并用元数据过滤5能独立搭建含多轮对话、来源追溯与Web界面的完整RAG系统重点与难点1重点:切片大小与重叠率的权衡(推荐512~1024字符、重叠20%~30%)2重点:Retriever与Generator的接口衔接和提示词约束3难点:跨页/跨段落切分导致语义割裂的工程处理方式4难点:MilvusSchema、索引类型与检索参数的联合调优《向量计算》配套课件第10章实战1:搭建一个“私有知识库问答助手”(RAG)第10章实战1:搭建一个“私有知识库问答助手”(RAG)3/43本章内容导航10.1PDF文档解析与文本切块10.2调用EmbeddingAPI进行向量化10.3存入向量数据库10.4结合LLMAPI实现"基于文档回答问题"10.5本章小结《向量计算》配套课件·第10章实战1:搭建一个“私有知识库问答助手”(RAG)10.1PDF文档解析与文本切块文档解析四大目的·切块的必要性·三类切分器·元数据与最佳实践《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)5/43文档解析:从异构文档到可索引文本●PDF:产品手册、技术规范、研究报告●Word/网页/Markdown:政策流程、知识库文章、开发指南●提取文本:从各种格式中抽取纯文本●保留结构:标题、段落、列表的层级●清理噪声:去除页眉、页脚、页码●识别元数据:文档标题、作者、创建时间图10-1学术论文的PDF文档截图《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)6/43为什么必须做文本切块(TextChunking)●向量表示模糊:整篇手册主题过多,向量难以精确表达●检索精度低:一个具体问题会召回整篇文档的大量噪声●上下文超载:GPT-3.5仅4096tokens,整篇文档超限●难以追溯来源:无法定位答案在文档中的具体位置●解决方案:切分为语义完整的Chunk,每个片段独立索引《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)7/43表10-1RAG系统核心Python库库名用途说明langchainRAG框架提供完整的RAG链式调用能力pypdfPDF解析从PDF中提取文本chromadb向量数据库轻量级向量数据库,适合快速原型pymilvusMilvus数据库高性能向量数据库,适合生产环境openaiOpenAIAPI提供Embedding和LLM服务注:安装:!pipinstalllangchainlangchain-communitylangchain-openaipypdfpython-docxbeautifulsoup4chromadb(生产环境改用pymilvus)。《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)8/43加载单个PDF文档//pythonfromlangchain_community.document_loadersimportPyPDFLoader#加载PDF文档pdf_loader=PyPDFLoader("product_manual.pdf")#执行加载documents=pdf_loader.load()#查看加载结果print(f"加载了{len(documents)}个页面")print(f"第一个页面的内容:\n{documents[0].page_content[:500]}...")print(f"第一个页面的元数据:\n{documents[0].metadata}")注:输出示例:"加载了156个页面",并打印首页正文前500字符与元数据。《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)9/43批量加载目录下所有PDF//pythonfromlangchain_community.document_loadersimportPyPDFLoaderimportglobimportos#获取所有PDF文件pdf_files=glob.glob("documents/*.pdf")#加载所有PDFall_documents=[]forpdf_fileinpdf_files:pdf_loader=PyPDFLoader(pdf_file)docs=pdf_loader.load()#为每个文档添加文件名信息fordocindocs:doc.metadata['filename']=os.path.basename(pdf_file)all_documents.extend(docs)print(f"已加载:{pdf_file}({len(docs)}页)")print(f"\n总共加载了{len(all_documents)}个文档片段")注:同理可换用Docx2txtLoader/UnstructuredMarkdownLoader/UnstructuredHTMLLoader/TextLoader处理其他格式。《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)10/43切分器1:按固定长度切分//pythonfromlangchain.text_splitterimportCharacterTextSplitter#创建字符级切分器text_splitter=CharacterTextSplitter(chunk_size=1000,#每个切片1000字符chunk_overlap=200,#切片之间重叠200字符separator="\n\n"#优先在段落分隔处切分)#执行切分chunks=text_splitter.split_documents(all_documents)print(f"切分后得到{len(chunks)}个文本块")print(f"第一个文本块:\n{chunks[0].page_content}")《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)11/43切分器2:递归切分(保持语义完整)//pythonfromlangchain.text_splitterimportRecursiveCharacterTextSplitter#创建递归切分器recursive_splitter=RecursiveCharacterTextSplitter(chunk_size=1000,#切片大小chunk_overlap=200,#重叠大小length_function=len,#长度计算函数separators=["\n\n",#段落分隔"\n",#句子分隔"。",#中文句号"!",#中文感叹号"?",#中文问号";",#中文分号"",#空格""#字符级切分]注:按separators优先级依次尝试:段落→句子→中文标点→空格→字符;执行用recursive_splitter.split_documents(all_documents)。《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)12/43切分器3:按Markdown标题层级切分//pythonfromlangchain.text_splitterimportMarkdownHeaderTextSplitter#定义标题层级markdown_splitter=MarkdownHeaderTextSplitter(headers_to_split_on=[("#","Header1"),("##","Header2"),("###","Header3"),])md_content="""#产品手册##第一章:产品概述###1.1产品简介本芯片采用超导量子比特技术...###1.2技术参数量子比特数量:72个...##第二章:安装指南..."""注:执行markdown_splitter.split_text(md_content)后,每个切片自动携带Header1/2/3元数据。《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)13/43为每个切片丰富元数据//python#为切片添加元数据fori,chunkinenumerate(chunks):#基础元数据chunk.metadata['chunk_id']=f"chunk_{i}"chunk.metadata['chunk_index']=i#文档信息chunk.metadata['document_type']='产品手册'chunk.metadata['language']='zh-CN'#切片信息chunk.metadata['chunk_length']=len(chunk.page_content)chunk.metadata['chunk_word_count']=len(chunk.page_content.split())#标题信息(如果有的话)if'Header1'inchunk.metadata:chunk.metadata['title']=chunk.metadata['Header1']elif'filename'inchunk.metadata:chunk.metadata['title']=chunk.metadata['filename']#查看元数据丰富的切片print(f"第一个切片的元数据:\n{chunks[0].metadata}")注:元数据三大作用:检索过滤(按类型/时间)、答案追溯(来源与页码)、排序优化(按重要性加权)。《向量计算》配套课件10.1PDF文档解析与文本切块第10章实战1:搭建一个“私有知识库问答助手”(RAG)14/43表10-2不同切片大小的适用场景切片大小适用场景优缺点256~512字符简短FAQ、快速问答精度高,但可能丢失上下文512~1024字符通用问答平衡精度和完整性(推荐)1024~2048字符长文档理解完整性好,但可能包含噪声2048+字符技术文档深度分析上下文丰富,但检索精度较低注:重叠取切片大小的20%~30%(1000→重叠200~300);切片开头补所属章节标题;优先在段落边界切分。《向量计算》配套课件·第10章实战1:搭建一个“私有知识库问答助手”(RAG)10.2调用EmbeddingAPI进行向量化文本向量化的含义·模型选型·OpenAI与开源模型·性能优化《向量计算》配套课件10.2调用EmbeddingAPI进行向量化第10章实战1:搭建一个“私有知识库问答助手”(RAG)16/43什么是文本向量化(TextEmbedding)●把文本转化为计算机能理解的数字向量表示●每段文字→一个包含数百个数字的列表,即这段文字的"坐标"●语义相似的文字在向量空间中距离相近●维度:text-embedding-3-small1536维/-large3072维●BGE-large-zh1024维·jina-embeddings-v2768维《向量计算》配套课件10.2调用EmbeddingAPI进行向量化第10章实战1:搭建一个“私有知识库问答助手”(RAG)17/43表10-3中文文本Embedding模型推荐模型维度特点适用场景bge-large-zh1024中文优化,性能强中文企业知识库bge-small-zh512轻量快速中文实时检索m3e-large1024多语言支持中英混合文档text-embedding-3-small1536OpenAI官方,稳定通用场景(推荐)注:选型四则:纯中文优先BGE/m3e;多语言选OpenAI/Jina;实时选768维以下轻量模型;高精度选1024维以上。《向量计算》配套课件10.2调用EmbeddingAPI进行向量化第10章实战1:搭建一个“私有知识库问答助手”(RAG)18/43配置密钥并向量化单个文本importosfromopenaiimportOpenAI#设置API密钥os.environ['OPENAI_API_KEY']='your-api-key-here'#创建OpenAI客户端client=OpenAI()//python#调用EmbeddingAPIresponse=client.embeddings.create(model="text-embedding-3-small",input="量子计算芯片采用了超导量子比特技术")#获取向量embedding_vector=response.data[0].embedding#查看向量信息print(f"向量维度:{len(embedding_vector)}")print(f"向量前10个值:{embedding_vector[:10]}")《向量计算》配套课件10.2调用EmbeddingAPI进行向量化第10章实战1:搭建一个“私有知识库问答助手”(RAG)19/43批量向量化:一次调用多条文本//python#批量向量化texts=["量子计算芯片采用了超导量子比特技术","该芯片实现了72个量子比特","相干时间提升了30%","芯片采用3D封装技术","功耗降低了40%"]response=client.embeddings.create(model="text-embedding-3-small",input=texts#一次性向量化多个文本)#获取所有向量vectors=[item.embeddingforiteminresponse.data]print(f"成功向量化{len(vectors)}个文本")print(f"每个向量的维度:{len(vectors[0])}")《向量计算》配套课件10.2调用EmbeddingAPI进行向量化第10章实战1:搭建一个“私有知识库问答助手”(RAG)20/43使用开源模型BGE(中文优化)//python#安装依赖!pipinstallsentence-transformersfromsentence_transformersimportSentenceTransformer#加载BGE中文模型model=SentenceTransformer('BAAI/bge-large-zh')#向量化文本texts=["量子计算芯片采用了超导量子比特技术","该芯片实现了72个量子比特"]vectors=model.encode(texts)print(f"向量维度:{vectors.shape[1]}")#1024print(f"向量化了{len(vectors)}个文本")注:不想走API就用sentence-transformers本地加载BGE/m3e;LangChain亦封装了OpenAIEmbeddings等统一接口。《向量计算》配套课件10.2调用EmbeddingAPI进行向量化第10章实战1:搭建一个“私有知识库问答助手”(RAG)21/43向量化性能优化三板斧●批量向量化:一次请求多条文本,减少API调用次数●结果缓存:以MD5为键存pickle,相同文本不重复计算●GPU加速:本地跑Embedding模型时显著提速●思路:先算一次、长期复用——索引阶段成本远高于查询阶段《向量计算》配套课件·第10章实战1:搭建一个“私有知识库问答助手”(RAG)10.3存入向量数据库为什么需要专用库·五大主流产品对比·Chroma实操·Milvus实操·索引优化《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)23/43为什么需要向量数据库●传统数据库的局限:不支持相似度计算–线性扫描复杂度O(n),无法处理大规模数据–缺乏专门针对向量的索引结构●向量数据库的优势:内置HNSW/IVF/PQ高效索引–SIMD指令集与GPU加速相似度计算–水平扩展支持十亿级向量,检索时可叠加元数据过滤《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)24/43表10-4主流向量数据库对比数据库特点开源/商业适用规模学习成本Chroma轻量级,易用开源十万级低Milvus高性能,功能全开源百万级+中Pinecone云原生,全托管商业百万级+低Weaviate模块化设计开源百万级中QdrantRust实现,快速开源百万级低注:选型:学习原型用Chroma,企业生产用Milvus,不想运维用Pinecone,需要模块化用Weaviate。《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)25/43Chroma:创建客户端与集合//pythonimportchromadbfromchromadb.configimportSettings#创建内存模式客户端(数据存储在内存中)chroma_client=chromadb.Client()#或者:创建持久化模式客户端(数据存储到磁盘)chroma_client=chromadb.PersistentClient(path="./chroma_db"#数据存储目录)#创建集合collection=chroma_client.create_collection(name="product_knowledge",metadata={"description":"公司产品知识库"})#或者:获取已存在的集合collection=chroma_client.get_collection(name="product_knowledge")《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)26/43Chroma:向集合写入数据//python#准备数据documents=["量子计算芯片采用超导量子比特技术","该芯片实现了72个量子比特","相干时间提升了30%","芯片采用3D封装技术","功耗降低了40%"]#为每个文档添加IDids=[f"doc_{i}"foriinrange(len(documents))]#添加元数据metadatas=[{"source":"技术手册","chapter":"第一章"},{"source":"技术手册","chapter":"第一章"},{"source":"技术手册","chapter":"第一章"},{"source":"技术手册","chapter":"第二章"},{"source":"技术手册","chapter":"第二章"}]#添加到集合collection.add(documents=documents,ids=ids,metadatas=metadatas)print(f"成功添加{len(documents)}个文档到集合")《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)27/43Chroma:从集合中检索//python#查询results=collection.query(query_texts=["芯片的功耗是多少?"],n_results=3#返回最相关的3个结果)#查看结果print(f"检索到{len(results['documents'][0])}个相关文档")fori,(doc,metadata)inenumerate(zip(results['documents'][0],results['metadatas'][0])):print(f"\n===结果{i+1}===")print(f"文档:{doc}")print(f"来源:{metadata['source']}")print(f"章节:{metadata['chapter']}")《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)28/43LangChain集成Chroma(含元数据过滤)//pythonfromlangchain_chromaimportChromafromlangchain_openaiimportOpenAIEmbeddings#创建Embedding模型embeddings=OpenAIEmbeddings(model="text-embedding-3-small")#创建向量数据库vectorstore=Chroma.from_documents(documents=chunks,#之前切分的文本块embedding=embeddings,collection_name="product_knowledge",persist_directory="./chroma_db"#持久化存储目录)print(f"向量数据库创建成功,包含{len(chunks)}个向量")//python#仅检索"技术手册"类型的文档filtered_results=vectorstore.similarity_search("芯片的功耗是多少?",filter={"document_type":"技术手册","language":"zh-CN"},k=3)forresultinfiltered_results:print(result.page_content[:200])注:similarity_search_with_score可返回距离分数,便于设定阈值与排序。《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)29/43Milvus:向量检索//python#查询向量query_vector=embeddings.embed_query("芯片的功耗是多少?")#检索参数search_params={"metric_type":"COSINE","params":{"nprobe":10}}#执行检索results=collection.search(data=[query_vector],anns_field="embedding",param=search_params,limit=3,output_fields=["content","metadata"])#查看结果fori,resultinenumerate(results[0]):print(f"\n===结果{i+1}===")print(f"距离:{result.distance:.4f}")print(f"内容:{result.entity.get('content')[:200]}...")注:前置三步:connections.connect(host="localhost",port="19530")→用FieldSchema/CollectionSchema建集合→create_index;检索前须collection.load(),metric_type与索引保持一致。《向量计算》配套课件10.3存入向量数据库第10章实战1:搭建一个“私有知识库问答助手”(RAG)30/43表10-5向量数据库索引类型对比索引类型特点适用场景IVF_FLAT平衡精度和速度通用场景IVF_SQ8压缩存储,内存占用小大规模数据HNSW速度最快,精度高实时检索ANNOY内存友好,支持分布式大规模数据注:量化(如SQ/PQ)可进一步压缩向量存储空间与计算时间;nprobe等参数需在精度与延迟间调平。《向量计算》配套课件·第10章实战1:搭建一个“私有知识库问答助手”(RAG)10.4结合LLMAPI实现"基于文档回答问题"检索器与生成器·RAG链·提示词模板·多轮对话·来源追溯·Web界面《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)32/43RAG系统的完整架构:检索器+生成器●检索器Retriever输入:用户查询–处理:查询向量化→相似度计算→Top-K文档–输出:最相关的K个文档片段●生成器Generator输入:用户查询+检索到的文档–处理:构建提示词→调用LLMAPI→生成答案–输出:准确、有依据的答案《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)33/43用LangChain构建第一条RAG链//pythonfromlangchain.chainsimportRetrievalQAfromlangchain_openaiimportChatOpenAI#创建大语言模型llm=ChatOpenAI(model="gpt-4-turbo",temperature=0#设置为0,减少随机性)#创建检索器retriever=vectorstore.as_retriever(search_kwargs={"k":3}#检索最相关的3个文档)#创建RAG链rag_chain=RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",#"stuff"表示将所有检索到的文档一起放入提示词retriever=retriever,return_source_documents=True#返回检索到的源文档)注:rag_chain.invoke({"query":query})后,response['result']是答案,response['source_documents']是检索到的片段。《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)34/43自定义提示词模板//pythonfrommptsimportPromptTemplate#创建自定义提示词模板template="""你是一个专业的技术顾问。请基于以下参考信息回答用户的问题。【参考信息】:{context}【用户问题】:{question}【回答要求】:1.仅基于参考信息回答,不要编造信息2.如果参考信息中没有相关内容,请明确说明3.回答要准确、简洁、专业4.在答案中标注信息的来源文档【你的回答】:"""注:用PromptTemplate(input_variables=["context","question"])包装后,经chain_type_kwargs={"prompt":prompt}注入RAG链。《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)35/43支持多轮对话的RAG链#创建对话式RAG链conversational_rag_chain=ConversationalRetrievalChain.from_llm(llm=llm,retriever=retriever,memory=memory,return_source_documents=True,condense_question_prompt=PromptTemplate.from_template("""以下是历史对话和当前问题。请将当前问题重新表述成一个独立的完整问题。历史对话:{chat_history}当前问题:{question}重新表述后的问题:"""))注:先建ConversationBufferMemory(memory_key="chat_history",return_messages=True,output_key="answer");三步工作:问题重述→检索增强→记忆管理。《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)36/43答案附带来源追溯//pythonfromlangchain.chainsimportRetrievalQAfrommptsimportPromptTemplate#创建带来源的提示词模板template="""你是一个专业的技术顾问。请基于以下参考信息回答用户的问题。【参考信息】:{context}【用户问题】:{question}【回答要求】:1.仅基于参考信息回答,不要编造信息2.在回答的每一句话后面,用【文档X】标注来源3.格式示例:芯片采用超导量子比特技术【文档1】,实现了72个量子比特【文档2】"""prompt=PromptTemplate(template=template,input_variables=["context","question"])#创建RAG链rag_chain=RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",retriever=retriever,注:在提示词中要求每句话后用【文档X】标注出处,显著增强答案可信度。《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)37/43搭建StreamlitWeb界面●侧边栏设置:输入API密钥●问题输入框:用户在此提问●答案显示区:展示生成结果●来源展示区:展开查看参考文档●优化1流式输出:实时看到生成过程●优化2异步处理:支撑多用户并发图10-2私有知识库问答系统《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)38/43完整RAG系统:四个模块各司其职●Config集中管理模型名、切片参数、集合名与目录●DocumentProcessor递归切分+批量加载PDF+补元数据●RAGAssistant建库/检索/生成,返回答案与来源●main加载→切分→入库→连续问答的跑通入口●一条链跑完10.1~10.4:Loader→Splitter→Embedding→Chroma→RetrievalQA《向量计算》配套课件10.4结合LLMAPI实现"基于文档回答问题"第10章实战1:搭建一个“私有知识库问答助手”(RAG)39/43完整RAG系统:配置部分#====================配置部分====================classConfig:#OpenAI配置OPENAI_API_KEY=os.environ.get('OPENAI_API_KEY','your-api-key-here')EMBEDDING_MODEL="text-embedding-3-small"LLM_MODEL="gpt-4-turbo"#向量数据库配置CHROMA_PERSIST_DIR="./chroma_db"COLLECTION_NAME="product_knowledge"#文档

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论