RAG系统学习之——RAG技术详解与实战指南

表格RAG技术实战指南 表格RAG(Retrieval-Augmented Generation)是一种结合检索和生成能力的框架,旨在增强LLMs对表格数据的理解和处理能力。其核心在于通过检索与用户查询相关的表格内容,并将这些内容输入LLM生成准确回答。与传统RAG聚焦于非结构化文本不同,表格RAG处理结构化表格数据,因此表格序列化是关键技术环节。Serialize(Table),Query其中,Serialize是将表格数据(Table)转换为文本的过程,Query是用户查询,LLM是大型语言模型。 阅读详情

目录

  1. RAG出现的背景
  2. RAG技术定义
  3. RAG优缺点分析
  4. 实战项目 - 本地RAG系统
  5. 未来展望
  6. 总结

第一部分:RAG出现的背景

1.1 大语言模型的局限性

在深入了解RAG(检索增强生成)技术之前,我们需要先理解为什么这项技术会出现,以及它解决了什么问题。

知识截止时间问题

大语言模型(LLM)的训练数据存在时间截止问题。即使是最先进的模型,如GPT-4、Claude等,其训练数据都有明确的时间边界。以2025年为基准,即使是2024年底发布的模型,其训练数据也只截止到某个特定时间点,无法获取最新的信息、知识更新和时事动态。(联网搜索只是一个插件)

幻觉(Hallucination)现象

LLM存在一个固有的缺陷——"幻觉"现象,即模型会生成看似合理但实际不准确的信息。这包括:

  • 编造不存在的事实
  • 混淆不相关的概念
  • 生成看似专业但实际错误的答案
  • 缺乏对信息准确性的验证机制

例如,当被问及特定年份的统计数据时,模型可能会根据训练模式"推测"出一个看起来合理但实际错误的数字。

领域知识缺失

通用的大语言模型虽然知识面广泛,但在特定垂直领域可能缺乏深度专业知识。比如医疗诊断、法律条文、金融分析等专业领域,需要更精确和可靠的信息来源。

1.2 技术发展背景

2023-2025年RAG技术快速发展

RAG技术从2023年开始受到广泛关注,到2025年已经成为大模型应用的主流范式之一。根据最新研究,RAG技术正在经历快速演进,包括DeepRAG、RealRAG、SafeRAG等新方法的不断涌现。

企业级应用需求推动

随着AI技术在企业中的应用深入,企业对知识管理、文档问答、客户服务自动化等场景的需求激增。RAG技术正好满足了这些需求:

  • 知识库问答:企业可以上传内部文档,构建专属知识库
  • 文档处理:自动分析和理解大量文档内容
  • 客户服务:基于企业知识库提供准确回答
  • 合规性检查:基于最新法规和标准进行检查

开源生态成熟

RAG技术的快速发展离不开成熟的开源生态系统:

  • LangChain:提供完整的RAG应用开发框架
  • Ollama:简化本地LLM部署和管理
  • ChromaDB:高效的向量数据库解决方案
  • Streamlit:快速构建RAG应用界面

这些工具的成熟使得开发者可以快速构建功能完整的RAG应用。

1.3 市场需求驱动

成本效益考虑

相比传统的模型微调(Fine-tuning),RAG技术具有显著的成本优势:

  • 无需重新训练:避免昂贵的模型训练成本
  • 快速更新:知识库更新比模型重新训练更简单快捷
  • 灵活性强:一个模型可以处理多个领域的知识库

隐私和数据安全

在数据隐私日益重要的今天,RAG技术支持本地部署,避免敏感数据上传到云端:

  • 本地处理:所有数据处理在本地完成
  • 数据控制:企业完全控制数据流向
  • 合规性:满足各种数据保护法规要求

第二部分:RAG技术定义

2.1 核心概念

检索增强生成(Retrieval-Augmented Generation)定义

RAG是一种结合了信息检索技术与语言生成的AI技术架构。其核心思想是:在生成回答之前,先从外部知识库中检索相关信息,然后将这些检索到的信息作为上下文提供给语言模型,用于生成更准确、更相关的回答。

简单来说,RAG的工作流程可以分为三个步骤:

  1. 检索:根据用户问题,从知识库中找到相关信息
  2. 增强:将检索到的信息作为上下文
  3. 生成:基于增强的上下文生成回答

RAG vs 传统文本生成

方面传统文本生成RAG生成
知识来源训练时获得的知识实时检索的外部知识
准确性可能出现幻觉基于真实文档,准确率更高
时效性受训练数据时间限制可以访问最新信息
可解释性难以追溯答案来源可以引用具体文档段落
扩展性需要重新训练只需更新知识库

RAG vs Fine-tuning(微调)

方面RAGFine-tuning
成本低,无需重新训练模型高,需要大量计算资源
实施时间快,几小时到几天慢,需要数天到数周
知识更新简单,替换文档即可复杂,需要重新训练
模型数量一个模型处理多个领域一个模型专攻一个领域
解释性强,可以追溯文档弱,难以解释学习到的知识
适用场景知识密集型任务风格或格式转换任务

2.2 技术架构

RAG系统的核心架构包含三个主要阶段:

阶段一:索引(Indexing)

  • 文档加载:处理各种格式的文档(PDF、Word、TXT等)
  • 文本分块:将长文档分割成适当大小的段落
  • 向量化:使用embedding模型将文本转换为向量表示
  • 存储:将向量存储到向量数据库中

阶段二:检索(Retrieval)

  • 接收用户查询
  • 将查询向量化
  • 在向量数据库中搜索相似向量
  • 检索最相关的文档片段

阶段三:生成(Generation)

  • 将检索到的文档片段与用户查询组合成提示词
  • 将增强的提示词发送给语言模型
  • 生成基于检索内容的回答
  • 可选:将回答与原文进行事实核查

2.3 技术演进

RAG技术经历了快速的演进过程,从简单的检索增强发展到了复杂的多模态智能系统:

1. Naive RAG(简单RAG)

  • 采用基本的向量检索方法
  • 简单的文本匹配和检索
  • 结构简单但功能有限
  • 适用于基础的知识问答场景

2. Advanced RAG(高级RAG)

  • 引入更智能的检索策略
  • 包含查询重写、查询扩展等技术
  • 引入重排序(Re-ranking)机制
  • 提高检索质量和生成准确性

3. Modular RAG(模块化RAG)

  • 采用模块化设计思想
  • 不同功能模块可以灵活组合
  • 支持跨组件的端到端训练
  • 提供更高的系统灵活性和可扩展性

4. Graph RAG(图谱RAG)

  • 引入知识图谱技术
  • 利用实体关系进行智能检索
  • 提供更丰富的上下文理解
  • 适用于复杂关系数据的处理

5. Agentic RAG(智能体RAG)

  • 集成智能体(Agent)技术
  • 支持复杂的推理和决策过程
  • 具备自主学习和适应能力
  • 代表RAG技术的最前沿发展

第三部分:RAG优缺点分析

3.1 主要优势

知识时效性

RAG最大的优势之一是能够获取最新信息。通过连接外部知识库,系统可以:

  • 实时获取最新数据
  • 更新知识库无需重新训练模型
  • 处理动态变化的信息环境
  • 提供具有时效性的准确回答

减少幻觉现象

通过基于真实文档生成回答,RAG显著减少了传统语言模型的幻觉问题:

  • 答案有据可查,可以追溯到具体文档
  • 减少编造事实的情况
  • 提供更可靠的信息
  • 增强用户对AI系统的信任度

