RAG系统学习之——基于LangChain+Milvus+Ollama+Streamlit搭建本地RAG系统

『AI先锋杯·14天征文挑战第8期』 10w+人浏览 328人参与

前言

RAG(Retrieval-Augmented Generation)是一种结合了信息检索生成式AI的技术架构,能够让大语言模型基于外部知识库进行问答,有效解决模型知识截止日期和幻觉问题。

本文将详细介绍如何用LangChain+Milvus+Ollama+Streamlit搭建一个完全本地化的RAG系统。

技术架构

  • LangChain: 负责RAG管道的编排和文档处理
  • Milvus: 高性能向量数据库,负责文档向量的存储和检索
  • Ollama: 本地大语言模型运行框架
  • Streamlit: 提供友好的Web前端交互界面

环境准备

1. 安装依赖

# 创建虚拟环境
python -m venv rag_env
source rag_env/bin/activate  # Linux/Mac
# rag_env\Scripts\activate  # Windows

# 安装核心依赖
pip install langchain langchain-ollama pymilvus sentence-transformers streamlit streamlit-chat
pip install pypdf2 tiktoken chromadb plotly pandas  # 前端界面和数据分析

2. 启动Milvus(Standalone版)

# 启动Milvus(推荐使用Docker)
docker run -d \
  --name milvus-standalone \
  --security-opt seccomp:unconfined \
  -p 19530:19530 \
  -p 9091:9091 \
  -v milvus-data:/milvus/data \
  milvusdb/milvus:latest

# 下载并启动Ollama模型
ollama serve
ollama pull llama2  # 或其他模型

核心代码实现

1. 文档处理模块

from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_ollama import OllamaEmbeddings
from langchain_community.vectorstores import Milvus

class DocumentProcessor:
    def __init__(self):
        # 初始化嵌入模型(Ollama提供)
        self.embeddings = OllamaEmbeddings(model="llama2")
        # 文档分割器
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000,
            chunk_overlap=200,
            length_function=len,
        )
        
    def load_and_split_documents(self, file_paths):
        """加载并分割文档"""
        documents = []
        for file_path in file_paths:
            if file_path.endswith('.pdf'):
                loader = PyPDFLoader(file_path)
                docs = loader.load()
                documents.extend(docs)
            else:
                # 处理其他格式文档
                pass
        
        # 分割文档
        splits = self.text_splitter.split_documents(documents)
        return splits
    
    def create_vectorstore(self, documents, collection_name="rag_docs"):
        """创建向量数据库"""
        # 清空现有集合
        vectorstore = Milvus.from_documents(
            documents=documents,
            embedding=self.embeddings,
            collection_name=collection_name,
            drop_old=True  # 删除旧集合
        )
        return vectorstore

2. RAG查询引擎

from langchain_ollama import ChatOllama
from langchain.chains import RetrievalQA
from langchain.prompts import PromptTemplate

class RAGQueryEngine:
    def __init__(self, vectorstore):
        # 初始化本地LLM
        self.llm = ChatOllama(
            model="llama2",
            temperature=0.1,
            max_tokens=2000
        )
        
        # 创建检索器
        self.retriever = vectorstore.as_retriever(
            search_type="similarity",
            search_kwargs={"k": 4}  # 返回4个最相关的文档片段
        )
        
        # 创建自定义提示词
        self.prompt = PromptTemplate(
            template="""基于以下上下文信息回答问题:
            
            上下文:
            {context}
            
            问题:{question}
            
            回答要求:
            1. 基于上下文信息回答
            2. 如果上下文中没有相关信息,说明无法回答
            3. 保持回答简洁明确
            
            回答:""",
            input_variables=["context", "question"]
        )
        
        # 创建QA链
        self.qa_chain = RetrievalQA.from_chain_type(
            llm=self.llm,
            chain_type="stuff",
            retriever=self.retriever,
            chain_type_kwargs={"prompt": self.prompt},
            return_source_documents=True  # 返回源文档
        )
    
    def query(self, question):
        """执行查询"""
        result = self.qa_chain({"query": question})
        return {
            "answer": result["result"],
            "source_documents": result["source_documents"]
        }

