提交 c6287b3b authored 作者: 陈泽健's avatar 陈泽健

docs: PRD 文档按模块归档到子目录

- Docs/需求文档/问题处理助手/ — 排查助手全部 PRD + 技术文档(29 个)
- Docs/需求文档/服务管理/ — 平台化改造 + 返回首页改造 PRD(4 个)
- Docs/需求文档/服务监测/ — 预留,后续服务监测相关文档归入
- Docs/离线部署方案/ — 离线部署 PRD 文档(2 个)
Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
上级 d3468c4b
# PRD 计划执行文档 — 离线部署方案
> 版本:1.0 | 日期:2026-07-14 | 分支:troubleshoot-ai-assistant
---
## 执行步骤总览
| 步骤 | 内容 | 优先级 |
|------|------|--------|
| 1 | config.json 新增 offline_mode 配置 | P0 |
| 2 | container.py 加载 offline_mode 默认值 | P0 |
| 3 | ai_service.py 新增离线模式分支 | P0 |
| 4 | routes/troubleshoot.py 适配离线返回格式 | P0 |
| 5 | index.html 前端适配离线模式展示 | P0 |
| 6 | /api/health 暴露 offline_mode | P1 |
| 7 | 单元测试补充离线模式用例 | P1 |
| 8 | 离线部署文档 | P2 |
---
### 步骤 1:config.json 新增配置
**文件**`skill/code/web/config.json`
```json
{
"offline_mode": false,
...
}
```
---
### 步骤 2:container.py 加载默认值
**文件**`skill/code/web/container.py`
`load_config()` 中补充 `offline_mode` 默认值 `False`,与 `embedding_enabled` 一致。
---
### 步骤 3:ai_service.py 新增离线模式分支
**文件**`skill/code/web/services/ai_service.py`
新增函数:
```python
def build_offline_analysis(matched_cases, query):
"""离线模式:从匹配案例提取排查建议(不调 AI)"""
# 1. 提取 Top N 案例的解决方案字段
# 2. 拼接成结构化排查建议
# 3. 返回格式与在线模式 analysis 结构兼容
return {
"summary": "基于知识库匹配的排查建议",
"possible_causes": [...], # 从匹配案例提取
"steps": [...], # 从匹配案例提取
"offline": True,
}
```
**注意**:不修改 `call_claude_api` / `call_claude_api_stream` 签名。
---
### 步骤 4:routes/troubleshoot.py 适配离线
**文件**`skill/code/web/routes/troubleshoot.py`
`/api/troubleshoot``/api/analyze_stream` 中加分支:
```python
offline = container.get_config().get('offline_mode', False)
if offline:
# 离线模式:跳过 AI,直接格式化搜索结果
analysis = build_offline_analysis(matched_cases, query)
return success_response(data={
'analysis': analysis,
'cases': matched_cases,
'offline': True,
})
else:
# 在线模式:原有逻辑
...
```
---
### 步骤 5:index.html 前端适配
**文件**`skill/code/web/templates/index.html`
适配点:
1. 响应中若 `offline: true`
- 标题显示"📋 相关案例参考(离线模式)"
- 不显示流式输出动画,直接渲染结果
- 顶部加横幅:"当前为离线模式,结果基于知识库匹配"
2. 结果区域渲染 `analysis``cases`(结构兼容)
---
### 步骤 6:/api/health 暴露 offline_mode
**文件**`skill/code/web/routes/troubleshoot.py``health_check`
```python
'offline_mode': container.get_config().get('offline_mode', False),
```
---
### 步骤 7:单元测试
**文件**`skill/code/tests/test_routes_troubleshoot.py`
补充用例:
- `test_troubleshoot_offline_mode` — offline_mode=True 时返回 offline 标记,不调 AI
- `test_troubleshoot_online_mode` — offline_mode=False 时调 AI(原有用例)
---
### 步骤 8:离线部署文档
**文件**`ARCHITECTURE.md` 补充"离线部署"章节
内容:
- 离线环境前置条件
- config.json 配置说明
- 向量文件离线生成方法(在线生成后拷贝)
- 服务管理/服务监测离线部署说明
---
## 变更文件清单
| 文件 | 操作 | 说明 |
|------|------|------|
| `skill/code/web/config.json` | 修改 | 新增 offline_mode |
| `skill/code/web/container.py` | 修改 | 加载 offline_mode 默认值 |
| `skill/code/web/services/ai_service.py` | 修改 | 新增 build_offline_analysis |
| `skill/code/web/routes/troubleshoot.py` | 修改 | 离线模式分支 + health |
| `skill/code/web/templates/index.html` | 修改 | 离线模式前端展示 |
| `skill/code/tests/test_routes_troubleshoot.py` | 修改 | 补充离线用例 |
| `ARCHITECTURE.md` | 修改 | 离线部署章节 |
---
## 验证
1. `cd skill/code && python -m pytest -v` — 全绿
2. 在线模式验证:`offline_mode: false`,排查流程调 AI 正常
3. 离线模式验证:`offline_mode: true`,排查返回搜索结果 + offline 标记,无 AI 调用
4. `/api/health` 返回 `offline_mode` 字段
5. 部署到 5.60,分别验证两种模式
---
## 风险与注意
- **向量搜索**:离线环境无法调 Embedding API 生成查询向量。若已预生成 `搜索向量.json`,可在离线环境使用(查询向量仍需实时生成,离线会降级 TF-IDF)。建议离线环境 `embedding_enabled: false`
- **缓存一致性**:离线模式结果也可缓存,cache_manager 逻辑不变。
- **降级链路**:在线模式下 API 调用失败时,可考虑自动降级到离线模式(本期不做,配置开关即可)。
# PRD 需求文档 — 离线部署方案
> 版本:1.0 | 日期:2026-07-14 | 分支:troubleshoot-ai-assistant
---
## 1. 需求背景
运行维护平台部署到客户现场服务器时,通常处于内网/离线环境,无法访问外部 AI API(Claude)。当前问题排查助手依赖 Claude API 进行 AI 分析,在离线环境下不可用。
需要为平台提供离线部署能力,使三个核心模块在内网环境下均可正常使用。
---
## 2. 现状分析
| 模块 | 外部依赖 | 离线可用性 |
|------|----------|-----------|
| 问题排查助手 | Claude API(AI 分析)+ TF-IDF 搜索(本地) | ❌ AI 不可用,搜索可用 |
| 服务管理 | 无(占位) | ✅ |
| 服务监测 | SSH 连接(局域网) | ✅ |
| 平台首页 / 认证 | 无(Flask 本地) | ✅ |
**核心卡点**:问题排查助手的 AI 分析功能依赖外网 API。
---
## 3. 离线方案设计
### 3.1 问题排查助手 — 离线 Q&A 模式
**原理**:跳过 Claude API 调用,直接将 TF-IDF 搜索匹配结果作为排查建议返回。
**在线 vs 离线流程对比**
```
【在线模式】
用户提问 → TF-IDF 搜索匹配 → 匹配结果 + 提问 → Claude API → AI 分析报告
【离线模式】
用户提问 → TF-IDF 搜索匹配 → 匹配结果格式化 → 直接返回排查建议
```
**离线模式返回内容**
| 区域 | 在线模式 | 离线模式 |
|------|---------|---------|
| 问题概述 | AI 生成 | 从匹配结果中提取摘要 |
| 可能原因 | AI 生成 | 列出匹配案例的常见原因 |
| 排查步骤 | AI 生成 | 列出匹配案例的历史解决步骤 |
| 相关案例 | 搜索结果 | 搜索结果(与在线一致) |
**前端展示差异**
- 离线模式下标题显示"📋 相关案例参考"而非"🤖 AI 分析结果"
- 离线模式下不显示流式输出动画,直接渲染搜索结果
- 离线模式下加提示横幅:"当前为离线模式,结果基于知识库匹配,无 AI 分析"
### 3.2 配置开关
**文件**`config.json`
新增配置项:
```json
{
"offline_mode": false
}
```
- `offline_mode: false`(默认)— 在线模式,调 Claude API
- `offline_mode: true` — 离线模式,跳过 API,直接返回搜索结果
**读取方式**:通过 `container.get_config()` 读取,与现有 `embedding_enabled` 等配置一致。
### 3.3 API 行为变更
**`POST /api/troubleshoot`**
| 场景 | 在线模式 | 离线模式 |
|------|---------|---------|
| 搜索 | TF-IDF / 向量搜索 | TF-IDF 搜索(向量在离线环境也无法生成,降级 TF-IDF) |
| AI 分析 | 调 Claude API | 跳过,直接格式化搜索结果 |
| 返回格式 | `{analysis, cases}` | `{analysis: null, cases, offline: true}` |
| 耗时 | 20-60 秒 | <1 秒 |
**`POST /api/analyze_stream`**
离线模式下不调用流式 API,直接返回完整 JSON 响应(非 SSE)。
### 3.4 /api/health 响应
新增 `offline_mode` 字段:
```json
{
"status": "ok",
"version": "1.4.0",
"offline_mode": true,
...
}
```
---
## 4. 非功能需求
| 项目 | 要求 |
|------|------|
| 部署无感切换 | 只需改 config.json 即可切换在线/离线模式,无需改代码 |
| 搜索质量 | 离线模式下搜索逻辑不变,TF-IDF 完全本地运行 |
| 响应速度 | 离线模式下排查响应 <1 秒(无 API 调用) |
| 向量搜索 | 离线环境下无法调 Embedding API 生成向量,自动降级 TF-IDF |
| 前端适配 | 离线模式结果展示需清晰标注"离线模式" |
---
## 5. 约束
- 离线模式下不提供 AI 总结和步骤建议,仅返回知识库匹配结果
- 离线模式不影响现有在线模式的行为(配置开关隔离)
- 不修改 `search_engine.py` 公开接口
- 向量预计算文件(`搜索向量.json`)可在在线环境预生成后拷贝到离线环境使用
---
## 6. 后续扩展(本期不做)
- **本地小模型推理**:部署 Ollama + 小参数模型,在离线环境提供轻量 AI 分析
- **预缓存 AI 回答**:对高频问题预生成 AI 回答,离线时查缓存
- **知识库离线导入**:支持 U 盘/离线文件导入新的 Q&A 记录
# PRD 计划执行文档 — 离线部署方案
> 版本:2.0 | 日期:2026-07-15 | 分支:troubleshoot-ai-assistant
---
## 执行步骤总览
| 步骤 | 内容 | 优先级 | 预估改动 |
|------|------|--------|----------|
| 1 | config.json 新增 `offline_mode` 配置 | P0 | 1 行 |
| 2 | container.py 加载 `offline_mode` 默认值 | P0 | 2 行 |
| 3 | ai_service.py 新增 `build_offline_analysis()` | P0 | ~60 行 |
| 4 | routes/troubleshoot.py 三处路由 + health 适配 | P0 | ~30 行 |
| 5 | index.html 前端离线适配 | P0 | ~40 行 |
| 6 | 单元测试补充离线模式用例 | P1 | ~30 行 |
| 7 | Dockerfile + docker-compose.yml | P1 | 新建 2 文件 |
| 8 | deploy 脚本适配容器化部署 | P2 | 修改 |
---
### 步骤 1:config.json 新增配置
**文件**`skill/code/web/config.json`
```json
{
"offline_mode": false,
...
}
```
---
### 步骤 2:container.py 加载默认值
**文件**`skill/code/web/container.py`
`load_config()` 的默认返回值中补充 `"offline_mode": False`
---
### 步骤 3:ai_service.py 新增离线分析函数
**文件**`skill/code/web/services/ai_service.py`
新增函数:
```python
def build_offline_analysis(query, matched_cases):
"""离线模式:从匹配案例构建排查建议(不调 AI)
参数:
query: 用户问题描述
matched_cases: SearchEngine.search() 返回的匹配案例列表
返回:
{
"mode": "offline",
"summary": "基于知识库匹配的排查参考",
"cases": [...], # 完整案例记录
"note": "当前为离线模式,结果基于历史知识库匹配"
}
"""
```
实现逻辑:
1. 遍历 `matched_cases`,从 `record` 中提取 `project``title``phenomenon``solution``file`
2. 按相似度降序排列
3. 生成离线排查建议文本(Markdown 格式,可直接渲染)
4. 返回结构化数据
**注意**:不修改 `call_claude_api` / `call_claude_api_stream` 签名。
---
### 步骤 4:routes/troubleshoot.py 适配离线
**文件**`skill/code/web/routes/troubleshoot.py`
三处路由加离线分支:
1. **`POST /api/troubleshoot`**(行 57-114):
```python
if container.get_config().get('offline_mode', False):
analysis = build_offline_analysis(query, matched_cases_data)
return jsonify({
'success': True,
'response': analysis['text'],
'matched_cases': format_matched_cases(matched_cases_data),
'offline': True,
})
# 否则走原有在线逻辑...
```
2. **`POST /api/analyze`**(行 150-):
同样加离线分支。
3. **`POST /api/analyze_stream`**
离线模式下不返回 SSE 流式,直接返回完整 JSON
4. **`GET /api/health`**
`'offline_mode': config.get('offline_mode', False)`
---
### 步骤 5:index.html 前端适配
**文件**`skill/code/web/templates/index.html`
适配点:
1. **响应解析**:检测 `data.offline === true`
2. **标题切换**
- 在线:`🤖 AI 分析结果`
- 离线:`📋 离线排查参考(基于知识库匹配)`
3. **横幅提示**:离线模式下在结果区顶部显示提示横幅
4. **流式输出**:离线模式下跳过 SSE 流式,直接渲染 JSON 响应
5. **案例展示**:离线模式下展示完整案例记录(标题 + 现象 + 解决方案 + 文件路径)
---
### 步骤 6:单元测试
**文件**`skill/code/tests/test_routes_troubleshoot.py`
补充用例:
- `test_troubleshoot_offline_mode` offline_mode=True 时返回 `offline: true`,不调 AI
- `test_troubleshoot_online_mode` offline_mode=False 时走原逻辑
- `test_health_offline_mode` health 接口返回 offline_mode 字段
**conftest.py**:可能需要加 fixture 注入 `offline_mode` 配置。
---
### 步骤 7:Dockerfile + docker-compose.yml
**新建文件**:项目根目录
**Dockerfile**
```dockerfile
FROM python:3.10-slim
WORKDIR /app
RUN pip install flask scikit-learn scipy numpy jieba gunicorn werkzeug paramiko
COPY skill/code/web/ /app/web/
COPY skill/code/SKILL.md /app/SKILL.md
COPY deploy/搜索索引.json /app/搜索索引.json
EXPOSE 8088
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8088", "--chdir", "/app/web", "server:app"]
```
**docker-compose.yml**:
```yaml
version: '3.8'
services:
troubleshoot:
build: .
ports:
- "8088:8088"
restart: always
volumes:
- ./config.json:/app/web/config.json:ro
- ./users.json:/app/web/users.json:ro
- ./logs:/app/logs
environment:
- PYTHONIOENCODING=utf-8
```
---
### 步骤 8:deploy 脚本适配容器化
**文件**`deploy/upload_to_server.py`
新增:
- Docker 镜像构建命令
- `docker save` 导出镜像
- 或直接 `docker compose up -d --build`
---
## 变更文件清单
| 文件 | 操作 | 说明 |
|------|------|------|
| `skill/code/web/config.json` | 修改 | 新增 `offline_mode: false` |
| `skill/code/web/container.py` | 修改 | `load_config` 默认值补 `offline_mode` |
| `skill/code/web/services/ai_service.py` | 修改 | 新增 `build_offline_analysis` |
| `skill/code/web/routes/troubleshoot.py` | 修改 | 三处路由 + health 离线分支 |
| `skill/code/web/templates/index.html` | 修改 | 离线模式前端展示 |
| `skill/code/tests/test_routes_troubleshoot.py` | 修改 | 离线用例 |
| `Dockerfile` | **新建** | 容器化构建文件 |
| `docker-compose.yml` | **新建** | 容器编排 |
---
## 验证
1. `cd skill/code && python -m pytest -v` — 全绿
2. 在线模式验证:`offline_mode: false`,排查流程调 AI 正常
3. 离线模式验证:`offline_mode: true`,排查返回搜索结果 + `offline: true`,无 AI 调用
4. `/api/health` 返回 `offline_mode` 字段
5. Docker 构建:`docker build -t troubleshoot .` 成功
6. Docker 运行:`docker run -p 8088:8088 troubleshoot`,访问正常
\ No newline at end of file
# PRD 需求文档 — 离线部署方案
> 版本:2.0 | 日期:2026-07-15 | 分支:troubleshoot-ai-assistant
---
## 1. 需求背景
运行维护平台部署到客户现场服务器时,通常处于**内网/离线环境**,无法访问外部 AI API(Claude)。当前问题排查助手依赖 Claude API 进行 AI 分析,在离线环境下不可用。
同时,现场部署采用**容器化(Docker)**方式,不直接部署在宿主机上。三个模块(问题排查助手、服务管理、服务监测)需要在容器化离线环境中稳定运行。
---
## 2. 现状分析
| 模块 | 外部依赖 | 离线可用性 | 备注 |
|------|----------|-----------|------|
| 问题排查助手 | Claude API + TF-IDF 搜索 | ❌ AI 不可用 | 搜索可用,AI 分析不可用 |
| 服务管理 | 无(占位) | ✅ | 后续走 SSH 连接内部系统 |
| 服务监测 | SSH(局域网) | ✅ | SSH 连接目标服务器 |
| 平台首页 / 认证 | 无(Flask 本地) | ✅ | — |
**核心卡点**:问题排查助手的 AI 分析功能依赖外网 API。
---
## 3. 离线方案设计
### 3.1 问题排查助手 — 离线 Q&A 模式
**原理**:跳过 Claude API 调用,直接将 TF-IDF 搜索匹配结果作为排查建议返回。
**流程对比**
```
【在线模式】
用户提问 → TF-IDF 搜索 → 匹配结果 + 提问 → Claude API → AI 分析报告
【离线模式】
用户提问 → TF-IDF 搜索 → 匹配结果格式化 → 直接返回离线排查建议
```
**离线模式返回内容**
| 区域 | 在线模式 | 离线模式 |
|------|---------|---------|
| 标题 | 🤖 AI 分析结果 | 📋 离线排查参考(基于知识库匹配) |
| 匹配案例列表 | 简要列表 | 完整记录(标题 + 现象 + 解决方案 + 相似度) |
| AI 分析 | Claude 生成 | 无(标注"离线模式,无 AI 分析") |
| 响应时间 | 20-60 秒 | <1 秒 |
| 横幅提示 | 无 | "当前为离线模式,结果基于历史知识库匹配" |
**匹配案例展示格式(详细版)**
```
案例1(相似度:92%)
项目:厦门银行
标题:门口屏 MQTT 绑定失败
现象:门口屏绑定时报 MQTT 连接错误,无法完成绑定
解决方案:升级门口屏到 5.0+ 版本,使用默认 MQTT 凭据
参考文件:record_001.md
案例2(相似度:75%)
项目:展厅
标题:门口屏不显示会议信息
现象:会议开始后门口屏不显示会议主题和参会人
解决方案:检查 EMQX 容器状态,确认 docker ps -a | grep uemqx 有输出
参考文件:record_002.md
```
### 3.2 配置开关
**文件**`config.json`
```json
{
"offline_mode": false
}
```
- `offline_mode: false`(默认)— 在线模式,调 Claude API
- `offline_mode: true` — 离线模式,跳过 API,直接返回搜索结果
### 3.3 部署方式 — 容器化
现场服务器采用 Docker 容器化部署,不直接部署在宿主机:
```
宿主机
├── Docker
│ ├── troubleshooot 容器(运行维护平台)
│ │ ├── Flask/Gunicorn + Python
│ │ ├── 知识库(357 条记录)
│ │ └── 配置文件
│ └── 其他服务容器
```
**Dockerfile 要点**
- 基础镜像:`python:3.10-slim`
- 依赖:Flask, scikit-learn, scipy, numpy, jieba(TF-IDF 搜索引擎所需)
- **不需要** requests 的 API 调用(离线模式),但保留以便在线模式切换
- 端口:8088
- 启动命令:`gunicorn -w 4 -b 0.0.0.0:8088 server:app`(生产)或 `python server.py`(调试)
**容器化优势**
- 环境一致性:镜像打包后现场直接 `docker run`,无需手动安装 Python 依赖
- 进程守护:`docker restart policy = always`,容器挂了自动重启
- 资源隔离:不污染宿主机环境
### 3.4 API 行为变更
**`POST /api/troubleshoot`**
| 场景 | 在线模式 | 离线模式 |
|------|---------|---------|
| 搜索 | TF-IDF | TF-IDF |
| AI 分析 | 调 Claude API | 跳过,格式化搜索结果 |
| 返回 | `{analysis, cases}` | `{analysis: null, cases, offline: true}` |
| 耗时 | 20-60 秒 | <1 秒 |
**`POST /api/analyze`**:同上。
**`POST /api/analyze_stream`**
离线模式下不调用流式 API,直接返回完整 JSON(非 SSE),响应格式:
```json
{
"success": true,
"offline": true,
"analysis": null,
"matched_cases": [...]
}
```
### 3.5 /api/health 响应
新增 `offline_mode` 字段:
```json
{
"status": "ok",
"version": "1.4.0",
"offline_mode": true
}
```
---
## 4. 容器化部署方案
### 4.1 Dockerfile
```dockerfile
FROM python:3.10-slim
WORKDIR /app
# 安装依赖
RUN pip install flask scikit-learn scipy numpy jieba gunicorn werkzeug
# 拷贝代码
COPY skill/code/web/ /app/web/
COPY skill/code/SKILL.md /app/SKILL.md
# 端口
EXPOSE 8088
# 启动
CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8088", "server:app"]
```
### 4.2 docker-compose.yml(推荐)
```yaml
version: '3.8'
services:
troubleshoot:
build: .
ports:
- "8088:8088"
restart: always
volumes:
- ./config.json:/app/web/config.json:ro
- ./users.json:/app/web/users.json:ro
- ./records:/app/web/records:ro
- ./logs:/app/logs
environment:
- PYTHONIOENCODING=utf-8
- SECRET_KEY=${SECRET_KEY}
```
### 4.3 现场部署流程
```
# 1. 在线环境构建镜像
docker build -t troubleshoot:latest .
# 2. 导出镜像
docker save troubleshoot:latest | gzip > troubleshoot.tar.gz
# 3. 拷贝到现场服务器(U盘/内网传输)
scp troubleshoot.tar.gz user@field-server:/opt/
# 4. 现场服务器加载并启动
docker load < troubleshoot.tar.gz
docker compose up -d
```
---
## 5. 非功能需求
| 项目 | 要求 |
|------|------|
| 配置切换 | 改 config.json 的 `offline_mode` 即可,无需改代码 |
| 搜索质量 | 离线模式下 TF-IDF 搜索逻辑不变,纯本地运行 |
| 响应速度 | 离线模式排查 <1 秒(无 API 调用) |
| 前端适配 | 离线模式结果展示清晰标注"离线模式" |
| 容器化 | 提供 Dockerfile + docker-compose.yml |
| 进程守护 | Docker restart policy always + gunicorn 多 worker |
| 日志持久化 | 日志挂载到宿主机 volume |
---
## 6. 约束
- 离线模式下不提供 AI 分析和步骤建议,仅返回知识库匹配结果
- 离线模式不影响现有在线模式行为(配置开关隔离)
- 不修改 `search_engine.py` / `safety_filter.py` / `cache_manager.py` 公开接口
- Docker 镜像构建在在线环境完成,现场只需 `docker load` + `docker run`
---
## 7. 后续扩展(本期不做)
- **本地小模型推理**:Docker 内嵌 Ollama + 小参数模型
- **知识库离线导入**:支持通过平台界面上传离线 Q&A 文档
- **配置热更新**:修改 config.json 后无需重启容器
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论