可解释性强

RAG系统具有良好的可解释性:

  • 可以显示答案来源于哪些文档
  • 用户可以验证信息的准确性
  • 支持引用和标注功能
  • 便于审计和合规性检查

成本效益显著

相比其他技术方案,RAG具有明显的成本优势:

  • 避免昂贵的模型训练成本
  • 减少计算资源需求
  • 缩短开发周期
  • 降低技术门槛

部署灵活性

RAG技术支持多种部署方式:

  • 云端部署:便于扩展和维护
  • 本地部署:保护数据隐私
  • 混合部署:平衡性能和安全性
  • 边缘部署:支持离线使用

3.2 主要挑战

检索质量依赖

RAG系统的效果很大程度上依赖于检索质量:

  • 垃圾进垃圾出(GIGO)原则依然适用
  • 文档质量直接影响系统性能
  • 检索算法的选择影响结果准确性
  • 需要精心设计文档预处理策略

向量表示局限性

当前的向量表示技术仍存在局限:

  • 语义理解的深度不足
  • 难以处理复杂的逻辑推理
  • 可能遗漏重要的语义关系
  • 对多语言支持有待改善

文档处理复杂性

实际应用中需要处理各种复杂格式的文档:

  • PDF解析:表格、图表、图片处理困难
  • 文档格式:Word、HTML、Markdown等格式差异
  • 语言混用:多种语言混合的文档处理
  • 结构化数据:表格、数据库等结构化信息处理

实时性能挑战

在处理大规模文档时面临的性能挑战:

  • 大规模向量检索的延迟问题
  • 内存使用量和存储空间需求
  • 并发处理能力限制
  • 响应速度与准确性的平衡

评估困难

RAG系统的效果评估存在挑战:

  • 缺乏统一的质量评估标准
  • 难以量化检索和生成的综合效果
  • 主观评价与客观指标的差异
  • 不同应用场景需要不同的评估方法

安全性考虑

RAG系统面临的安全挑战包括:

  • 对抗攻击防护:恶意文档可能影响系统输出
  • 数据投毒:恶意插入虚假信息
  • 隐私泄露:敏感信息可能被意外检索
  • 版权问题:知识库内容的版权保护

3.3 适用场景分析

✅ 适合RAG的场景

  1. 企业知识库问答

    • 内部文档管理
    • 员工培训材料
    • 技术文档查询
    • 政策法规解读
  2. 文档分析和总结

    • 法律文档分析
    • 学术论文总结
    • 报告内容提取
    • 合规性检查
  3. 客户服务自动化

    • 基于知识库的FAQ
    • 产品支持文档
    • 常见问题解答
    • 投诉处理支持
  4. 专业领域咨询

    • 医疗健康咨询
    • 法律条文解释
    • 技术支持服务
    • 教育培训内容

❌ 不适合RAG的场景

  1. 创意写作任务

    • 小说创作
    • 诗歌写作
    • 营销文案
    • 创意设计
  2. 纯数学推理

    • 复杂数学计算
    • 定理证明
    • 逻辑推理题
    • 算法优化
  3. 实时数据分析

    • 股票价格预测
    • 实时监控告警
    • 动态定价
    • 实时推荐
  4. 需要精确数值计算的任务

    • 科学计算
    • 工程设计
    • 财务分析
    • 统计建模

第四部分:实战项目 - 本地RAG系统

4.1 项目概述

在这个实战项目中,我们将构建一个完整的本地RAG系统,具备以下特性:

核心功能

  • 支持多种文档格式上传(PDF、TXT、DOCX)
  • 基于本地Ollama模型进行问答
  • 使用Streamlit构建用户友好的Web界面
  • 实时文档处理和向量化
  • 检索结果可视化

技术栈

  • 后端:Python 3.9+
  • 向量数据库:ChromaDB
  • 机器学习框架:LangChain
  • LLM:Ollama(支持多种本地模型)
  • Web界面:Streamlit
  • 文档处理:PyPDF2、python-docx

项目结构

rag_system/
├── app.py                 # Streamlit主应用
├── requirements.txt       # 依赖包列表
├── config.py             # 配置文件
├── utils/
│   ├── __init__.py
│   ├── document_loader.py    # 文档加载模块
│   ├── vector_store.py       # 向量存储模块
│   ├── retriever.py          # 检索模块
│   └── llm_handler.py        # LLM处理模块
├── data/
│   ├── documents/            # 上传的文档
│   └── vector_store/         # 向量数据库存储
└── temp/                 # 临时文件

4.2 环境准备

系统要求

  • Python 3.9 或更高版本
  • 至少4GB可用内存
  • 足够的存储空间(用于存储向量数据)
  • Ollama安装和配置

安装Ollama

首先安装Ollama框架:

# 在macOS上安装
brew install ollama

# 在Linux上安装
curl -fsSL https://ollama.ai/install.sh | sh

# 在Windows上
# 下载安装包:https://ollama.ai/download

安装并启动模型

# 下载Llama2模型(或其他可用模型)
ollama pull llama2
ollama pull nomic-embed-text

# 验证模型安装
ollama list

创建虚拟环境并安装Python依赖

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

# 创建requirements.txt
cat > requirements.txt << EOF
streamlit==1.28.0
langchain==0.1.0
langchain-community==0.0.10
chromadb==0.4.18
sentence-transformers==2.2.2
PyPDF2==3.0.1
python-docx==1.1.0
python-multipart==0.0.6
ollama==0.1.7
pandas==2.1.0
matplotlib==3.7.0
plotly==5.17.0
EOF

# 安装依赖
pip install -r requirements.txt

4.3 核心代码实现

4.3.1 主应用文件 (app.py)

import streamlit as st
import os
import tempfile
from pathlib import Path
import sys

# 添加项目路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from utils.document_loader import DocumentLoader
from utils.vector_store import VectorStoreManager
from utils.retriever import RAGRetriever
from utils.llm_handler import LLMHandler
from config import Config

# 页面配置
st.set_page_config(
    page_title="本地RAG系统",
    page_icon="📚",
    layout="wide",
    initial_sidebar_state="expanded"
)

# 自定义CSS
st.markdown("""
<style>
    .main-header {
        font-size: 3rem;
        color: #1f77b4;
        text-align: center;
        margin-bottom: 2rem;
    }
    .section-header {
        font-size: 1.5rem;
        color: #2e86ab;
        margin-top: 2rem;
        margin-bottom: 1rem;
    }
    .info-box {
        background-color: #f0f2f6;
        padding: 1rem;
        border-radius: 0.5rem;
        border-left: 4px solid #1f77b4;
        margin: 1rem 0;
    }
</style>
""", unsafe_allow_html=True)

def initialize_session_state():
    """初始化会话状态"""
    if 'vector_store_manager' not in st.session_state:
        st.session_state.vector_store_manager = VectorStoreManager()
    
    if 'document_loader' not in st.session_state:
        st.session_state.document_loader = DocumentLoader()
    
    if 'llm_handler' not in st.session_state:
        st.session_state.llm_handler = LLMHandler()
    
    if 'retriever' not in st.session_state:
        st.session_state.retriever = RAGRetriever(
            st.session_state.vector_store_manager
        )
    
    if 'chat_history' not in st.session_state:
        st.session_state.chat_history = []
    
    if 'documents_processed' not in st.session_state:
        st.session_state.documents_processed = False