3. 系统集成模块

class LocalRAGSystem:
    def __init__(self):
        self.doc_processor = DocumentProcessor()
        self.vectorstore = None
        self.query_engine = None
        
    def build_system(self, document_paths):
        """构建RAG系统"""
        print("📚 正在处理文档...")
        documents = self.doc_processor.load_and_split_documents(document_paths)
        print(f"✅ 文档处理完成,共{len(documents)}个片段")
        
        print("🗄️  正在构建向量数据库...")
        self.vectorstore = self.doc_processor.create_vectorstore(documents)
        print("✅ 向量数据库构建完成")
        
        print("🤖 正在初始化查询引擎...")
        self.query_engine = RAGQueryEngine(self.vectorstore)
        print("✅ 查询引擎初始化完成")
        
    def chat(self, question):
        """执行对话"""
        if not self.query_engine:
            return "系统未初始化,请先调用build_system()"
        
        print(f"❓ 问题:{question}")
        result = self.query_engine.query(question)
        print(f"💬 回答:{result['answer']}")
        
        # 显示引用源
        print("\n📖 参考文档片段:")
        for i, doc in enumerate(result['source_documents'][:2], 1):
            print(f"{i}. {doc.page_content[:100]}...")
        
        return result

完整使用示例

def main():
    # 初始化RAG系统
    rag_system = LocalRAGSystem()
    
    # 构建系统(提供文档路径)
    document_paths = ["./documents/技术文档.pdf", "./documents/FAQ.md"]
    rag_system.build_system(document_paths)
    
    # 执行查询
    questions = [
        "什么是LangChain框架?",
        "如何使用Milvus进行向量检索?",
        "RAG系统的优势是什么?"
    ]
    
    for question in questions:
        print("\n" + "="*50)
        rag_system.chat(question)
        print("="*50)

if __name__ == "__main__":
    main()

高级功能扩展

1. 多文档类型支持

from langchain_community.document_loaders import (
    TextLoader, CSVLoader, ExcelLoader, UnstructuredFileLoader
)

class AdvancedDocumentProcessor(DocumentProcessor):
    def load_and_split_documents(self, file_paths):
        """支持多种文档格式"""
        documents = []
        
        for file_path in file_paths:
            if file_path.endswith('.pdf'):
                loader = PyPDFLoader(file_path)
            elif file_path.endswith('.txt'):
                loader = TextLoader(file_path, encoding='utf-8')
            elif file_path.endswith('.csv'):
                loader = CSVLoader(file_path)
            elif file_path.endswith(('.xlsx', '.xls')):
                loader = ExcelLoader(file_path)
            else:
                # 使用通用文档处理器
                loader = UnstructuredFileLoader(file_path)
            
            docs = loader.load()
            documents.extend(docs)
        
        return self.text_splitter.split_documents(documents)

2. 查询结果过滤

class EnhancedRAGQueryEngine(RAGQueryEngine):
    def __init__(self, vectorstore):
        super().__init__(vectorstore)
        self.confidence_threshold = 0.7
    
    def query_with_confidence(self, question):
        """带置信度评估的查询"""
        result = self.query_engine.query(question)
        
        # 简单的置信度评估(基于相似度分数)
        similarities = [doc.metadata.get('score', 0) 
                       for doc in result['source_documents']]
        avg_similarity = sum(similarities) / len(similarities) if similarities else 0
        
        if avg_similarity < self.confidence_threshold:
            result['answer'] += f"\n\n⚠️  注意:检索置信度较低({avg_similarity:.2f}),回答仅供参考。"
        
        result['confidence'] = avg_similarity
        return result

Streamlit前端界面设计

1. 主界面应用

import streamlit as st
import tempfile
import os
from streamlit_chat import message
import json

