RAG01-项目概述

项目概述

1 项目简介

1.1 项目背景

近年来,ChatGPT 等大模型(LLM)快速普及,AI大模型 已成为企业数字化升级的重点方向。
但 AI大模型 在真实业务中有两个常见问题:

  1. 知识更新慢:模型主要依赖训练时的数据,无法自动掌握最新信息。

  2. 不了解企业私有数据:如公司制度、产品文档、内部 FAQ 等。

这会导致回答“看起来合理但实际不对”,即常说的幻觉问题。
为解决这些问题,企业常用两种方案:

  • 方案一:模型微调

    用企业数据继续训练模型,让模型更懂行业术语和业务场景。需要继续训练模型,成本高,难度高。

  • 方案二:RAG(Retrieval-Augmented Generation,检索增强生成)

    先从企业知识库检索相关内容,再交给大模型生成答案。

    该方案上线快、成本相对低、更新方便,是目前落地最广的方案之一。

本项目采用 LangChain + Qwen 构建学科在线答疑系统-简称EduRAG,核心目标是:

  • 提升回答准确率与时效性

  • 降低人工答疑压力

  • 形成可复用的企业级问答方案

通过本课程,你将掌握:

  1. 如何构建一个RAG系统:本地知识库构建 → 向量检索 → RAG 问答链路搭建 → 项目部署与验证

  2. 如何在其他行业及通用企业场景中实现一个类似的RAG系统

1.2 RAG原理

image

1.3 项目架构 ¶

在线答疑系统RAG主要步骤:

  • 第一步:将已有的FQA数据集存储到Mysql数据库中

  • 第二步:基于query检索Mysql数据库:将query和现有问题匹配(做相似度计算),如果阈值>=[0.85, 10.0],就认为问题比较明确,直接返回对应的答案;否则,进入RAG检索系统

  • 第三步:搭建本地知识库:加载本地文档 -> 文档分割 -> 文档向量化 -> 存储向量数据库(Milvus)

  • 第四步:基于query检索Milvus数据库:将query进行向量表示,并从Milvus数据库中检索出相似的top-k个文档片段。

  • 第五步:将query和检索出的top-k文档片段拼接,送入大模型,生成答案。

flowchart LR;
%% =========================
    %% 主数据流
    %% =========================
    Query([用户问题query]) --> FQA系统
    FQA系统 -->|不超过阈值| RAG系统
    RAG系统 --> FinalAnswer([最终答案])
    FQA系统 -->|超过阈值| FinalAnswer([最终答案])

FQA系统

flowchart LR;

    %% =========================
    %% 离线阶段
    %% =========================

    subgraph 数据准备-离线阶段

        A[1.结构化FQA数据]
        B[(2.MySQL数据库)]
        C[3.jieba分词]
        E[4.构建BM25检索器]

        A --> B
        B --> C
        C --> E

    end
    style 数据准备-离线阶段 fill:none,stroke:#000000

    %% =========================
    %% 在线阶段
    %% =========================

    subgraph 问题检索-在线阶段

        U[1.用户问题]
        V[2.jieba分词]
        W[3.BM25相似度检索]
        X{4.双重阈值判断}

        Y[5.1 Redis查询FQA答案]
        Z[6.返回FQA答案]

        N[5.2 调用RAG系统]

        U --> V
        V --> W
        W --> X

        X -- 是 --> Y
        Y --> Z

        X -- 否 --> N

    end
    style 问题检索-在线阶段 fill:none,stroke:#000000

    %% =========================
    %% 共享组件
    %% =========================

    R[(Redis缓存FQA)]

    %% 在线读缓存
    Y --> R

    %% Redis未命中查MySQL
    R -.未命中.-> B

    %% 离线BM25提供在线检索
    E -.BM25索引.-> W

RAG系统

