RAG Python App

项目代码参考了Tech with Tim ProductionRAGPythonApp,并对其源代码进行了一定修改,如更换 OpenAI 的嵌入模型和大语言模型等,并开源在 github 上: ProductionRAGPythonApp,但对我来说更重要的是能够通过代码学习整个 RAG 的思想及 API 调用的方法等,欢迎 PR!

项目的环境配置和运行方法请参考项目的 README 文件,这里我主要对 RAG 学习过程中遇到的问题、库进行梳理工作,让我们开始吧!

首先,我们使用 uv 创建一个项目

1
pip install uv

对项目进行初始化:

1
2
(base) richard@RicharddeMacBook-Air RAGProductionApp % uv init .
Initialized project `ragproductionapp` at `/Users/richard/CUMT-ChatBot/RAGProductionApp`

给项目添加相关依赖:

1
(base) richard@RicharddeMacBook-Air RAGProductionApp % uv add fastapi llama-index-core llama-index-readers-file python-dotenv qdrant-client unicorn streamlit openai

什么是 uv?
uv 是一个高性能的 Python 项目管理工具,主要用于依赖管理、虚拟环境管理以及项目构建。

  • 项目初始化后自动生成相关文件,结构如下
1
2
3
4
5
6
7
(base) richard@RicharddeMacBook-Air uv-learning % tree
.
├── main.py
├── .gitignore
├── pyproject.toml
├── python-version
└── README.md

我们逐个拆解一下每个文件的作用:

  • pyproject.toml
    • 声明项目核心信息,包括名称、版本、描述等
    • 规定项目依赖的 Python 版本和第三方包,用于包管理工具(如 uv、pip)识别依赖
    • 关联项目说明文档(README.md),方便用户和工具查看项目详情
1
2
3
4
5
6
7
[project]
name = "python-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []

当使用 uv add <denpendencies> 命令添加依赖时,uv 会自动更新 pyproject.tomldependencies 列表;复现环境时,执行 uv pip install . 即可根据 pyproject.toml 安装所有依赖,就像是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[project]
name = "ragproductionapp"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"fastapi>=0.116.1",
"inngest>=0.5.6",
"llama-index-core>=0.14.0",
"llama-index-readers-file>=0.5.4",
"openai>=1.107.0",
"python-dotenv>=1.1.1",
"qdrant-client>=1.15.1",
"streamlit>=1.49.1",
"uvicorn>=0.35.0",
]

uv 也提供创建虚拟环境的方式:

1
2
3
4
uv venv       # 创建 .venv 虚拟环境
source .venv/bin/activate # 激活 Linux/Mac
.venv\Scripts\activate # 激活 Windows
uv pip install . # 在虚拟环境中安装依赖
1
2
3
4
5
(hexo-rag) richard@RicharddeMacBook-Air RAGProductionApp % uv run uvicorn main:app
INFO: Started server process [20305]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(hexo-rag) richard@RicharddeMacBook-Air RAGProductionApp % npx inngest-cli@latest dev -u  http://127.0.0.1:8000/api/inngest --no-discovery 
Need to install the following packages:
inngest-cli@1.13.4
Ok to proceed? (y) y

[09:03:30.568] INF starting executor grpc server svc=executor addr=:50053
[09:03:30.569] INF service starting caller=executor service=executor
[09:03:30.569] INF service starting caller=devserver service=devserver
[09:03:30.569] INF starting event stream backend=redis
[09:03:30.569] INF service starting caller=runner service=runner
[09:03:30.569] INF subscribing to function queue
[09:03:30.569] INF service starting caller=api service=api
[09:03:30.569] INF starting server caller=api addr=0.0.0.0:8288
[09:03:30.569] INF service starting caller=connect-gateway service=connect-gateway
[09:03:30.570] INF starting connect gateway grpc server caller=connect-gateway addr=:50052
[09:03:30.571] INF subscribing to events topic=events


Inngest Dev Server online at 0.0.0.0:8288, visible at the following URLs:

- http://127.0.0.1:8288 (http://localhost:8288)
- http://10.6.227.126:8288

