# RAGFlow 引入可行性分析

> **创建日期**: 2026-06-17
> **状态**: 调研完成，待决策
> **目标**: 评估将 RAGFlow 作为 Fischer AgentKit 知识库的可行性、技术路径与风险

---

## 一、RAGFlow 项目概览

| 维度 | 详情 |
|------|------|
| 仓库 | https://github.com/infiniflow/ragflow |
| License | Apache-2.0 |
| GitHub Stars | ~80k（2025 年度 Top 10） |
| 最新版本 | v0.25.6（2026-05-26） |
| 核心定位 | 基于深度文档理解的 RAG 引擎，构建 AI Agent 上下文层 |
| 技术栈 | Python 后端 + React/TS 前端 + Docker 部署 |

### 核心差异化能力

- **DeepDoc 引擎**：OCR（15+ 语言）、版面识别（10 类组件：文本/标题/图/表/页眉页脚/公式等）、表格结构识别（TSR）
- **混合检索**：向量 + 全文 + 稀疏向量，支持 ColBERT late-interaction
- **高级特性**：GraphRAG、RAPTOR（层级摘要树）、Parent-Child 分块、rerank、上下文压缩
- **16+ 文档格式**：PDF/DOCX/PPT/Excel/图片/扫描件/网页/结构化数据等
- **Agent 工作流**：可视化编排、Memory 模块（v0.23.0+）、MCP 协议集成

### 部署资源要求（官方）

- CPU ≥ 4 核
- RAM ≥ 16 GB
- Disk ≥ 50 GB
- Docker ≥ 24.0.0 & Docker Compose ≥ v2.26.1

---

## 二、可行性结论：高度可行 ✅

Fischer AgentKit 已具备**成熟的适配器架构**，专门为对接外部知识库设计，RAGFlow 的 HTTP REST API 可直接映射到现有协议。

### 关键契合点

1. **协议匹配**：现有 `KnowledgeBase` Protocol（`src/agentkit/memory/knowledge_base.py:53-83`）定义了 `ingest()/query()/delete_by_id()/list_sources()/health_check()`，RAGFlow API 完全覆盖这些语义

2. **适配器基类就绪**：`KBAdapter`（`src/agentkit/memory/adapters/base.py:22-160`）已封装 httpx 客户端、生命周期管理、认证流程，子类只需实现 `_make_client()` 和 `search()`

3. **现有先例**：已有 `FeishuKBAdapter`、`ConfluenceAdapter`、`GenericHTTPAdapter` 三个适配器，模式成熟

4. **SemanticMemory 解耦**：`SemanticMemory`（`src/agentkit/memory/semantic.py:14-121`）通过 `rag_service` 注入，不直接依赖具体实现

5. **API 标准化**：RAGFlow 使用 Bearer Token 认证、RESTful JSON 接口，与 `HttpRAGService` 期望的接口形态一致

---

## 三、重点技术路径

### 路径 1：新增 RAGFlowAdapter（推荐）

在 `src/agentkit/memory/adapters/` 下新增 `ragflow.py`，继承 `KBAdapter`。

**API 映射表**：

| KBAdapter 方法 | RAGFlow API | 说明 |
|----------------|-------------|------|
| `search(query, top_k)` | `POST /api/v1/retrieval` | body: `{question, dataset_ids, top_k, similarity_threshold, vector_similarity_weight}` |
| `ingest(documents)` | `POST /api/v1/datasets/{id}/documents` + `POST /api/v1/datasets/{id}/chunks` | 上传后需触发异步解析 |
| `delete_by_id(id)` | `DELETE /api/v1/datasets/{id}/documents/{doc_id}` | |
| `list_sources()` | `GET /api/v1/datasets` | RAGFlow 的 dataset 概念 = Fischer 的 source |
| `health_check()` | `GET /api/v1/datasets` 或 `/v1/health` | |
| `get_document(doc_id)` | `GET /api/v1/datasets/{id}/documents/{doc_id}` | |

**关键实现要点**：
- `_make_client()` 配置 `base_url` + `Authorization: Bearer <api_key>`
- `search()` 需将 RAGFlow 返回的 chunk 结构（`content/document_id/dataset_id/similarity`）标准化为 `QueryResult`
- `ingest()` 需处理 RAGFlow 的**异步解析流程**：上传 → 触发 parse → 轮询状态（非同步返回）
- 在 `adapters/__init__.py` 注册导出