class StreamlitRAGInterface:
    def __init__(self):
        self.initialize_session_state()
    
    def initialize_session_state(self):
        """初始化Streamlit会话状态"""
        if 'rag_system' not in st.session_state:
            st.session_state.rag_system = LocalRAGSystem()
        if 'chat_history' not in st.session_state:
            st.session_state.chat_history = []
        if 'system_built' not in st.session_state:
            st.session_state.system_built = False
        if 'uploaded_files' not in st.session_state:
            st.session_state.uploaded_files = []
    
    def render_sidebar(self):
        """渲染侧边栏"""
        with st.sidebar:
            st.title("🔧 RAG系统配置")
            
            # 模型配置
            st.subheader("🤖 模型配置")
            model_options = ["llama2", "llama3", "codellama", "mistral"]
            selected_model = st.selectbox("选择模型", model_options, index=0)
            
            temperature = st.slider("生成温度", 0.0, 1.0, 0.1)
            max_tokens = st.slider("最大令牌数", 500, 4000, 2000)
            
            # 文档上传
            st.subheader("📚 文档管理")
            uploaded_files = st.file_uploader(
                "上传文档", 
                type=['pdf', 'txt', 'md', 'csv', 'xlsx'],
                accept_multiple_files=True
            )
            
            if uploaded_files:
                st.session_state.uploaded_files = uploaded_files
            
            # 系统构建
            if st.button("🚀 构建RAG系统", type="primary"):
                self.build_system_from_uploads()
            
            # 系统状态
            st.subheader("📊 系统状态")
            if st.session_state.system_built:
                st.success("✅ 系统已就绪")
                if st.button("🔄 重置系统"):
                    self.reset_system()
            else:
                st.warning("⏳ 等待系统构建")
                
            # 参数配置
            st.subheader("⚙️ 检索参数")
            k_value = st.slider("检索文档数量", 1, 10, 4)
            
            return {
                'model': selected_model,
                'temperature': temperature,
                'max_tokens': max_tokens,
                'k_value': k_value
            }
    
    def build_system_from_uploads(self):
        """从上传的文件构建系统"""
        if not st.session_state.uploaded_files:
            st.error("请先上传文档")
            return
        
        try:
            with st.spinner("正在处理文档..."):
                # 保存临时文件
                temp_files = []
                for uploaded_file in st.session_state.uploaded_files:
                    temp_dir = tempfile.mkdtemp()
                    temp_path = os.path.join(temp_dir, uploaded_file.name)
                    
                    with open(temp_path, "wb") as f:
                        f.write(uploaded_file.getvalue())
                    temp_files.append(temp_path)
                
                # 构建系统
                st.session_state.rag_system.build_system(temp_files)
                st.session_state.system_built = True
                st.session_state.chat_history = []
                
                st.success(f"✅ 成功处理 {len(temp_files)} 个文档")
                
        except Exception as e:
            st.error(f"构建失败: {str(e)}")
    
    def reset_system(self):
        """重置系统"""
        st.session_state.rag_system = LocalRAGSystem()
        st.session_state.chat_history = []
        st.session_state.system_built = False
        st.session_state.uploaded_files = []
        st.rerun()
    
    def render_chat_interface(self, config):
        """渲染聊天界面"""
        st.title("💬 本地RAG智能问答系统")
        
        if not st.session_state.system_built:
            st.warning("请先在侧边栏构建RAG系统")
            return
        
        # 聊天历史显示
        chat_container = st.container()
        
        with chat_container:
            for i, (user_msg, bot_msg) in enumerate(st.session_state.chat_history):
                message(user_msg, is_user=True, key=f"user_{i}")
                message(bot_msg, is_user=False, key=f"bot_{i}")
        
        # 用户输入
        if query := st.chat_input("请输入您的问题..."):
            # 用户消息
            with st.spinner("正在思考..."):
                try:
                    # 配置模型参数
                    st.session_state.rag_system.query_engine.llm.temperature = config['temperature']
                    st.session_state.rag_system.query_engine.llm.max_tokens = config['max_tokens']
                    
                    # 执行查询
                    result = st.session_state.rag_system.chat(query)
                    
                    # 更新聊天历史
                    st.session_state.chat_history.append((query, result['answer']))
                    
                    # 刷新页面显示新消息
                    st.rerun()
                    
                except Exception as e:
                    st.error(f"查询失败: {str(e)}")