def main():
    # 初始化应用
    initialize_session_state()
    
    # 主标题
    st.markdown('<h1 class="main-header">📚 本地RAG知识库系统</h1>', 
                unsafe_allow_html=True)
    
    # 侧边栏
    with st.sidebar:
        st.header("🔧 系统设置")
        
        # 模型选择
        model_options = ["llama2", "llama2:7b", "codellama", "mistral"]
        selected_model = st.selectbox(
            "选择LLM模型",
            model_options,
            index=0
        )
        
        # 检索参数
        top_k = st.slider("检索文档数量", 1, 10, 3)
        
        # 清除按钮
        if st.button("🗑️ 清除所有数据", type="secondary"):
            st.session_state.vector_store_manager.clear_all()
            st.session_state.chat_history = []
            st.session_state.documents_processed = False
            st.success("数据已清除!")
            st.rerun()
        
        st.divider()
        
        # 系统状态
        st.header("📊 系统状态")
        status_placeholder = st.empty()
        
        # 更新状态显示
        with status_placeholder.container():
            vector_count = st.session_state.vector_store_manager.get_vector_count()
            st.metric("向量数量", vector_count)
            
            if st.session_state.documents_processed:
                st.success("✅ 文档已处理")
            else:
                st.warning("⏳ 等待文档上传")

    # 主要内容区域
    col1, col2 = st.columns([1, 1])
    
    with col1:
        st.markdown('<h2 class="section-header">📁 文档上传</h2>', 
                    unsafe_allow_html=True)
        
        uploaded_files = st.file_uploader(
            "上传文档文件",
            type=['pdf', 'txt', 'docx'],
            accept_multiple_files=True,
            help="支持PDF、TXT、DOCX格式的文档"
        )
        
        if uploaded_files:
            process_documents(uploaded_files)
        
        # 显示已上传的文档列表
        if st.session_state.vector_store_manager.has_documents():
            st.markdown("### 📋 已处理文档")
            documents = st.session_state.vector_store_manager.get_document_list()
            for doc in documents:
                st.text(f"📄 {doc}")

    with col2:
        st.markdown('<h2 class="section-header">💬 智能问答</h2>', 
                    unsafe_allow_html=True)
        
        # 聊天界面
        if st.session_state.chat_history:
            for message in st.session_state.chat_history:
                if message['role'] == 'user':
                    st.markdown(f"**用户**: {message['content']}")
                else:
                    st.markdown(f"**AI**: {message['content']}")
                st.divider()
        
        # 用户输入
        user_input = st.text_input(
            "请输入您的问题",
            placeholder="例如:文档中提到的关键技术有哪些?",
            key="user_input"
        )
        
        col_query, col_clear = st.columns([4, 1])
        
        with col_query:
            if st.button("🚀 提交问题", type="primary") and user_input:
                process_query(user_input, selected_model, top_k)
        
        with col_clear:
            if st.button("🗑️ 清空聊天", type="secondary"):
                st.session_state.chat_history = []
                st.rerun()

def process_documents(uploaded_files):
    """处理上传的文档"""
    if not uploaded_files:
        return
    
    with st.spinner("正在处理文档..."):
        for uploaded_file in uploaded_files:
            try:
                # 保存临时文件
                with tempfile.NamedTemporaryFile(delete=False, 
                                               suffix=f".{uploaded_file.name.split('.')[-1]}") as tmp_file:
                    tmp_file.write(uploaded_file.getvalue())
                    tmp_file_path = tmp_file.name
                
                # 处理文档
                docs = st.session_state.document_loader.load_document(tmp_file_path)
                
                if docs:
                    # 添加到向量存储
                    st.session_state.vector_store_manager.add_documents(docs)
                    st.success(f"✅ 已处理文档: {uploaded_file.name}")
                else:
                    st.warning(f"⚠️ 无法处理文档: {uploaded_file.name}")
                
                # 清理临时文件
                os.unlink(tmp_file_path)
                
            except Exception as e:
                st.error(f"❌ 处理文档失败: {uploaded_file.name} - {str(e)}")
    
    st.session_state.documents_processed = True
    st.rerun()

def process_query(query, model, top_k):
    """处理用户查询"""
    try:
        # 添加用户消息到历史
        st.session_state.chat_history.append({
            'role': 'user',
            'content': query
        })
        
        with st.spinner("正在检索和生成答案..."):
            # 检索相关文档
            retrieved_docs = st.session_state.retriever.retrieve(query, top_k=top_k)
            
            # 生成回答
            answer = st.session_state.llm_handler.generate_answer(
                query, retrieved_docs, model
            )
            
            # 添加AI回答到历史
            st.session_state.chat_history.append({
                'role': 'assistant',
                'content': answer
            })
            
        st.rerun()
        
    except Exception as e:
        st.error(f"❌ 查询处理失败: {str(e)}")

if __name__ == "__main__":
    main()

4.3.2 配置文件 (config.py)

import os
from pathlib import Path

class Config:
    """应用配置"""
    
    # 基础路径
    BASE_DIR = Path(__file__).parent
    DATA_DIR = BASE_DIR / "data"
    TEMP_DIR = BASE_DIR / "temp"
    
    # 向量数据库配置
    VECTOR_DB_DIR = DATA_DIR / "vector_store"
    CHROMA_SETTINGS = {
        "persist_directory": str(VECTOR_DB_DIR),
        "anonymized_telemetry": False
    }
    
    # 文档处理配置
    CHUNK_SIZE = 1000
    CHUNK_OVERLAP = 200
    MAX_CHUNK_SIZE = 2000
    
    # 嵌入模型配置
    EMBEDDING_MODEL_NAME = "sentence-transformers/all-MiniLM-L6-v2"
    
    # Ollama配置
    OLLAMA_HOST = "http://localhost:11434"
    DEFAULT_MODEL = "llama2"
    
    # 检索配置
    DEFAULT_TOP_K = 3
    SIMILARITY_THRESHOLD = 0.7
    
    # 支持的文件格式
    SUPPORTED_FORMATS = ['.pdf', '.txt', '.docx']
    
    # 创建必要目录
    @classmethod
    def create_directories(cls):
        """创建必要的目录"""
        cls.DATA_DIR.mkdir(exist_ok=True)
        cls.VECTOR_DB_DIR.mkdir(exist_ok=True)
        cls.TEMP_DIR.mkdir(exist_ok=True)
        
        # 创建子目录
        (cls.DATA_DIR / "documents").mkdir(exist_ok=True)

4.3.3 文档加载模块 (utils/document_loader.py)

import os
import io
from typing import List, Union, Optional
from pathlib import Path

import PyPDF2
from docx import Document
from langchain.schema import Document as LangchainDocument
from langchain.text_splitter import RecursiveCharacterTextSplitter

from config import Config