### 路径 2：复用 HttpRAGService（最快，但能力受限）

现有 `HttpRAGService` 已实现 `/search` 和 `/bases/{kb_id}/retrieve` 调用。RAGFlow 的 retrieval 端点路径不同（`/api/v1/retrieval`），需在 RAGFlow 侧部署一层 API 网关适配，或扩展 HttpRAGService 支持自定义路径模板。

**局限**：无法利用 RAGFlow 的文档上传/解析/分块能力，只能做检索。

### 路径 3：通过 ragflow-sdk 集成（不推荐）

`pip install ragflow-sdk` 直接调用 Python SDK。**违背 Fischer 的"配置驱动、不直接依赖业务系统代码"原则**，且引入额外依赖。

### 配置集成方案

在 `agentkit.yaml` 的 `memory.semantic` 段扩展：

```yaml
memory:
  semantic:
    enabled: true
    adapter: "ragflow"
    base_url: "http://ragflow-ecs-internal-ip:9380"
    api_key: "${RAGFLOW_API_KEY}"
    dataset_ids:
      - "industry-kb-dataset-id"
      - "enterprise-kb-dataset-id"
    timeout: 30
    retrieval:
      similarity_threshold: 0.2
      vector_similarity_weight: 0.3
      top_k: 10
      rerank_id: "BAAI/bge-reranker-v2-m3"
    ingest:
      mode: "async"
      poll_interval: 5
      poll_timeout: 600
    health_check:
      interval: 60
      fail_threshold: 3
```

### 与现有 LocalRAGService 的关系

`LocalRAGService`（pgvector）与 RAGFlow 定位不同：
- **LocalRAGService**：轻量、同进程、适合中小规模文本知识
- **RAGFlow**：重量级、独立服务、擅长复杂文档（PDF/扫描件/表格）深度解析

建议**并存**，通过 `MultiSourceRetriever` 聚合，按文档类型路由：纯文本走 Local，复杂文档走 RAGFlow。

---

## 四、风险分析与缓解措施评估

### 高风险项

#### 风险 1：资源占用重（16GB+ RAM）

**原措施**：slim 镜像 + 外部 embedding API / 独立机器部署

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ✅ 可行但需分场景。slim 镜像（~2GB）确实省去内置 embedding 模型，但 DeepDoc 的 OCR/TSR/Layout 模型仍打包在内，RAM 峰值仍需 8GB+ |
| 缓解效果 | ⚠️ 部分有效。slim 仅省 embedding 部分（约 4-6GB），DeepDoc 推理时仍会瞬时占用 2-4GB |
| 次生风险 | 🔴 外部 embedding API 引入新依赖链：① 网络延迟叠加（检索路径变成 Fischer→RAGFlow→外部Embedding API，3 跳）；② 外部 API 限流/宕机时 RAGFlow 解析直接失败；③ 跨网络传输文档内容存在数据泄露面 |

**更优解**：
- **方案 A（推荐）**：RAGFlow 独立机器/K8s 节点部署，与 Fischer 集群物理隔离，仅通过 HTTP API 通信
- **方案 B**：若必须同机，用 cgroup/Docker CPU+memory limits 硬隔离 RAGFlow 容器
- **不建议**：外部 embedding API 方案，除非已有内部 embedding 服务

#### 风险 2：架构栈重叠（Redis/MySQL/ES vs Fischer 的 Redis/PG）

**原措施**：复用 Fischer 的 Redis；ES/Infinity 无法复用 PG

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ⚠️ Redis 复用技术上可行但有陷阱。RAGFlow 用 Redis 做 Celery broker + 缓存，Fischer 用 Redis 做 RedisMessageBus（Streams）+ TaskStore。两者可用不同 db number 隔离 |
| 缓解效果 | ⚠️ 有限。省下的仅是 Redis 实例（~100MB），ES/Infinity（2-4GB）和 MySQL（1-2GB）仍需独立部署，重叠问题仅解决 10-15% |
| 次生风险 | 🔴 Redis 复用有严重隐患：① RAGFlow 的 Celery 任务高峰期会打满 Redis 连接池，影响 Fischer 的 RedisMessageBus 消息投递；② key 命名空间若冲突可能导致数据污染；③ RAGFlow 升级时 Redis schema 变更可能波及 Fischer |

