文档目录
一、总体说明与介绍
二、为什么使用RAG
三、环境搭建
四、完整的RAG代码示例
五、优化建议
一、总体说明与介绍
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合向量检索和生成式语言模型(LLM)的新型技术。它通过实时从外部知识库中检索相关的知识片段作为上下文,增强模型对问题回答的准确性与实时性,广泛应用于企业内部知识库、智能客服、医疗咨询等领域。
本技术文档将指导您如何使用LangChain框架结合Ollama服务,搭建一个本地运行的高效RAG知识库。
二、为什么使用RAG
| 优点 |
说明 |
推荐使用场景 |
| 实时更新 |
无需频繁重新训练模型即可更新知识库内容 |
企业内部知识库,实时信息更新场景 |
| 提升准确性 |
减少语言模型“幻觉”现象,提高答案准确性 |
法律咨询、医疗健康 |
| 降低成本 |
维护知识库成本远低于重新训练大型模型 |
小型公司内部知识库、客服 |
| 数据私密性 |
数据本地存储和处理,保护隐私安全 |
企业私有数据处理 |
三、环境搭建
环境依赖与安装步骤
1 2
| pip3 install langchain langchain-community chromadb ollama sentence-transformers pip3 install pypdf "unstructured[all-docs]" python-docx python-pptx lxml openpyxl
|
包说明:
| 软件或包名称 |
安装方式 |
作用说明 |
| LangChain |
pip install langchain langchain-community |
链式调用AI任务,文档加载 |
| ChromaDB |
pip install chromadb |
本地向量数据库 |
| Ollama |
官网安装 |
本地运行LLM |
| sentence-transformers |
pip install sentence-transformers |
向量嵌入 |
| 文档处理库 |
pip install pypdf "unstructured[all-docs]" python-docx python-pptx lxml openpyxl |
加载多种文档类型,如PDF、Word、Excel等 |
三、模型安装与启动
| 操作 |
命令 |
说明 |
| 启动Ollama |
ollama serve |
启动Ollama本地模型服务 |
| 下载DeepSeek模型 |
ollama pull deepseek-r1:1.5b |
下载本地LLM模型用于问答 |
| 下载嵌入模型 |
ollama pull nomic-embed-text:latest |
文本转向量的嵌入模型 |
四、完整的RAG代码示例
以下是完整的Python示例代码,使用LangChain实现基于Ollama的本地RAG知识库。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| # pip3 install langchain langchain-community chromadb ollama sentence-transformers # pip3 install pypdf "unstructured[all-docs]" python-docx python-pptx lxml openpyxl
from langchain_chroma import Chroma from langchain_community.document_loaders import TextLoader, PyPDFLoader, UnstructuredWordDocumentLoader, \ UnstructuredPowerPointLoader, UnstructuredHTMLLoader, UnstructuredMarkdownLoader, UnstructuredCSVLoader, \ UnstructuredExcelLoader from langchain_community.llms.ollama import Ollama from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_ollama import OllamaEmbeddings from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载文档 def load_documents(*filepaths): # 修改函数,接收可变数量的文件路径 loaders = [] for filepath in filepaths: # 遍历文件路径列表 if filepath.endswith(".pdf"): loaders.append(PyPDFLoader(filepath)) elif filepath.endswith(".txt"): loaders.append(TextLoader(filepath)) elif filepath.endswith(".docx"): loaders.append(UnstructuredWordDocumentLoader(filepath)) elif filepath.endswith(".pptx"): loaders.append(UnstructuredPowerPointLoader(filepath)) elif filepath.endswith(".html"): loaders.append(UnstructuredHTMLLoader(filepath)) elif filepath.endswith(".md"): loaders.append(UnstructuredMarkdownLoader(filepath)) elif filepath.endswith(".csv"): loaders.append(UnstructuredCSVLoader(filepath)) elif filepath.endswith(".xlsx"): loaders.append(UnstructuredExcelLoader(filepath))
documents = [] for loader in loaders: documents.extend(loader.load()) return documents
# 获取用户输入的文件路径 fileList = [] while True: inputWord = input("请输入文件全路径,输入q结束:") if inputWord == "q": break else: fileList.append(inputWord)
# 解包 fileList 并传递给 load_documents documents = load_documents(*fileList) # 使用 * 解包
# 2. 分割文本 text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=0) texts = text_splitter.split_documents(documents)
# 3. 创建向量数据库 embeddings = OllamaEmbeddings(model="nomic-embed-text:latest") db = Chroma.from_documents(texts, embeddings)
# 4. 创建检索器 retriever = db.as_retriever()
# 5. 创建问答链 llm = Ollama(model="deepseek-r1:14b")
# 定义 RAG 提示模板 RAG_TEMPLATE = """ You are an assistant for question-answering tasks.
<context> {context} </context>
Question: {question} """ rag_prompt = ChatPromptTemplate.from_template(RAG_TEMPLATE)
# 格式化文档函数 def format_docs(docs): return "\n\n".join(doc.page_content for doc in docs)
# 使用管道操作符构建问答链 qa_chain = ( {"context": retriever | format_docs, "question": RunnablePassthrough()} | rag_prompt | llm | StrOutputParser() )
# 6. 交互式提问 while True: query = input("请输入你的问题(输入q退出):") if query.lower() == "q": break result = qa_chain.invoke(query) print(result)
|
五、优化建议
- 调整
chunk_size(如300~1000字符)提高检索的准确性。
- 根据应用需求调整检索文档数量
k(默认3-5个)提升答案相关度。
- 使用量化模型(如DeepSeek量化版)减少内存占用,提高响应速度。