class DocumentLoader:
    """文档加载和预处理类"""
    
    def __init__(self):
        self.config = Config()
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=self.config.CHUNK_SIZE,
            chunk_overlap=self.config.CHUNK_OVERLAP,
            length_function=len,
        )
    
    def load_document(self, file_path: Union[str, Path]) -> Optional[List[LangchainDocument]]:
        """
        加载单个文档
        
        Args:
            file_path: 文档文件路径
            
        Returns:
            文档对象列表,如果加载失败则返回None
        """
        file_path = Path(file_path)
        
        if not file_path.exists():
            print(f"文件不存在: {file_path}")
            return None
        
        file_extension = file_path.suffix.lower()
        
        try:
            if file_extension == '.pdf':
                return self._load_pdf(file_path)
            elif file_extension == '.txt':
                return self._load_text(file_path)
            elif file_extension == '.docx':
                return self._load_docx(file_path)
            else:
                print(f"不支持的文件格式: {file_extension}")
                return None
                
        except Exception as e:
            print(f"加载文档失败 {file_path}: {str(e)}")
            return None
    
    def _load_pdf(self, file_path: Path) -> List[LangchainDocument]:
        """加载PDF文档"""
        documents = []
        
        try:
            with open(file_path, 'rb') as file:
                pdf_reader = PyPDF2.PdfReader(file)
                text = ""
                
                for page_num, page in enumerate(pdf_reader.pages):
                    page_text = page.extract_text()
                    if page_text.strip():
                        text += f"\n--- 第{page_num + 1}页 ---\n"
                        text += page_text.strip()
            
            if text.strip():
                # 分割文本
                chunks = self.text_splitter.split_text(text)
                
                for i, chunk in enumerate(chunks):
                    documents.append(LangchainDocument(
                        page_content=chunk,
                        metadata={
                            "source": str(file_path),
                            "page": i // (self.config.CHUNK_SIZE // 500),  # 估算页数
                            "chunk_id": i
                        }
                    ))
        
        except Exception as e:
            raise Exception(f"PDF处理失败: {str(e)}")
        
        return documents
    
    def _load_text(self, file_path: Path) -> List[LangchainDocument]:
        """加载文本文档"""
        try:
            with open(file_path, 'r', encoding='utf-8') as file:
                text = file.read()
            
            if not text.strip():
                return []
            
            # 分割文本
            chunks = self.text_splitter.split_text(text)
            documents = []
            
            for i, chunk in enumerate(chunks):
                documents.append(LangchainDocument(
                    page_content=chunk,
                    metadata={
                        "source": str(file_path),
                        "chunk_id": i
                    }
                ))
            
            return documents
            
        except Exception as e:
            raise Exception(f"文本文件处理失败: {str(e)}")
    
    def _load_docx(self, file_path: Path) -> List[LangchainDocument]:
        """加载Word文档"""
        try:
            doc = Document(file_path)
            text = ""
            
            # 提取段落
            for paragraph in doc.paragraphs:
                if paragraph.text.strip():
                    text += paragraph.text + "\n"
            
            # 提取表格
            for table in doc.tables:
                for row in table.rows:
                    row_text = []
                    for cell in row.cells:
                        if cell.text.strip():
                            row_text.append(cell.text.strip())
                    if row_text:
                        text += " | ".join(row_text) + "\n"
            
            if not text.strip():
                return []
            
            # 分割文本
            chunks = self.text_splitter.split_text(text)
            documents = []
            
            for i, chunk in enumerate(chunks):
                documents.append(LangchainDocument(
                    page_content=chunk,
                    metadata={
                        "source": str(file_path),
                        "chunk_id": i
                    }
                ))
            
            return documents
            
        except Exception as e:
            raise Exception(f"Word文档处理失败: {str(e)}")
    
    def load_multiple_documents(self, file_paths: List[Union[str, Path]]) -> List[LangchainDocument]:
        """
        批量加载文档
        
        Args:
            file_paths: 文档文件路径列表
            
        Returns:
            所有文档的合并列表
        """
        all_documents = []
        
        for file_path in file_paths:
            documents = self.load_document(file_path)
            if documents:
                all_documents.extend(documents)
        
        return all_documents
    
    def validate_file_format(self, file_path: Union[str, Path]) -> bool:
        """
        验证文件格式
        
        Args:
            file_path: 文件路径
            
        Returns:
            是否为支持的文件格式
        """
        file_path = Path(file_path)
        return file_path.suffix.lower() in self.config.SUPPORTED_FORMATS

4.3.4 向量存储模块 (utils/vector_store.py)

import os
from typing import List, Optional, Dict, Any
from pathlib import Path

from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.schema import Document as LangchainDocument

from config import Config

class VectorStoreManager:
    """向量存储管理器"""
    
    def __init__(self, collection_name: str = "documents"):
        self.config = Config()
        self.collection_name = collection_name
        self.vector_store: Optional[Chroma] = None
        self.embeddings = None
        self._initialize_embeddings()
        self._load_or_create_vector_store()
    
    def _initialize_embeddings(self):
        """初始化嵌入模型"""
        try:
            self.embeddings = HuggingFaceEmbeddings(
                model_name=self.config.EMBEDDING_MODEL_NAME,
                model_kwargs={'device': 'cpu'},
                encode_kwargs={'normalize_embeddings': True}
            )
        except Exception as e:
            raise Exception(f"嵌入模型初始化失败: {str(e)}")
    
    def _load_or_create_vector_store(self):
        """加载或创建向量存储"""
        try:
            # 检查是否已有向量存储
            if os.path.exists(self.config.VECTOR_DB_DIR) and \
               os.listdir(self.config.VECTOR_DB_DIR):
                
                self.vector_store = Chroma(
                    persist_directory=str(self.config.VECTOR_DB_DIR),
                    embedding_function=self.embeddings,
                    collection_name=self.collection_name
                )
            else:
                # 创建新的向量存储
                self.vector_store = Chroma(
                    collection_name=self.collection_name,
                    embedding_function=self.embeddings,
                    persist_directory=str(self.config.VECTOR_DB_DIR)
                )
                
        except Exception as e:
            raise Exception(f"向量存储初始化失败: {str(e)}")
    
    def add_documents(self, documents: List[LangchainDocument]) -> bool:
        """
        添加文档到向量存储
        
        Args:
            documents: 文档列表
            
        Returns:
            是否添加成功
        """
        if not documents:
            return False
        
        try:
            # 提取文本内容
            texts = [doc.page_content for doc in documents]
            metadatas = [doc.metadata for doc in documents]
            
            # 添加到向量存储
            self.vector_store.add_texts(
                texts=texts,
                metadatas=metadatas
            )
            
            # 持久化
            self.vector_store.persist()
            
            return True
            
        except Exception as e:
            print(f"添加文档失败: {str(e)}")
            return False
    
    def similarity_search(self, query: str, k: int = 3) -> List[LangchainDocument]:
        """
        基于相似性搜索文档
        
        Args:
            query: 查询文本
            k: 返回文档数量
            
        Returns:
            相似文档列表
        """
        try:
            return self.vector_store.similarity_search(
                query=query,
                k=k
            )
        except Exception as e:
            print(f"相似性搜索失败: {str(e)}")
            return []
    
    def similarity_search_with_score(self, query: str, k: int = 3) -> List[tuple]:
        """
        带分数的相似性搜索
        
        Args:
            query: 查询文本
            k: 返回文档数量
            
        Returns:
            包含文档和相似度分数的元组列表
        """
        try:
            return self.vector_store.similarity_search_with_score(
                query=query,
                k=k
            )
        except Exception as e:
            print(f"带分数的相似性搜索失败: {str(e)}")
            return []
    
    def get_vector_count(self) -> int:
        """获取向量数量"""
        try:
            if self.vector_store:
                return self.vector_store._collection.count()
            return 0
        except:
            return 0
    
    def has_documents(self) -> bool:
        """检查是否有文档"""
        return self.get_vector_count() > 0
    
    def get_document_list(self) -> List[str]:
        """获取文档列表"""
        try:
            if not self.vector_store:
                return []
            
            # 获取所有文档的元数据
            docs = self.vector_store.get()
            sources = set()
            
            if 'metadatas' in docs and docs['metadatas']:
                for metadata in docs['metadatas']:
                    if 'source' in metadata:
                        sources.add(Path(metadata['source']).name)
            
            return sorted(list(sources))
            
        except Exception as e:
            print(f"获取文档列表失败: {str(e)}")
            return []
    
    def clear_all(self):
        """清除所有数据"""
        try:
            if self.vector_store:
                self.vector_store.delete_collection()
                self._load_or_create_vector_store()
        except Exception as e:
            print(f"清除数据失败: {str(e)}")
    
    def update_collection_name(self, new_name: str):
        """更新集合名称"""
        self.collection_name = new_name
        self._load_or_create_vector_store()
    
    def get_collection_info(self) -> Dict[str, Any]:
        """获取集合信息"""
        try:
            if not self.vector_store:
                return {"error": "向量存储未初始化"}
            
            count = self.vector_store._collection.count()
            
            return {
                "collection_name": self.collection_name,
                "vector_count": count,
                "embeddings_model": self.config.EMBEDDING_MODEL_NAME,
                "persist_directory": str(self.config.VECTOR_DB_DIR)
            }
            
        except Exception as e:
            return {"error": str(e)}