**更优解**：
- **方案 A（推荐）**：完全不共享，独立 Redis 实例。RAGFlow 自带 docker-compose 已包含 Redis，保持默认部署不动
- **方案 B**：若强需共享，用 Redis Sentinel/Cluster 的不同 db（RAGFlow 用 db=1，Fischer 用 db=0），并配置独立的 `maxmemory-policy` 和连接池上限
- **ES/Infinity**：无更优解，RAGFlow 强依赖其混合检索能力，PG+pgvector 无法替代

#### 风险 3：异步解析延迟（大文档数分钟）

**原措施**：适配器内轮询 / 异步任务模式

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ✅ 可行，Fischer 已有完整异步任务基础设施。TaskStore 支持 PENDING→RUNNING→COMPLETED 状态机，tasks 路由已有 submit/status/list/cancel API |
| 缓解效果 | ✅ 有效。将 RAGFlow ingest 拆为"提交上传→返回 task_id→后台轮询解析状态→更新 task"四步 |
| 次生风险 | 🟡 中等：① 轮询频率若过高会冲击 RAGFlow API（建议 5-10s 间隔，指数退避）；② task TTL 与 RAGFlow 解析时长不匹配；③ 用户在解析未完成时检索会得到空结果 |

**更优解**：
- **方案 A（推荐）**：用 RAGFlow 的 Webhook 回调替代轮询。RAGFlow v0.23.0+ 支持 Webhook 触发，解析完成后主动回调 Fischer 的 `/api/v1/tasks/{id}/callback`
- **方案 B**：若 Webhook 不可用，用 RedisMessageBus 发布解析完成事件，适配器订阅后更新 task 状态
- **方案 C**：分离 ingest 和 query 路径——ingest 走异步 task，query 永远同步

### 中风险项

#### 风险 4：Embedding 模型锁定

**原措施**：规划期确定模型；不同 dataset 用不同模型

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ⚠️ 部分可行。"不同 dataset 不同模型"技术上成立，但跨 dataset 检索时向量维度不一致会导致召回失效 |
| 缓解效果 | ⚠️ 有限。锁定后若需切换模型，必须重建整个 dataset |
| 次生风险 | 🟡 模型碎片化：多个 dataset 用不同 embedding，SemanticMemory 的 `kb_weights` 加权策略失效 |

**更优解**：
- **方案 A（推荐）**：全组织统一 embedding 模型（建议 `BAAI/bge-large-zh-v1.5` 或 `bge-m3`），所有 dataset 强制一致
- **方案 B**：若必须多模型，在适配器层按 dataset 分组检索，组内归一化 score 后再融合
- **根本性建议**：将 embedding 模型选择纳入 Fischer 的 LLM Gateway 统一管理

#### 风险 5：ARM64 支持缺失

**原措施**：x86 Docker / 自行构建

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ✅ 可行。自行构建有官方文档支持 |
| 缓解效果 | ✅ 有效，但构建耗时（含模型下载约 30-60 分钟） |
| 次生风险 | 🟢 低。主要是构建产物维护成本 |

**更优解**：
- **方案 A**：开发环境用 x86 Docker Desktop；生产环境强制 x86 服务器
- **方案 B**：若有 CI/CD，用 GitHub Actions 在 ARM64 runner 上自动构建并推送到私有 registry

#### 风险 6：版本快速迭代（API breaking change）

**原措施**：锁定版本；适配器层兼容

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ✅ 可行。锁定版本是标准做法 |
| 缓解效果 | ✅ 有效但被动。锁定版本意味着无法获得 bug 修复和新特性 |
| 次生风险 | 🟡 安全漏洞累积：长期不升级会错过安全补丁 |

**更优解**：
- **方案 A（推荐）**：适配器层做 API 版本抽象。定义 `RAGFlowAPIVersion` 枚举，适配器根据版本号选择不同的端点路径和响应解析逻辑
- **方案 B**：跟随 RAGFlow 的 minor 版本（如固定 v0.25.x），patch 版本自动升级

#### 风险 7：数据模型映射损耗

**原措施**：适配器层完整字段映射，特有字段入 metadata

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ✅ 完全可行。这是适配器模式的标准职责 |
| 缓解效果 | ✅ 有效。QueryResult 的 metadata 字段是 dict，可容纳任意额外字段 |
| 次生风险 | 🟢 极低 |

**更优解**：当前方案已足够。增强建议：定义 `RAGFlowChunkMetadata` Pydantic 模型，结构化 RAGFlow 特有字段

