# PRD_需求文档_问题排查助手流式返回优化

## 基本信息

| 项目 | 内容 |
|------|------|
| 文档类型 | 需求文档 |
| 创建日期 | 2026-07-12 |
| 负责人 | 研发组 |
| 优先级 | 高 |
| 状态 | 规划中 |
| 关联文档 | [PRD_需求文档_问题知识库智能排查助手](./PRD_需求文档_问题知识库智能排查助手.md) |

---

## 一、背景与目标

### 1.1 当前问题

| 问题 | 说明 |
|------|------|
| **响应时间长** | AI 分析阶段需要 20-50 秒，用户需等待完整响应才能看到结果 |
| **用户体验差** | 长时间无反馈，用户不知道系统是否在工作 |
| **易导致重复提交** | 用户等不及可能多次点击"帮我排查"按钮 |

### 1.2 目标

实现 **SSE（Server-Sent Events）流式返回**，让 AI 边生成边推送：
1. 用户点击后 2-3 秒即可看到第一个字
2. 内容逐步显示，类似 ChatGPT 的打字效果
3. 用户感知响应更快，无需等待完整响应

### 1.3 不变内容

- **API 调用费用不变**：流式返回只是改变数据传输方式，Token 用量和费用相同
- **功能逻辑不变**：搜索匹配 + AI 分析 + 安全过滤的流程不变
- **安全过滤不变**：流式返回的内容仍需经过安全过滤器

---

## 二、核心场景

### 优化前后对比

#### 优化前（普通请求）

```
用户点击"帮我排查"
       ↓
等待 20-50 秒（页面无变化）
       ↓
一次性返回完整结果
```

**问题**：用户长时间看不到反馈，体验差。

#### 优化后（流式返回）

```
用户点击"帮我排查"
       ↓
等待 2-3 秒
       ↓
第一个字开始显示（"### 📋 匹配到的历史案例..."）
       ↓
内容逐步显示（打字效果）
       ↓
每生成一段，前端追加显示
       ↓
20-50 秒后，完整结果展示完毕
```

**优势**：用户感知响应快，有即时反馈。

---

## 三、技术方案

### 3.1 SSE（Server-Sent Events）原理

SSE 是一种 HTTP 长连接技术，服务器可以主动向客户端推送数据：

```
HTTP 请求：
GET /api/analyze/stream HTTP/1.1
Accept: text/event-stream

HTTP 响应：
Content-Type: text/event-stream

data: {"type": "start", "message": "开始分析..."}

data: {"type": "chunk", "content": "### 📋 匹配到的历史案例"}

data: {"type": "chunk", "content": "\n\n1. 厦门银行-门口屏MQTT绑定失败"}

data: {"type": "done", "message": "分析完成"}
```

### 3.2 实现架构

```
┌─────────────────────────────────────────────────────────┐
│  前端 (index.html)                                       │
│  ┌─────────────────────────────────────────────────────┐│
│  │  EventSource 连接                                   ││
│  │  const source = new EventSource('/api/analyze/...') ││
│  │                                                     ││
│  │  source.onmessage = (event) => {                   ││
│  │      const data = JSON.parse(event.data)           ││
│  │      if (data.type === 'chunk') {                  ││
│  │          appendContent(data.content)  // 追加显示  ││
│  │      }                                             ││
│  │  }                                                 ││
│  └─────────────────────────────────────────────────────┘│
└─────────────────────────┬───────────────────────────────┘
                          │ SSE 连接
                          ▼
┌─────────────────────────────────────────────────────────┐
│  后端 (server.py)                                        │
│  ┌─────────────────────────────────────────────────────┐│
│  │  @app.route('/api/analyze/stream')                  ││
│  │  def analyze_stream():                              ││
│  │      def generate():                                ││
│  │          yield 'data: {"type": "start"}\n\n'        ││
│  │          for chunk in claude_stream():              ││
│  │              yield f'data: {chunk}\n\n'             ││
│  │          yield 'data: {"type": "done"}\n\n'         ││
│  │      return Response(generate(), mimetype='text/...')│
│  └─────────────────────────────────────────────────────┘│
└─────────────────────────┬───────────────────────────────┘
                          │ 流式 API 调用
                          ▼
┌─────────────────────────────────────────────────────────┐
│  Claude API                                              │
│  支持 stream=True 参数，返回生成器                        │
└─────────────────────────────────────────────────────────┘
```

### 3.3 安全过滤的处理

流式返回的安全过滤需要在**流结束后**统一处理：