4.3.5 检索模块 (utils/retriever.py)

from typing import List, Dict, Any, Optional
from langchain.schema import Document as LangchainDocument

from utils.vector_store import VectorStoreManager

class RAGRetriever:
    """RAG检索器"""
    
    def __init__(self, vector_store_manager: VectorStoreManager):
        self.vector_store_manager = vector_store_manager
    
    def retrieve(self, query: str, top_k: int = 3) -> List[Dict[str, Any]]:
        """
        检索相关文档
        
        Args:
            query: 用户查询
            top_k: 返回文档数量
            
        Returns:
            检索结果列表,包含文档内容、元数据和相似度分数
        """
        try:
            # 执行相似性搜索
            docs_with_scores = self.vector_store_manager.similarity_search_with_score(
                query=query, 
                k=top_k
            )
            
            results = []
            for doc, score in docs_with_scores:
                results.append({
                    "content": doc.page_content,
                    "metadata": doc.metadata,
                    "similarity_score": score,
                    "source": doc.metadata.get("source", "unknown"),
                    "chunk_id": doc.metadata.get("chunk_id", "unknown")
                })
            
            return results
            
        except Exception as e:
            print(f"检索失败: {str(e)}")
            return []
    
    def retrieve_with_context(self, query: str, top_k: int = 3) -> str:
        """
        检索并构造上下文文本
        
        Args:
            query: 用户查询
            top_k: 返回文档数量
            
        Returns:
            构造的上下文文本
        """
        retrieved_docs = self.retrieve(query, top_k)
        
        if not retrieved_docs:
            return "未找到相关内容。"
        
        context_parts = []
        for i, doc in enumerate(retrieved_docs, 1):
            context_parts.append(f"=== 文档片段 {i} ===")
            context_parts.append(f"内容: {doc['content']}")
            context_parts.append(f"来源: {doc['source']}")
            context_parts.append(f"相关度: {doc['similarity_score']:.3f}")
            context_parts.append("")
        
        return "\n".join(context_parts)
    
    def get_retrieval_info(self, query: str, top_k: int = 3) -> Dict[str, Any]:
        """获取检索详细信息"""
        retrieved_docs = self.retrieve(query, top_k)
        
        return {
            "query": query,
            "total_results": len(retrieved_docs),
            "results": retrieved_docs,
            "avg_similarity": sum(doc["similarity_score"] for doc in retrieved_docs) / len(retrieved_docs) if retrieved_docs else 0
        }

4.3.6 LLM处理模块 (utils/llm_handler.py)

import requests
import json
from typing import List, Dict, Any, Optional

from langchain.schema import Document as LangchainDocument
from utils.retriever import RAGRetriever

class LLMHandler:
    """大语言模型处理器"""
    
    def __init__(self):
        self.base_url = "http://localhost:11434/api/generate"
    
    def generate_answer(self, 
                       query: str, 
                       retrieved_docs: List[Dict[str, Any]], 
                       model: str = "llama2",
                       temperature: float = 0.7) -> str:
        """
        生成回答
        
        Args:
            query: 用户查询
            retrieved_docs: 检索到的文档
            model: 模型名称
            temperature: 生成温度
            
        Returns:
            生成的答案
        """
        try:
            # 构造上下文
            context = self._construct_context(query, retrieved_docs)
            
            # 构造提示词
            prompt = self._create_prompt(query, context)
            
            # 调用Ollama API
            response = self._call_ollama_api(prompt, model, temperature)
            
            return response
            
        except Exception as e:
            return f"生成回答时发生错误: {str(e)}"
    
    def _construct_context(self, query: str, retrieved_docs: List[Dict[str, Any]]) -> str:
        """构造上下文信息"""
        if not retrieved_docs:
            return "未找到相关信息。"
        
        context_parts = []
        context_parts.append("以下是与问题相关的信息片段:\n")
        
        for i, doc in enumerate(retrieved_docs, 1):
            context_parts.append(f"【片段 {i}】")
            context_parts.append(f"内容:{doc['content']}")
            context_parts.append(f"来源:{doc['source']}")
            if 'chunk_id' in doc['metadata']:
                context_parts.append(f"位置:第{doc['metadata']['chunk_id']}段")
            context_parts.append("")
        
        return "\n".join(context_parts)
    
    def _create_prompt(self, query: str, context: str) -> str:
        """创建提示词"""
        prompt = f"""你是一个专业的问答助手。请根据提供的上下文信息回答用户的问题。

用户问题:{query}

相关上下文:
{context}

请注意:
1. 回答必须基于提供的上下文信息
2. 如果上下文信息不足,请明确说明
3. 回答要准确、简洁、条理清晰
4. 如果有具体的数据或事实,请引用来源

回答:"""
        return prompt
    
    def _call_ollama_api(self, prompt: str, model: str, temperature: float) -> str:
        """调用Ollama API"""
        try:
            payload = {
                "model": model,
                "prompt": prompt,
                "stream": False,
                "options": {
                    "temperature": temperature,
                    "num_predict": 1000,
                    "top_k": 40,
                    "top_p": 0.9,
                }
            }
            
            response = requests.post(
                self.base_url,
                json=payload,
                headers={"Content-Type": "application/json"},
                timeout=60
            )
            
            if response.status_code == 200:
                result = response.json()
                return result.get("response", "生成回答时出现未知错误。")
            else:
                raise Exception(f"API调用失败:{response.status_code} - {response.text}")
                
        except requests.exceptions.RequestException as e:
            raise Exception(f"网络请求失败:{str(e)}")
        except json.JSONDecodeError as e:
            raise Exception(f"响应解析失败:{str(e)}")
        except Exception as e:
            raise Exception(f"LLM调用失败:{str(e)}")
    
    def generate_with_citations(self, 
                               query: str, 
                               retrieved_docs: List[Dict[str, Any]], 
                               model: str = "llama2") -> Dict[str, Any]:
        """生成带引用的回答"""
        try:
            # 生成普通回答
            answer = self.generate_answer(query, retrieved_docs, model)
            
            # 提取引用信息
            citations = []
            for i, doc in enumerate(retrieved_docs):
                citations.append({
                    "source": doc['source'],
                    "chunk_id": doc.get('chunk_id', 'unknown'),
                    "similarity_score": doc['similarity_score']
                })
            
            return {
                "answer": answer,
                "citations": citations,
                "num_sources": len(citations)
            }
            
        except Exception as e:
            return {
                "answer": f"生成回答时发生错误: {str(e)}",
                "citations": [],
                "num_sources": 0
            }
    
    def check_model_availability(self, model: str = "llama2") -> bool:
        """检查模型是否可用"""
        try:
            test_payload = {
                "model": model,
                "prompt": "Hi",
                "stream": False
            }
            
            response = requests.post(
                self.base_url,
                json=test_payload,
                headers={"Content-Type": "application/json"},
                timeout=10
            )
            
            return response.status_code == 200
            
        except:
            return False