### 低风险项

#### 风险 8：网络调用开销

**原措施**：timeout + 降级

| 评估维度 | 结论 |
|----------|------|
| 可行性 | ✅ 可行。SemanticMemory 已有 try/except 降级到空结果 |
| 缓解效果 | ✅ 有效 |
| 次生风险 | 🟡 降级静默化：检索失败返回空列表，用户无感知 |

**更优解**：在降级时记录 metric，并向前端 WebSocket 推送 `error` 事件；增加 circuit breaker

#### 风险 9 & 10：认证差异 / 功能重叠

**评估**：两项措施均完全可行且无次生风险，无需更优解。

### 综合评估矩阵

| 风险 | 原措施可行性 | 次生风险 | 缓解效果 | 更优解收益 |
|------|:---:|:---:|:---:|------|
| 1. 资源占用 | ⚠️ 部分 | 🔴 高 | ⚠️ 部分 | 独立部署彻底解决 |
| 2. 架构栈重叠 | ⚠️ 部分 | 🔴 高 | ⚠️ 仅10-15% | 独立Redis实例，不共享 |
| 3. 异步解析 | ✅ 可行 | 🟡 中 | ✅ 有效 | Webhook回调消除轮询 |
| 4. Embedding锁定 | ⚠️ 部分 | 🟡 中 | ⚠️ 有限 | 统一模型+网关治理 |
| 5. ARM64 | ✅ 可行 | 🟢 低 | ✅ 有效 | CI自动构建 |
| 6. 版本迭代 | ✅ 可行 | 🟡 中 | ⚠️ 被动 | API版本抽象层 |
| 7. 数据映射 | ✅ 可行 | 🟢 极低 | ✅ 有效 | 已足够 |
| 8. 网络开销 | ✅ 可行 | 🟡 低 | ✅ 有效 | metric+WS通知 |

### 关键结论

1. **原措施中 2 项有严重次生风险需立即调整**：
   - 风险 1 的"外部 embedding API"方案 → 改为独立机器部署
   - 风险 2 的"复用 Redis"方案 → 改为独立 Redis 实例

2. **1 项有明确更优解**：
   - 风险 3 的"轮询"→ 改用 RAGFlow Webhook 回调

3. **最关键的系统性建议**：将 RAGFlow 视为完全独立的外部服务（而非与 Fischer 共享基础设施的组件），通过 HTTP API 松耦合

4. **embedding 模型治理应统一到 Fischer 的 LLM Gateway**，避免模型碎片化和 score 不可比问题

---

## 五、独立部署配置方案（阿里云）

### 架构拓扑

```
┌─────────────────────────────────────────────────────────────┐
│  阿里云 VPC (10.0.0.0/16)                                    │
│                                                              │
│  ┌──────────────────────┐         ┌───────────────────────┐ │
│  │ Fischer ECS (已有)    │         │ RAGFlow ECS (新增)     │ │
│  │ 10.0.1.10            │  HTTPS  │ 10.0.2.10             │ │
│  │ agentkit serve:8001  │◄───────►│ ragflow:9380          │ │
│  │ Redis:6379 (内嵌)    │         │ Infinity:23321        │ │
│  │ PG:5432 (内嵌)       │         │ MySQL:3306 Redis:6380 │ │
│  └──────────────────────┘         └───────────────────────┘ │
│         │                                  │                 │
│         │          ┌──────────────────────┐│                 │
│         └─────────►│  阿里云 NAS / ESSD   │◄┘                 │
│                    │  (文档持久化存储)     │                  │
│                    └──────────────────────┘                  │
└─────────────────────────────────────────────────────────────┘
```

### 资源需求核算（修正后）

RAGFlow 各组件实际内存占用：

| 组件 | 最小可运行 | 推荐生产 | 说明 |
|------|-----------|---------|------|
| RAGFlow Server + DeepDoc | 2GB | 4GB | Python 进程，DeepDoc 推理时峰值 +2GB |
| Elasticsearch | 4GB（heap 2g） | 8GB（heap 4g） | JVM heap = 容器内存 50% |
| Infinity（替代ES） | 2GB | 3GB | Rust 实现，无 JVM 开销 |
| MySQL | 1GB | 2GB | 元数据存储，数据量小 |
| Redis | 512MB | 1GB | Celery broker + 缓存 |
| MinIO | 512MB | 1GB | 文档对象存储 |
| 系统开销 | 1GB | 2GB | OS + Docker daemon |

