e4e2de47bb
提交 OTP/RBAC/Tier0/Tier1/P0+P2 测试报告、方案A E2E 验证、知识库迭代设计(PRD/mermaid/html 原型)、项目状态看板更新; 根配置 docker-compose.yml/mkdocs.yml。
1148 lines
54 KiB
Markdown
1148 lines
54 KiB
Markdown
# 增量架构设计:知识库自动迭代修复 + 生产痛点缓解
|
||
|
||
> 文档版本: v1.0
|
||
> 日期: 2026-07-07
|
||
> 架构师: 高见远(software-architect)
|
||
> 关联文档: 增量PRD-知识库迭代与痛点缓解-20260707.md / 主PRD-v1.2 §11.1 D1-D9 / 复杂场景重构技术方案 v1.1
|
||
> 设计理念: 对齐 TeliChat 白盒图模型,以 Neo4j 图即真相源为核心,三条通道 Suggestion → 审核 → 写图 → 派生 flat 视图
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
1. [Part A: 系统设计](#part-a-系统设计)
|
||
- 1. 实现方案与框架选型
|
||
- 2. 文件列表及相对路径
|
||
- 3. 数据结构与接口(Mermaid 类图)
|
||
- 4. 程序调用流程(Mermaid 时序图)
|
||
- 5. 待明确事项
|
||
2. [Part B: 任务分解](#part-b-任务分解)
|
||
- 6. 依赖包列表
|
||
- 7. 任务列表(有序、含依赖)
|
||
- 8. 共享知识
|
||
- 9. 任务依赖图
|
||
|
||
---
|
||
|
||
# Part A: 系统设计
|
||
|
||
## 1. 实现方案与框架选型
|
||
|
||
### 1.1 核心技术挑战
|
||
|
||
| # | 挑战 | 难在哪 | 对应决策 |
|
||
|---|------|--------|----------|
|
||
| 1 | 桩→真AI生成 | `_generate_*_suggestion` 返回 `[待AI生成]`,需真实调用 Dify 并输出结构化 JSON | D2, P0-1 |
|
||
| 2 | 知识迭代产物直写 Neo4j 图 | 当前 backend **无任何 Neo4j 模块**,需从零构建客户端+图schema+写操作 | D1, P0-4 |
|
||
| 3 | 审批状态机五态流转 | pending→queued→approved→applied→graph_synced,需串联 API+服务+Neo4j | D7, P0-6 |
|
||
| 4 | 置信门控统一契约 | AI 回复需统一带 `confidence`,低于 0.7 触发「转人工+上下文」 | D3, P0-3 |
|
||
| 5 | 三通道输入归一化 | A(会话-Dify)/B(训练师手动)/C(文档-RAGFlow) 三种来源统一落 `KnowledgeSuggestion` | D2 |
|
||
| 6 | Qwen-VL 截图理解 | 员工发截图→本地 Qwen-VL→Dify 后端→结构化描述入上下文 | D5, P1-3 |
|
||
|
||
### 1.2 框架与库选型
|
||
|
||
#### 1.2.1 Neo4j 驱动:`neo4j` 官方异步驱动
|
||
|
||
```
|
||
neo4j@^5.26.0 — 官方 Python 异步驱动(支持 async/await,与 FastAPI 生态天然匹配)
|
||
```
|
||
|
||
**选型理由**:
|
||
- `neo4j` 5.x 原生支持 `AsyncDriver` + `AsyncSession`,与 FastAPI/SQLAlchemy async 生态一致,无需额外线程池。
|
||
- 支持 `execute_read`/`execute_write` 事务分离,图写操作天然适合写事务。
|
||
- 自带 `neo4j.time` 类型映射、连接池、重试策略,减轻自建客户端负担。
|
||
|
||
**替代方案评估**:
|
||
- `py2neo`:已停止维护(最后 release 2021),不支持 Neo4j 5.x,淘汰。
|
||
- `neomodel`:基于 py2neo,同样不维护,且 OGM 过度抽象不利于直接 Cypher 控制,淘汰。
|
||
|
||
**连接配置**(写入 `app/config.py`):
|
||
```python
|
||
neo4j_uri: str = "bolt://localhost:7687" # Neo4j bolt 协议
|
||
neo4j_user: str = "neo4j"
|
||
neo4j_password: str = "" # 仅从环境变量注入
|
||
neo4j_database: str = "neo4j" # 默认数据库
|
||
neo4j_max_connection_lifetime: int = 3600 # 连接最大存活时间(秒)
|
||
neo4j_max_connection_pool_size: int = 50 # 连接池上限
|
||
```
|
||
|
||
#### 1.2.2 Dify 集成:复用现有 `WingmanService` 范式
|
||
|
||
**不做新客户端**,直接扩展 `WingmanService`:
|
||
- 新增 `generate_knowledge_suggestion()` 方法,复用 `_build_context_messages` + `_call_wingman_api` + `_parse_json_response`。
|
||
- 新增专用 `_KNOWLEDGE_SUGGESTION_PROMPT` 模板,要求输出结构化 JSON:
|
||
```json
|
||
{
|
||
"suggestion_type": "new_faq|update",
|
||
"title": "问题标题",
|
||
"content": "答案内容",
|
||
"category": "硬件|软件|网络|安全|账号|其他",
|
||
"tags": ["VPN", "连接"],
|
||
"confidence": 0.86,
|
||
"issue": "VPN问题",
|
||
"action": "VPN连接修复",
|
||
"relation_type": "LEADS_TO",
|
||
"parent_issue": "网络问题"
|
||
}
|
||
```
|
||
|
||
#### 1.2.3 RAGFlow 集成:复用现有 `integrations/ragflow/` 客户端
|
||
|
||
- 现有 `backend/app/integrations/ragflow/client.py` 已有基础 API 客户端。
|
||
- 新增 `RagflowIngestionService` 封装"上传文档→等待处理→拉取结构化结果→生成 KnowledgeSuggestion"流程。
|
||
|
||
#### 1.2.4 Qwen-VL 调用方式:经 Dify 后端
|
||
|
||
- Qwen-VL(`Qwen3-VL-8B-Instruct`)本地部署,Dify 工作流中配置 `vision-completion` 节点。
|
||
- 后端接收图片消息→上传至临时存储→调用 Dify vision 工作流(非流式)→获取结构化描述文本→注入当前会话上下文。
|
||
- 预留接口参数 `vision_model` 以便后续升级至 Qwen3-VL-32B-Instruct。
|
||
|
||
#### 1.2.5 架构模式
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ 三层架构(后端) │
|
||
│ │
|
||
│ API 层(router.py + knowledge_iteration.py + wingman.py) │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ 服务层(KnowledgeIterationService + WingmanService │
|
||
│ + Neo4jClient + VisionService + RagflowIngestion) │
|
||
│ │ │
|
||
│ ▼ │
|
||
│ 持久层(SQLAlchemy/PostgreSQL + neo4j AsyncDriver/Neo4j) │
|
||
│ │
|
||
│ 前端:三端独立 │
|
||
│ - H5(员工端): Vue3+Vant4 — 分诊卡片+置信门控+截图上传 │
|
||
│ - 坐席控制台: Vue3+ElementPlus — 内联审批+排除+独立队列 │
|
||
│ - 管理后台: Vue3+Element+Tailwind — 提案审阅+训练师录入 │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 1.3 图 Schema 迁移策略
|
||
|
||
**原则**:对齐复杂场景重构 v1.1 的 TeliChat 白盒图模型,以 **Issue → Action → Relation** 为核心。
|
||
|
||
#### 1.3.1 Neo4j 节点标签与属性
|
||
|
||
| 标签 | 属性 | 对齐复杂场景重构 |
|
||
|------|------|-----------------|
|
||
| `Issue` | `uuid`, `name`, `category`, `created_at`, `updated_at`, `source_suggestion_id` | `Issue {name, category}` |
|
||
| `Action` | `uuid`, `name`, `description`, `created_at`, `updated_at`, `source_suggestion_id` | `Action {name}` |
|
||
| `Info` | `uuid`, `name`, `value`, `modifiers`(list), `created_at` | `Info {name}` + 信息项修饰 |
|
||
| `Session` | `session_id`, `current_node` | `Session {id, current_node}` |
|
||
|
||
#### 1.3.2 关系类型
|
||
|
||
| 关系 | 方向 | 属性 | 对齐复杂场景重构 |
|
||
|------|------|------|-----------------|
|
||
| `LEADS_TO` | Issue→Issue 或 Issue→Action | `order: int`, `weight: float` | 完全对齐 |
|
||
| `RELATES_TO` | Issue↔Issue | `type: str` | `CAN_JUMP_TO` → 简化为 `RELATES_TO {type:"jump"}` |
|
||
| `HAS_ACTION` | Issue→Action | — | `LEADS_TO` 已覆盖 |
|
||
| `PROVIDED` | Session→Info | `timestamp: datetime`, `status: str` | 完全对齐 |
|
||
| `CORRECTED_TO` | Info→Info | `timestamp: datetime` | 完全对齐 |
|
||
|
||
#### 1.3.3 图初始化 Cypher
|
||
|
||
```cypher
|
||
// 创建约束
|
||
CREATE CONSTRAINT issue_uuid IF NOT EXISTS FOR (i:Issue) REQUIRE i.uuid IS UNIQUE;
|
||
CREATE CONSTRAINT action_uuid IF NOT EXISTS FOR (a:Action) REQUIRE a.uuid IS UNIQUE;
|
||
|
||
// 创建索引
|
||
CREATE INDEX issue_category IF NOT EXISTS FOR (i:Issue) ON (i.category);
|
||
CREATE INDEX issue_name IF NOT EXISTS FOR (i:Issue) ON (i.name);
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 文件列表及相对路径
|
||
|
||
> 标注说明:`[新]` 新增文件 / `[改]` 修改文件 / `[不]` 故意不动
|
||
|
||
### 2.1 后端 — 配置与依赖
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/requirements.txt` | `[改]` | 新增 `neo4j>=5.26.0`、`Pillow>=10.0`(截图预处理) |
|
||
| `backend/app/config.py` | `[改]` | 新增 Neo4j / Qwen-VL / confidence_gate_threshold / RAGFlow ingestion 配置项 |
|
||
| `backend/alembic/versions/xxxx_add_graph_confidence_audience_fields.py` | `[新]` | Alembic migration:KnowledgeSuggestion + KnowledgeBase 字段扩展 |
|
||
|
||
### 2.2 后端 — 模型层
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/app/models/knowledge_suggestion.py` | `[改]` | 新增 `confidence`, `audience`, `issue`, `action`, `relation_type`, `parent_issue`, `graph_meta`(JSON), `graph_sync_status`, `source_failed`, `queued_at`, `applied_at` |
|
||
| `backend/app/models/knowledge_base.py` | `[改]` | 新增 `graph_sync_status`, `graph_node_uuid` 字段 |
|
||
|
||
### 2.3 后端 — Schema 层
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/app/schemas/knowledge_suggestion.py` | `[改]` | 所有请求/响应 Schema 新增图字段、audience、confidence;新增 `KnowledgeSuggestionRewrite`(改写请求) |
|
||
| `backend/app/schemas/enums.py` | `[新]` | `AudienceEnum`, `SuggestionStatusEnum`, `GraphSyncStatusEnum`, `SourceTypeEnum`, `RelationTypeEnum` 枚举集中定义 |
|
||
|
||
### 2.4 后端 — Neo4j 模块(全新)
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/app/services/neo4j_client.py` | `[新]` | Neo4j AsyncDriver 封装(连接池、写事务、读事务、图初始化) |
|
||
| `backend/app/models/neo4j_schema.py` | `[新]` | Neo4j 图节点/关系 Pydantic 模型:`IssueNode`, `ActionNode`, `RelationEdge` |
|
||
|
||
### 2.5 后端 — 服务层
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/app/services/knowledge_iteration_service.py` | `[改]` | **核心重写**:真 AI 生成(替换 TODO 占位)、Dify 调用、审批状态机五态流转、Neo4j 图写入、audience 自动标注、conf<0.7 转人工标记 |
|
||
| `backend/app/services/wingman_service.py` | `[改]` | 新增 `generate_knowledge_suggestion()`、`_KNOWLEDGE_SUGGESTION_PROMPT` |
|
||
| `backend/app/services/vision_service.py` | `[新]` | Qwen-VL 截图理解服务(上传→Dify vision workflow→结构化描述→注入上下文) |
|
||
| `backend/app/services/ragflow_ingestion_service.py` | `[新]` | RAGFlow 文档上传→ETL→结构化→生成 KnowledgeSuggestion(通道 C) |
|
||
| `backend/app/services/content_moderation_service.py` | `[不]` | **不动** — 维持 WARN 不升级 |
|
||
|
||
### 2.6 后端 — API 层
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/app/api/router.py` | `[改]` | **取消 L32 注释**,挂载 `knowledge_iteration_router`(prefix=`/admin/knowledge-iteration`);新增 `vision_router`、`approval_queue_router` |
|
||
| `backend/app/api/knowledge_iteration.py` | `[改]` | 扩展现有 6 端点:list 支持 audience/confidence 筛选;approve/reject 触发 Neo4j 写图+状态流转;新增 `rewrite` 端点 |
|
||
| `backend/app/api/approval_queue.py` | `[新]` | 独立队列 API:`GET /queued`、`POST /{id}/queue`、`POST /{id}/dequeue`、`GET /stats` |
|
||
| `backend/app/api/vision.py` | `[新]` | 图片上传+视觉理解 API:`POST /api/vision/analyze` → 返回结构化描述 |
|
||
| `backend/app/api/ragflow_ingestion.py` | `[新]` | RAGFlow 文档上传+处理 API:`POST /api/ragflow/ingest` → 返回 pending 提案 |
|
||
|
||
### 2.7 前端 — H5 员工端(Vue3+Vant4)
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `frontend-h5/src/components/TriageCard.vue` | `[新]` | 分诊置顶卡片组件(是/否/概率选择题、步骤进度条、专家模式开关)D4/P1-1 |
|
||
| `frontend-h5/src/components/ConfidenceGateBanner.vue` | `[新]` | 置信门控横幅:conf<0.7 时显示「转人工」入口+已收集上下文快照 D3/P0-3 |
|
||
| `frontend-h5/src/components/ImageUploader.vue` | `[新]` | 截图上传+中途补图组件(调用 vision API)D5/P1-3 |
|
||
| `frontend-h5/src/composables/useConfidenceGate.ts` | `[新]` | 置信门控逻辑复用 composable |
|
||
|
||
### 2.8 前端 — 坐席控制台(Vue3+ElementPlus)
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `frontend-agent/src/components/chat/ApprovalInlineCard.vue` | `[新]` | 内联审批卡片(采纳/驳回/改写 + 拓扑预览 + audience 下拉)D7/P0-6 |
|
||
| `frontend-agent/src/components/chat/AgentExclusionPanel.vue` | `[新]` | 坐席排除控件(勾选排除错误项+加推荐标记+不能代用户确认)D9/P1-2 |
|
||
| `frontend-agent/src/views/ApprovalQueue.vue` | `[新]` | 独立队列页(提案列表+筛选+批量操作)D7/P0-6 |
|
||
| `frontend-agent/src/composables/useApprovalQueue.ts` | `[新]` | 审批队列状态管理 composable |
|
||
|
||
### 2.9 前端 — 管理后台(Vue3+Element+Tailwind)
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `frontend-admin/src/views/KnowledgeIteration.vue` | `[新]` | 知识迭代提案管理页(列表+审阅+图字段编辑+训练师手动录入入口) |
|
||
| `frontend-admin/src/views/RagflowIngestion.vue` | `[新]` | RAGFlow 文档上传页(通道 C)P1-5 |
|
||
|
||
### 2.10 测试
|
||
|
||
| 相对路径 | 操作 | 说明 |
|
||
|----------|------|------|
|
||
| `backend/tests/test_knowledge_iteration.py` | `[改]` | 更新 4/4 桩断言→真实 AI 生成断言 |
|
||
| `backend/tests/test_neo4j_client.py` | `[新]` | Neo4j 客户端单元测试(连接/CRUD/图遍历) |
|
||
| `backend/tests/test_confidence_gate.py` | `[新]` | 置信门控逻辑测试 |
|
||
| `backend/tests/test_approval_state_machine.py` | `[新]` | 审批状态机测试(五态流转) |
|
||
|
||
---
|
||
|
||
## 3. 数据结构与接口(Mermaid 类图)
|
||
|
||
```mermaid
|
||
classDiagram
|
||
direction TB
|
||
|
||
%% ── 枚举 ──────────────────────────────────────────
|
||
class AudienceEnum {
|
||
<<enumeration>>
|
||
employee_quick_reply
|
||
engineer_workguide
|
||
}
|
||
|
||
class SuggestionStatusEnum {
|
||
<<enumeration>>
|
||
pending
|
||
queued
|
||
approved
|
||
rejected
|
||
applied
|
||
graph_synced
|
||
expired
|
||
}
|
||
|
||
class GraphSyncStatusEnum {
|
||
<<enumeration>>
|
||
pending
|
||
synced
|
||
failed
|
||
}
|
||
|
||
class SourceTypeEnum {
|
||
<<enumeration>>
|
||
annotation
|
||
conversation
|
||
ai_uncertain
|
||
manual
|
||
document_ragflow
|
||
}
|
||
|
||
class RelationTypeEnum {
|
||
<<enumeration>>
|
||
LEADS_TO
|
||
RELATES_TO
|
||
CAN_JUMP_TO
|
||
}
|
||
|
||
%% ── PostgreSQL 模型 ───────────────────────────────
|
||
class KnowledgeSuggestion {
|
||
+str id
|
||
+str suggestion_type
|
||
+SuggestionStatusEnum status
|
||
+str title
|
||
+str content
|
||
+str category
|
||
+List~str~ tags
|
||
+SourceTypeEnum source_type
|
||
+List~str~ source_data
|
||
+str reason
|
||
+str reject_reason
|
||
+str reviewer_id
|
||
+datetime reviewed_at
|
||
+datetime created_at
|
||
+datetime updated_at
|
||
+float confidence
|
||
+AudienceEnum audience
|
||
+str issue
|
||
+str action
|
||
+RelationTypeEnum relation_type
|
||
+str parent_issue
|
||
+dict graph_meta
|
||
+GraphSyncStatusEnum graph_sync_status
|
||
+bool source_failed
|
||
+datetime queued_at
|
||
+datetime applied_at
|
||
}
|
||
|
||
class KnowledgeBase {
|
||
+str id
|
||
+str category
|
||
+str title
|
||
+str content
|
||
+List~str~ tags
|
||
+int view_count
|
||
+int use_count
|
||
+GraphSyncStatusEnum graph_sync_status
|
||
+str graph_node_uuid
|
||
+datetime created_at
|
||
+datetime updated_at
|
||
}
|
||
|
||
class Conversation {
|
||
+str id
|
||
+str employee_id
|
||
+str status
|
||
+str session_type
|
||
+datetime created_at
|
||
}
|
||
|
||
%% ── Neo4j 图节点模型 ──────────────────────────────
|
||
class IssueNode {
|
||
+str uuid
|
||
+str name
|
||
+str category
|
||
+datetime created_at
|
||
+datetime updated_at
|
||
+str source_suggestion_id
|
||
}
|
||
|
||
class ActionNode {
|
||
+str uuid
|
||
+str name
|
||
+str description
|
||
+datetime created_at
|
||
+str source_suggestion_id
|
||
}
|
||
|
||
class InfoNode {
|
||
+str uuid
|
||
+str name
|
||
+str value
|
||
+List~str~ modifiers
|
||
+datetime created_at
|
||
}
|
||
|
||
class RelationEdge {
|
||
+str from_uuid
|
||
+str to_uuid
|
||
+RelationTypeEnum type
|
||
+int order
|
||
+float weight
|
||
}
|
||
|
||
%% ── Pydantic Schema ───────────────────────────────
|
||
class KnowledgeSuggestionCreate {
|
||
+str suggestion_type
|
||
+str title
|
||
+str content
|
||
+str category
|
||
+List~str~ tags
|
||
+SourceTypeEnum source_type
|
||
+List~str~ source_data
|
||
+str reason
|
||
+float confidence
|
||
+AudienceEnum audience
|
||
+str issue
|
||
+str action
|
||
+RelationTypeEnum relation_type
|
||
+str parent_issue
|
||
+dict graph_meta
|
||
}
|
||
|
||
class KnowledgeSuggestionResponse {
|
||
+str id
|
||
+str suggestion_type
|
||
+SuggestionStatusEnum status
|
||
+str title
|
||
+str content
|
||
+str category
|
||
+List~str~ tags
|
||
+SourceTypeEnum source_type
|
||
+float confidence
|
||
+AudienceEnum audience
|
||
+str issue
|
||
+str action
|
||
+RelationTypeEnum relation_type
|
||
+str parent_issue
|
||
+dict graph_meta
|
||
+GraphSyncStatusEnum graph_sync_status
|
||
+bool source_failed
|
||
+datetime queued_at
|
||
+datetime applied_at
|
||
+datetime created_at
|
||
}
|
||
|
||
class KnowledgeSuggestionApprove {
|
||
<<request>>
|
||
}
|
||
|
||
class KnowledgeSuggestionReject {
|
||
<<request>>
|
||
+str reject_reason
|
||
}
|
||
|
||
class KnowledgeSuggestionRewrite {
|
||
<<request>>
|
||
+str title
|
||
+str content
|
||
+str category
|
||
+List~str~ tags
|
||
+float confidence
|
||
+AudienceEnum audience
|
||
+str issue
|
||
+str action
|
||
+RelationTypeEnum relation_type
|
||
+str parent_issue
|
||
}
|
||
|
||
class VisionRequest {
|
||
<<request>>
|
||
+str conversation_id
|
||
+bytes image_file
|
||
}
|
||
|
||
class VisionResponse {
|
||
+str description
|
||
+float confidence
|
||
+dict metadata
|
||
}
|
||
|
||
class RagflowIngestionRequest {
|
||
<<request>>
|
||
+str file_name
|
||
+bytes file_data
|
||
+str category_hint
|
||
}
|
||
|
||
class RagflowIngestionResponse {
|
||
+str task_id
|
||
+str status
|
||
+List~KnowledgeSuggestionResponse~ suggestions
|
||
}
|
||
|
||
%% ── 服务类 ────────────────────────────────────────
|
||
class KnowledgeIterationService {
|
||
-str ai_api_url
|
||
-str ai_api_key
|
||
+analyze_and_generate_suggestions(db, days) dict
|
||
-_analyze_annotation_data(db, days) dict
|
||
-_analyze_conversation_data(db, days) dict
|
||
-_generate_update_suggestion(db, source_type, source_data, reason) KnowledgeSuggestion
|
||
-_generate_new_faq_suggestion(db, source_type, source_data, reason) KnowledgeSuggestion
|
||
-_check_existing_suggestion(db, source_id) bool
|
||
-_auto_tag_audience(db, source_type, source_data) AudienceEnum
|
||
+approve_suggestion(db, suggestion_id, reviewer_id) KnowledgeSuggestion
|
||
+reject_suggestion(db, suggestion_id, reviewer_id, reason) KnowledgeSuggestion
|
||
+rewrite_suggestion(db, suggestion_id, reviewer_id, data) KnowledgeSuggestion
|
||
+queue_suggestion(db, suggestion_id) KnowledgeSuggestion
|
||
+dequeue_approve(db, suggestion_id, reviewer_id) KnowledgeSuggestion
|
||
+sync_to_neo4j(neo4j_client, suggestion) bool
|
||
+get_suggestion_stats(db) dict
|
||
+get_queue_stats(db) dict
|
||
}
|
||
|
||
class WingmanService {
|
||
-str api_url
|
||
-str api_key
|
||
-int timeout
|
||
-httpx.AsyncClient _client
|
||
+generate_draft(conversation_id, messages, db) dict
|
||
+generate_summary(conversation_id, messages) dict
|
||
+suggest_tags(conversation_id, messages, existing_tags) dict
|
||
+generate_knowledge_suggestion(context_messages) dict
|
||
-_build_context_messages(messages, system_prompt) list
|
||
-_call_wingman_api(context_messages) str
|
||
-_parse_json_response(content, default) dict
|
||
-_estimate_confidence(content) float
|
||
+close()
|
||
}
|
||
|
||
class Neo4jClient {
|
||
-str uri
|
||
-str user
|
||
-str password
|
||
-str database
|
||
-AsyncDriver _driver
|
||
+initialize()
|
||
+close()
|
||
+create_issue_node(issue) IssueNode
|
||
+create_action_node(action) ActionNode
|
||
+create_relation(from_uuid, to_uuid, rel) RelationEdge
|
||
+merge_issue(name, category, props) IssueNode
|
||
+merge_action(name, props) ActionNode
|
||
+find_issue_by_name(name) IssueNode
|
||
+find_related_issues(uuid, rel_type) List~IssueNode~
|
||
+execute_write_query(cypher, params) result
|
||
+execute_read_query(cypher, params) result
|
||
+health_check() bool
|
||
}
|
||
|
||
class VisionService {
|
||
-str dify_vision_api_url
|
||
-str dify_vision_api_key
|
||
-str local_vision_model
|
||
+analyze_screenshot(image_bytes, conversation_id) VisionResponse
|
||
-_preprocess_image(image_bytes) bytes
|
||
-_call_vision_workflow(processed_image) dict
|
||
+inject_to_conversation_context(description, conversation_id)
|
||
}
|
||
|
||
class RagflowIngestionService {
|
||
-RagflowClient client
|
||
+upload_and_process(file_data, file_name, category_hint) RagflowIngestionResponse
|
||
+poll_processing_status(task_id) str
|
||
+create_suggestions_from_result(result) List~KnowledgeSuggestion~
|
||
}
|
||
|
||
%% ── 关系 ──────────────────────────────────────────
|
||
KnowledgeSuggestion ..> AudienceEnum : uses
|
||
KnowledgeSuggestion ..> SuggestionStatusEnum : uses
|
||
KnowledgeSuggestion ..> SourceTypeEnum : uses
|
||
KnowledgeSuggestion ..> RelationTypeEnum : uses
|
||
KnowledgeSuggestion ..> GraphSyncStatusEnum : uses
|
||
KnowledgeBase ..> GraphSyncStatusEnum : uses
|
||
|
||
KnowledgeIterationService --> WingmanService : 调用 AI 生成
|
||
KnowledgeIterationService --> Neo4jClient : 写图同步
|
||
KnowledgeIterationService --> KnowledgeSuggestion : 管理
|
||
KnowledgeIterationService --> KnowledgeBase : 落库
|
||
|
||
KnowledgeSuggestionCreate --> KnowledgeSuggestion : 创建
|
||
KnowledgeSuggestionResponse --> KnowledgeSuggestion : 返回
|
||
KnowledgeSuggestionApprove --> KnowledgeSuggestion : 状态变更
|
||
KnowledgeSuggestionReject --> KnowledgeSuggestion : 状态变更
|
||
KnowledgeSuggestionRewrite --> KnowledgeSuggestion : 内容更新
|
||
|
||
IssueNode <--> RelationEdge : 关联
|
||
ActionNode <--> RelationEdge : 关联
|
||
Neo4jClient --> IssueNode : CRUD
|
||
Neo4jClient --> ActionNode : CRUD
|
||
Neo4jClient --> RelationEdge : 管理
|
||
|
||
VisionService --> WingmanService : 复用 _call_wingman_api 范式
|
||
RagflowIngestionService --> KnowledgeSuggestion : 产出
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 程序调用流程(Mermaid 时序图)
|
||
|
||
### 4.1 主流程:会话 → Dify → 建议 → 内联审批 → 写 Neo4j 图
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
actor 员工 as 👤 员工
|
||
actor 坐席 as 👤 坐席
|
||
actor 训练师 as 👤 AI训练师
|
||
participant H5 as H5前端
|
||
participant AgentFE as 坐席控制台
|
||
participant API as FastAPI
|
||
participant KIS as KnowledgeIterationService
|
||
participant WS as WingmanService
|
||
participant Dify as Dify AI Platform
|
||
participant DB as PostgreSQL
|
||
participant NEO as Neo4jClient
|
||
participant N4J as Neo4j 图数据库
|
||
|
||
Note over 员工,N4J: === 通道 A: 会话→Dify→建议 ===
|
||
|
||
员工->>H5: 发送 IT 问题(如"VPN 连不上")
|
||
H5->>API: POST /api/h5/conversations/current/messages
|
||
API->>Dify: 调用 Dify Agent(员工端 AI)
|
||
Dify-->>API: AI 回复 + confidence: 0.62
|
||
API-->>H5: 返回消息(含 confidence)
|
||
|
||
alt confidence < 0.7(门控触发)
|
||
H5->>H5: 渲染「转人工」卡片 + 已收集上下文
|
||
员工->>H5: 点击「转人工」
|
||
H5->>API: POST 转人工请求(附上下文快照)
|
||
end
|
||
|
||
Note over API,N4J: === 会话结束后触发分析 ===
|
||
|
||
API->>KIS: analyze_and_generate_suggestions(db, days=7)
|
||
KIS->>DB: 查询过去N天转人工/标注为无用 的会话
|
||
DB-->>KIS: 返回候选数据
|
||
|
||
loop 每个候选会话
|
||
KIS->>WS: generate_knowledge_suggestion(context_messages)
|
||
WS->>WS: _build_context_messages(messages, KN_SUGGEST_PROMPT)
|
||
WS->>Dify: _call_wingman_api(context_messages)
|
||
Dify-->>WS: 结构化 JSON(title/content/category/tags/confidence/issue/action/relation)
|
||
WS->>WS: _parse_json_response(content, default)
|
||
WS-->>KIS: dict {title, content, category, confidence, issue, action, ...}
|
||
|
||
KIS->>KIS: _auto_tag_audience(source_type, source_data)
|
||
Note over KIS: source_session_type=="employee" → employee_quick_reply<br/>source_session_type=="engineer" → engineer_workguide
|
||
|
||
KIS->>DB: INSERT KnowledgeSuggestion(status=pending, 含图字段)
|
||
end
|
||
|
||
KIS->>API: 返回分析结果统计
|
||
|
||
Note over 坐席,N4J: === D7 内联审批 ===
|
||
|
||
坐席->>AgentFE: 浏览会话中的提案卡片
|
||
AgentFE->>API: GET /api/admin/knowledge-iteration/suggestions?status=pending
|
||
API-->>AgentFE: 提案列表(含拓扑预览、confidence、audience)
|
||
|
||
alt 坐席选择「内联审批」
|
||
坐席->>AgentFE: 在会话内联卡片点击「采纳」
|
||
AgentFE->>API: POST /api/admin/knowledge-iteration/suggestions/{id}/approve
|
||
Note over API: 鉴权: require_admin / require_trainer
|
||
|
||
API->>KIS: approve_suggestion(db, suggestion_id, reviewer_id)
|
||
KIS->>DB: UPDATE status=approved, reviewed_at=now()
|
||
KIS->>DB: INSERT KnowledgeBase (含 graph_sync_status=pending)
|
||
KIS->>DB: UPDATE suggestion status=applied
|
||
|
||
Note over KIS,N4J: D1 解读2·直接写图
|
||
|
||
KIS->>NEO: merge_issue(issue_name, category, props)
|
||
NEO->>N4J: MERGE (i:Issue {name: $name}) ON CREATE SET i+=$props
|
||
N4J-->>NEO: IssueNode(uuid=...)
|
||
|
||
KIS->>NEO: merge_action(action_name, props)
|
||
NEO->>N4J: MERGE (a:Action {name: $name}) ON CREATE SET a+=$props
|
||
N4J-->>NEO: ActionNode(uuid=...)
|
||
|
||
KIS->>NEO: create_relation(issue_uuid, action_uuid, rel)
|
||
NEO->>N4J: MATCH (i),(a) WHERE i.uuid=$i AND a.uuid=$a CREATE (i)-[:LEADS_TO {order:$o,weight:$w}]->(a)
|
||
|
||
KIS->>DB: UPDATE suggestion graph_sync_status=synced
|
||
KIS->>DB: UPDATE KnowledgeBase graph_sync_status=synced, graph_node_uuid=...
|
||
|
||
API-->>AgentFE: 200 OK(含更新后提案)
|
||
else 坐席选择「驳回」
|
||
AgentFE->>API: POST /api/admin/knowledge-iteration/suggestions/{id}/reject {reject_reason}
|
||
API->>KIS: reject_suggestion(db, id, reviewer_id, reason)
|
||
KIS->>DB: UPDATE status=rejected
|
||
API-->>AgentFE: 200 OK
|
||
else 坐席选择「改写」
|
||
AgentFE->>API: POST /api/admin/knowledge-iteration/suggestions/{id}/rewrite {title, content, ...}
|
||
API->>KIS: rewrite_suggestion(db, id, reviewer_id, data)
|
||
KIS->>DB: UPDATE title/content/category/tags/confidence...
|
||
KIS->>DB: UPDATE status=pending(重新审批)
|
||
API-->>AgentFE: 200 OK
|
||
end
|
||
|
||
Note over 训练师,N4J: === D7 独立队列(未处理提案) ===
|
||
|
||
训练师->>AgentFE: 打开独立队列页
|
||
AgentFE->>API: GET /api/admin/approval-queue/queued?status=pending
|
||
Note over API: 未处理的=SESSION_CLOSED 后仍 pending 的提案<br/>或手动标记 queued
|
||
API-->>AgentFE: 队列列表
|
||
|
||
训练师->>AgentFE: 审核队列中的提案
|
||
AgentFE->>API: POST /api/admin/approval-queue/{id}/dequeue-approve
|
||
Note over API,N4J: 同 approve_suggestion 流程→写图
|
||
```
|
||
|
||
### 4.2 子流程:截图 → Qwen-VL 视觉理解
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
actor 员工 as 👤 员工
|
||
participant H5 as H5前端
|
||
participant API as FastAPI
|
||
participant VS as VisionService
|
||
participant Dify as Dify(Qwen-VL 工作流)
|
||
participant QwenVL as Qwen3-VL-8B-Instruct
|
||
participant DB as PostgreSQL
|
||
|
||
员工->>H5: 点击📷上传截图
|
||
H5->>H5: 预览截图、允许追加描述文字
|
||
员工->>H5: [发送]
|
||
H5->>API: POST /api/vision/analyze(multipart: image + conversation_id)
|
||
|
||
API->>VS: analyze_screenshot(image_bytes, conversation_id)
|
||
VS->>VS: _preprocess_image(image_bytes) → resize/compress
|
||
VS->>Dify: POST Dify vision workflow(携带 image base64)
|
||
Dify->>QwenVL: 调用本地 Qwen-VL 推理
|
||
QwenVL-->>Dify: 结构化描述 JSON
|
||
Dify-->>VS: {description, detected_ui_elements, error_codes, ...}
|
||
VS-->>API: VisionResponse {description, confidence, metadata}
|
||
|
||
API->>VS: inject_to_conversation_context(description, conversation_id)
|
||
VS->>DB: INSERT/UPDATE 会话消息(sender_type=system, content=视觉理解描述)
|
||
|
||
API-->>H5: {code:0, data: {description, confidence}}
|
||
H5->>H5: 展示「AI 已理解截图内容:…」
|
||
|
||
Note over H5: 后续消息中,视觉描述作为上下文参与 Dify 推理
|
||
```
|
||
|
||
### 4.3 子流程:文档 → RAGFlow → KB(通道 C)
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
actor 训练师 as 👤 AI训练师
|
||
participant AdminFE as 管理后台
|
||
participant API as FastAPI
|
||
participant RIS as RagflowIngestionService
|
||
participant RGF as RAGFlow Server
|
||
participant KIS as KnowledgeIterationService
|
||
participant DB as PostgreSQL
|
||
|
||
训练师->>AdminFE: 上传非标准格式文档(.docx/.pdf/图片)
|
||
AdminFE->>API: POST /api/ragflow/ingest(multipart: file + category_hint)
|
||
|
||
API->>RIS: upload_and_process(file_data, file_name, category_hint)
|
||
RIS->>RGF: POST /api/v1/datasets/{id}/documents/upload
|
||
RGF-->>RIS: {document_id, status: "processing"}
|
||
|
||
loop 轮询处理状态(最多 5 分钟)
|
||
RIS->>RGF: GET /api/v1/datasets/{id}/documents/{doc_id}
|
||
RGF-->>RIS: {status: "completed|failed"}
|
||
end
|
||
|
||
RIS->>RGF: GET /api/v1/datasets/{id}/documents/{doc_id}/chunks
|
||
RGF-->>RIS: 结构化段落列表
|
||
|
||
RIS->>RIS: create_suggestions_from_result(chunks)
|
||
Note over RIS: 每个段落 → KnowledgeSuggestion<br/>source_type=document_ragflow
|
||
|
||
loop 每个结构化片段
|
||
RIS->>KIS: 创建 pending 提案(复用 D7 审批流)
|
||
KIS->>DB: INSERT KnowledgeSuggestion(status=pending, audience=engineer_workguide)
|
||
end
|
||
|
||
RIS-->>API: RagflowIngestionResponse {task_id, status, suggestions}
|
||
API-->>AdminFE: 200 OK(提案列表,等待训练师审核)
|
||
```
|
||
|
||
### 4.4 子流程:坐席代答/排除(D9)
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
actor 坐席 as 👤 坐席
|
||
actor 员工 as 👤 员工
|
||
participant AgentFE as 坐席控制台
|
||
participant H5 as H5前端
|
||
participant API as FastAPI
|
||
participant DB as PostgreSQL
|
||
|
||
Note over 员工: AI 已发送分诊选择题(如"您的系统版本是?")
|
||
Note over 坐席: 坐席通过镜像看到相同选择题
|
||
|
||
坐席->>AgentFE: 在排除面板中勾选「macOS」为错误项
|
||
AgentFE->>AgentFE: 选项置灰/划除(local UI)
|
||
坐席->>AgentFE: 点击「Win10」加推荐标记⭐
|
||
|
||
AgentFE->>API: POST /api/triage/{message_id}/agent-exclude<br/>{excluded_options: ["macOS"], recommended_option: "Win10"}
|
||
API->>DB: 记录排除动作到审计日志(D7 留痕)
|
||
API-->>AgentFE: 200 OK
|
||
|
||
Note over API,H5: WebSocket 推送排除/推荐事件到员工 H5
|
||
|
||
H5->>H5: 渲染「坐席已排除"macOS",推荐您选 Win10/Win11」
|
||
Note over H5: 坐席不可代用户点确认——最终确认按钮仍在用户侧
|
||
|
||
员工->>H5: 自主选择「Win10」并确认
|
||
H5->>API: POST /api/triage/{message_id}/user-confirm {selected: "Win10"}
|
||
|
||
alt 30s 未确认
|
||
H5->>H5: 推送确认/取消提醒卡片(D9 超时机制)
|
||
end
|
||
```
|
||
|
||
### 4.5 子流程:审批状态机五态流转
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant SRC as 通道A/B/C
|
||
participant KIS as KnowledgeIterationService
|
||
participant DB as PostgreSQL
|
||
participant NEO as Neo4jClient
|
||
participant N4J as Neo4j
|
||
|
||
Note over SRC,N4J: pending → queued → approved → applied → graph_synced
|
||
|
||
SRC->>KIS: 生成提案(Dify/手动/RAGFlow)
|
||
KIS->>DB: INSERT status=pending
|
||
|
||
alt 会话关闭且提案仍 pending
|
||
KIS->>DB: UPDATE status=queued, queued_at=now()
|
||
Note over DB: 进入独立队列(D7)
|
||
end
|
||
|
||
alt 训练师内联审批「采纳」
|
||
KIS->>DB: UPDATE status=approved, reviewer_id=..., reviewed_at=now()
|
||
KIS->>DB: INSERT KnowledgeBase(同步创建 flat KB 条目)
|
||
KIS->>DB: UPDATE suggestion status=applied, applied_at=now()
|
||
Note over DB: applied → KB 条目已落库
|
||
|
||
KIS->>NEO: merge_issue + merge_action + create_relation
|
||
NEO->>N4J: Cypher 事务写入
|
||
N4J-->>NEO: OK
|
||
KIS->>DB: UPDATE suggestion graph_sync_status=synced
|
||
KIS->>DB: UPDATE knowledge_base graph_sync_status=synced
|
||
Note over DB: graph_synced → 图已同步
|
||
|
||
else 训练师「驳回」
|
||
KIS->>DB: UPDATE status=rejected, reject_reason=...
|
||
|
||
else 训练师「改写」
|
||
KIS->>DB: UPDATE content/title/... + status=pending
|
||
Note over DB: 回退到 pending,重新走审批
|
||
|
||
else 超时(待确认参数)
|
||
KIS->>DB: UPDATE status=expired
|
||
Note over DB: 转训练师独立工单(D7)
|
||
end
|
||
|
||
alt Neo4j 写图失败(graph_sync_status=failed)
|
||
KIS->>DB: UPDATE graph_sync_status=failed
|
||
Note over DB: 已有 applied 的 KB 条目,图同步失败进入重试队列
|
||
end
|
||
```
|
||
|
||
---
|
||
|
||
## 5. 待明确事项(来自增量PRD §8 + 架构分析)
|
||
|
||
| # | 待明确事项 | 当前假设/默认值 | 影响范围 |
|
||
|---|-----------|---------------|---------|
|
||
| 1 | **Neo4j 测试容器选型** | 推荐 `testcontainers-python[neo4j]`,本地开发用 Docker Neo4j 容器;CI 用 `neo4j:5-enterprise` 镜像 | 测试策略/pytest fixture |
|
||
| 2 | **分诊概率展示形式** | 默认**百分比**(如"72%"),精确到整数;不直接披露原始 confidence 给员工 | H5 TriageCard 组件 |
|
||
| 3 | **专家模式默认值** | 默认**关**(分步模式),普通员工首屏体验优先 | H5 ExpertModeToggle 组件 |
|
||
| 4 | **独立队列超时时间** | 默认 **72 小时** 未处理→`expired`,到期前 24 小时企微通知训练师 | ApprovalQueueService |
|
||
| 5 | **置信阈值分场景微调** | 默认统一 0.7,预留 `confidence_thresholds` JSON 配置字段(按 category),本期不实现按场景分阈值 | config.py |
|
||
| 6 | **audience 第三类** | 当前仅 `employee_quick_reply` / `engineer_workguide` 两类;如需"管理运营KB"由后续 P2 扩展 | AudienceEnum |
|
||
| 7 | **Qwen-VL 部署资源** | 假设本地已部署 Qwen3-VL-8B-Instruct(显存≥24GB),Dify 工作流已配置 vision-completion 节点 | VisionService / P1-3 |
|
||
| 8 | **RAGFlow 触发时机** | **训练师手动上传**触发,非定时扫描;格式范围:.docx/.pdf/.txt/.png/.jpg | P1-5 |
|
||
| 9 | **坐席代答超时** | 30s 未确认→推送提醒卡片;**不自动采用**推荐项(严格 D9:最终确认权在用户) | AgentExclusionPanel |
|
||
| 10 | **Neo4j 客户端分期** | Neo4j 客户端基础设施在 **T01 实现**,图写入在 **T03 串联** | 任务编排 |
|
||
|
||
---
|
||
|
||
# Part B: 任务分解
|
||
|
||
## 6. 依赖包列表
|
||
|
||
```
|
||
# ── 核心新增 ──
|
||
neo4j>=5.26.0 # Neo4j 官方异步驱动(bolt 协议)
|
||
Pillow>=10.0.0 # 截图预处理(resize/compress)
|
||
|
||
# ── 测试(仅测试环境) ──
|
||
testcontainers[neo4j]>=4.0.0 # Neo4j 测试容器(CI 本地模拟)
|
||
pytest-asyncio>=0.23.0 # 异步测试 fixture(已有)
|
||
|
||
# ── 复用(无需新增) ──
|
||
# httpx>=0.25.0 — 已有,Dify/RAGFlow HTTP 调用
|
||
# sqlalchemy>=2.0 — 已有,ORM
|
||
# fastapi>=0.110 — 已有,Web 框架
|
||
# pydantic>=2.0 — 已有,Schema 验证
|
||
# alembic>=1.13 — 已有,数据库迁移
|
||
# redis>=5.0 — 已有,缓存/队列
|
||
# wordfilter>=0.3 — 已有,敏感词检测(不动)
|
||
```
|
||
|
||
## 7. 任务列表(有序、含依赖)
|
||
|
||
### T01: 项目基础设施 — Neo4j 环境 + 配置 + 迁移
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| **Task ID** | T01 |
|
||
| **优先级** | P0(Tier0 前置,阻塞所有后续任务) |
|
||
| **工期** | 1-2 天 |
|
||
| **依赖** | 无 |
|
||
|
||
**目标**:搭建 Neo4j 连接基础设施、Alembic 迁移新增字段、配置项扩展。
|
||
|
||
**源文件**(7 个):
|
||
|
||
| # | 文件 | 操作 | 关键内容 |
|
||
|---|------|------|---------|
|
||
| 1 | `backend/requirements.txt` | `[改]` | 新增 `neo4j>=5.26.0`、`Pillow>=10.0.0` |
|
||
| 2 | `backend/app/config.py` | `[改]` | 新增 `neo4j_uri/neo4j_user/neo4j_password/neo4j_database` 配置项;新增 `confidence_gate_threshold: float = 0.7`;新增 `ragflow_ingestion_enabled: bool = False` |
|
||
| 3 | `backend/app/services/neo4j_client.py` | `[新]` | `Neo4jClient` 类:`__init__`(uri/user/password/database)→`AsyncDriver`;`initialize()`→验证连接+创建约束/索引;`close()`→释放驱动;`health_check()`→`RETURN 1`;`execute_write_query(cypher, params)`→写事务;`execute_read_query(cypher, params)`→读事务 |
|
||
| 4 | `backend/app/models/neo4j_schema.py` | `[新]` | Pydantic 模型:`IssueNode(uuid,name,category,created_at,updated_at,source_suggestion_id)`;`ActionNode(uuid,name,description,created_at,source_suggestion_id)`;`RelationEdge(from_uuid,to_uuid,type,order,weight)` |
|
||
| 5 | `backend/alembic/versions/xxxx_add_graph_confidence_audience.py` | `[新]` | Alembic migration:`knowledge_suggestions` 表新增 `confidence`(Float)、`audience`(String(30))、`issue`(String(256))、`action`(String(256))、`relation_type`(String(30))、`parent_issue`(String(256))、`graph_meta`(JSON)、`graph_sync_status`(String(20), default='pending')、`source_failed`(Boolean, default=False)、`queued_at`(DateTime)、`applied_at`(DateTime);`knowledge_base` 表新增 `graph_sync_status`(String(20))、`graph_node_uuid`(String(36)) |
|
||
| 6 | `backend/app/schemas/enums.py` | `[新]` | `AudienceEnum(employee_quick_reply, engineer_workguide)`、`SuggestionStatusEnum(pending,queued,approved,rejected,applied,graph_synced,expired)`、`GraphSyncStatusEnum(pending,synced,failed)`、`SourceTypeEnum(annotation,conversation,ai_uncertain,manual,document_ragflow)`、`RelationTypeEnum(LEADS_TO,RELATES_TO,CAN_JUMP_TO)` |
|
||
| 7 | `docker-compose.dev.yml` | `[改]` | 新增 `neo4j` 服务定义(image: `neo4j:5-enterprise`, ports: `7474:7474`/`7687:7687`, env: `NEO4J_AUTH=neo4j/test1234`) |
|
||
|
||
**验收标准**:
|
||
- `Neo4jClient.health_check()` 返回 `True`(Docker Neo4j 启动后)
|
||
- Alembic migration 在 PostgreSQL 可执行 `upgrade`/`downgrade`
|
||
- `config.py` 新增配置项可通过环境变量注入
|
||
|
||
---
|
||
|
||
### T02: 数据与状态层 — 模型扩展 + Schema + Neo4j 基础 CRUD
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| **Task ID** | T02 |
|
||
| **优先级** | P0(Tier1) |
|
||
| **工期** | 1-2 天 |
|
||
| **依赖** | T01 |
|
||
|
||
**目标**:扩展 PostgreSQL 模型与 Pydantic Schema,实现 Neo4j 基础图节点 CRUD。
|
||
|
||
**源文件**(7 个):
|
||
|
||
| # | 文件 | 操作 | 关键内容 |
|
||
|---|------|------|---------|
|
||
| 1 | `backend/app/models/knowledge_suggestion.py` | `[改]` | 在 `KnowledgeSuggestion` 类中新增 12 个字段:`confidence: Mapped[Optional[float]]`、`audience: Mapped[Optional[str]]`(String(30))、`issue: Mapped[Optional[str]]`(String(256))、`action: Mapped[Optional[str]]`(String(256))、`relation_type: Mapped[Optional[str]]`(String(30))、`parent_issue: Mapped[Optional[str]]`(String(256))、`graph_meta: Mapped[Optional[dict]]`(JSON)、`graph_sync_status: Mapped[str]`(String(20), default='pending')、`source_failed: Mapped[bool]`(Boolean, default=False)、`queued_at: Mapped[Optional[datetime]]`、`applied_at: Mapped[Optional[datetime]]`;新增索引 `idx_suggestion_audience`、`idx_suggestion_confidence`、`idx_suggestion_graph_sync` |
|
||
| 2 | `backend/app/models/knowledge_base.py` | `[改]` | 新增 `graph_sync_status: Mapped[str]`(String(20), default='pending')、`graph_node_uuid: Mapped[Optional[str]]`(String(36)) |
|
||
| 3 | `backend/app/schemas/knowledge_suggestion.py` | `[改]` | `KnowledgeSuggestionCreate`:新增 `confidence`(Optional[float])、`audience`(Optional[AudienceEnum])、`issue/action/relation_type/parent_issue`(Optional[str])、`graph_meta`(Optional[dict])。`KnowledgeSuggestionResponse`:新增全部 12 个扩展字段。新增 `KnowledgeSuggestionRewrite`(用于训练师改写提案) |
|
||
| 4 | `backend/app/services/neo4j_client.py` | `[改]` | 扩展 T01 的 `Neo4jClient`:`create_issue_node(issue: IssueNode) → IssueNode`;`create_action_node(action: ActionNode) → ActionNode`;`create_relation(from_uuid, to_uuid, rel: RelationEdge) → bool`;`merge_issue(name, category, props) → IssueNode`(MERGE 幂等);`merge_action(name, props) → ActionNode`;`find_issue_by_name(name) → Optional[IssueNode]`;`find_related_issues(uuid, rel_type) → List[IssueNode]` |
|
||
| 5 | `backend/app/schemas/enums.py` | `[改]` | 补充枚举文档注释 + `__str__` 方法 |
|
||
| 6 | `backend/tests/test_neo4j_client.py` | `[新]` | 测试:`test_health_check`、`test_create_issue_node`、`test_create_action_node`、`test_create_relation`、`test_merge_issue_idempotent`、`test_find_issue_by_name`、`test_find_related_issues` |
|
||
| 7 | `backend/app/dependencies.py` | `[改]` | 新增 `dep_neo4j_client()` 依赖注入函数(单例/请求级) |
|
||
|
||
**验收标准**:
|
||
- `KnowledgeSuggestion` 模型新字段可通过 SQLAlchemy 正常读写
|
||
- `KnowledgeSuggestionCreate` 可接受图字段并验证类型
|
||
- `Neo4jClient` 所有 CRUD 方法通过 pytest(需要 Neo4j 测试容器)
|
||
|
||
---
|
||
|
||
### T03: 核心业务服务 — AI 生成 + 置信门控 + 审批 + 写图
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| **Task ID** | T03 |
|
||
| **优先级** | P0(Tier1 核心) |
|
||
| **工期** | 2-3 天 |
|
||
| **依赖** | T02 |
|
||
|
||
**目标**:实现真 AI 知识建议生成、置信门控逻辑、审批状态机、audience 自动标注、Neo4j 图同步。
|
||
|
||
**源文件**(8 个):
|
||
|
||
| # | 文件 | 操作 | 关键内容 |
|
||
|---|------|------|---------|
|
||
| 1 | `backend/app/services/wingman_service.py` | `[改]` | 新增 `_KNOWLEDGE_SUGGESTION_PROMPT`(要求输出结构化 JSON:title/content/category/tags/confidence/issue/action/relation_type/parent_issue);新增 `generate_knowledge_suggestion(context_messages: List[Dict]) → Dict[str, Any]` 方法(复用 `_build_context_messages`+`_call_wingman_api`+`_parse_json_response`) |
|
||
| 2 | `backend/app/services/knowledge_iteration_service.py` | `[改]` | **核心重写**:`_generate_update_suggestion` 和 `_generate_new_faq_suggestion` 移除 `[待AI生成]` 占位→调用 `WingmanService.generate_knowledge_suggestion()`;Dify 不可用时设 `source_failed=True`;新增 `_auto_tag_audience(db, source_type, source_data) → AudienceEnum`(查 `Conversation.session_type`→映射 audience);新增 `_apply_confidence_gate(suggestion) → bool`(conf<0.7→标记 source_failed);`approve_suggestion` 扩展→状态机五态流转+Neo4j 写图(调用 `Neo4jClient.merge_issue/merge_action/create_relation`);新增 `rewrite_suggestion(db, id, reviewer_id, data)`;新增 `queue_suggestion(db, id)`;新增 `dequeue_approve(db, id, reviewer_id)`;新增 `sync_to_neo4j(neo4j_client, suggestion) → bool` |
|
||
| 3 | `backend/app/services/vision_service.py` | `[新]` | `VisionService` 类:`__init__`(dify_vision_api_url, dify_vision_api_key, model="Qwen3-VL-8B-Instruct");`analyze_screenshot(image_bytes, conversation_id) → VisionResponse`;`_preprocess_image(image_bytes) → bytes`(Pillow resize→max 1024px, compress JPEG quality=85);`_call_vision_workflow(processed_image) → dict`(httpx→Dify vision workflow);`inject_to_conversation_context(description, conversation_id)` |
|
||
| 4 | `backend/app/services/ragflow_ingestion_service.py` | `[新]` | `RagflowIngestionService` 类:`upload_and_process(file_data, file_name, category_hint) → RagflowIngestionResponse`;`poll_processing_status(task_id, max_wait=300) → str`;`create_suggestions_from_result(chunks) → List[KnowledgeSuggestion]`(source_type=document_ragflow, audience=engineer_workguide) |
|
||
| 5 | `backend/tests/test_knowledge_iteration.py` | `[改]` | 重写 4/4 桩断言→真 AI 生成断言(Mock Dify 返回→验证 title/content 非 `[待AI生成]`);新增 `test_source_failed_on_dify_unavailable`;新增 `test_auto_tag_audience`;新增 `test_confidence_gate_below_threshold` |
|
||
| 6 | `backend/tests/test_approval_state_machine.py` | `[新]` | 测试五态流转:`test_pending_to_approved`、`test_approved_to_applied_to_graph_synced`、`test_rejected`、`test_rewrite_resets_to_pending`、`test_pending_to_queued`、`test_queued_to_approved`、`test_expired` |
|
||
| 7 | `backend/tests/test_confidence_gate.py` | `[新]` | 测试:`test_confidence_above_07_passes`、`test_confidence_below_07_marks_source_failed`、`test_threshold_configurable` |
|
||
| 8 | `backend/app/services/__init__.py` | `[改]` | 导出新增服务类 |
|
||
|
||
**验收标准**:
|
||
- `_generate_*_suggestion` 生成内容不再含 `[待AI生成]`(通过 Dify/Mock)
|
||
- Dify 不可用时 `source_failed=True`,不写伪数据
|
||
- `confidence < 0.7` 的提案标记 `source_failed=True`
|
||
- `approve_suggestion` 触发 Neo4j 图写入,`graph_sync_status` 正确流转到 `synced`
|
||
- 审批状态机所有合法转换通过测试
|
||
|
||
---
|
||
|
||
### T04: API 层 — 路由挂载 + 新端点 + Qwen-VL + RAGFlow
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| **Task ID** | T04 |
|
||
| **优先级** | P0(Tier1) |
|
||
| **工期** | 1-2 天 |
|
||
| **依赖** | T03 |
|
||
|
||
**目标**:挂载知识迭代路由、新增独立队列/视觉/RAGFlow API、更新前端接口契约。
|
||
|
||
**源文件**(7 个):
|
||
|
||
| # | 文件 | 操作 | 关键内容 |
|
||
|---|------|------|---------|
|
||
| 1 | `backend/app/api/router.py` | `[改]` | **取消 L32 注释**:`from app.api.knowledge_iteration import router as knowledge_iteration_router`;`api_router.include_router(knowledge_iteration_router, prefix="/admin/knowledge-iteration", tags=["知识库自动迭代"])`;新增 `vision_router`、`approval_queue_router`、`ragflow_router` 挂载 |
|
||
| 2 | `backend/app/api/knowledge_iteration.py` | `[改]` | 扩展现有 6 端点:`list_suggestions` 新增 `audience`/`confidence_min`/`confidence_max` 查询参数;`approve_suggestion` 改为调用 `KnowledgeIterationService.approve_suggestion`(触发 Neo4j 写图+状态流转);新增 `POST /suggestions/{id}/rewrite`(训练师改写);`POST /suggestions/{id}/queue`(进队列);`POST /suggestions/{id}/dequeue-approve`(队列审批) |
|
||
| 3 | `backend/app/api/approval_queue.py` | `[新]` | `GET /queued?status=queued&audience=&page=&page_size=`(独立队列列表);`GET /queued/stats`(队列统计);`POST /queued/{id}/dequeue-approve`(队列中审批) |
|
||
| 4 | `backend/app/api/vision.py` | `[新]` | `POST /api/vision/analyze`(multipart: image + conversation_id → VisionResponse);`GET /api/vision/models`(可用的 vision 模型列表) |
|
||
| 5 | `backend/app/api/ragflow_ingestion.py` | `[新]` | `POST /api/ragflow/ingest`(multipart: file + category_hint → RagflowIngestionResponse);`GET /api/ragflow/tasks/{task_id}`(查询处理状态) |
|
||
| 6 | `backend/app/api/__init__.py` | `[改]` | 导出新路由模块 |
|
||
| 7 | `backend/tests/test_api_knowledge_iteration.py` | `[新]` | API 集成测试:`test_list_suggestions_with_new_filters`、`test_approve_triggers_graph_sync`、`test_rewrite_endpoint`、`test_queue_endpoint` |
|
||
|
||
**验收标准**:
|
||
- `GET /api/admin/knowledge-iteration/suggestions` 返回 200(非 404)
|
||
- OpenAPI 文档可见 knowledge_iteration 路由(P0-2)
|
||
- `POST /api/admin/knowledge-iteration/suggestions/{id}/approve` 触发 Neo4j 写图(P0-6)
|
||
- `POST /api/vision/analyze` 返回结构化描述(P1-3)
|
||
- `POST /api/ragflow/ingest` 返回 pending 提案(P1-5)
|
||
|
||
---
|
||
|
||
### T05: 前端组件 — 分诊卡片 + 审批UI + 排除控件 + 队列
|
||
|
||
| 属性 | 值 |
|
||
|------|-----|
|
||
| **Task ID** | T05 |
|
||
| **优先级** | P0/P1(Tier1) |
|
||
| **工期** | 2-3 天 |
|
||
| **依赖** | T04 |
|
||
|
||
**目标**:三端前端组件落地,覆盖分诊门控、内联审批、坐席排除、独立队列、RAGFlow 上传。
|
||
|
||
**源文件**(12 个):
|
||
|
||
| # | 文件 | 操作 | 关键内容 | 落点 |
|
||
|---|------|------|---------|------|
|
||
| 1 | `frontend-h5/src/components/TriageCard.vue` | `[新]` | 分诊置顶卡片:AI 分步问题(是/否/概率选择题)、步骤进度(1/3)、专家模式开关 | H5(P1-1/D4) |
|
||
| 2 | `frontend-h5/src/components/ConfidenceGateBanner.vue` | `[新]` | 置信门控横幅:conf<0.7 时渲染「转人工」入口+已收集上下文快照 | H5(P0-3/D3) |
|
||
| 3 | `frontend-h5/src/components/ImageUploader.vue` | `[新]` | 截图上传+中途补图+视觉理解结果展示 | H5(P1-3/D5) |
|
||
| 4 | `frontend-h5/src/composables/useConfidenceGate.ts` | `[新]` | conf<0.7 判定、转人工上下文组装、阈值读取 | H5 |
|
||
| 5 | `frontend-agent/src/components/chat/ApprovalInlineCard.vue` | `[新]` | 内联审批卡片:title/content/confidence/topology 预览(Issue→Action 小图)、[采纳][驳回][改写] 按钮、audience 下拉 | 坐席(P0-6/D7) |
|
||
| 6 | `frontend-agent/src/components/chat/AgentExclusionPanel.vue` | `[新]` | 坐席排除:多选排除+推荐标记+30s 倒计时+不可代确认 | 坐席(P1-2/D9) |
|
||
| 7 | `frontend-agent/src/views/ApprovalQueue.vue` | `[新]` | 独立队列页:表格(来源/audience/confidence/状态/时间)+批量操作+筛选 | 坐席(P0-6/D7) |
|
||
| 8 | `frontend-agent/src/composables/useApprovalQueue.ts` | `[新]` | 队列数据获取、筛选状态、审批动作封装 | 坐席 |
|
||
| 9 | `frontend-admin/src/views/KnowledgeIteration.vue` | `[新]` | 知识迭代管理:提案列表+审阅+图字段编辑(issue/action/relation/parent)+训练师手动录入入口 | 管理后台(P0-6/P2-1) |
|
||
| 10 | `frontend-admin/src/views/RagflowIngestion.vue` | `[新]` | RAGFlow 文档上传:拖拽上传+处理进度+生成提案预览 | 管理后台(P1-5) |
|
||
| 11 | `frontend-agent/src/App.vue` | `[改]` | 注册审批队列路由 `/approval-queue` | 坐席 |
|
||
| 12 | `frontend-admin/src/router/index.ts` | `[改]` | 注册 knowledge-iteration、ragflow-ingestion 路由 | 管理后台 |
|
||
|
||
**验收标准**:
|
||
- 员工端 AI 回复 conf<0.7 时出现「转人工」卡片(P0-3)
|
||
- 坐席端会话中显示内联审批卡片(P0-6)
|
||
- 独立队列页可查看/筛选/审批(P0-6)
|
||
- 坐席可排除选项但不能代用户确认(P1-2)
|
||
- 管理后台可上传文档触发 RAGFlow(P1-5)
|
||
|
||
---
|
||
|
||
## 8. 共享知识
|
||
|
||
### 8.1 Neo4j 图节点属性与复杂场景重构命名映射约定
|
||
|
||
| 本设计 | 复杂场景重构 v1.1 | 说明 |
|
||
|--------|------------------|------|
|
||
| `Issue.name` | `Issue.name` | **完全对齐**,如"VPN问题" |
|
||
| `Issue.category` | `Issue.category` | **完全对齐**,如"网络" |
|
||
| `Action.name` | `Action.name` | **完全对齐**,如"个人VPN开通" |
|
||
| `RelationEdge.type=LEADS_TO` | `LEADS_TO {type:"可选", order:N}` | **完全对齐**,`order` 和 `weight` 为图边属性 |
|
||
| `RelationEdge.type=RELATES_TO` | `CAN_JUMP_TO {type:"跳转"}` | **语义简化**:统一用 `RELATES_TO` 含子类型 |
|
||
| `InfoNode.modifiers` | `InformationItem.modifiers` | **完全对齐**:`固定/增量/明确/隐含/复述/必需` 六种修饰 |
|
||
| `Issue.parent_issue` | 无直接对应 | **扩展**:通过 `KnowledgeSuggestion.parent_issue` 关联父 Issue,写入 Neo4j 时创建 `LEADS_TO` 或 `RELATES_TO` 关系 |
|
||
|
||
**图写入时的去重策略**:使用 `MERGE` 而非 `CREATE`,按 `Issue.name` / `Action.name` 唯一键幂等写入。
|
||
|
||
### 8.2 confidence 计算口径
|
||
|
||
| 来源 | 计算方式 | 说明 |
|
||
|------|---------|------|
|
||
| Dify 生成 | Dify 工作流输出中包含 `confidence` 字段(由 LLM 自评 + prompt 约束输出 0.0-1.0) | 通道 A 自动 |
|
||
| 训练师手动 | 默认 1.0(训练师录入视为最高置信) | 通道 B |
|
||
| RAGFlow 预处理 | 默认 0.85(结构化提取降一档) | 通道 C |
|
||
| Wingman 估算 | 复用现有 `_estimate_confidence()`(基于内容长度/不确定措辞启发式) | 通道 A 兜底 |
|
||
| 门控阈值 | **全局 0.7**(`settings.confidence_gate_threshold`),低于此值标记 `source_failed=True` + 前端渲染转人工 | D3 |
|
||
|
||
### 8.3 audience 判定规则
|
||
|
||
```
|
||
判定函数: determine_audience(source_type, source_data)
|
||
|
||
IF source_type == "manual" OR source_type == "document_ragflow":
|
||
→ 默认 engineer_workguide(坐席可改)
|
||
|
||
IF source_type in ("annotation", "conversation", "ai_uncertain"):
|
||
→ 查 Conversation.session_type:
|
||
"employee" → employee_quick_reply
|
||
"engineer" → engineer_workguide
|
||
(其他/未知) → employee_quick_reply(保守默认)
|
||
|
||
训练师审核时可覆盖 audience。
|
||
```
|
||
|
||
### 8.4 审计日志格式
|
||
|
||
所有审批/改写/排除动作写入审计日志(复用现有 `audit_logs` 表),格式:
|
||
```json
|
||
{
|
||
"action": "approve_suggestion|reject_suggestion|rewrite_suggestion|agent_exclude",
|
||
"target_id": "<suggestion_id or message_id>",
|
||
"operator_id": "<reviewer_id or agent_id>",
|
||
"timestamp": "ISO8601",
|
||
"details": {"previous_status": "pending", "new_status": "approved", ...}
|
||
}
|
||
```
|
||
|
||
### 8.5 后端 API 统一响应格式
|
||
|
||
所有 API 沿用现有格式:
|
||
```json
|
||
{"code": 0, "message": "success", "data": {...}}
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 任务依赖图
|
||
|
||
```mermaid
|
||
graph TD
|
||
T01["T01: 项目基础设施<br/>Neo4j + 配置 + 迁移<br/>P0 · Tier0<br/>7 文件"]
|
||
T02["T02: 数据与状态层<br/>模型 + Schema + Neo4j CRUD<br/>P0 · Tier1<br/>7 文件"]
|
||
T03["T03: 核心业务服务<br/>AI生成 + 门控 + 审批 + 写图<br/>P0 · Tier1<br/>8 文件"]
|
||
T04["T04: API 层<br/>路由挂载 + 新端点 + Vision + RAGFlow<br/>P0 · Tier1<br/>7 文件"]
|
||
T05["T05: 前端组件<br/>分诊 + 审批UI + 排除 + 队列<br/>P0/P1 · Tier1<br/>12 文件"]
|
||
|
||
T01 --> T02
|
||
T02 --> T03
|
||
T03 --> T04
|
||
T04 --> T05
|
||
|
||
style T01 fill:#FF6B6B,color:#fff
|
||
style T02 fill:#4ECDC4,color:#fff
|
||
style T03 fill:#45B7D1,color:#fff
|
||
style T04 fill:#96CEB4,color:#fff
|
||
style T05 fill:#FFEAA7,color:#333
|
||
```
|
||
|
||
**Tier 分期说明**:
|
||
- **Tier0(T01)**:Neo4j 客户端 + 图 schema + 配置 + 迁移 → **前置阶段**,必须最先完成。
|
||
- **Tier1(T02-T05)**:数据层 → 服务层 → API 层 → 前端 → **核心交付阶段**,串行依赖链。
|
||
- **不在本次迭代**:复杂场景引擎(非线性跳转/多意图并行/任务中断恢复)、敏感词 BLOCK 升级、DLP 实质整合、Neo4j 图测试容器 CI 集成(P2)。
|
||
|
||
---
|
||
*本文档为增量架构设计 v1.0,架构师高见远(software-architect),2026-07-07*
|