4.4 运行系统

启动应用

# 确保虚拟环境已激活
source rag_env/bin/activate  # Linux/macOS
# 或
rag_env\Scripts\activate     # Windows

# 确保Ollama正在运行
ollama serve

# 启动Streamlit应用
streamlit run app.py

系统使用流程

  1. 文档上传

    • 支持拖拽或点击上传PDF、TXT、DOCX文件
    • 系统会自动处理和向量化文档
    • 可查看处理进度和结果
  2. 智能问答

    • 在右侧输入框中输入问题
    • 系统检索相关文档片段
    • 基于检索内容生成准确回答
    • 可查看引用的文档来源
  3. 系统功能

    • 清除数据:重置知识库
    • 模型选择:切换不同的LLM模型
    • 检索参数:调整检索文档数量

4.5 性能优化与部署

性能优化建议

  1. 文档预处理优化

    # 在utils/document_loader.py中添加
    def optimize_chunking(self, text: str, chunk_size: int = 1000):
        """智能分块策略"""
        # 按句子分割,保持语义完整性
        sentences = text.split('。')
        chunks = []
        current_chunk = ""
        
        for sentence in sentences:
            if len(current_chunk + sentence) < chunk_size:
                current_chunk += sentence + "。"
            else:
                if current_chunk:
                    chunks.append(current_chunk.strip())
                current_chunk = sentence + "。"
        
        if current_chunk:
            chunks.append(current_chunk.strip())
        
        return chunks
    
  2. 缓存机制

    # 添加缓存装饰器
    from functools import lru_cache
    
    @lru_cache(maxsize=1000)
    def get_embedding_cached(self, text: str):
        """缓存嵌入向量"""
        return self.embeddings.embed_query(text)
    
  3. 批量处理

    def batch_process_documents(self, documents: List[LangchainDocument], batch_size: int = 100):
        """批量处理文档"""
        for i in range(0, len(documents), batch_size):
            batch = documents[i:i + batch_size]
            self.add_documents(batch)
            print(f"已处理 {i + len(batch)} / {len(documents)} 文档")
    

部署选项

  1. Docker容器化

    FROM python:3.9-slim
    
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    
    COPY . .
    
    EXPOSE 8501
    
    CMD ["streamlit", "run", "app.py", "--server.address", "0.0.0.0"]
    
  2. 生产环境配置

    # production_config.py
    class ProductionConfig:
        # 使用更强的嵌入模型
        EMBEDDING_MODEL_NAME = "sentence-transformers/all-mpnet-base-v2"
        
        # 增加并发处理
        MAX_CONCURRENT_REQUESTS = 10
        
        # 启用缓存
        ENABLE_CACHE = True
        
        # 监控和日志
        ENABLE_MONITORING = True
    

这个完整的RAG系统提供了一个功能齐全的本地知识库解决方案,支持多种文档格式,具有良好的扩展性和定制性。开发者可以根据具体需求进一步优化和扩展功能。


第五部分:未来展望

5.1 技术发展趋势

RAG技术在2025年及未来几年将继续快速发展,根据当前研究趋势,我们可以看到以下几个重要发展方向11:

多模态RAG

未来的RAG系统将不仅仅局限于文本处理,而是能够处理多种模态的数据:

  • 图像理解:系统能够检索和理解图像内容,结合文本信息进行综合分析
  • 音频处理:支持语音文档的检索和问答
  • 视频内容:能够分析和检索视频中的文本和视觉信息
  • 表格数据:更好地处理结构化数据和图表信息

这种多模态能力将使RAG系统更加智能和实用,能够处理更复杂的信息查询任务。

自适应检索策略

传统的RAG系统使用固定的检索策略,未来的系统将具备自适应能力:

  • 查询类型识别:自动识别查询是事实性问题、分析性问题还是创意性问题
  • 动态检索深度:根据问题复杂度调整检索文档的数量和深度
  • 智能查询重写:自动优化用户查询以提高检索效果
  • 个性化检索:根据用户偏好和历史行为调整检索策略

强化学习应用

强化学习技术将被更广泛地应用于RAG系统优化:

  • 反馈学习:基于用户满意度持续优化检索和生成策略
  • 奖励机制设计:建立更科学的评估指标,奖励高质量的回答
  • 在线学习:系统能够从实际使用中不断学习和改进
  • 对抗训练:提高系统对对抗攻击的鲁棒性

小型语言模型的RAG应用

随着模型压缩和优化技术的发展,小型语言模型将更适合RAG应用:

  • 移动端部署:在手机等移动设备上运行RAG系统
  • 边缘计算:在边缘节点上部署轻量级RAG服务
  • 实时响应:更快的响应速度,适合实时应用场景
  • 隐私保护:数据处理更接近用户端,保护隐私

5.2 产业应用前景

企业数字化转型

RAG将成为企业数字化转型的重要工具:

  • 知识管理:企业内部知识库的智能化和自动化
  • 培训系统:基于企业文档的个性化培训内容生成
  • 决策支持:基于历史数据和文档的智能决策建议
  • 合规监控:自动化的合规性检查和报告生成

垂直行业深度应用

各个垂直行业将发展出专业的RAG解决方案:

医疗健康

  • 医学文献检索和问答
  • 临床决策支持系统
  • 药物信息查询
  • 个性化健康建议

金融服务

  • 法规合规文档分析
  • 投资研究报告生成
  • 风险评估文档审查
  • 客户咨询自动化

教育培训

  • 个性化学习路径推荐
  • 智能答疑系统
  • 课程内容自动生成
  • 学习效果评估

法律服务

  • 法律条文检索和分析
  • 合同审查和风险识别
  • 案例研究和法理分析
  • 法律文档生成

智能助手集成

RAG技术将深度集成到各种智能助手中:

  • 个人助理:更准确的个人信息查询和建议
  • 客服机器人:基于企业知识库的智能客服
  • 教育助手:个性化学习辅导和问题解答
  • 工作助手:办公文档智能处理和分析

5.3 技术挑战与解决方向

标准化和规范化

随着RAG技术的普及,需要建立更完善的标准:

  • 评估指标标准化:建立统一的质量评估标准
  • 接口规范化:制定不同组件间的标准接口
  • 数据格式标准:统一文档和元数据的格式规范
  • 安全标准:建立RAG系统的安全规范

可解释性和透明度

提升RAG系统的可解释性:

  • 决策过程可视化:展示检索和生成的具体过程
  • 引用追踪:精确追踪每个答案的来源文档
  • 置信度评估:为每个回答提供可靠性评分
  • 用户反馈机制:收集和分析用户反馈以改进系统

安全和隐私保护

加强RAG系统的安全性:

  • 数据投毒防护:检测和过滤恶意文档
  • 隐私信息保护:自动识别和处理敏感信息
  • 访问控制:细粒度的数据访问权限管理
  • 审计日志:完整的使用记录和追踪

计算效率优化