### 按业务规模分档推荐

#### 档位 1：POC / 小规模（< 1000 文档）

| 配置 | 规格 | 月费 |
|------|------|------|
| 实例 | ecs.g7.xlarge（4c16g） | ¥450 |
| 数据盘 | ESSD PL0 100GB | ¥45 |
| **合计** | | **~¥500/月** |

#### 档位 2：中小规模（1000-10000 文档）⭐ 推荐

| 配置 | 规格 | 月费 |
|------|------|------|
| 实例 | ecs.g7.2xlarge（8c32g） | ¥900 |
| 数据盘 | ESSD PL1 200GB | ¥150 |
| **合计** | | **~¥1,050/月** |

资源分配：
```
RAGFlow Server:  4GB
ES (heap 4g):    8GB  或  Infinity: 3GB
MySQL:           2GB
Redis:           1GB
MinIO:           1GB
系统余量:        16GB（含 DeepDoc 推理峰值）
```

#### 档位 3：中大规模（1万-10万文档）

| 配置 | 规格 | 月费 |
|------|------|------|
| 实例 | ecs.g7.3xlarge（12c48g） | ¥1,350 |
| 数据盘 | ESSD PL1 500GB | ¥375 |
| **合计** | | **~¥1,725/月** |

### 降配三个手段

1. **用 Infinity 替代 Elasticsearch**（省 4-6GB）：Rust 实现，无 JVM 开销
2. **slim 镜像 + 外部 Embedding**（省 4GB）：embedding 走阿里云百炼 `text-embedding-v2`
3. **MySQL/Redis 用 RAGFlow 自带**（不共享，彻底隔离）

### 综合最优方案（性价比最高）

| 项目 | 选择 | 理由 |
|------|------|------|
| 实例 | ecs.g7.2xlarge（8c32g） | 留足 DeepDoc 推理余量 |
| 文档引擎 | Infinity（非 ES） | 省 5GB 内存 |
| 镜像 | v0.25.6-slim | 不含 embedding 模型 |
| Embedding | 阿里云百炼 text-embedding-v2 | 外部 API，按量付费极低 |
| MySQL/Redis | RAGFlow 自带 | 不共享，彻底隔离 |
| 数据盘 | ESSD PL1 200GB | IOPS 够用 |
| **月费** | **~¥1,050** | |

资源实际占用预估：
```
RAGFlow Server (slim):  2GB
DeepDoc 推理峰值:        +2GB（间歇性）
Infinity:               3GB
MySQL:                  2GB
Redis:                  1GB
MinIO:                  1GB
系统:                   2GB
────────────────────────────
总计:                   ~13GB（32GB 机器余量充足）
```

### 极限降配方案（仅 POC 验证用）

| 项目 | 选择 | 月费 |
|------|------|------|
| 实例 | ecs.g7.xlarge（4c16g） | ¥450 |
| 文档引擎 | Infinity | |
| 镜像 | slim + 外部 embedding | |
| **月费** | | **~¥500** |

⚠️ 4c16g 下 DeepDoc 解析大 PDF（>50页）可能触发 OOM，仅适合验证检索效果。

---

## 六、RAGFlow 侧 Docker Compose 配置

```yaml
# /opt/ragflow/docker/docker-compose.yml（基于官方 v0.25.6 调整）
services:
  ragflow-server:
    image: registry.cn-hangzhou.aliyuncs.com/infiniflow/ragflow:v0.25.6-slim
    container_name: ragflow-server
    ports:
      - "10.0.2.10:9380:9380"        # 仅绑定内网 IP，不暴露公网
      - "10.0.2.10:80:80"
    environment:
      - SVR_HTTP_PORT=9380
      - MYSQL_HOST=mysql
      - MYSQL_PORT=3306
      - REDIS_HOST=redis
      - REDIS_PORT=6380               # 与 Fischer Redis 端口隔离
      - DOC_ENGINE=infinity            # 使用 Infinity 替代 ES
      - MINIO_HOST=minio:9000
    volumes:
      - /data/ragflow/ragflow-logs:/ragflow/logs
      - /data/ragflow/ragflow-data:/ragflow/data
    depends_on:
      - mysql
      - redis
      - minio
      - infinity
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 8G

  infinity:
    image: infiniflow/infinity:v0.6.0
    container_name: ragflow-infinity
    volumes:
      - /data/ragflow/infinity-data:/infinity/data
    deploy:
      resources:
        limits:
          memory: 4G

  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
      - MYSQL_DATABASE=ragflow
    volumes:
      - /data/ragflow/mysql-data:/var/lib/mysql
    deploy:
      resources:
        limits:
          memory: 2G

  redis:
    image: redis:7-alpine
    command: redis-server --port 6380 --maxmemory 1gb --maxmemory-policy allkeys-lru
    volumes:
      - /data/ragflow/redis-data:/data
    deploy:
      resources:
        limits:
          memory: 2G

  minio:
    image: minio/minio:latest
    command: server /data --console-address ":9001"
    environment:
      - MINIO_ROOT_USER=${MINIO_ROOT_USER}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
    volumes:
      - /data/ragflow/minio-data:/data
    deploy:
      resources:
        limits:
          memory: 1G
```