def main():
    """主函数"""
    st.set_page_config(
        page_title="RAG智能问答系统",
        page_icon="🤖",
        layout="wide"
    )
    
    # 添加自定义CSS
    st.markdown("""
    .main-header {
        text-align: center;
        padding: 1rem;
        background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
        border-radius: 10px;
        margin-bottom: 2rem;
    }

    .chat-message {
        padding: 1rem;
        border-radius: 10px;
        margin: 0.5rem 0;
    }

    .user-message {
        background-color: #e3f2fd;
        border-left: 5px solid #2196f3;
    }

    .bot-message {
        background-color: #f3e5f5;
        border-left: 5px solid #9c27b0;
    }

    """, unsafe_allow_html=True)

    # 初始化界面
    app = StreamlitRAGInterface()
    config = app.render_sidebar()
    app.render_chat_interface(config)

if __name__ == "__main__":
    main()

2. 配置文件

# config.py - 配置文件
import os
from typing import Dict, Any

class Config:
    # 模型配置
    DEFAULT_MODEL = "llama2"
    AVAILABLE_MODELS = ["llama2", "llama3", "codellama", "mistral"]
    
    # 向量数据库配置
    MILVUS_HOST = os.getenv("MILVUS_HOST", "localhost")
    MILVUS_PORT = os.getenv("MILVUS_PORT", "19530")
    COLLECTION_NAME = "rag_docs"
    
    # 文档处理配置
    CHUNK_SIZE = 1000
    CHUNK_OVERLAP = 200
    SUPPORTED_FILE_TYPES = ['pdf', 'txt', 'md', 'csv', 'xlsx']
    
    # Streamlit配置
    PAGE_TITLE = "RAG智能问答系统"
    PAGE_ICON = "🤖"
    LAYOUT = "wide"
    
    # UI配置
    MAX_UPLOAD_SIZE = 50 * 1024 * 1024  # 50MB
    CHAT_HISTORY_LIMIT = 100
    
    # 检索配置
    DEFAULT_TOP_K = 4
    CONFIDENCE_THRESHOLD = 0.7

部署建议

1. Docker化部署

# Dockerfile
FROM python:3.10-slim

WORKDIR /app