flowchart LR;
%%{init:{"themeVariables":{"fontSize":"18px","nodeSpacing":15,"rankSpacing":15}}}%%

    %% =========================
    %% 在线阶段
    %% =========================
    subgraph 用户提问阶段-在线

        direction TB

        Start([用户查询]) --> Classify{查询分类<br/>bert意图识别模型}

        Classify -->|通用知识| DirectLLM["直接调用LLM<br/>生成回答"]

        Classify -->|专业咨询| Strategy{选择检索策略<br/>LLM}

        Strategy -->|明确查询| DirectRetrieval["直接检索"]

        Strategy -->|抽象问题| HyDERetrieval["假设问题检索<br/>生成假设答案"]

        Strategy -->|复杂查询| SubQuery["子查询检索"]

        Strategy -->|啰嗦问题| BacktrackRetrieval["回溯问题检索"]

        DirectRetrieval --> OptimizeQuery["LLM优化query"]
        HyDERetrieval --> OptimizeQuery
        SubQuery --> OptimizeQuery
        BacktrackRetrieval --> OptimizeQuery

        OptimizeQuery --> Search["检索向量库<br/>得到上下文context"]

        Search --> BuildPrompt["拼接Prompt<br/>优化query+context+history"]

        BuildPrompt --> Generate["LLM生成回答"]

        DirectLLM --> Output([返回回答])

        Generate --> HasAnswer["是否有答案<br/>无答案则引导人工支持"]

        HasAnswer --> Output

    end

    style 用户提问阶段-在线 fill:none,stroke:#000000

    %% =========================
    %% 离线阶段
    %% =========================
    subgraph 文档向量存储阶段-离线

        direction TB

            StartDoc([本地知识文档])

            StartDoc --> PDFLoader["PDF加载器"]
            StartDoc --> DOCLoader["DOC加载器"]
            StartDoc --> TXTLoader["TXT加载器"]
            StartDoc --> PPTLoader["PPT加载器"]

            PDFLoader --> Document["文档对象"]
            DOCLoader --> Document
            TXTLoader --> Document
            PPTLoader --> Document

            Document --> ParentChunk["父块分块"]

            ParentChunk --> SubChunk["子块分块"]

            SubChunk --> SubChunkList["子块集合"]

            SubChunkList --> Embed["文档向量化<br/>(bge-m3本地模型)"]

            Embed --> Milvus[(Milvus)]

            classDef milvusLarge font-size:32px,stroke-width:5px;
            class Milvus milvusLarge;

    end

    style 文档向量存储阶段-离线 fill:none,stroke:#000000

    %% =========================
    %% 在线检索连接离线向量库
    %% =========================
    Milvus --> Search

1.4 项目结构 ¶

integrated_qa_system/
├── base/
│   ├── config.py              # 配置管理,加载 config.ini
│   ├── logger.py              # 日志设置
├── rag_qa/
│   ├── core/
│   │   ├── document_processor.py # 文档处理模块
│   │   ├── prompts.py         # RAG 提示模板
│   │   ├── query_classifier.py # 查询分类器
│   │   ├── strategy_selector.py # 检索策略选择器
│   │   ├── vector_store.py    # 向量存储与检索
│   │   ├── rag_system.py      # RAG 系统核心逻辑
│   ├── edu_document_loaders/  # 文档加载模块
│   ├── edu_text_spliter/      # 文本分割模块
│   ├── models/                # 模型模块
│   ├── rag_assesment/         # RAGAS评估模块
│   ├── main.py                # RAG 系统独立入口,支持存储和查询
├── mysql_qa/
│   ├── db/
│   │   ├── mysql_client.py    # MySQL 数据库操作
│   ├── cache/
│   │   ├── redis_client.py    # Redis 缓存操作
│   ├── retrieval/
│   │   ├── bm25_search.py     # BM25 搜索
│   ├── utils/
│   │   ├── preprocess.py      # 文本预处理
│   ├── main.py                # MySQL 系统独立入口,支持查询
├── config.ini                 # 配置文件,包含所有模块的配置
├── main.py                    # 集成系统入口,结合 RAG 和 MySQL
├── app.py                     # FastAPI主服务入口
├── requirements.txt           # 依赖文件
└── logs/
    └── app.log                # 日志文件

2 项目环境(window)

2.1 前置说明 ¶