### 系统级配置（必做）

```bash
# 1. 内核参数（ES 必须，Infinity 建议也设置）
sudo sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf

# 2. 创建数据目录
sudo mkdir -p /data/ragflow/{infinity-data,mysql-data,redis-data,minio-data,ragflow-data,ragflow-logs}
sudo chown -R 1000:1000 /data/ragflow

# 3. Docker 镜像加速（阿里云容器镜像服务）
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<EOF
{
  "registry-mirrors": ["https://your-acs-mirror.mirror.aliyuncs.com"]
}
EOF
sudo systemctl restart docker
```

---

## 七、Fischer 侧 agentkit.yaml 配置

在现有 `agentkit.yaml` 中新增 memory 段：

```yaml
# 在现有 agentkit.yaml 末尾追加
memory:
  semantic:
    enabled: true
    adapter: "ragflow"                    # 新增 adapter 类型标识
    base_url: "http://10.0.2.10:9380"     # RAGFlow ECS 内网 IP
    api_key: "${RAGFLOW_API_KEY}"         # 从环境变量读取
    timeout: 30
    knowledge_base_ids:                   # RAGFlow dataset IDs
      - "dataset_industry_kb"
      - "dataset_enterprise_kb"
    # RAGFlow 检索参数
    retrieval:
      similarity_threshold: 0.2           # 低于此分数不返回
      vector_similarity_weight: 0.3       # 向量权重 (0-1)
      top_k: 10                           # 单次召回数
      rerank_id: "BAAI/bge-reranker-v2-m3"  # 可选 rerank 模型
    # 异步 ingest 配置
    ingest:
      mode: "async"                       # async | sync
      poll_interval: 5                    # 轮询间隔(秒)
      poll_timeout: 600                   # 最大等待(秒)
    # 健康检查
    health_check:
      interval: 60                        # 检查间隔(秒)
      fail_threshold: 3                   # 连续失败 N 次熔断
```

### 环境变量（Fischer ECS 的 .env）

```bash
# RAGFlow API Key（在 RAGFlow Web UI > 设置 > API Key 生成）
RAGFLOW_API_KEY=ragflow-xxxxxxxxxxxxxxxxxxxxxxxx

# 可选：embedding 模型走阿里云百炼
DASHSCOPE_API_KEY=sk-xxxxxxxxxxxx
```

---

## 八、阿里云网络与安全配置

### VPC 安全组规则

**RAGFlow ECS 安全组**（仅允许 Fischer 内网访问）：

| 方向 | 协议 | 端口 | 源/目标 | 用途 |
|------|------|------|---------|------|
| 入 | TCP | 9380 | 10.0.1.10/32 (Fischer) | RAGFlow API |
| 入 | TCP | 80 | 10.0.1.10/32 (Fischer) | RAGFlow Web（可选） |
| 入 | TCP | 22 | 管理跳板机 IP | SSH 运维 |
| 出 | TCP | 443 | 0.0.0.0/0 | 拉取镜像、调用外部 LLM |
| 入 | TCP | * | 0.0.0.0/0 | **拒绝**（默认） |

### API Key 安全

RAGFlow API Key 通过阿里云 KMS 加密存储，运行时解密注入：

```bash
# 加密 API Key 到 KMS
aliyun kms Encrypt \
  --KeyId key-ragflow \
  --Plaintext "$(echo -n 'ragflow-xxx' | base64)"

# Fischer 启动脚本中解密
export RAGFLOW_API_KEY=$(aliyun kms Decrypt \
  --CiphertextBlob "encrypted-blob" \
  --query Plaintext | base64 -d)
```

