LangChain RAG 基础
基于你已经学习完文档加载文本分割向量存储Chroma语义检索一、什么是 RAG超通俗解释RAG Retrieval-Augmented Generation检索增强生成大白话大模型本身不知道你的文档内容所以先去文档里检索相关内容把检索到的内容喂给大模型让大模型只根据文档内容回答这就叫RAG。二、RAG 标准 5 步流程必须背下来加载文档PDF / TXT / Word文本分割切成小块保留语义向量化小块 → 向量存入向量库Chroma / FAISS用户提问 → 检索 → 给模型回答三、RAG 为什么比直接问 LLM 强LLM 会瞎编RAG只根据文档回答不会编LLM 不知道你的私有数据RAG 可以读取私有文档RAG 回答永远准确、可追溯四、现在我带你实现最简单、最标准、可直接运行的 RAG 系统只用你已经学过的知识Document LoaderText SplitterChroma 向量库EmbeddingLLM Prompt普通 Chain五、完整可运行代码极简纯净版 RAG1. 安装依赖pip install -U langchain langchain-openai langchain-community pypdf chromadb python-dotenv2. 完整代码直接跑import os from dotenv import load_dotenv # 你学过的所有模块 from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_community.vectorstores import Chroma from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough # 加载环境变量 load_dotenv() # 配置 PDF_PATH test.pdf # 你的PDF CHROMA_PATH ./chroma_db # 豆包模型 llm ChatOpenAI( api_keyos.getenv(DOUBAO_API_KEY), base_urlhttps://ark.cn-beijing.volces.com/api/v3, modeldoubao-pro-32k, temperature0 # 必须0保证不瞎编 ) # 嵌入模型 embedding OpenAIEmbeddings( api_keyos.getenv(DOUBAO_API_KEY), base_urlhttps://ark.cn-beijing.volces.com/api/v3 ) # 1. 加载PDF loader PyPDFLoader(PDF_PATH) docs loader.load() # 2. 文本分割 splitter RecursiveCharacterTextSplitter( chunk_size1000, chunk_overlap200, separators[\n\n, \n, 。, , , ] ) chunks splitter.split_documents(docs) # 3. 构建向量库Chroma vector_db Chroma.from_documents( documentschunks, embeddingembedding, persist_directoryCHROMA_PATH ) vector_db.persist() # 4. 检索器核心 retriever vector_db.as_retriever(search_kwargs{k: 3}) # 5. RAG 提示词 prompt ChatPromptTemplate.from_template( 你是一个严格的文档问答助手。 只根据下面的【文档内容】回答问题绝对不能编造信息。 文档内容 {context} 用户问题 {question} 如果文档中没有答案请直接回复 文档中没有相关内容 ) # 6. 构建 RAG 链 rag_chain ( {context: retriever, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() ) # 7. 运行 RAG print(✅ RAG 系统启动成功开始提问吧) while True: q input(你) if q q: break ans rag_chain.invoke(q) print(, ans, \n)六、这个 RAG 系统能做什么上传任意 PDF问文档里的内容只根据文档回答不会编不知道就说文档中没有相关内容回答准确、可靠七、我用最简单的话讲清楚 RAG 链的结构rag_chain ( {context: retriever, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() )逐行解释context retriever→ 去向量库检索相关内容question 用户问题→ 直接传递问题把两者拼起来给 PromptLLM 根据文档回答输出解析成字符串这就是最简单、最标准的 RAG 结构八、总结一句最核心的话RAG 检索 提示 生成检索 从文档找答案提示 告诉模型只看文档生成 模型回答分隔符一、给 RAG 文档问答做可视化网页界面可视化界面 RAG用Streamlit做零前端代码、一行命令就能跑自带漂亮网页 UI侧边栏上传 PDF自动加载、分割、建 Chroma 向量库聊天式对话框基于文档 RAG 回答不瞎编展示检索到的参考文档片段1. 安装依赖pip install -U langchain langchain-openai langchain-community pypdf chromadb python-dotenv streamlit2. 项目结构你的项目文件夹/ ├── .env ├── app_rag_ui.py # 可视化界面主程序 └── test.pdf # 可上传任意PDF3. .env 文件DOUBAO_API_KEY你的豆包API_KEY二、完整可运行代码app_rag_ui.pyimport os import shutil from dotenv import load_dotenv import streamlit as st # LangChain 相关 from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings, ChatOpenAI from langchain_community.vectorstores import Chroma from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough # 加载环境变量 load_dotenv() # 全局配置 CHROMA_DB_DIR ./chroma_rag_ui_db CHUNK_SIZE 1000 CHUNK_OVERLAP 200 # 初始化 LLM llm ChatOpenAI( api_keyos.getenv(DOUBAO_API_KEY), base_urlhttps://ark.cn-beijing.volces.com/api/v3, modeldoubao-pro-32k, temperature0.0 ) # 初始化嵌入模型 embedding OpenAIEmbeddings( api_keyos.getenv(DOUBAO_API_KEY), base_urlhttps://ark.cn-beijing.volces.com/api/v3 ) # 工具函数 def clear_chroma_db(): 清空旧向量库 if os.path.exists(CHROMA_DB_DIR): shutil.rmtree(CHROMA_DB_DIR) def load_and_split_pdf(pdf_path): 加载PDF 语义分割 loader PyPDFLoader(pdf_path) docs loader.load() splitter RecursiveCharacterTextSplitter( chunk_sizeCHUNK_SIZE, chunk_overlapCHUNK_OVERLAP, separators[\n\n, \n, 。, , , ] ) chunks splitter.split_documents(docs) return chunks def build_vector_db(chunks): 构建Chroma向量库 vector_db Chroma.from_documents( documentschunks, embeddingembedding, persist_directoryCHROMA_DB_DIR ) vector_db.persist() return vector_db def build_rag_chain(vector_db): 构建RAG问答链 retriever vector_db.as_retriever(k3) prompt ChatPromptTemplate.from_template( 你是专业文档问答助手**严格仅根据提供的文档上下文回答**。 规则 1. 只使用上下文信息禁止编造、禁止使用外部知识 2. 没有相关内容就直接回复文档中没有相关内容 3. 回答简洁条理清晰 文档上下文 {context} 用户问题 {question} ) rag_chain ( {context: retriever, question: RunnablePassthrough()} | prompt | llm | StrOutputParser() ) return rag_chain, retriever # Streamlit 页面 st.set_page_config(page_titleRAG 文档问答机器人, layoutwide) st.title( RAG 文档问答可视化系统) # 侧边栏 with st.sidebar: st.header( 文档上传) uploaded_file st.file_uploader(上传 PDF 文件, typepdf) if uploaded_file: # 保存临时PDF temp_pdf_path temp_upload.pdf with open(temp_pdf_path, wb) as f: f.write(uploaded_file.read()) # 清空旧库 clear_chroma_db() with st.spinner(正在加载文档、分割、构建向量库...): chunks load_and_split_pdf(temp_pdf_path) vector_db build_vector_db(chunks) rag_chain, retriever build_rag_chain(vector_db) # 存入session全局复用 st.session_state[rag_chain] rag_chain st.session_state[retriever] retriever st.success(✅ 文档加载完成可以开始提问) # 主页面聊天 if chat_history not in st.session_state: st.session_state[chat_history] [] # 渲染历史对话 for msg in st.session_state[chat_history]: with st.chat_message(msg[role]): st.markdown(msg[content]) # 输入框 user_query st.chat_input(请输入你的问题...) if user_query: # 展示用户问题 st.chat_message(user).markdown(user_query) st.session_state[chat_history].append({role:user,content:user_query}) if rag_chain not in st.session_state: ans ⚠️ 请先在侧边栏上传 PDF 文档 else: # RAG 生成回答 with st.spinner(AI 正在思考并检索文档...): ans st.session_state[rag_chain].invoke(user_query) # 检索参考片段 refs st.session_state[retriever].get_relevant_documents(user_query) # 展示AI回答 with st.chat_message(assistant): st.markdown(ans) # 折叠展示参考文档片段 with st.expander( 查看检索参考文档片段): for idx, doc in enumerate(refs, 1): st.write(f**参考片段 {idx}第{doc.metadata.get(page,未知)}页**) st.write(doc.page_content) st.divider() st.session_state[chat_history].append({role:assistant,content:ans})三、运行方式终端执行streamlit run app_rag_ui.py自动弹出浏览器网页界面功能左侧上传任意 PDF自动加载 → 分割 → 向量化 → 存入 Chroma下方对话框直接提问底部可展开查看检索到的原文参考片段严格基于文档回答不瞎编四、界面功能亮点 网页可视化不用控制台 支持随时上传新 PDF自动清空旧向量库 聊天式对话历史 可查看每一轮用到的检索原文片段 页码 纯 RAG 标准流程语义检索比关键词匹配精准很多