# 安装系统依赖
RUN apt-get update && apt-get install -y \
    build-essential \
    curl \
    && rm -rf /var/lib/apt/lists/*

# 安装Python依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 暴露端口
EXPOSE 8501

# 启动命令
CMD ["streamlit", "run", "streamlit_app.py", "--server.port=8501", "--server.address=0.0.0.0"]

2. Docker Compose配置

# docker-compose.yml
version: '3.8'

services:
  milvus:
    image: milvusdb/milvus:latest
    container_name: milvus-standalone
    command: ["milvus", "run", "standalone"]
    environment:
      ETCD_ENDPOINTS: etcd:2379
      MINIO_ADDRESS: minio:9000
    volumes:
      - milvus_data:/milvus/data
    ports:
      - "19530:19530"
    networks:
      - rag_network

  streamlit-app:
    build: .
    container_name: streamlit-rag
    ports:
      - "8501:8501"
    environment:
      - MILVUS_HOST=milvus
      - MILVUS_PORT=19530
    depends_on:
      - milvus
    networks:
      - rag_network

volumes:
  milvus_data:

networks:
  rag_network:
    driver: bridge

3. 独立部署(开发环境)

# 1. 启动Milvus
docker run -d --name milvus-standalone \
  --security-opt seccomp:unconfined \
  -p 19530:19530 \
  -p 9091:9091 \
  -v milvus-data:/milvus/data \
  milvusdb/milvus:latest

# 2. 启动Ollama
ollama serve
ollama pull llama2

# 3. 启动Streamlit应用
streamlit run streamlit_app.py --server.port 8501 --server.address 0.0.0.0

# 4. 访问 http://localhost:8501

4. 一键启动脚本

#!/bin/bash
# setup.sh - 一键安装脚本

echo "🚀 开始搭建RAG系统..."

# 1. 创建虚拟环境
echo "📦 创建Python虚拟环境..."
python -m venv rag_env
source rag_env/bin/activate

# 2. 安装依赖
echo "📚 安装Python依赖..."
pip install --upgrade pip
pip install langchain langchain-ollama pymilvus sentence-transformers streamlit streamlit-chat
pip install pypdf2 tiktoken chromadb plotly pandas

# 3. 启动Milvus
echo "🗄️ 启动Milvus向量数据库..."
docker run -d \
  --name milvus-standalone \
  --security-opt seccomp:unconfined \
  -p 19530:19530 \
  -p 9091:9091 \
  -v milvus-data:/milvus/data \
  milvusdb/milvus:latest

# 4. 等待服务就绪
echo "⏳ 等待服务启动..."
sleep 30

# 5. 检查Ollama
echo "🤖 检查Ollama服务..."
if ! command -v ollama &> /dev/null; then
    echo "❌ 请先安装Ollama: https://ollama.ai"
    exit 1
fi

# 6. 启动模型
echo "📥 下载模型..."
ollama pull llama2

# 7. 启动应用
echo "🌐 启动Streamlit应用..."
echo "🎉 RAG系统已启动!请访问: http://localhost:8501"
streamlit run streamlit_app.py --server.port 8501 --server.address 0.0.0.0

快速测试

创建测试文档进行验证:

# test_document.txt

什么是RAG系统?
RAG(Retrieval-Augmented Generation)是一种结合了信息检索和生成式AI的技术架构。

LangChain有哪些主要功能?
LangChain是一个用于开发基于LLM的应用程序的框架,提供了丰富的组件和工具。

Milvus是什么数据库?
Milvus是一个开源的向量数据库,专门用于存储和检索大规模向量数据。

总结

通过LangChain+Milvus+Ollama+Streamlit的完整组合,我们成功搭建了一个功能完善的本地化RAG系统,具有以下特点:

🔧 核心技术栈

  • LangChain: RAG管道编排和文档处理
  • Milvus: 高性能向量数据库存储
  • Ollama: 完全本地化的大语言模型
  • Streamlit: 友好的Web前端交互界面

🌟 系统特色

  • 数据隐私保护: 完全本地化,数据不上传云端
  • 灵活文档处理: 支持PDF、TXT、CSV等多种格式
  • 可视化交互: 美观的Web界面,支持聊天式问答
  • 实时系统监控: 聊天历史、统计分析等功能
  • 一键部署: Docker支持,快速部署上线
  • 高可扩展性: 模块化设计,便于二次开发

🎯 应用场景

  • 企业内部知识库: 安全访问公司文档和FAQ
  • 客户服务系统: 基于企业资料的智能客服
  • 教育培训平台: 个性化学习助手
  • 科研文献助手: 快速检索和分析学术论文

📈 性能优化建议

1.模型选择: 根据硬件资源选择合适的本地模型

2.索引优化: 调整Milvus索引参数提升检索速度

3.缓存策略: 对热门查询结果进行缓存

4.批量处理: 文档向量化时使用批处理提升效率

5.负载均衡: 生产环境考虑多实例部署

    这种架构特别适合需要数据安全控制、高度定制化和良好用户体验的企业环境。

    <think>我们正在构建一个基于PDF的RAG应用,使用LangChainMilvus和BGE-M3嵌入模型。以下是步骤和示例代码:###步骤概述1.**环境准备**:安装必要的库。2.**加载PDF文档**:使用LangChain的文档加载器读取PDF文件。3.**文档切分**:将文档分割成适合处理的块。4.**嵌入模型**:使用BGE-M3模型生成文本嵌入(稠密向量和稀疏向量)。5.**向量存储**:将嵌入向量存入Milvus向量数据库。6.**检索与生成**:构建检索链,根据用户查询检索相关文档片段,并生成回答。###详细步骤与代码示例####1.环境准备安装所需库:```bashpipinstalllangchainlangchain-communitypymilvusunstructuredpython-dotenvtransformerstorch```####2.加载PDF文档使用LangChain的`PyPDFLoader`加载PDF文件:```pythonfromlangchain_community.document_loadersimportPyPDFLoaderloader=PyPDFLoader("example.pdf")documents=loader.load()```####3.文档切分使用文本分割器将文档分割成较小的块:```pythonfromlangchain.text_splitterimportRecursiveCharacterTextSplittertext_splitter=RecursiveCharacterTextSplitter(chunk_size=1000,chunk_overlap=200,)docs=text_splitter.split_documents(documents)```####4.嵌入模型我们使用BGE-M3嵌入模型。注意:BGE-M3支持生成稠密向量和稀疏向量。Milvus支持混合检索(稠密+稀疏),但需要Milvus2.4以上版本。首先,我们需要一个自定义的嵌入类来使用BGE-M3模型:```pythonfromlangchain.embeddingsimportEmbeddingsfromtypingimportListimporttorchfromtransformersimportAutoModel,AutoTokenizerclassBGEM3Embeddings(Embeddings):def__init__(self,model_name="BAAI/bge-m3",device="cuda"iftorch.cuda.is_available()else"cpu"):self.tokenizer=AutoTokenizer.from_pretrained(model_name)self.model=AutoModel.from_pretrained(model_name).to(device)self.device=devicedefembed_documents(self,texts:List[str])->List[List[float]]:#生成稠密向量inputs=self.tokenizer(texts,padding=True,truncation=True,return_tensors="pt",max_length=8192).to(self.device)withtorch.no_grad():outputs=self.model(**inputs)#使用[CLS]token的表示作为文档向量dense_embeddings=outputs.last_hidden_state[:,0].cpu().numpy().tolist()returndense_embeddingsdefembed_query(self,text:str)->List[float]:returnself.embed_documents([text])[0]```####5.向量存储初始化Milvus向量数据库,并存储嵌入向量。首先,确保Milvus服务正在运行。然后,使用LangChainMilvus集成:```pythonfromlangchain.vectorstoresimportMilvus#初始化嵌入模型embeddings=BGEM3Embeddings()#连接Milvusvector_db=Milvus.from_documents(documents=docs,embedding=embeddings,connection_args={"host":"localhost","port":"19530"},collection_name="pdf_rag_collection",auto_id=True)```####6.检索与生成构建一个检索问答链,使用检索到的文档片段生成答案。```pythonfromlangchain.chainsimportRetrievalQAfromlangchain.llmsimportOpenAI#这里可以使用其他LLM,比如ChatGLM#假设使用OpenAI,但也可以替换为本地模型如ChatGLMimportosos.environ["OPENAI_API_KEY"]="your-openai-api-key"llm=OpenAI(temperature=0)#创建检索链qa_chain=RetrievalQA.from_chain_type(llm=llm,chain_type="stuff",retriever=vector_db.as_retriever(),return_source_documents=True)#进行提问query="文档中主要讨论了哪些内容?"result=qa_chain({"query":query})print("答案:",result["result"])print("来源文档:",result["source_documents"])```###注意事项1.**BGE-M3模型**:它支持长文本(最多8192个token),适合处理文档块。2.**Milvus配置**:确保Milvus服务运行,并注意集合(collection)的配置(如索引类型)以支持混合检索(如果使用稀疏向量)。上述示例仅使用了稠密向量。3.**本地LLM**:如果需要使用本地大模型(如ChatGLM),只需替换`llm`部分。例如,使用`langchain.llms`中的`ChatGLM`类(如果有)或自定义LLM封装。###优化方向-**混合检索**:BGE-M3也生成稀疏向量,可以改进存储和检索部分以同时利用稠密和稀疏向量,提高召回率。-**多模态**:BGE-M3是多模态嵌入模型,但本示例仅处理文本。如需处理图像,需要扩展。###引用以上实现参考了LangChainMilvus的官方文档,以及BGE-M3的相关资料[^4]。§§相关问题§§1.如何优化基于PDF的RAG应用的检索效果?2.在Milvus中如何同时存储和检索稠密向量和稀疏向量?3.如何将本地大模型(如ChatGLM)集成到LangChainRAG应用中?</think>### 使用LangChain + Milvus + BGE-M3构建基于PDF的RAG应用教程 #### 1. 环境准备 ```bash # 安装核心依赖 pip install langchain langchain-community pymilvus unstructured python-dotenv transformers ``` #### 2. 初始化向量数据库 (Milvus) ```java // MilvusConfig.java (Spring Boot配置) import io.milvus.v2.client.ConnectConfig; import io.milvus.v2.client.MilvusClientV2; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MilvusConfig { @Bean public MilvusClientV2 milvusClient() { return new MilvusClientV2( ConnectConfig.builder() .uri("http://localhost:19530") // Milvus地址 .build() ); } } ``` #### 3. PDF处理与向量化 ```python # PDF加载与切分 from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter loader = PyPDFLoader("path/to/document.pdf") documents = loader.load() text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200 ) docs = text_splitter.split_documents(documents) # BGE-M3嵌入模型 from langchain.embeddings import HuggingFaceBgeEmbeddings model_name = "BAAI/bge-m3" encode_kwargs = {'normalize_embeddings': True} embeddings = HuggingFaceBgeEmbeddings( model_name=model_name, encode_kwargs=encode_kwargs ) ``` #### 4. 向量存储与检索 ```python # 存储向量到Milvus from langchain.vectorstores import Milvus vector_db = Milvus.from_documents( documents=docs, embedding=embeddings, connection_args={"host": "localhost", "port": "19530"}, collection_name="pdf_rag", auto_id=True ) # 创建检索器 retriever = vector_db.as_retriever( search_type="mmr", # 最大边际相关性 search_kwargs={"k": 5} ) ``` #### 5. RAG问答链实现 ```python # 构建问答链 from langchain.chains import RetrievalQA from langchain_community.llms import ChatGLM llm = ChatGLM(endpoint_url="http://localhost:8000") # 本地ChatGLM服务 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=retriever, return_source_documents=True ) # 执行查询 query = "文档中提到的关键技术是什么?" result = qa_chain({"query": query}) print(f"答案: {result['result']}") print(f"来源: {result['source_documents'][0].page_content[:200]}...") ``` #### 6. 部署优化建议 1. **文档预处理**: ```python # 添加PDF元数据处理 loader = PyPDFLoader("file.pdf", extract_images=True) # 启用图像提取 ``` 2. **混合检索优化**: ```python # 同时使用稠密和稀疏向量 retriever = vector_db.as_retriever( search_type="hybrid", search_kwargs={ "k": 10, "dense_weight": 0.7, "sparse_weight": 0.3 } ) ``` 3. **性能监控**: ```python # 启用检索日志 import logging logging.basicConfig() logging.getLogger("langchain.retrievers").setLevel(logging.INFO) ``` ### 关键组件说明 | 组件 | 作用 | 推荐配置 | |------|------|----------| | **BGE-M3** | 多语言文本嵌入 | `normalize_embeddings=True` | | **Milvus** | 向量存储检索 | 启用混合索引(HNSW + BM25) | | **LangChain** | 流程编排 | 使用`RecursiveCharacterSplitter`处理长文本 | > 注意:BGE-M3支持**8192 Token长文本**和**多语言处理**,特别适合PDF文档的复杂内容[^4]。部署时建议使用GPU加速嵌入计算。
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    Jack_abu

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值