提高RAG系统的计算效率:

  • 向量检索优化:更快的向量相似度计算算法
  • 模型压缩:减小模型大小以提高推理速度
  • 分布式计算:支持大规模数据的分布式处理
  • 缓存策略:智能缓存减少重复计算

总结

RAG(检索增强生成)技术作为当前AI领域的热点技术,通过巧妙地结合信息检索和语言生成的能力,有效解决了大语言模型在知识时效性、准确性和可解释性方面的局限性。

核心价值

  1. 时效性突破:RAG使AI系统能够获取最新信息,突破了传统模型的知识截止限制
  2. 准确性提升:通过基于真实文档生成,大幅减少了AI"幻觉"现象
  3. 成本效益:相比模型微调,RAG提供了更经济、更灵活的解决方案
  4. 可解释性:系统能够追溯答案来源,提供可验证的信息

技术发展

从简单的Naive RAG发展到复杂的Agentic RAG,技术不断成熟和完善。多模态RAG、自适应检索、强化学习优化等新方向的出现,预示着RAG技术将在更多领域发挥重要作用。

实践应用

通过本篇文章的实战项目,我们展示了如何使用Python、Ollama、Streamlit等现代工具构建一个功能完整的本地RAG系统。这个系统具备文档上传、智能问答、结果可视化等核心功能,为开发者提供了一个很好的学习起点。

未来展望

RAG技术正朝着多模态、智能化、个性化的方向发展。未来的RAG系统将更加智能、高效和安全,在企业数字化转型、垂直行业应用、智能助手集成等方面发挥重要作用。

对于AI开发者而言,掌握RAG技术不仅能够解决当前的实际问题,更能为未来在AI领域的深入发展奠定坚实基础。随着技术的不断进步和生态系统的日趋完善,RAG必将成为AI应用开发的重要范式之一。

学习建议

  1. 理论与实践结合:深入理解RAG的原理,同时通过实际项目加深理解
  2. 关注最新进展:跟踪RAG领域的最新研究和技术发展
  3. 多场景应用:尝试在不同领域和场景中应用RAG技术
  4. 持续优化:在实际使用中不断优化和改进RAG系统

RAG技术代表了AI应用开发的一个重要方向,掌握这项技术将为您的AI开发之路开辟更广阔的空间。随着技术的不断演进,我们有理由相信RAG将在构建更智能、更可靠的AI系统中发挥越来越重要的作用。

RAG全流程详解:原理、步骤与实战技术推荐 在生成回答之前,先从外部知识库中检索相关信息,再将检索到的内容与用户问题一同输入大语言模型,生成基于知识的高质量回答。它结合了信息检索(IR)和生成模型的优势,既提升了回答的准确性,也增加了系统的可解释性。RAG通过将检索与生成结合,显著提升了大语言模型回答问题的准确性和实用性。掌握每个步骤的核心要点和最佳实践,能够帮助你快速搭建适合自己业务场景的智能问答系统。预处理提升检索精度精排提高相关性和忠实度灵活Prompt设计引导模型生成自动评估驱动持续优化。 阅读详情

相关推荐

【人工智能】DeepSeek 与 RAG 技术:构建知识增强型问答系统的实战

本文深入探讨了如何利用 DeepSeek R1 模型结合检索增强生成(RAG)技术,构建一个高效的知识增强型问答系统。RAG 技术通过结合信息检索与生成模型的优势,能够显著提升问答系统的准确性和上下文相关性。文章详细介绍了 DeepSeek R1 的技术架构、RAG 系统的设计与实现,包括环境搭建、知识库构建、检索模块优化以及生成模块的细化调优。提供了大量 Python 代码示例,涵盖数据预处理、向量嵌入、检索与生成全流程,并辅以中文注释和数学公式解释关键算法原理。文章旨在为开发者提供一个从理论到实践的完整

一个被知识诅咒的人 1350

RAG系统实战:11个关键技术模块详解+避坑指南(建议收藏学习)

本文全面解析RAG系统的11个核心模块,为开发者提供从数据导入到复杂检索的完整技术指南。重点包括:数据导入的质量控制与多源处理技巧、文本分块的最佳实践、嵌入模型选型与评估、向量存储优化策略、查询优化方法、检索准确性提升手段、后处理技术、生成过程控制、评估体系构建以及前沿的复杂检索范式。文章强调RAG系统是系统工程,需平衡组件选择与工程细节,提供了可落地的实操清单和避坑建议,涵盖数据处理、算法优化、性能调优等关键环节,适合不同阶段的开发者参考实践。

优快云_430422的博客 1138

LeGO-LOAM运行kitti数据集

文章目录1. kitti-lego-loam2. 改动3. 实验结果4. evo轨迹测评 1. kitti-lego-loam 链接:kitti-lego-loam kitti-lego-loam提供了将kitti序列转化成rosbag的代码,在kittibag中. 需要注意下数据文件的存放顺序,以00序列为例: datafolder          |____results          &

Zlp19970106的博客 8704

AI大模型核心知识点与实战学习路线

掌握Prompt+LangChain+RAG三大核心技术的开发者,薪资溢价达45%。本文浓缩1000+学员教学经验,带你系统构建大模型知识体系。

Langchain的博客 449

手把手教你理解瑞萨RH850芯片的HSM:从硬件隔离到软件中断通信

本文深入解析瑞萨RH850芯片的HSM架构,从硬件隔离到软件中断通信的完整实现。通过详细讲解HSM的硬件组件、启动流程、核间通信机制及安全服务实现,帮助开发者掌握芯片级安全技术,提升汽车电子和工业控制领域的安全防护能力。

weixin_33925615的博客 379

ansys workbench 静力结构分析 高阶教程

ansys workbench 静力结构分析 高阶教程 目录ansys workbench 静力结构分析 高阶教程新建工程模型导入设置材料模型简化: 主要内容: 材料设置、模型简化、网格细化、约束分析、接触设置、求解设置、报错处理、结果分析 基础教程: ansys workbench 静力结构分析 基础操作流程(入门) ansys版本: 19.0(16.0及以上均可) 参考资料: 推荐教学视频《有限元分析 张晔》(超详细 ???? )、ansys workbench 超级学习手册(查阅用) 说明:一些基

weixin_43434624的博客 5万+

【宠粉赠书】大模型RAG实战:RAG原理、应用与系统构建

为了回馈粉丝们的厚爱,今天小智给大家送上一套大模型RAG实战指南——《大模型RAG实战:RAG原理、应用与系统构建》。这是一本已经被市场公认的大模型RAG的标准性著作,极具实战性和技巧性,阅读本书,先人一步实现能力跃迁,提升你的开发技能,与我们一起在智能开发的道路上不断前行。

踏雨歌青春,诗酒趁年华 5890

Gemini Enterprise免费试用攻略:解锁企业级AI平台的隐藏技巧与避坑指南

本文详细介绍了Gemini Enterprise免费试用的全流程攻略,包括注册优化、团队协作、资源管理和典型应用场景。通过解锁企业级AI平台的核心功能如Gemini 3.0 Pro模型和Nano Banana图像生成系统,帮助企业高效评估AI与业务的契合度。文章还提供了安全合规与数据管理的实用建议,确保试用过程顺畅无忧。

weixin_29233857的博客 657

24年9月大模型新书:大模型RAG实战-RAG原理、应用与系统构建

来啦,很久没给大家更新大模型的新书了,这次拿到了这本24年9月的新书,给大家详细介绍一波,就是这本 《大模型RAG实战-RAG原理、应用与系统构建》