本教程介绍如何在 Windows 11 和 M1 芯片的 macOS 系统上使用 Docker 同时部署和运行单机版 Milvus(向量数据库)和 Redis(键值存储数据库)。教程分为两部分,分别针对不同操作系统提供详细步骤。

  • 操作系统

    • Windows 11
  • 硬件要求

    • 至少 8GB 内存(建议 16GB 或更高)。

    • 至少 20GB 可用磁盘空间(Milvus 和 Redis 数据存储)。

  • 网络要求

    • 稳定的互联网连接,用于拉取 Docker 镜像。
  • 软件版本

    • Milvus:2.4.4(最新稳定版)。

    • Redis:7.2(最新稳定版)。

  • 端口要求

    • Milvus:19530(gRPC)、9091(RESTful API)。

    • Redis:6379(默认端口)。

    • 确保以上端口未被占用。

2.2 python虚拟环境 ¶

1 创建虚拟环境 ¶

# 创建虚拟环境, 安装3.10及以上的python解析器 (比如3.10.18)
conda create -n edu_rag python=3.10.18
# 切换虚拟环境
conda activate edu_rag

2 找到依赖文件 ¶

requirements.txt文件

3 安装项目依赖包 ¶

# 安装依赖包, 在requirements.txt对应路径下执行以下命令
pip install -r requirements.txt

image-20250814174558612

如果安装过程不顺利,可以按需逐个安装:

# conda create -n edu_rag python==3.10.18
# conda activate edu_rag
# Python版本:3.10.18
# 使用方法:先安装python 3.10.18或者创建一个conda的3.10.18的环境,并激活。然后运行以下命令
pip install ollama==0.4.4
pip install requests==2.32.3
pip install numexpr==2.11.0
pip install unstructured==0.11.0
pip install langchain-core==1.2.16
pip install langchain_community==0.4.1
pip install langchain-ollama==1.0.1
pip install langchain_unstructured==1.0.1
pip install langchain_experimental==0.4.1
pip install langchain_chroma==1.1.0
pip install langchain-text-splitters==1.1.1
pip install langgraph==1.0.8
pip install nltk==3.9.1
pip install chromadb==1.3.5
pip install wikipedia==1.4.0
pip install faiss-cpu
pip install pymilvus==2.5.4
pip install pandas==2.3.1
pip install jieba
pip install rank_bm25==0.2.2
pip install redis==5.3.1
pip install pymysql==1.1.1
pip install opencv-python==4.10.0.84
pip install PyMuPDF==1.23.16
pip install python-docx==1.1.2
pip install pillow==10.4.0
pip install rapidocr-onnxruntime==1.3.8
pip install python-pptx==0.6.23
pip install transformers==4.45.0
pip install modelscope==1.23.0
pip install addict==2.4.0
pip install datasets==3.3.1
pip install simplejson==3.19.2
pip install sortedcontainers==2.4.0
pip install markdown==3.6
pip install sentence-transformers==3.0.1
pip install milvus-model==0.2.5
pip install tiktoken==0.7.0
pip install sentencepiece==0.2.0
pip install ragas==0.2.6
pip install starlette==0.46.2
pip install fastapi==0.115.12
pip install FlagEmbedding==1.3.5
pip install peft==0.18.1

2.3 安装DockerDesktop ¶

1 安装WSL ¶

参考 https://learn.microsoft.com/zh-cn/windows/wsl/install

  • 启用WSL 打开具有管理员权限的PowerShell,运行以下命令以安装WSL
wsl --install

1753623042372

1753623117795

输入命令后效果如下

image-20250814174828917

安装完后自动跳转页面,关闭即可

image-20250814174921643

安装完成后,重启电脑

2 安装docker ¶

下载并安装Docker Desktop

  • 访问 Docker官方网站,下载适用于Windows/Mac的Docker Desktop安装包。(可以直接下载共享文件中的安装包)

image-20250822095538468

安装Docker Desktop

  • 双击下载的安装文件(老师发的资料中有),按照提示一路下一步完成安装

  • 安装完成后,点击 close and restart 重启电脑以完成配置

image-20250814175817544

验证Docker安装

  • 打开PowerShell或命令提示符,运行以下命令,验证是否成功安装
docker --version
docker compose version

image.png

2.4 配置DockerCompose文件 ¶

1 创建项目目录 ¶

  • 在本地磁盘(例如:C盘)创建文件夹milvus_redis,用于存放Milvus和Redis的配置文件和数据:

1753623917487

2 创建docker-compose文件 ¶

先创建docker-compose.txt格式文件, 然后修改为docker-compose.yml格式

1753623986186

3 添加内容 ¶

把以下内容复制粘贴到你创建的docker-compose.yml文件:


# version: '3.5'
# Windows/x86_64 Version
# Redis Password set to: 1234
services:
    etcd:
        container_name: milvus-etcd
        image: quay.io/coreos/etcd:v3.5.5
        environment:
            - ETCD_AUTO_COMPACTION_MODE=revision
            - ETCD_AUTO_COMPACTION_RETENTION=1000
            - ETCD_QUOTA_BACKEND_BYTES=4294967296
            - ETCD_ENABLE_V2=true
        volumes:
            - ./volumes/etcd:/etcd/data
        command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd/data
    minio:
        container_name: milvus-minio
        image: minio/minio:RELEASE.2023-03-20T20-16-18Z
        environment:
            MINIO_ACCESS_KEY: minioadmin
            MINIO_SECRET_KEY: minioadmin
        volumes:
            - ./volumes/minio:/minio/data
        command: minio server /minio/data
        healthcheck:
            test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
            interval: 30s
            timeout: 20s
            retries: 3
    standalone:
        container_name: milvus-standalone
        # 使用多架构镜像,Docker on Windows 会自动拉取 x86_64 版本
        image: milvusdb/milvus:v2.4.4
        command: ["milvus", "run", "standalone"]
        environment:
            - ETCD_ENDPOINTS=etcd:2379
            - MINIO_ADDRESS=minio:9000
        volumes:
            - ./volumes/milvus:/var/lib/milvus
        ports:
            - "19530:19530"
            - "9091:9091"
        depends_on:
            - "etcd"
            - "minio"
    redis:
        container_name: milvus-redis
        image: redis:latest
        restart: always
        ports:
            - "6379:6379"
        volumes:
            - ./volumes/redis:/data
        # 设置 Redis 密码为 1234
        command: redis-server --requirepass 1234
    # ==================== MySQL ====================
    mysql:
        container_name: mysql
        image: mysql:8.0
        restart: always
        environment:
            MYSQL_ROOT_PASSWORD: "123456"
            MYSQL_DATABASE: subjects_kg
            MYSQL_CHARSET: utf8mb4
            MYSQL_COLLATION: utf8mb4_unicode_ci
            TZ: Asia/Shanghai
        ports:
            - "3307:3306"
        volumes:
            - ./volumes/mysql/data:/var/lib/mysql
            - ./volumes/mysql/conf:/etc/mysql/conf.d
            - ./volumes/mysql/init:/docker-entrypoint-initdb.d
        command:
            - --default-authentication-plugin=mysql_native_password
            - --character-set-server=utf8mb4
            - --collation-server=utf8mb4_unicode_ci
            - --lower-case-table-names=1
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p123456"]
            interval: 10s
            timeout: 5s
            retries: 5
            start_period: 30s

networks:
    default:
        name: milvus-network

说明

  • Milvus 服务

    • image : 使用 Milvus 官方镜像 milvusdb/milvus:v2.4.10 。

    • ports : 映射 gRPC(19530)和 RESTful API(9091)端口。

    • volumes : 数据持久化存储到本地 ./volumes/milvus 目录。

    • environment : 配置日志级别和 Etcd 参数。

    • command : 启动 Milvus 单机模式。

  • Redis 服务

    • image : 使用 Redis 官方镜像 redis:7.2 。

    • ports : 映射默认端口 6379 。

    • volumes : 数据持久化存储到本地 ./volumes/redis 目录。

    • command : 启用 AOF(Append Only File)持久化模式。

    • volumes : 定义持久化存储卷。

  • mysql 服务

    • image : 使用 MySQL 官方镜像 mysql:8.0

    • ports : 映射端口 3307:3306,宿主机通过 3307 访问容器内 MySQL。

    • environment : 配置 MYSQL_ROOT_PASSWORDMYSQL_DATABASE、字符集与时区(Asia/Shanghai)。

    • volumes : 挂载数据目录 ./volumes/mysql/data、配置目录 ./volumes/mysql/conf、初始化脚本目录 ./volumes/mysql/init,确保数据与初始化SQL持久化。

    • command : 指定 mysql_native_password 认证方式,并设置 utf8mb4 字符集、排序规则及表名大小写策略。

    • healthcheck : 通过 mysqladmin ping 做健康检查,确保服务启动后可用。

