# https://github.com/rag-web-ui/rag-web-ui 项目说明书

生成时间：2026-07-06 06:58:19 UTC

## 目录

- [项目概述与系统架构](#page-1)
- [后端核心系统：API、数据模型与服务层](#page-2)
- [AI 与向量检索集成：LLM、Embedding 与向量库工厂](#page-3)
- [前端、部署与运维：Docker、Next.js 与常见故障](#page-4)

<a id='page-1'></a>

## 项目概述与系统架构

### 相关页面

相关主题：[后端核心系统：API、数据模型与服务层](#page-2), [AI 与向量检索集成：LLM、Embedding 与向量库工厂](#page-3), [前端、部署与运维：Docker、Next.js 与常见故障](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [README.md](https://github.com/rag-web-ui/rag-web-ui/blob/main/README.md)
- [README.zh-CN.md](https://github.com/rag-web-ui/rag-web-ui/blob/main/README.zh-CN.md)
- [backend/app/main.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/main.py)
- [backend/app/core/config.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/core/config.py)
- [backend/app/core/security.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/core/security.py)
- [backend/app/api/api_v1/auth.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/api_v1/auth.py)
- [backend/app/api/api_v1/api.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/api_v1/api.py)
- [docker-compose.yml](https://github.com/rag-web-ui/rag-web-ui/blob/main/docker-compose.yml)
- [docker-compose.dev.yml](https://github.com/rag-web-ui/rag-web-ui/blob/main/docker-compose.dev.yml)
- [backend/Dockerfile](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/Dockerfile)
</details>

# 项目概述与系统架构

## 1. 项目定位与核心能力

rag-web-ui 是一个面向 RAG（Retrieval-Augmented Generation，检索增强生成）场景的开源 Web 应用，提供从「文档上传 → 知识库构建 → 问答交互」的一站式能力。仓库同时提供中英两份 README，说明其面向多语种用户的设计意图 资料来源：[README.md:1-30]() 资料来源：[README.zh-CN.md:1-30]()。

核心能力包括：

- **多源文档支持**：用户可在前端上传文件，由后端解析、切片、向量化后存入向量库。
- **可插拔的模型提供方**：通过 `.env` 中的 `CHAT_PROVIDER`、`EMBEDDINGS_PROVIDER` 字段切换不同 LLM 与 Embedding 后端，例如 OpenAI 兼容 API、HuggingFace Embeddings 等。
- **独立的多租户隔离**：每个用户拥有独立的知识库与聊天记录（issue #49 提示多租户能力正在被持续强化）。
- **基于 LangChain 的检索链**：问答时使用 LangChain 的 Runnable 组合，将「检索上下文 + 用户问题」组装为 Prompt 后送入 LLM（issue #70 中可看到 `RunnableParallel<answer>` 的运行链路）。

## 2. 整体系统架构

系统整体采用「前后端分离 + 容器化编排」的结构，运行依赖由 Docker Compose 统一声明 资料来源：[docker-compose.yml:1-80]()。

```mermaid
flowchart LR
    User[浏览器用户] --> FE[Frontend<br/>React/Next.js]
    FE -- HTTP/SSE --> BE[Backend<br/>FastAPI]
    BE -- Embeddings --> EP[Embeddings Provider<br/>OpenAI / HuggingFace]
    BE -- LLM Chat --> CP[Chat Provider<br/>OpenAI 兼容]
    BE -- 向量存取 --> VDB[(ChromaDB)]
    BE -- 文件下载 --> S3[(S3 Compatible<br/>对象存储)]
    VDB -- 检索上下文 --> BE
```

部署形态上，仓库使用容器间网络通信：当 `extra_hosts: host.docker.internal` 注入后，容器内可访问宿主机服务（例如本机 LLM 端点），这对 Linux 上的 Docker 用户尤其重要 资料来源：[docker-compose.yml:30-60]() 资料来源：[docker-compose.dev.yml:1-50]()。

## 3. 后端核心模块

后端基于 FastAPI 构建，并通过统一的 lifespan 管理向量库等全局资源 资料来源：[backend/app/main.py:1-80]()。主要组成如下：

| 模块 | 职责 |
| --- | --- |
| `app/main.py` | 应用入口，挂载路由、初始化 lifespan |
| `app/core/config.py` | 集中读取 `.env`，提供 Provider、模型名、API Key 等配置 |
| `app/core/security.py` | 密码哈希、JWT 校验、`get_current_user` 依赖注入 |
| `app/api/api_v1/api.py` | 路由聚合，挂载 chat、knowledge、auth 等子路由 |
| `app/api/api_v1/auth.py` | 注册、登录、获取当前用户等接口 |

issue #83 指出 `auth.py` 与 `security.py` 中存在 `get_current_user` 重复定义，建议将实现收敛在 `core/security.py` 并在 `auth.py` 中复用，这是后端代码组织层面需要关注的可维护性问题 资料来源：[backend/app/api/api_v1/auth.py:1-40]() 资料来源：[backend/app/core/security.py:1-60]()。

## 4. 数据流：从上传到问答

数据流贯穿文档处理、检索和生成三个阶段：

1. **上传与暂存**：前端上传文件到后端，后端将原始文件作为临时对象写入 S3 兼容存储以便后续重试和并发消费（issue #82 中出现的 `NoSuchKey` 错误即发生在该环节）。
2. **解析与量化**：后端拉取临时文件 → 按策略切片 → 调用 `EMBEDDINGS_PROVIDER` 生成向量 → 写入 ChromaDB。issue #54 提示「文档量化失败后无法重试/删除」的恢复能力是关键改进点。
3. **问答检索**：用户消息经 `RunnableParallel` 同时调度「向量检索」与「答案生成」，检索结果作为 `context` 注入 Prompt，再交由 `CHAT_PROVIDER` 调用 LLM 完成回答 资料来源：[backend/app/api/api_v1/api.py:1-50]()。

模型层面，v0.8.0 起 `EMBEDDINGS_PROVIDER` 已支持 `huggingface`，通过 `sentence-transformers` 在本地加载任意 HF Embedding 模型，与 LLM 端点的配置完全解耦 资料来源：[backend/app/core/config.py:1-120]()。issue #71 进一步提出对接 Groq/Cerebras 等云端推理服务的需求，规划通过与 OpenAI 兼容的 VLLM 服务器协议接入。

## 5. 已知边界与社区关注点

综合社区反馈可归纳出当前架构上的几个常见痛点：

- **链路错误可见性**：issue #70 中 `KeyError('context')` 暴露出检索失败时整条链直接报错，前端体验受影响；需在链内做容错回退。
- **前端渲染压力**：issue #69 报告长响应下 `Maximum update depth exceeded`，说明对话组件在高频更新场景下需要拆分渲染粒度。
- **文档处理幂等性**：issue #54 要求对量化失败的文档提供重试/删除入口，避免脏数据长期滞留。
- **部署健壮性**：issue #73 反映 `rag-web-ui-frontend unhealthy`，通常与健康检查脚本、容器启动顺序有关，参见 `deploy-local.md` 排查。
- **扩展性建议**：issue #84 提议引入 LangGraph 把「直接 HTTP 调用后端」升级为基于图的工作流，从而支持多步检索与工具调用。

以上反馈共同指向一个演进方向：在保持「FastAPI + LangChain + ChromaDB + S3」这一稳固主干的同时，提升链路容错、文档处理幂等以及多 Provider 适配的扩展性。

资料来源：[backend/Dockerfile:1-50]()

---

<a id='page-2'></a>

## 后端核心系统：API、数据模型与服务层

### 相关页面

相关主题：[项目概述与系统架构](#page-1), [AI 与向量检索集成：LLM、Embedding 与向量库工厂](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [backend/app/main.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/main.py)
- [backend/app/api/api_v1/auth.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/api_v1/auth.py)
- [backend/app/api/api_v1/chat.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/api_v1/chat.py)
- [backend/app/api/api_v1/knowledge_base.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/api_v1/knowledge_base.py)
- [backend/app/api/api_v1/api_keys.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/api_v1/api_keys.py)
- [backend/app/api/openapi/api.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/openapi/api.py)
- [backend/app/api/openapi/knowledge.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/api/openapi/knowledge.py)
- [backend/app/core/security.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/core/security.py)
- [backend/app/schemas/](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/schemas)
- [backend/app/services/](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services)
</details>

# 后端核心系统：API、数据模型与服务层

## 1. 概览与整体职责

rag-web-ui 的后端采用典型的 FastAPI 分层架构，整体入口由 `backend/app/main.py` 启动并挂载两套 API 路由：受保护的 `api_v1` 内部接口与无需登录的 `openapi` 公共接口。前端通过 `api_v1` 完成知识库、会话、API Key 等敏感操作，通过 `openapi` 完成跨租户共享的问答与知识检索。`资料来源：[backend/app/main.py]()` `资料来源：[backend/app/api/api_v1/auth.py]()` `资料来源：[backend/app/api/openapi/api.py]()`

后端核心系统承担三类关键职责：

- **接口编排**：聚合 `auth`、`chat`、`knowledge_base`、`api_keys` 等子路由，统一鉴权与异常处理。
- **数据建模**：通过 `schemas/` 下的 Pydantic 模型定义用户、知识库、文档、会话、消息等实体的入参与出参。
- **服务实现**：在 `services/` 与 `core/` 中封装 LangChain 链、向量库检索、文件存储、密码哈希等可复用逻辑。

## 2. API 路由层

### 2.1 内部路由 `api_v1`

`api_v1` 是登录后的受保护接口集合，统一通过 `Depends(get_current_user)` 完成身份校验：

- `auth.py`：注册、登录、获取当前用户。社区 #83 指出该文件与 `core/security.py` 中存在重复的 `get_current_user`，建议保留 `core/security.py` 作为唯一定义并由 `auth.py` 复用导入，以降低维护风险。`资料来源：[backend/app/api/api_v1/auth.py]()` `资料来源：[backend/app/core/security.py]()`
- `chat.py`：基于 LangChain `RunnableParallel` 实现检索增强问答，社区 #70 中出现的 `KeyError('context')` 即源于该链路在缺少 `context` 字段时未做兜底。`资料来源：[backend/app/api/api_v1/chat.py]()`
- `knowledge_base.py`：知识库的创建、列表、上传、删除及文档量化状态查询，承载社区 #54、#72、#82 中关于上传失败、S3 `NoSuchKey` 与量化重试等问题的处理路径。`资料来源：[backend/app/api/api_v1/knowledge_base.py]()`
- `api_keys.py`：用户级别的 LLM/Embedding 凭据管理，配合 `CHAT_PROVIDER` 与 `EMBEDDINGS_PROVIDER` 环境变量切换 OpenAI、HuggingFace 等后端（v0.8.0 起支持 HuggingFace）。`资料来源：[backend/app/api/api_v1/api_keys.py]()`

### 2.2 公共路由 `openapi`

`openapi/api.py` 与 `openapi/knowledge.py` 提供免登录的问答入口，主要用于跨租户共享、嵌入式集成或外部 webhook 场景，鉴权依赖 API Key 而非用户会话。

### 2.3 请求流转示意

```mermaid
flowchart LR
  FE[前端/外部客户端] -->|登录态| APIv1[/api/v1/*/]
  FE -->|API Key| OPEN[/openapi/*/]
  APIv1 --> Sec[core/security.py 鉴权]
  OPEN --> KeyAuth[API Key 校验]
  Sec --> Svc[services/ 业务逻辑]
  KeyAuth --> Svc
  Svc --> LLM[LLM / Embeddings]
  Svc --> VDB[ChromaDB / 向量库]
  Svc --> S3[(对象存储)]
```

## 3. 数据模型层

`schemas/` 下的 Pydantic 模型承担两类作用：

- **入参校验**：例如登录请求、文档上传元数据、问答请求体，强制字段类型与必填约束，避免脏数据进入服务层。
- **出参序列化**：例如知识库列表、文档量化状态、消息流式响应，保证前端拿到结构稳定的 JSON。

设计上，模型层不持有数据库会话，只做字段映射与转换；持久化逻辑交由 `services/` 完成，从而保持“薄模型、厚服务”的边界。

## 4. 服务层与认证安全

`services/` 目录封装了与外部系统交互的逻辑：LangChain 链组装（解决 #70 `context` 缺失问题需要在此层注入默认 `context`）、向量库的读写（应对 #54 量化失败的重试/删除）、S3/本地混合存储（应对 #82 的 `NoSuchKey`）。

`core/security.py` 集中了认证原语：

- `get_password_hash` / `verify_password`：自 v0.7.5 起改用 `bcrypt.hashpw` 与 `bcrypt.checkpw` 直接实现，移除 `passlib` 并固定 BCrypt 4.0.1，确保跨平台哈希一致。`资料来源：[backend/app/core/security.py]()`
- `get_current_user`：从 JWT 解析用户身份，建议作为唯一实现，被 `api_v1/auth.py` 等路由复用（参见 #83）。
- `create_access_token`：基于配置签发带过期的令牌。

社区已知问题与本系统直接相关：多租户隔离（#49）需要在服务层查询时按 `user_id` 过滤；DNS 解析失败（#36）通常发生在 `httpx` 调用 LLM 时，应在服务层加入重试与超时配置；上传链路（#72）的 ChromaDB 连接错误提示需结合 `services/` 中的客户端初始化排查。

---

<a id='page-3'></a>

## AI 与向量检索集成：LLM、Embedding 与向量库工厂

### 相关页面

相关主题：[项目概述与系统架构](#page-1), [后端核心系统：API、数据模型与服务层](#page-2), [前端、部署与运维：Docker、Next.js 与常见故障](#page-4)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [backend/app/services/llm/llm_factory.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/llm/llm_factory.py)
- [backend/app/services/embedding/embedding_factory.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/embedding/embedding_factory.py)
- [backend/app/services/vector_store/factory.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/factory.py)
- [backend/app/services/vector_store/base.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/base.py)
- [backend/app/services/vector_store/chroma.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/chroma.py)
- [backend/app/services/vector_store/qdrant.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/qdrant.py)
</details>

# AI 与向量检索集成：LLM、Embedding 与向量库工厂

## 1. 整体职责与设计目标

`rag-web-ui` 的后端把"对话生成（LLM）"、"文本向量化（Embedding）"以及"向量库检索（Vector Store）"三件最容易更换实现的事，统统收敛到 `backend/app/services/` 下的三个工厂模块。这种"工厂 + 抽象基类"的设计，让上层 RAG 链路（检索 → 拼装 prompt → 调用 LLM → 流式输出）只依赖统一接口，而具体后端（OpenAI、HuggingFace、ChromaDB、Qdrant 等）可以由环境变量按需切换。

这套机制直接回应了社区里出现频次较高的诉求：

- 在 [v0.8.0](https://github.com/rag-web-ui/rag-web-ui/releases/tag/v0.8.0) 发布中加入了 HuggingFace Embedding 支持（[#77](https://github.com/rag-web-ui/rag-web-ui/issues/77)），用户希望 LLM 和 Embedding 能各自独立指定 provider，不再被绑死在同一个 OpenAI 端点上。
- 在 [Issue #71](https://github.com/rag-web-ui/rag-web-ui/issues/71) 中，社区希望接入 Groq Cloud、Cerebras 等云模型；维护者表示通过 VLLM 的 OpenAI 兼容服务即可继续复用本套工厂。
- 在 [Issue #70](https://github.com/rag-web-ui/rag-web-ui/issues/70) 的 `KeyError('context')` 报错中，错误的根因是 LangChain Chain 在没有命中向量库时把 `context` 字段漏传，这也说明"检索 → 上下文注入"这条链路对工厂实现的一致性非常敏感。

## 2. LLM 工厂：对话模型的选择入口

`LLMFactory` 位于 [backend/app/services/llm/llm_factory.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/llm/llm_factory.py)，其职责是根据 `CHAT_PROVIDER`（如 `openai`、`vllm` 等）返回 LangChain 兼容的 `BaseChatModel` 实例。它读取以下关键配置：

- `CHAT_PROVIDER`：决定走 OpenAI 协议还是其它兼容协议
- `OPENAI_API_KEY`、`OPENAI_API_BASE`：通用鉴权与端点
- `OPENAI_MODEL`：具体模型名

由于使用 OpenAI 兼容协议，任何暴露 `/v1/chat/completions` 的服务（自建 vLLM、OneAPI、以及未来的 Groq/Cerebras 代理）都可以直接接入，无需改业务代码。资料来源：[backend/app/services/llm/llm_factory.py:1-80]()

## 3. Embedding 工厂：可独立切换的向量化后端

`EmbeddingFactory` 位于 [backend/app/services/embedding/embedding_factory.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/embedding/embedding_factory.py)，其与 LLM 工厂解耦，通过 `EMBEDDINGS_PROVIDER` 独立路由：

| Provider | 典型用途 | 关键配置 |
|---|---|---|
| `openai` | 调用云端 Embedding API（也兼容各类第三方网关，例如 [Issue #72](https://github.com/rag-web-ui/rag-web-ui/issues/72) 中的百川） | `OPENAI_API_KEY`、`OPENAI_API_BASE`、`OPENAI_EMBEDDINGS_MODEL` |
| `huggingface` | 本地 `sentence-transformers` 推理，离线/隐私场景（[#77](https://github.com/rag-web-ui/rag-web-ui/issues/77)） | `HUGGINGFACE_MODEL_NAME` 等 |

设计要点在于：LLM 和 Embedding 的 `*_PROVIDER`、`*_API_BASE`、`*_MODEL` 全部是分开的，调用方不会假设两者来自同一家服务。这正好解决了 [Issue #77](https://github.com/rag-web-ui/rag-web-ui/issues/77) 中"OpenAI 只有一个端点"的痛点。资料来源：[backend/app/services/embedding/embedding_factory.py:1-120]()

## 4. 向量库工厂：检索后端的统一抽象

向量检索是 RAG 质量的关键，仓库用"基类 + 多个实现 + 顶层工厂"的分层方式来组织。

### 4.1 抽象基类

[backend/app/services/vector_store/base.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/base.py) 定义了所有向量库必须实现的接口，覆盖：集合/库的创建与删除、文档写入（带 embedding）、相似度检索、删除文档等。这样上层 RAG 逻辑只面向 `VectorStoreBase`，对具体后端无感知。资料来源：[backend/app/services/vector_store/base.py:1-90]()

### 4.2 工厂路由

[backend/app/services/vector_store/factory.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/factory.py) 读取 `VECTOR_STORE_PROVIDER`（如 `chroma`、`qdrant`），返回对应的实现单例。工厂内通常会缓存实例，避免每个请求都重建客户端连接。资料来源：[backend/app/services/vector_store/factory.py:1-60]()

### 4.3 ChromaDB 实现

[backend/app/services/vector_store/chroma.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/chroma.py) 是默认实现，封装了 Chroma 的 `PersistentClient`/`HttpClient` 两种模式，并负责把 LangChain 的 `Document` 转换成 Chroma 的 `add`/`query` 调用。需要注意：社区中 [Issue #70](https://github.com/rag-web-ui/rag-web-ui/issues/70) 出现的 `KeyError('context')` 往往发生在 Chroma 检索返回为空、上下文键未被注入 prompt 模板时，需在调用层做空结果兜底。资料来源：[backend/app/services/vector_store/chroma.py:1-150]()

### 4.4 Qdrant 实现

[backend/app/services/vector_store/qdrant.py](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/app/services/vector_store/qdrant.py) 提供 Qdrant 客户端封装，支持集合的 `recreate_collection`、点（point）写入以及基于 `search` 的相似度检索。当用户希望使用自有部署的 Qdrant 时，只需在 `.env` 中切换 provider 即可，业务侧无感知。资料来源：[backend/app/services/vector_store/qdrant.py:1-150]()

## 5. 三者协作：从查询到回答

下面是请求在三个工厂之间流转的简化时序：

```mermaid
sequenceDiagram
    participant U as 用户/前端
    participant API as RAG API
    participant LLM as LLMFactory
    participant EMB as EmbeddingFactory
    participant VS as VectorStoreFactory
    participant DB as 向量库(Chroma/Qdrant)
    U->>API: 发送问题
    API->>EMB: embed_query(问题)
    EMB-->>API: 向量
    API->>VS: similarity_search(vector, top_k)
    VS->>DB: 查询近邻
    DB-->>VS: 命中文档
    VS-->>API: 上下文片段
    API->>LLM: invoke(prompt = 上下文 + 问题)
    LLM-->>API: 流式回答
    API-->>U: SSE 流式响应
```

阅读这张图时建议结合社区反馈：例如 [Issue #54](https://github.com/rag-web-ui/rag-web-ui/issues/54) 提到的"文档处理失败后无法重试/删除"，根因是 `vector_store` 的写入与"知识库元数据"在 `Document` 维度上未完全对齐，导致 UI 拿不到处理失败文档的句柄——这正是后续在 `base.py` 与上层服务间需要补齐"幂等写入 + 失败回滚"的地方。资料来源：[backend/app/services/vector_store/base.py:30-90]()、[backend/app/services/vector_store/factory.py:1-60]()、[backend/app/services/embedding/embedding_factory.py:40-120]()、[backend/app/services/llm/llm_factory.py:30-80]()

## 6. 选型与扩展建议

- **优先沿用 OpenAI 协议**：除非有强隐私要求，LLM 与 Embedding 都建议走 OpenAI 兼容服务，可最快复用现有 provider 路由。
- **本地 Embedding**：v0.8.0 起支持 HuggingFace provider，适合在没有外网的环境（如内网部署）启用，但要注意首次加载模型耗时与内存占用。
- **向量库选型**：开发/小规模用 Chroma 即可；如需分布式、过滤检索或更大规模，可切到 Qdrant，二者通过 `VECTOR_STORE_PROVIDER` 切换，业务代码无需改动。
- **关注社区演进方向**：[Issue #84](https://github.com/rag-web-ui/rag-web-ui/issues/84) 提出未来使用 LangGraph 改造检索流程，届时本套工厂抽象将作为节点（Node）继续复用。

---

<a id='page-4'></a>

## 前端、部署与运维：Docker、Next.js 与常见故障

### 相关页面

相关主题：[项目概述与系统架构](#page-1), [后端核心系统：API、数据模型与服务层](#page-2), [AI 与向量检索集成：LLM、Embedding 与向量库工厂](#page-3)

<details>
<summary>相关源码文件</summary>

以下源码文件用于生成本页说明：

- [docker-compose.yml](https://github.com/rag-web-ui/rag-web-ui/blob/main/docker-compose.yml)
- [docker-compose.dev.yml](https://github.com/rag-web-ui/rag-web-ui/blob/main/docker-compose.dev.yml)
- [backend/Dockerfile](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/Dockerfile)
- [backend/Dockerfile.dev](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/Dockerfile.dev)
- [backend/entrypoint.sh](https://github.com/rag-web-ui/rag-web-ui/blob/main/backend/entrypoint.sh)
- [frontend/Dockerfile](https://github.com/rag-web-ui/rag-web-ui/blob/main/frontend/Dockerfile)
- [docs/troubleshooting.md](https://github.com/rag-web-ui/rag-web-ui/blob/main/docs/troubleshooting.md)
</details>

# 前端、部署与运维：Docker、Next.js 与常见故障

本页面向运维与集成工程师介绍 rag-web-ui 的容器化部署方式、前端构建产物形态，以及部署/运行过程中在社区中高频出现的故障模式与对应排查思路。范围限定于 Docker 编排、Next.js 前端镜像与 FastAPI 后端镜像的构建与启动层面，不涉及具体业务逻辑（见其他 wiki 页面）。

## 1. 部署架构总览

项目通过 `docker-compose.yml` 统一编排前端、后端以及 ChromaDB 三个核心服务，以容器网络互通的方式提供完整 RAG 体验：

| 服务 | 角色 | 关键端口/依赖 |
|------|------|---------------|
| `frontend` | Next.js Web UI，对外暴露用户界面 | 监听 3000，反向代理到 `backend` |
| `backend` | FastAPI + LangChain 业务服务 | 监听 8000，调用 LLM/Embeddings 厂商 API |
| `chromadb` | 向量数据库 | 通过 `chromadb:8000` 在容器网络内被 `backend` 访问 |

`docker-compose.dev.yml` 在生产编排之上增加了开发期的卷挂载、热重载与调试端口，使开发者可以直接编辑源码而无需重建镜像。`资料来源：[docker-compose.yml:1-40]()` `资料来源：[docker-compose.dev.yml:1-30]()`

在 v0.7.3 版本中，编排文件针对 Linux Docker 主机兼容性进行了修复：所有服务均显式声明 `extra_hosts: host.docker.internal:host-gateway`，以便容器内能够解析宿主机的本地服务（如本地 LLM 端点）。`资料来源：[docker-compose.yml:host.docker.internal 配置块]()` 同时，`backend/Dockerfile` 与 `backend/Dockerfile.dev` 显式安装了 `curl`，用于健康检查与端点探测。`资料来源：[backend/Dockerfile:curl 安装步骤]()` `资料来源：[backend/Dockerfile.dev:curl 安装步骤]()`

## 2. 前端服务：Next.js 容器化

前端基于 Next.js 构建，产物由 `frontend/Dockerfile` 进行多阶段构建：先在 builder 阶段执行依赖安装与 `next build`，再在 runner 阶段仅保留 `.next` 产物与 `node_modules`（剔除开发依赖），从而显著压缩最终镜像体积。容器启动时执行 `npm run start` 监听 3000 端口。`资料来源：[frontend/Dockerfile:多阶段构建段落]()`

环境变量通过 `NEXT_PUBLIC_*` 前缀注入到前端运行时，例如 `NEXT_PUBLIC_API_URL` 用于指向后端地址。Docker Compose 通过 `environment` 块将宿主环境变量透传至容器，因此同一镜像可在不同环境（开发/生产）下复用。`资料来源：[docker-compose.yml:frontend environment 段]()`

## 3. 后端服务：FastAPI 容器化

后端使用 `backend/Dockerfile`（生产）与 `backend/Dockerfile.dev`（开发）两类镜像。生产镜像基于 Python 精简基础镜像，安装 `requirements.txt` 中依赖后，复制 `app/` 应用代码与 `entrypoint.sh` 启动脚本。`资料来源：[backend/Dockerfile:依赖安装段落]()`

`entrypoint.sh` 在容器启动时完成以下工作：`资料来源：[backend/entrypoint.sh:1-25]()`

1. 等待 ChromaDB 等外部依赖可达（通过 `curl` 健康探测）；
2. 执行数据库迁移或初始化脚本；
3. 启动 Uvicorn，加载 `app.main:app`。

开发镜像则保留 `uvicorn --reload` 与源码卷挂载，便于本地调试。`资料来源：[backend/Dockerfile.dev:开发模式启动命令]()`

## 4. 常见故障与排查

### 4.1 `rag-web-ui-frontend` 启动后 unhealthy

issue #73 报告了 `docker compose ps` 中 `rag-web-ui-frontend` 长时间处于 `unhealthy` 状态。该问题通常源于：

- 容器内 Node 进程尚未就绪，但 Docker 健康检查在 `start_period` 之外执行；
- 后端不可达导致前端 SSR 阶段抛错。

排查步骤：先 `docker compose logs frontend` 查看 Next.js 启动日志；其次确认 `NEXT_PUBLIC_API_URL` 已正确指向 `http://backend:8000`（容器网络名而非 `localhost`）；最后通过 `docker compose exec frontend wget -qO- http://backend:8000/health` 验证后端连通性。`资料来源：[docs/troubleshooting.md:健康检查章节]()`

### 4.2 DNS 解析失败（`Temporary failure in name resolution`）

issue #36 反馈在聊天接口调用时出现 `[Errno -3] Temporary failure in name resolution`。该错误常因后端容器无法解析外部 LLM 域名。处理方式：在宿主机确认 DNS 正常后，于 `docker-compose.yml` 的 `backend` 服务下追加 `dns` 配置指向公共解析器（如 `8.8.8.8`），并重启服务。`资料来源：[docs/troubleshooting.md:DNS 章节]()`

### 4.3 React 前端 `Maximum update depth exceeded`

issue #69 指出当聊天返回内容过长时，Next.js 客户端组件会触发 `Maximum update depth exceeded`。该问题属于渲染循环，建议在对话消息列表组件中：

- 对长消息进行分页/虚拟滚动（例如 `react-window`）；
- 使用 `useMemo`/`useCallback` 避免引用变化触发 `setState`。`资料来源：[docs/troubleshooting.md:前端性能章节]()`

### 4.4 多租户数据隔离

issue #49 反馈不同账号登录后查询结果相同，疑似未做租户隔离。运维侧需确认后端环境变量中租户开关（如 `ENABLE_TENANT_ISOLATION`）已开启，并核对 ChromaDB collection 命名是否携带用户/租户前缀。`资料来源：[docs/troubleshooting.md:多租户章节]()`

## 5. 升级与维护建议

- 升级到 v0.7.3 及以上版本，确保 `extra_hosts` 已声明，否则 Linux 主机上的本地 LLM/Embeddings 端点无法在容器内访问。`资料来源：[v0.7.3 release notes]()`
- 升级到 v0.7.5 及以上版本，使用直接基于 `bcrypt` 的密码哈希实现，避免 `passlib` 与新版 `bcrypt` 之间的兼容问题。`资料来源：[v0.7.5 release notes]()`
- 升级到 v0.8.0 后可独立配置 `EMBEDDINGS_PROVIDER=huggingface`，让 Embeddings 与 LLM 使用不同后端而互不影响。`资料来源：[v0.8.0 release notes]()`

---

<!-- evidence_pipeline_checked: true -->
<!-- evidence_injected: true -->

---

## Doramagic 踩坑日志

项目：rag-web-ui/rag-web-ui

摘要：发现 19 个潜在踩坑项，其中 3 个为 high/blocking；最高优先级：安装坑 - 来源证据：Backend combined with knowledge base Q&A reports an error, and the error message is as follows。

## 1. 安装坑 · 来源证据：Backend combined with knowledge base Q&A reports an error, and the error message is as follows

- 严重度：high
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：Backend combined with knowledge base Q&A reports an error, and the error message is as follows
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/70 | 来源类型 github_issue 暴露的待验证使用条件。

## 2. 能力坑 · 能力证据存在缺口

- 严重度：high
- 证据强度：source_linked
- 发现：Sandbox install result is missing.
- 对用户的影响：缺口未补前，Doramagic 不能把该能力当作可靠推荐卖点。
- 证据：evidence.evidence_gaps | https://github.com/rag-web-ui/rag-web-ui | Sandbox install result is missing.

## 3. 运行坑 · 沙箱验证已有失败原因

- 严重度：high
- 证据强度：runtime_trace
- 发现：llm_blocked_sandbox_execution
- 对用户的影响：失败原因未处理前，不应向用户暗示项目可顺利运行。
- 观测结果：sandbox_install_status=blocked; sandbox_quickstart_status=blocked; failure=llm_blocked_sandbox_execution
- 证据：sandbox_validation_results | planner_decision=llm_blocked; planner_reason=The candidate command 'docker compose up -d' is not present in the deterministic allowlist (echo/python/node) and does not match any isolated_install_policy form (pip/npm/npx/uvx/docker run). 'docker compose up -d' would also start services persistently in the sandbox, whic…

## 4. 安装坑 · 依赖 Docker 环境

- 严重度：medium
- 证据强度：runtime_trace
- 发现：安装/运行入口包含 Docker 命令：docker compose up -d
- 对用户的影响：非工程用户可能没有 Docker，启动成本明显增加。
- 复现命令：`docker compose up -d`
- 证据：identity.distribution | https://github.com/rag-web-ui/rag-web-ui | docker compose up -d

## 5. 安装坑 · 安装命令尚未沙箱验证

- 严重度：medium
- 证据强度：runtime_trace
- 发现：当前 install_status=documented，还只是文档/元数据线索。
- 对用户的影响：命令可能缺步骤、过期或依赖本地环境，不能直接作为用户承诺。
- 复现命令：`docker compose up -d`
- 观测结果：sandbox_install_status=blocked; sandbox_quickstart_status=blocked; failure=llm_blocked_sandbox_execution
- 证据：downstream_validation.install_status | https://github.com/rag-web-ui/rag-web-ui | install_status=documented; command=docker compose up -d

## 6. 安装坑 · 来源证据：when process file get error "Failed to download temp file: S3 operation failed; code: NoSuchKey..."

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安装相关的待验证问题：when process file get error "Failed to download temp file: S3 operation failed; code: NoSuchKey..."
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/82 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 7. 能力坑 · 能力判断依赖假设

- 严重度：medium
- 证据强度：source_linked
- 发现：README/documentation is current enough for a first validation pass.
- 对用户的影响：假设不成立时，用户拿不到承诺的能力。
- 证据：capability.assumptions | https://github.com/rag-web-ui/rag-web-ui | README/documentation is current enough for a first validation pass.

## 8. 运行坑 · Quick Start 尚未实际跑通

- 严重度：medium
- 证据强度：runtime_trace
- 发现：quickstart_status=not_attempted。
- 对用户的影响：用户只能看到安装线索，不能确信 10 分钟内能形成最小可试路径。
- 观测结果：sandbox_install_status=blocked; sandbox_quickstart_status=blocked; failure=llm_blocked_sandbox_execution
- 证据：downstream_validation.quickstart_status | https://github.com/rag-web-ui/rag-web-ui | quickstart_status=not_attempted; sandbox_quickstart_status=blocked

## 9. 运行坑 · 来源证据：Front end bug

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个运行相关的待验证问题：Front end bug
- 对用户的影响：可能增加新用户试用和生产接入成本。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/69 | 来源类型 github_issue 暴露的待验证使用条件。

## 10. 维护坑 · 维护活跃度未知

- 严重度：medium
- 证据强度：source_linked
- 发现：未记录 last_activity_observed。
- 对用户的影响：新项目、停更项目和活跃项目会被混在一起，推荐信任度下降。
- 证据：evidence.maintainer_signals | https://github.com/rag-web-ui/rag-web-ui | last_activity_observed missing

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 证据：downstream_validation.risk_items | https://github.com/rag-web-ui/rag-web-ui | no_demo; severity=medium

## 12. 安全/权限坑 · 存在安全注意事项

- 严重度：medium
- 证据强度：source_linked
- 发现：No sandbox install has been executed yet; downstream must verify before user use.
- 对用户的影响：用户安装前需要知道权限边界和敏感操作。
- 证据：risks.safety_notes | https://github.com/rag-web-ui/rag-web-ui | No sandbox install has been executed yet; downstream must verify before user use.

## 13. 安全/权限坑 · 存在评分风险

- 严重度：medium
- 证据强度：source_linked
- 发现：no_demo
- 对用户的影响：风险会影响是否适合普通用户安装。
- 证据：risks.scoring_risks | https://github.com/rag-web-ui/rag-web-ui | no_demo; severity=medium

## 14. 安全/权限坑 · 来源证据：Duplicate get_current_user in auth.py and security.py

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：Duplicate get_current_user in auth.py and security.py
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/83 | 来源类型 github_issue 暴露的待验证使用条件。

## 15. 安全/权限坑 · 来源证据：upload file failure

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：upload file failure
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/72 | 来源讨论提到 python 相关条件，需在安装/试用前复核。

## 16. 安全/权限坑 · 来源证据：添加文档到知识库量化处理报错后，无法重试，也不能从知识库中将该文档再量化或者删除

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：添加文档到知识库量化处理报错后，无法重试，也不能从知识库中将该文档再量化或者删除
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/54 | 来源讨论提到 docker 相关条件，需在安装/试用前复核。

## 17. 安全/权限坑 · 来源证据：聊天发送消息返回Temporary failure in name resolution，不知道什么原因

- 严重度：medium
- 证据强度：source_linked
- 发现：GitHub 社区证据显示该项目存在一个安全/权限相关的待验证问题：聊天发送消息返回Temporary failure in name resolution，不知道什么原因
- 对用户的影响：可能影响授权、密钥配置或安全边界。
- 证据：community_evidence:github | https://github.com/rag-web-ui/rag-web-ui/issues/36 | 来源讨论提到 docker 相关条件，需在安装/试用前复核。

## 18. 维护坑 · issue/PR 响应质量未知

- 严重度：low
- 证据强度：source_linked
- 发现：issue_or_pr_quality=unknown。
- 对用户的影响：用户无法判断遇到问题后是否有人维护。
- 证据：evidence.maintainer_signals | https://github.com/rag-web-ui/rag-web-ui | issue_or_pr_quality=unknown

## 19. 维护坑 · 发布节奏不明确

- 严重度：low
- 证据强度：source_linked
- 发现：release_recency=unknown。
- 对用户的影响：安装命令和文档可能落后于代码，用户踩坑概率升高。
- 证据：evidence.maintainer_signals | https://github.com/rag-web-ui/rag-web-ui | release_recency=unknown

<!-- canonical_name: rag-web-ui/rag-web-ui; human_manual_source: deepwiki_human_wiki -->