---

## 九、可选阿里云托管服务替代

| RAGFlow 组件 | 阿里云替代 | 优势 | 成本 |
|--------------|-----------|------|------|
| Elasticsearch | 阿里云 ES | 免运维、自动备份、监控 | ~¥800/月（2核4G） |
| MySQL | RDS MySQL | 高可用、自动备份 | ~¥200/月（1核2G） |
| Redis | Tair/Redis 实例 | 免运维、持久化 | ~¥150/月（1G） |
| MinIO（文档存储） | OSS | 11个9 持久性、低成本 | ~¥0.12/GB/月 |
| 服务器 | ACK（K8s） | 弹性伸缩、滚动升级 | 节点费 + 管理费 |

### 成本对比

| 方案 | 月费 | 适用场景 |
|------|------|---------|
| 全自管 ECS（8c32g + Infinity + slim） | ~¥1,050 | 推荐起步 |
| ECS + 托管服务混合 | ~¥2,062 | 免运维需求 |
| 经济型 POC（4c16g） | ~¥500 | 仅验证 |

---

## 十、实施步骤

1. **POC 验证**：用 `docker compose` 起一个 RAGFlow slim + Infinity 实例，上传 1 个 PDF，调用 `/api/v1/retrieval` 验证检索效果
2. **实现 RAGFlowAdapter**：参考 `generic_http.py` 模式，重点处理异步解析和字段映射
3. **配置集成**：扩展 `agentkit.yaml` schema 和 SemanticMemory 初始化逻辑
4. **单元测试**：参考现有适配器测试，mock RAGFlow API 响应
5. **集成测试**：验证 RAGFlow + LocalRAGService 多源检索聚合

### 部署 Checklist

- [ ] RAGFlow ECS 创建并加入与 Fischer 相同的 VPC
- [ ] 安全组仅放行 Fischer 内网 IP 到 9380 端口
- [ ] `vm.max_map_count=262144` 永久生效
- [ ] 数据盘挂载到 `/data/ragflow/` 并设置正确权限
- [ ] RAGFlow docker-compose 启动，`docker logs -f ragflow-server` 显示就绪
- [ ] RAGFlow Web UI 创建 dataset，记录 dataset_id
- [ ] 生成 RAGFlow API Key，通过 KMS 加密存储
- [ ] Fischer `.env` 配置 `RAGFLOW_API_KEY`
- [ ] Fischer `agentkit.yaml` 配置 memory.semantic 段
- [ ] 从 Fischer ECS 执行 `curl http://10.0.2.10:9380/api/v1/datasets` 验证连通
- [ ] 上传测试文档，验证 ingest 异步解析完成
- [ ] 执行检索测试，验证 QueryResult 字段映射正确

---

## 十一、核心判断

RAGFlow 的价值在于 **DeepDoc 深度文档解析**这一项 Fischer 现有栈（pgvector + TextChunker）明显薄弱的能力。

- **如果业务场景涉及大量 PDF/扫描件/复杂表格** → 引入值得
- **若仅处理纯文本** → 现有的 `LocalRAGService` 已够用，不必承担 RAGFlow 的运维复杂度

### 关键决策点

1. RAGFlow 视为**完全独立的外部服务**，通过 HTTP API 松耦合，不共享基础设施
2. embedding 模型治理统一到 Fischer 的 LLM Gateway
3. 起步用全自管 ECS（8c32g + Infinity + slim，~¥1,050/月），验证业务价值后再评估是否迁移到托管服务
4. ECS 规格选 g7.2xlarge 是经过 RAGFlow 全栈资源分配计算的安全值，不建议低于 32GB RAM（生产环境）

---

## 参考资料

- RAGFlow 官网: https://ragflow.org/
- RAGFlow GitHub: https://github.com/infiniflow/ragflow
- RAGFlow HTTP API: https://ragflow.io/docs/dev/http_api_reference
- RAGFlow Python API: https://ragflow.io/docs/dev/python_api_reference
- RAGFlow 发布说明: https://ragflow.io/docs/release_notes
- Infinity 数据库: https://github.com/infiniflow/infinity
- RAGFlow 系统架构: https://deepwiki.com/infiniflow/ragflow/3-system-architecture