在浏览器中输入http://localhost:8288/runs进入控制台界面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(hexo-rag) richard@RicharddeMacBook-Air RAGProductionApp % docker run -d --name qdrantRagDb -p 6333:6333 -v "./qdrant_storage:/qdrant/storage" qdrant/qdrant
Unable to find image 'qdrant/qdrant:latest' locally
latest: Pulling from qdrant/qdrant
4f4fb700ef54: Pull complete
e363695fcb93: Pull complete
8867fa9eb8c4: Pull complete
93617c057df8: Pull complete
3638f8fe1dda: Pull complete
f907b10db73d: Pull complete
efc2301f4369: Pull complete
c3a47fd98373: Pull complete
Digest: sha256:0fb8897412abc81d1c0430a899b9a81eb8328aa634e7242d1bc804c1fe8fe863
Status: Downloaded newer image for qdrant/qdrant:latest
d0b630ffc2e6845ab104c2545da801a1b44af02d8d810f162ff57d2fecc50ee2

如果是windows用户路径需要修改使用"$(pwd)/qdrant_storage:/qdrant/storage"

注意要先启动docker desktop

1
uv run streamlit run .\streamlit_app.py

RAG

在学习代码之前,我们先了解一下 RAG 的基本原理,全称是 Retrieval-Augmented Generation,即“检索增强生成”,是构建个人知识库的关键技术。当前风靡全球的大模型如chatgpt、Gemini、Deepseek多为通用型,无法对高度个性化的问题给出精确解答。例如,若我想知道“学校南门每晚几点关门”或“矿大宿舍的报修电话是多少”,通用模型显然无法提供准确信息。

这正是RAG的价值所在:通过事先为模型提供特定的知识库,使模型能够基于这些定制化信息进行回答,从而实现大模型的个性化应用。

  1. 身份的转变:从“使用者”变为“创造者”,根据需求定制自己的AI应用
  2. 解决“幻觉”问题:通过提供精准的上下文并要求引用来源,能构建出值得信赖的AI应用,这对于企业级场景是刚需。
  3. 应对复杂场景:当您的知识库包含成千上万个文档时,简单的文件上传功能会显得力不从心,而RAG架构是为处理这种海量、复杂的检索任务而生的。
  4. 技术集成的核心:RAG不仅仅是一个独立技术,它更是将向量数据库、嵌入模型、大语言模型等现代AI核心组件串联起来的“胶水”。通过学习RAG,可以系统地学习了当前AI应用开发的核心技术栈。

(i) 索引

在用户提问之前我们需要将文档做成一个方便快速查找的索引:

  1. 加载数据:收集所有可能用到的文档,格式可以是 PDF、Word、TXT、网页 HTML、数据库记录等。
  2. 分割文本:由于长文本会包含很多无关信息,不利于精准检索,因此需要将长文档切分成更小的、语义完整的文本块(Chunks)。
  3. 向量化:使用一个“嵌入模型”将每个文本块转换成一串数字,即向量。这个向量可以理解为文本在数学空间中的“坐标”,语义相近的文本,其向量在空间中的距离也更近。
  4. 存储向量:将这些向量及其对应的原始文本存储到一个专门的数据库中,这个数据库被称为向量数据库。这个过程就像是给所有复习资料做了一个详细的目录索引。

(ii) 检索

当用户提出一个问题(即查询)时,RAG 系统开始在存储的数据库中查找:

  1. 查询向量化:使用与第一阶段相同的嵌入模型,将用户的问题也转换成一个查询向量。
  2. 相似性搜索:在向量数据库中,寻找与“查询向量”最相似的几个文本块向量。相似性通常通过计算向量间的距离(如余弦相似度)来衡量,距离越近,代表语义越相关。
  3. 获取参考文本:系统检索出最相关的 K 个文本块(例如,Top-3 或 Top-5),作为回答问题的参考依据。

(iii) 生成

现在通过前面的检索过程,我们已经获取到了与用户问题最相关的文本块,接下来我们需要将这些文本块与用户的问题一起输入到大模型中,让模型根据这些信息生成一个准确的回答。

  1. 组合提示:系统会构建一个精心设计的提示
  2. 增强生成:将组合好的提示发送给大语言模型。LLM 会基于这个“被增强了的”上下文信息来生成回答。
  3. 输出最终答案:LLM 产生的最终答案会返回给用户。这个答案不仅利用了模型自身的通用知识,更关键的是融入了从私有数据中检索到的最新、最相关的信息。

主函数

文本嵌入生成data_loader.py

向量存储vector_db.py

前端交互streamlit_app.py


RAG Python App
http://example.com/2025/11/16/Python/RAG-Python-App/
Author
Li Qinxuan
Posted on
November 16, 2025
Updated on
December 5, 2025
Licensed under