2301_81940605的博客 2103

二十一.基于国民MCU 的增加M4F DSP库调用的验证

Cortex-M4F内核不仅内置硬件FPU单元,还支持多种DSP指令集,比如支持单周期乘加指令(MAC)等。因此Cortex-M4执行所有的DSP指令集都可以在单周期内完成,而Cortex-M3和M0需要多个指令和多个周期才能完成同样的功能。比如开方运算,M3和M0只能通过迭代法(标准数学函数库)计算,而M4F直接调用VSQRT指令完成。参考:\Nationstech.N32G45x_Library.1.1.1\Nationstech.N32G45x_Library.1.1.1\projects\n32g4

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 934

Spatial-ORMLLM: Improve Spatial Relation Understanding in the Operating Room with Multimodal Larg...

手术室(OR)中的精准空间建模是众多临床任务的基础,可为术中感知、风险规避及手术决策提供支持。现有方法虽利用大规模多模态数据集进行 latent 空间对齐,以隐式学习空间关系,但却忽视了多模态大型语言模型(MLLM)的3D能力。然而,这种方法存在两个问题:1)手术室通常缺乏多台视频和音频传感器,多模态3D数据难以获取;2)仅依赖易获取的2D数据训练,无法捕捉复杂场景中的细粒度细节。为解决这一问题,我们提出——首个针对手术室3D空间推理的大型视觉语言模型。

UnknownBody_2的博客 592

学大模型RAG看这本书就够了!!—《大模型RAG实战-RAG原理、应用与系统构建》

第一章:介绍了RAG的发展第二章:介绍了Transformer相关的基本原理,包括embedding、编码器、解码器等第三章:介绍了RAG环节里比较核心的文本向量化模型。首先介绍了和文本向量化模型比较相关的基础概念。然后介绍了一些稠密向量检索模型和稀疏检索模型。第四章:这一张比较琐碎,内容也比较多:(1)在RAG场景下的提示词技巧。(2)文本切块方法,包含基于规则的以及基于模型的。(3)向量数据库的基本原理以及一些开源向量数据库。

qingkahui24689的博客 1437

【UML】第12篇 序列图(1/2)——基本概念和构成

序列图(Sequence Diagram)是一种用于显示对象之间交互的图形化表示。它描述了在特定场景下,对象之间按照时间顺序进行的消息传递和协作过程。在序列图中,对象被表示为带有垂直虚线的矩形,虚线表示对象的生命周期。对象之间的交互通过箭头表示的消息来表示,箭头从一个对象的生命线指向另一个对象的生命线,表示消息的发送和接收。

AI人人懂 3048

推荐这篇完整的RAG(Retrieval-Augmented Generation)技术学习指南

在 LLM、RAG 和向量数据库等方向都有很高的造诣。这篇指南将带你深入理解RAG技术,从基础概念到高级应用,再到系统评估,全方位解析了RAG在构建应用程序中的关键作用。什么是RAG:RAG是构建LLM(大语言模型)所支持应用程序的一个子集,主要通过使用外部知识源来增强生成的内容。RAG背后的动机:LLM有时会生成不准确的内容,这种现象被称为“幻觉”。RAG的主要目的是通过提供外部知识来减少这种幻觉现象,使模型的生成更为准确。

优快云_224022的博客 1450

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

大模型好书推荐 | 大模型RAG实战:RAG原理、应用与系统构建(附PDF)

《大模型RAG实战:RAG原理、应用与系统构建》是一本由NLP和AI领域的资深技术专家联合撰写的实战指南。随着大模型技术的爆发,尤其是ChatGPT等产品的兴起,知识库问答产品迅速走红,引发了RAG(检索增强生成)系统的广泛关注与讨论。

AAI666666的博客 2124

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

大模型RAG实战 | RAG系统构建与微调实战

OpenAI于2022年11月30日发布的ChatGPT几乎颠覆了现有的NLP范式, 使NLP算法的日常工作和技术栈都发生了一定的改变。最受关注的两个 落地方向分别为RAG(Retrieval-Augmented Generation,检索增强生 成)和Agent。

老皮的博客 1064

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

RAG技术全景解读:从原理到实践的学习指南

是一套融合检索技术与生成式大模型的创新技术架构。它的运作原理是为诸如GPT-4、Claude等大语言模型配备一个“知识补给库”,在模型生成内容前,先从外部知识库中调取相关信息,以此来有效规避大模型常见的。

ytt0523_com的博客 1277

大模型从入门到精通:大模型RAG系统学习路线(附实战代码)

2023年大模型技术爆发,RAG(检索增强生成)成为解决大模型幻觉问题的关键技术。本文将系统讲解RAG技术原理,并提供从零开始的学习路线图,包含3个核心阶段、6大实战技巧,助你快速掌握这一前沿技术!

m0_63171455的博客 1850

LLM大模型应用入门:RAG技术详解与实战指南

LLM大模型应用入门:RAG技术详解与实战指南

2301_81888214的博客 1221

【推广】图书|2024新书《大模型RAG实战:RAG原理、应用与系统构建》汪鹏、谷清水、卞龙鹏等,机械工业出版社

大模型RAG实战:RAG原理、应用与系统构建》不仅是一本技术指南,更是带领你领略AI前沿应用的钥匙。如果你希望在RAG技术领域站稳脚跟,或是寻求在大模型应用中的新突破,这本书无疑将是你的最佳选择。通过本书,你将深入理解RAG的技术原理,掌握如何在大规模数据场景下优化RAG系统,助你成为下一代AI系统的引领者。

shandianchengzi的博客 2346

什么是RAG技术?18种RAG技术综述,看完让你不迷茫

在测试环境中,我对上述 18 种 RAG 技术进行了严格评估。各技术在检索准确率、响应速度与实现复杂度方面各有所长,但实验数据清晰显示,

weixin_59191169的博客 2353

【必学收藏】RAG技术详解与大模型学习路径,从入门到实战

RAG技术通过将文档分块并创建嵌入向量,实现查询与文档的高效匹配。文章介绍了五种分块策略:固定大小分块简单但可能打断语义;语义分块保持语言流畅性但依赖阈值;递归分块结合分隔符和大小限制;基于文档结构的分块利用文档固有结构;基于LLM的分块语义准确但计算成本高。不同策略适用于不同场景,选择需考虑内容性质、模型功能和计算资源等因素。

2401_84815887的博客 830

系统性大模型RAG书籍出版--大模型RAG实战:大模型RAG实战:RAG原理、应用与系统构建(附PDF)

系统性大模型RAG书籍出版--大模型RAG实战:大模型RAG实战:RAG原理、应用与系统构建(附PDF)

DEVELOPERAA的博客 1244

大模型必备技能:RAG技术详解与实战,含学习资料,建议收藏

文章详解RAG技术的5种文本分块策略和4种RAG方案,涵盖原理、优缺点及适用场景。这些技术从简单到复杂,实际应用需根据文档类型、场景及成本性能权衡选择。文章强调学习大模型技术的重要性,并提供相关学习资源。

Android_XG的博客 1333
上一篇: Java中的Thread、ThreadLocalMap、ThreadLocal三者之间的关系,ThreadLocalMap.Entry的弱引用设计
下一篇: RAG系统学习之——基于LangChain+Milvus+Ollama+Streamlit搭建本地RAG系统
Jack_abu
博客等级 码龄10年 633粉丝 78原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

Jack_abu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值