# 阶段四记录：RAG 和外部服务接入骨架

日期：2026-07-06

## 本次目标

把阶段四从纯 mock 推进到可替换的外部服务接入骨架：飞书检索、模型调用、外部异常、失败日志和配置开关都要有明确边界。

## 已完成

- 新增统一外部服务异常 `ExternalServiceError`。
- 拆出 `FeishuKnowledgeService`：
  - 知识库检索不再使用 mock 文档。
  - 优先通过 `FEISHU_SEARCH_URL` 调用远端检索适配服务。
  - 未配置搜索接口或搜索接口异常时，回退为飞书直读。
  - 调用搜索接口时必须传入当前已开放知识库的 `spaceId/nodeId` 范围，搜索服务只能在这些节点内检索，不允许全局知识库搜索。
  - 支持 `FEISHU_TIMEOUT_SECONDS` 和 `FEISHU_RETRY_COUNT`。
  - 远端返回统一解析为 `RetrievedChunk`。
- 增强 `ModelClientService`：
  - 默认 `MOCK_MODEL_ENABLED=true`，继续使用 mock 模型。
  - 关闭 mock 且后台存在启用模型时，按 OpenAI 兼容 `chat/completions` 非流式格式调用。
  - 支持读取模型表中的 `api_url`、`api_key`、`model_name`、`temperature`、`max_token` 和 `timeout_second`。
- 增强 AI 请求日志：
  - 成功时记录完整请求日志。
  - 飞书或模型异常时记录失败日志。
- 增强 `/chat/completions`：
  - 外部服务异常会返回明确错误。
  - 失败时不消耗用户每日额度。

## 当前配置

```env
MOCK_MODEL_ENABLED=true
FEISHU_SEARCH_URL=
FEISHU_TIMEOUT_SECONDS=20
FEISHU_RETRY_COUNT=2
```

## 当前边界

- 搜索接口是优先方案，但必须支持按知识库节点范围检索。
- 飞书直读是搜索接口未配置或异常时的兜底方案。
- 不再允许使用本地 mock 知识库片段作为问答依据。
- 真实模型当前先支持 OpenAI 兼容非流式响应；用户端仍通过后端 SSE 分块输出。
- 模型原生流式透传和后端真实停止生成需要在模型供应商和 SDK/协议确认后继续补。

## 阶段四判断

阶段四的工程边界已经建立，可以支持后续真实接入：

1. 开放知识库过滤在检索前执行。
2. 飞书检索 provider 可替换。
3. Prompt 组装已独立。
4. 模型 provider 可替换。
5. 成功和失败 AI 请求日志都有记录路径。
6. 无命中兜底规则已生效。