2.5 启动Milvus和Redis ¶

1 拉取镜像并启动容器 ¶

  • 进入上述创建的milvus_redis目录下,打开具有管理员权限的PowerShell终端,运行:
# -d 表示后台运行容器
docker compose up -d

image.png

  • 注意: 拉取镜像时报错: Get “https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

以下为解决方法, 添加镜像源:

"registry-mirrors": [
  "https://docker.211678.top",
  "https://docker.1panel.live",
  "https://hub.rat.dev",
  "https://docker.m.daocloud.io",
  "https://do.nark.eu.org",
  "https://dockerpull.com",
  "https://dockerproxy.cn",
  "https://docker.awsl9527.cn"
]

1753625438227

image.png

重启docker生效
然后再次去milvus_redis 目录下,打开 PowerShell,运行:

# -d 表示后台运行容器
docker compose up -d

2 docker查看是否成功 ¶

启动成功后去docker看看是否正常启动

image.png

2.6 验证Milvus和Redis ¶

1 测试Milvus连接 ¶

from pymilvus import connections, utility

# 连接到 Milvus
connections.connect(host="localhost", port="19530")

# 检查版本
print(f"Milvus version: {utility.get_server_version()}")
e:\conda_envs\edu_rag\lib\site-packages\pymilvus\client\__init__.py:6: UserWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html. The pkg_resources package is slated for removal as early as 2025-11-30. Refrain from using this package or pin to Setuptools<81.
  from pkg_resources import DistributionNotFound, get_distribution
Milvus version: v2.4.4
  • 在edu_rag虚拟环境下运行脚本 # cmd终端执行命令 # 输出类似Milvus version: 2.4.10 表示Milvus部署成功 python test_milvus.py

2 测试Redis连接 ¶

import redis

# 连接到 Redis
client = redis.Redis(host="localhost", port=6379, password=1234, decode_responses=True)

# 测试读写
client.set("test_key", "Hello, Redis!")
value = client.get("test_key")
print(f"Redis value: {value}")
Redis value: Hello, Redis!
  • 在edu_rag虚拟环境下运行脚本 # cmd终端执行命令 # 输出类似Redis value: Hello, Redis! 表示Redis部署成功

3 测试mysql连接 ¶

import pymysql

try:
    conn = pymysql.connect(
        host="localhost",
        port=3307,          # 对应 docker-compose: 3307:3306
        user="root",
        password="123456",
        database="subjects_kg",
        charset="utf8mb4"
    )
    with conn.cursor() as cursor:
        cursor.execute("SELECT VERSION();")
        version = cursor.fetchone()[0]
        print(f"MySQL 连接成功,版本: {version}")
except Exception as e:
    print(f"MySQL 连接失败: {e}")
finally:
    try:
        conn.close()
    except:
        pass
MySQL 连接成功,版本: 8.0.46

2.7 安装Milvus可视化工具Attu ¶

1 安装 ¶

拉取可视化组件attu

docker pull zilliz/attu

运行可视化组件

# 启动容器,宿主机 30000 映射到容器 3000,并加入到 milvus-network 网络中,使得能通过容器名访问milvus
# docker run: 启动容器
# -d: 后台运行
# -p: 端口映射 宿主机端口:容器端口
# --network: 加入到 指定网络,需要和docker-compose.yml中的 milvus网络名称 一致
# --name: 容器名
docker run -d -p 30000:3000 --network milvus-network --name attu zilliz/attu

打开 http://127.0.0.1:30000

2 连接 ¶

在 Attu 页面的 Milvus Address 输入框中填写:

milvus-standalone:19530

image.png

image-2.png

本文为 程序员青阳 原创文章,遵循 CC BY-NC-SA 4.0 版权协议,转载请附上原文链接及本声明。

原文链接:https://heliufang.github.io/posts/2a487b58/index.html