```
方案一（推荐）：先缓存，过滤后再流式输出
  1. 接收完整 AI 响应
  2. 安全过滤
  3. 流式推送给前端

方案二：边生成边过滤（复杂）
  1. AI 生成一段
  2. 检测是否包含危险命令
  3. 安全则推送，危险则跳过
  4. 问题：可能打断语义完整性
```

**选择方案一**，理由：
- 保证过滤完整性
- 实现简单
- 用户体验影响小（过滤通常很快，<1 秒）

---

## 四、功能需求

### 4.1 新增接口

| 接口 | 方法 | 功能 |
|------|------|------|
| `/api/analyze/stream` | GET | 流式返回 AI 分析结果 |

### 4.2 接口参数

通过 URL 参数传递（SSE 只支持 GET）：

```
GET /api/analyze/stream?project_name=厦门银行&system_type=标准版预定2.0&apk_product=门口屏5.0&query=门口屏绑定失败
```

### 4.3 返回格式

```json
// 开始标记
data: {"type": "start", "message": "正在分析..."}

// 内容片段
data: {"type": "chunk", "content": "### 📋 匹配到的历史案例"}

data: {"type": "chunk", "content": "\n\n1. 厦门银行-门口屏MQTT绑定失败（相似度：92%）"}

// 匹配案例（单独推送，方便前端优先显示）
data: {"type": "matched_cases", "cases": [...]}

// 完成标记
data: {"type": "done", "api_time": 45.2}

// 错误标记
data: {"type": "error", "message": "API 调用失败"}
```

### 4.4 前端交互

| 阶段 | 显示内容 |
|------|----------|
| 点击"帮我排查" | 显示 loading 动画 |
| 收到 `start` | 显示"正在分析..." |
| 收到 `matched_cases` | 显示匹配案例卡片 |
| 收到 `chunk` | 追加显示内容（打字效果） |
| 收到 `done` | 显示"分析完成"，启用"提交入库"按钮 |
| 收到 `error` | 显示错误提示 |

---

## 五、验收标准

### 功能验收

- [ ] 点击"帮我排查"后 3 秒内开始显示内容
- [ ] 内容以打字效果逐步显示
- [ ] 匹配案例优先显示（在 AI 内容之前）
- [ ] 流式返回完成后，"提交入库"按钮可用
- [ ] API 调用失败时显示错误提示
- [ ] 安全过滤仍然生效，危险命令被过滤

### 性能验收

- [ ] 首字显示时间 < 3 秒
- [ ] 流式返回总耗时与非流式相同（20-50 秒）
- [ ] 不增加 API 调用费用

### 兼容性验收

- [ ] 保留原 `/api/analyze` 接口（非流式），保证兼容性
- [ ] 前端支持降级：SSE 不可用时回退到普通请求

---

## 六、非功能需求

| 需求 | 说明 |
|------|------|
| 向后兼容 | 原接口保留，不影响现有调用方 |
| 错误处理 | SSE 连接中断时前端显示提示 |
| 超时处理 | 连接超时（>120 秒）时自动断开 |
| 并发支持 | 支持多个用户同时使用流式返回 |

---

## 七、影响范围

### 7.1 涉及现有文件

| 文件 | 变更类型 | 说明 |
|------|----------|------|
| `code/web/server.py` | 更新 | 新增 `/api/analyze/stream` 接口 |
| `code/web/templates/index.html` | 更新 | 前端改用 EventSource 接收流式数据 |

### 7.2 新增文件

无

---

## 八、风险与应对

| 风险 | 应对 |
|------|------|
| Claude API 不支持流式 | 检查 API 文档，确认 stream 参数可用 |
| SSE 连接中断 | 前端实现重连机制，或降级到普通请求 |
| 浏览器兼容性 | IE 不支持 EventSource，但目标用户使用 Chrome/Edge，无影响 |
| 过滤延迟 | 先缓存完整响应，过滤后再流式推送 |

---

## 九、优化功能回填

| 优化项 | 状态 | 备注 |
|--------|------|------|
| 流式返回实现 | [ ] 待开发 | |
| 前端 EventSource 集成 | [ ] 待开发 | |
| 安全过滤适配 | [ ] 待开发 | |
| 错误处理 | [ ] 待开发 | |
| 兼容性测试 | [ ] 待测试 | |

---

## 变更记录

| 日期 | 版本 | 变更内容 | 变更人 |
|------|------|----------|--------|
| 2026-07-12 | v1.0 | 初始版本 | Claude |
