看懂这个项目 backend AI 代码的逐文件讲解
1. 这篇文档解决什么问题
如果你现在打开这个项目的 backend/,很可能会有这种感觉:
- 文件很多
- 名词很多
- 不知道先看哪个
- 即使看了某个文件,也不知道它在整体里扮演什么角色
这篇文档的目标不是逐行翻译源码,而是帮你建立一张“源码地图”:
每个关键文件是干什么的,它和谁配合,它在整条 AI 链路里处于哪一层。
你只要先把这张地图建立起来,再回去看代码,就会顺很多。
2. 先建立整体脑图:backend 在做什么
这个项目的 backend/ 本质上是一个:
基于 FastAPI + LangChain 的 AI 服务端
它主要负责 4 件事:
- 对外暴露 API
- 管理对话会话
- 执行 RAG 文档问答
- 执行 Agent 多工具问答
你可以先把后端理解成下面这条总链路:
前端请求
-> FastAPI 路由
-> 业务服务层
-> RAG / Agent
-> 模型 / 向量库 / 工具
-> 返回结果
所以你看 backend 的时候,不要把它当成一堆散文件,而要把它当成一条流。
3. backend 的推荐阅读顺序
先把结论放前面。
如果你是第一次读这个项目,最推荐按这个顺序:
backend/main.pybackend/app/router/chat.pybackend/app/router/chat_service.pybackend/app/rag/rag_service.pybackend/app/rag/vector_store.pybackend/app/rag/reorder_service.pybackend/app/agent/agent_tools.pybackend/app/agent/agent.pybackend/app/services/database_session_manager.pybackend/app/models/chat_history.pybackend/app/utils/factory.pybackend/app/utils/config.pybackend/app/utils/prompt_loader.pybackend/app/schemas/models.py
这个顺序的逻辑是:
- 先看入口
- 再看接口
- 再看业务总调度
- 再看 AI 核心实现
- 最后看配置、模型、数据结构
4. 第一站:backend/main.py
这是后端应用入口。
你可以把它理解成:
整个 FastAPI 服务的总开关
4.1 这个文件做了什么
主要职责有:
- 创建
FastAPI()实例 - 注册全局限流中间件
- 注册请求耗时中间件
- 注册 CORS
- 加载路由
- 注册异常处理
- 在启动时初始化数据库、Redis、会话管理器、重排序模型
4.2 为什么先看它
因为它能回答你两个最关键的问题:
- 这个服务启动后有哪些能力
- 启动时依赖了哪些基础设施
4.3 从它能看出什么
你会发现这个后端不是一个纯内存 demo,而是有真实工程能力的:
- MySQL
- Redis
- 会话持久化
- 限流
- 模型初始化
所以它已经是“可落地系统”,不是只演示 AI 调用。
5. 第二站:backend/app/router/chat.py
这是最值得优先看的路由文件。
它是整个 AI 能力的对外接口层。
5.1 这个文件提供了哪些能力
从接口上看,它主要暴露了:
- Agent 流式问答
- RAG 问答
- 获取会话历史
- 删除会话
- 获取会话列表
- 上传单个文件进向量库
- 上传多个文件进向量库
- 清空用户向量数据
- 文档重排序
5.2 为什么它重要
因为它相当于一张功能目录表。
你看到这些接口后,就知道这个后端到底支持哪些 AI 功能,而不是只在源码里猜。
5.3 怎么看这个文件
读这个文件时,不要一开始纠结每个细节。
你重点看:
- 每个接口的 URL
- 每个接口依赖哪些参数
- 每个接口最终调用谁
例如:
- RAG 问答会调用
router_service.handle_rag_query - 上传文件会调用
handle_add_vector_single - Agent 流式输出会调用
get_agent_stream_response
这就把你带到了下一层。
6. 第三站:backend/app/router/chat_service.py
这个文件名字虽然叫 chat_service.py,但它实际是:
路由层后面的业务编排层
也就是路由收到请求后,真正串起各个模块的地方。
6.1 这个文件为什么关键
因为它相当于后端 AI 业务的“总调度台”。
它把下面这些能力连接起来:
- Agent
- RAG
- 向量库
- 会话管理
- 重排序服务
6.2 这个文件里有哪些核心方法
重点方法包括:
handle_agent_queryhandle_rag_queryhandle_get_sessionhandle_delete_sessionhandle_get_user_sessionshandle_add_vector_singlehandle_add_vector_multipleclean_user_uploadhandle_reorder
6.3 它的阅读重点
你不用一开始深究所有异常处理。
先抓住一件事:
这个类的职责不是“做底层算法”,而是“把请求转给正确的底层模块”
例如:
- RAG 问答 ->
RagService - 上传文件 ->
VectorStoreService - 对话历史 ->
session_manager - 重排序 ->
reorder_service
所以它是业务编排层,而不是模型层。
7. 第四站:backend/app/rag/rag_service.py
这是项目里 RAG 的核心文件之一。
如果你要看“检索增强生成到底怎么落地”,这个文件一定要啃。
7.1 这个类在做什么
RagService 可以理解为:
专门负责“从知识库查资料并生成回答”的服务类
7.2 它内部做了哪些事
主要包括:
- 创建向量库服务
- 初始化检索器
- 加载 RAG 用的 Prompt
- 创建总结链
prompt -> model -> parser - 使用 HyDE 增强检索
- 调用重排序服务
- 对多个文档做分批摘要
- 合并摘要生成最终回答
7.3 为什么这个文件很值得学
因为它体现了一个比较完整、比较工程化的 RAG 思路,而不只是“检索一下然后直接回答”。
7.4 这个文件里的几个重点函数
initialize_retriever
作用:
- 延迟初始化检索器
为什么要这样做?
因为不是每次对象创建都一定要马上查库、建 retriever,延迟初始化能减少不必要开销。
generate_hypothetical_document
作用:
- 用 HyDE 生成假设性文档
这是比较高级一点的 RAG 技术。
它的思路是:
先让模型生成一段“可能的答案”,再拿这段文本去检索,比直接拿原问题检索更丰富。
retrieve_document
作用:
- 真正从知识库中召回文档
它内部会先做 HyDE,再调用 retriever。
reorder_documents
作用:
- 对候选文档做 rerank
这一步是为了提高最终上下文质量。
get_documents_and_summary
这是最核心的方法。
它大致做了这几步:
- 检索文档
- 提取文档内容
- 重排序
- 对前几个文档分别总结
- 再把多个摘要合成最终回答
这也是你最值得重点看的一段逻辑。
rag_summary
这是对外暴露的简化入口。
它把复杂过程包起来,外部只需要传 query 就行。
8. 第五站:backend/app/rag/vector_store.py
这是项目里另一个非常关键的文件。
如果 rag_service.py 是“RAG 的大脑调度”,那 vector_store.py 就是:
RAG 的知识库底座
8.1 它的职责是什么
主要负责:
- 连接 Chroma 向量库
- 加载各类知识文件
- 文本切分
- 生成 embedding
- 建立向量索引
- 构造检索器
- 混合检索
- 去重处理
- 删除用户文档
8.2 为什么这个文件很重要
因为一个 RAG 系统效果好不好,很大程度取决于知识库构建是否合理。
而这些工作,大多都发生在这里。
8.3 这个文件里最值得看的点
Chroma 初始化
这里会创建:
Chroma
说明知识库底层使用 Chroma 作为向量数据库。
文档切分器
这里初始化了 AsyncTextSplitter。
说明这个项目不是直接把整个文件塞进库里,而是先分块。
BM25 检索器
项目不仅有向量检索,还从文档中构造了:
BM25Retriever
这说明作者考虑到了关键词召回能力。
混合检索器
通过:
EnsembleRetriever
把向量检索和 BM25 检索融合起来。
这属于比“纯向量检索”更进一步的实现。
动态权重
get_dynamic_weights 会根据 query 长短动态调权重。
这是一种很典型的工程优化。
MD5 去重
文件被导入向量库前,会先计算 MD5。
这样做的好处是:
- 避免重复入库
- 节省存储
- 减少重复向量化开销
文件加载
这个文件还能根据扩展名调用不同 loader:
- txt
- md
- pptx
- docx
说明系统是面向真实文件知识库设计的。
8.4 读这个文件时要抓住什么
你要抓住的不是每个异步细节,而是这条大线:
文件 -> 文档 -> 切分 -> embedding -> 向量库 -> retriever
只要这条线顺了,RAG 的基础就顺了。
9. 第六站:backend/app/rag/reorder_service.py
这个文件负责重排序。
9.1 为什么需要它
因为第一次检索拿回来的文档,不一定排得最准。
所以项目又加了一层:
用 reranker 模型对“问题 + 文档”重新评分排序
9.2 这个文件做了什么
主要包括:
- 检查本地重排序模型是否存在
- 如果没有则下载
- 懒加载
CrossEncoder - 对文档列表打分
- 返回按相似度排序后的结果
9.3 它的重要意义
它说明这个项目不是“简单能跑就行”,而是在认真优化召回结果质量。
对于 RAG 来说,这一步往往很关键。
10. 第七站:backend/app/agent/agent_tools.py
这是 Agent 的工具箱文件。
10.1 这个文件的作用
它把一些 Python 函数暴露成 Agent 可以调用的工具。
10.2 这里定义了哪些工具
主要有:
rag_summary_toolsreorder_documents_toolsget_user_info_toolsget_weather_toolswhat_time_is_now
10.3 为什么这个文件值得重点看
因为它让你一下就能知道:
这个 Agent 到底“会什么”
一个 Agent 的边界,本质上就是由工具决定的。
10.4 最重要的工具是哪一个
最值得你关注的是:
rag_summary_tools
因为它体现了一个关键设计:
RAG 被封装成了 Agent 的一个工具
这意味着:
- 用户问知识库问题时
- Agent 可以自己决定调用 RAG
这就是 Agent 和 RAG 的连接点。
11. 第八站:backend/app/agent/agent.py
这是项目中 Agent 的核心实现文件。
11.1 这个文件在整体里处于什么位置
如果说 rag_service.py 是知识库问答核心,那 agent.py 就是:
多工具智能体的核心
11.2 这个文件主要做了什么
主要分几部分:
- 定义
AgentFactory - 配置默认工具
- 加载默认系统提示词
- 创建聊天模型
- 创建 Agent Prompt
- 创建 Tool Calling Agent
- 创建 AgentExecutor
- 提供普通响应函数
- 提供流式响应函数
11.3 为什么这里用了工厂模式
因为 Agent 的创建依赖很多东西:
- 模型
- 工具
- 提示词
- 执行器参数
把这些封装进工厂类后:
- 逻辑更集中
- 更方便复用
- 更容易避免全局状态污染
11.4 _create_chat_model
这一步负责创建聊天模型。
也就是 Agent 背后的“决策大脑”。
11.5 _create_prompt
这里用了:
ChatPromptTemplateMessagesPlaceholder
说明这个 Agent 不是单轮死问答,而是支持:
- 系统提示词
- 聊天历史
- 用户输入
- 中间思考轨迹
11.6 create_agent_executor
这是 AgentFactory 的核心方法。
它把模型、prompt、tools 拼起来,最终生成:
AgentExecutor
你可以把执行器理解成:
真正驱动 Agent 跑起来的执行引擎
11.7 get_agent_response
这是非流式 Agent 响应函数。
它做的事情包括:
- 创建新的 AgentExecutor
- 把历史对话转成消息对象
- 调用
astream执行 - 收集最终回答
- 收集中间步骤
11.8 get_agent_stream_response
这是流式版本。
它会:
- 实时产出模型输出
- 通过 SSE 格式发给前端
- 最后把完整回答写入会话历史
11.9 你读这个文件时应该抓住什么
重点不是记所有 LangChain API 名字,而是抓住这条链:
用户输入 -> Agent 判断 -> 是否调工具 -> 工具返回 -> Agent 继续 -> 最终输出
12. 第九站:backend/app/services/database_session_manager.py
这个文件不是 AI 算法本身,但非常重要。
因为它负责:
把对话真正存下来
12.1 这个文件做了什么
主要负责:
- 获取会话
- 新建会话
- 写入用户消息和助手消息
- 获取历史记录
- 删除会话
- 获取用户会话列表
12.2 为什么 AI 项目也必须看它
因为 Agent 和 RAG 的多轮体验离不开会话管理。
如果没有这个文件:
- 每次对话都是无记忆的
- 无法查看历史
- 无法继续之前的话题
12.3 你要重点理解的点
这里把数据库中的消息重新组装成:
(user_message, assistant_message)的历史结构
然后给 Agent 使用。
这说明:
持久化存储层和 LangChain 的聊天历史层是连接在一起的
13. 第十站:backend/app/models/chat_history.py
这个文件定义了数据库模型。
13.1 有哪些表
主要有两张表:
ChatSessionChatMessage
13.2 各自负责什么
ChatSession
负责保存会话本身的信息,例如:
- 会话 ID
- 用户 ID
- 标题
- 创建时间
- 更新时间
ChatMessage
负责保存具体消息,例如:
- 属于哪个会话
- 角色是 user 还是 assistant
- 文本内容
- 创建时间
13.3 为什么它重要
因为它决定了“聊天历史在数据库中长什么样”。
如果你以后要加:
- 多角色
- 消息元数据
- 消息附件
- 更复杂会话状态
通常都要从这里入手。
14. 第十一站:backend/app/db/db_config.py
这个文件负责数据库连接。
14.1 它做了什么
主要包括:
- 读取 MySQL 连接配置
- 创建异步引擎
- 创建异步 Session 工厂
- 初始化数据库表
- 提供数据库依赖
- 检查数据库连接健康状态
14.2 为什么要知道它
因为你会经常遇到这种情况:
- 项目启动失败
- 表没创建出来
- MySQL 连不上
这时候这个文件就是排查入口之一。
15. 第十二站:backend/app/core/rate_limit.py
这是限流逻辑。
15.1 它的作用
避免接口被高频刷爆。
15.2 它分成两层
- 路由依赖级限流
- 全局中间件限流
15.3 为什么它跟 AI 服务特别相关
因为 AI 请求通常:
- 更贵
- 更耗时
- 更吃资源
所以限流比普通 CRUD 服务更有必要。
16. 第十三站:backend/app/router/user.py
这个文件是用户信息接口。
16.1 它在 AI 主链路里有什么意义
它本身不是 RAG 或 Agent 主体,但它说明:
这个 AI 后端不是孤立的,它要和用户体系打通
例如:
- 根据 token 获取用户 ID
- 再去 Redis 查用户信息
这和“会话归属于谁”“上传的知识库属于谁”都有关。
17. 第十四站:backend/app/router/health.py
这个文件是健康检查接口。
17.1 为什么要看它
因为它会告诉你,后端启动后依赖了哪些基础服务:
- MySQL
- Redis
如果这两个服务不通,系统就绪检查会失败。
对于部署和排障很重要。
18. 第十五站:backend/app/utils/factory.py
这是模型工厂文件。
18.1 它做了什么
主要负责统一创建:
- 聊天模型
- embedding 模型
18.2 为什么要用工厂
因为模型实例的创建最好集中管理。
这样做的好处:
- 配置统一
- 更容易替换模型
- 业务代码不必到处写初始化细节
18.3 这个文件在整体链路中的位置
它相当于:
给 RAG 和 Agent 提供“模型来源”
19. 第十六站:backend/app/utils/config.py
这是配置加载入口。
19.1 它加载了哪些配置
rag.yamlchroma.yamlprompt.yamlagent.yaml
19.2 为什么它重要
因为你以后调项目时,很多效果和行为都不是改 Python 代码,而是改这里对应的 YAML。
例如:
- 模型名字
- 向量库目录
- chunk 大小
- prompt 文件位置
这就是典型的“配置驱动”设计。
20. 第十七站:backend/app/utils/prompt_loader.py
这个文件专门负责读取 Prompt 文件。
20.1 为什么单独做这个文件
因为 Prompt 在 AI 项目里地位很高。
单独封装后:
- 更好维护
- 更方便换模板
- 更利于配置化
20.2 你看这个文件时要理解什么
它说明 Prompt 不是写死在业务代码中的,而是:
- 先在 YAML 中配置路径
- 再按类型加载文本模板
这是一种很常见的 AI 工程实践。
21. 第十八站:backend/app/schemas/models.py
这是请求响应模型定义文件。
21.1 它有什么作用
主要定义了:
- 查询请求体
- RAG 请求体
- 会话响应结构
- Agent 步骤结构
- 重排序请求和响应结构
21.2 为什么这个文件也值得看
因为它能帮助你快速知道:
每个接口收什么、回什么
特别是 AgentStep 很有代表性,它说明这个项目不仅返回最终答案,还可以保留 Agent 中间步骤。
22. AI 主链路一:用户问一个知识库问题时发生了什么
现在我们把前面的文件串起来。
例如用户提问:
公司请假制度是什么?
后端大致流程如下:
- 请求进入
chat.py - 路由调用
chat_service.py的handle_rag_query handle_rag_query创建RagServiceRagService调用retrieve_documentretrieve_document通过VectorStoreService获取 retriever- retriever 从 Chroma / BM25 混合检索相关文档
reorder_service.py对候选文档重排序rag_service.py使用 Prompt + 模型生成最终总结- 路由把结果返回给前端
你只要把这 9 步记住,RAG 主链路就基本通了。
23. AI 主链路二:用户走 Agent 问答时发生了什么
例如用户问:
先帮我查知识库里的报销制度,再告诉我现在几点。
后端大致流程如下:
- 请求进入
chat.py的 Agent 流式接口 - 路由调用
get_agent_stream_response agent.py从数据库拿到历史会话- 创建新的 AgentExecutor
- Agent 根据用户问题判断需要调用哪些工具
- 如果需要查知识库,就调用
rag_summary_tools - 如果需要查时间,就调用
what_time_is_now - Agent 整合各工具结果形成最终回复
- 响应流式返回给前端
- 最终回答写入数据库会话
这就是 Agent 主链路。
24. 你可以怎么理解这些目录之间的关系
你可以把整个 backend 想成一个公司组织结构:
24.1 router/
前台接待。
负责:
- 接请求
- 看参数
- 分发给业务层
24.2 services/
业务调度中心。
负责:
- 把不同模块串起来
24.3 rag/
知识库问答部门。
负责:
- 检索
- 向量库
- 重排序
- 摘要回答
24.4 agent/
智能助手部门。
负责:
- 工具调用
- 多步任务
- 智能决策
24.5 models/ + db/
数据存储部门。
负责:
- 会话和消息落库
24.6 utils/
基础工具部门。
负责:
- 配置
- Prompt 加载
- 模型工厂
- 路径处理
这样理解后,目录就不会显得乱。
25. 初学者看源码时最容易卡住的点
25.1 一上来想逐行看懂
这很容易把自己看崩。
更好的方式是:
- 先知道这个文件是干什么的
- 再知道它调用了谁
- 最后才看具体实现细节
25.2 被 LangChain 类名吓住
比如:
ChatPromptTemplateMessagesPlaceholderAgentExecutorEnsembleRetriever
你先不要背 API。
先把它们翻译成人话:
- Prompt 模板
- 消息占位符
- Agent 执行器
- 混合检索器
这样理解会轻松很多。
25.3 把 RAG 和 Agent 混在一起
一定要分开理解:
- RAG 负责查知识库再回答
- Agent 负责决定是否调用工具
但在这个项目里,它们又被组合起来了:
- RAG 被封成了 Agent 的一个工具
这是理解这个项目 AI 结构的关键点。
26. 你接下来最适合怎么继续看代码
给你一个非常实用的方式。
第一轮:只看函数名和调用关系
目标:
- 搞清楚“谁调谁”
第二轮:只看 4 个核心文件
重点看:
chat_service.pyrag_service.pyvector_store.pyagent.py
目标:
- 搞懂 AI 主链路
第三轮:再看配置和存储
重点看:
factory.pyconfig.pyprompt_loader.pydatabase_session_manager.py
目标:
- 搞懂系统是如何真正跑起来的
第四轮:最后再看优化细节
重点看:
- HyDE
- rerank
- 动态权重
- 流式输出
目标:
- 搞懂“为什么这个项目比最基础 demo 更工程化”
27. 一张总图帮你看 backend AI 代码
flowchart TD
A["main.py 应用入口"] --> B["router/chat.py 接口层"]
B --> C["router/chat_service.py 业务编排"]
C --> D["rag/rag_service.py RAG 主流程"]
D --> E["rag/vector_store.py 知识库与检索"]
D --> F["rag/reorder_service.py 重排序"]
C --> G["agent/agent.py Agent 主流程"]
G --> H["agent/agent_tools.py 工具集合"]
H --> D
C --> I["services/database_session_manager.py 会话管理"]
I --> J["models/chat_history.py 数据模型"]
J --> K["db/db_config.py MySQL 连接"]
D --> L["utils/factory.py 模型工厂"]
G --> L
D --> M["utils/prompt_loader.py Prompt 加载"]
G --> M
L --> N["utils/config.py 配置入口"]
28. 最后做个一句话总结
如果你要用一句话概括这个项目的 backend AI 部分,可以这样说:
这个 backend 以 FastAPI 作为接口层,以
chat_service.py作为业务编排中心,下面分成 RAG 知识库问答链路和 Agent 多工具调用链路,同时通过数据库会话管理、配置化 Prompt、模型工厂、Redis 限流等基础设施,把 AI 能力做成了一个可运行的工程化服务。
如果你愿意,我下一步还能继续给你补:
- 《把 backend 关键文件画成调用关系图》
- 《按源码顺序带你读
rag_service.py》 - 《按源码顺序带你读
agent.py》