Files
wecom_it_smart_desk/docs/03-技术架构/增量设计-知识库迭代与痛点缓解-20260711.md
T
Simon bea288e414 feat: 2026-07-11 全量更新 - 代办集成+会议室预定+知识迭代修复+UI统一+Bug修复
== 已部署上线 (9项) ==
- 代办事项真实数据源集成 (企微审批API 8bug修复链)
- H5/坐席端 Logo样式统一+绿色背景
- 视频引导页修复 (localStorage key v2)
- 坐席端 v9 Vue版本修复 (ElMessage._context)
- 截图按钮 v10 修复 (getDisplayMedia user gesture)
- 扫码样式恢复+H5扫码登录跳转修复
- H5截图快捷键提示

== 代码完成待部署 (3项) ==
- 知识迭代3Bug修复 (#8 POST端点/#7 MERGE幂等/#6 过期检查)
- 会议室预定-小鱼易联终端 (40文件, 40/40测试通过)
- IT资产升级审批推送 (asset_service.py)

== 需求文档 (2项) ==
- 坐席端AI辅助消息框-PRD (4项新功能确认)
- 坐席端布局优化建议 v2.0 (7天计划)

== 新增文档 ==
- 日报-2026-07-11.md
- 知识迭代Bug修复报告-20260711.md
- 会议室预定-部署指南.md
- CHANGELOG.md 更新

== 测试 ==
- test_todo_integration.py: 40/40
- test_meetingroom.py: 40/40
- test_bugfix_ki_suggestions.py: 21/21
2026-07-11 23:13:10 +08:00

72 KiB
Raw Blame History

增量设计:知识库迭代与痛点缓解

文档版本v1.0
创建日期2026-07-11
文档类型:回溯文档(已部署功能)+ 前瞻设计(未实现功能)
测试报告引用docs/06-测试质量/Tier0-测试报告-20260708.md89/89 通过)
技术栈FastAPI + SQLAlchemy + PostgreSQL + Redis + Neo4j / Vue3 + Element Plus + Vant4 + ECharts


目录

  1. 概述
  2. 系统架构总览
  3. 各功能模块技术方案
  4. 功能依赖关系图
  5. 全链路数据流图
  6. 未实现功能设计
  7. 已知问题与后续优化方向

1. 概述

1.1 功能背景

IT智能服务台在持续运营中暴露出三大痛点:

  1. 知识库更新滞后:AI 回复不准确的问题需要人工发现→人工编写→人工录入,平均更新周期超过 2 周。
  2. 低置信回复无兜底AI 回复 confidence 低于阈值时,员工无感知,直接收到低质量回答,体验差。
  3. 重复知识堆积:多个来源(会话分析、标注分析、手动录入)生成的建议缺乏去重机制,导致知识图谱中出现重复 Issue 节点。

为解决上述痛点,本项目实施了"知识库迭代与痛点缓解"功能集,包含 10 个功能模块,覆盖从 AI 回复质量保障到知识图谱自动维护的完整闭环。

1.2 目标

目标 衡量指标
知识库自动迭代 会话关闭后自动生成知识建议,训练师审核后自动写入知识图谱
低置信兜底 confidence < 0.7 时前端展示转人工入口,携带上下文快照
知识去重 采纳建议前检测重复,支持合并去重操作
图谱可视化 管理后台 ECharts 力导向图展示 Neo4j 知识图谱全貌
分步分诊 复杂问题拆分为分步选择题,降低员工认知负担

1.3 范围

本功能集涉及 10 个功能模块,按部署状态分为两类:

# 功能 代码状态 部署状态 文档类型
1 分诊交互 仅前端组件 未接入后端 前瞻设计
2 置信门控 后端配置 + 前端组件 生产在线 回溯文档
3 内联审批卡片 后端 + 前端 生产在线 回溯文档
4 拓扑预览 仅原型 SVG 未实现后端子图查询 API 对接 前瞻设计
5 重复检测 后端 + 前端 生产在线 回溯文档
6 代答排除 仅前端组件方法 未实现 前瞻设计
7 知识迭代管理 47KB 服务 + 21KB API 生产在线 回溯文档
8 图谱可视化 Neo4j + ECharts Neo4j 运行中 回溯文档
9 合并去重 后端 + 前端 生产在线 回溯文档
10 会话关闭→建议→审核→写图 全链路 生产在线 回溯文档

1.4 术语表

术语 说明
KnowledgeSuggestion 知识建议,AI 分析生成的待审核知识条目
Issue 知识图谱中的问题节点(Neo4j :Issue 标签)
Action 知识图谱中的动作/解决方案节点(Neo4j :Action 标签)
confidence AI 生成置信度(0.0-1.0),门控阈值 0.7
audience 受众类型:employee_quick_reply(员工快捷回复)/ engineer_workguide(工程师作业指导)
五态流转 pending → queued → approved → applied → graph_synced
通道 A 会话/标注/AI不确定 → 自动生成知识建议
通道 B 训练师手动录入知识建议
通道 C RAGFlow 文档 ETL → 知识建议(预留,未实现)

2. 系统架构总览

2.1 架构总览图

graph TB
    subgraph "H5 员工端"
        H5_Triage[分诊卡片 TriageCard]
        H5_ConfGate[置信门控 ConfidenceGateBanner]
        H5_Chat[AI 对话]
    end

    subgraph "Agent 坐席端"
        AG_Approval[内联审批卡片 ApprovalInlineCard]
        AG_Queue[独立审批队列 ApprovalQueue]
        AG_Chat[坐席会话]
    end

    subgraph "Admin 管理后台"
        ADM_Knowledge[知识迭代管理 KnowledgeIteration]
        ADM_Graph[图谱可视化 ECharts]
    end

    subgraph "Backend FastAPI"
        API_Conv[会话 API conversations.py]
        API_KI[知识迭代 API knowledge_iteration.py]
        API_Queue[审批队列 API approval_queue.py]
        Svc_KI[知识迭代服务 KnowledgeIterationService]
        Svc_Wingman[Wingman AI 服务]
        Neo4j_Client[Neo4j 客户端]
    end

    subgraph "数据存储"
        PG[(PostgreSQL)]
        Redis[(Redis)]
        Neo4j[(Neo4j 图数据库)]
        Dify[Dify AI 平台]
    end

    %% H5 交互
    H5_Chat -->|AI回复| H5_ConfGate
    H5_Triage -->|分步选择| H5_Chat
    H5_ConfGate -->|confidence<0.7| API_Conv

    %% 会话关闭触发
    AG_Chat -->|结单| API_Conv
    API_Conv -->|异步触发| Svc_KI
    Svc_KI -->|调用AI| Svc_Wingman
    Svc_Wingman --> Dify
    Svc_KI -->|写入建议| PG

    %% 审批流程
    AG_Approval -->|采纳/驳回/改写| API_KI
    AG_Queue -->|队列审批| API_Queue
    ADM_Knowledge -->|管理审核| API_KI

    %% 知识落库 + 写图
    API_KI --> Svc_KI
    Svc_KI -->|创建KB条目| PG
    Svc_KI -->|写图| Neo4j_Client
    Neo4j_Client --> Neo4j

    %% 图谱可视化
    ADM_Graph -->|查询图数据| API_KI
    API_KI --> Neo4j_Client

    %% 重复检测
    ADM_Knowledge -->|检查重复| API_KI
    API_KI --> Svc_KI
    Svc_KI -->|查SQL| PG
    Svc_KI -->|查图| Neo4j_Client

    style H5_Triage fill:#fff3e0,stroke:#ff9800
    style H5_ConfGate fill:#e8f5e9,stroke:#4caf50
    style AG_Approval fill:#e3f2fd,stroke:#2196f3
    style Neo4j fill:#e8eaf6,stroke:#3f51b5
    style Dify fill:#fce4ec,stroke:#e91e63

2.2 技术栈分布

层级 技术选型 说明
后端框架 FastAPI + SQLAlchemy 2.0 (async) 异步 ORMAsyncSession
关系数据库 PostgreSQL knowledge_suggestions、knowledge_base 表
图数据库 Neo4j 6.2.0 (AsyncDriver) Issue/Action 节点 + 关系边
缓存 Redis 会话状态、恢复点
AI 平台 Dify (Wingman Agent) 知识建议生成、意图识别
管理后台 Vue3 + Element Plus + ECharts 列表管理 + 力导向图
坐席端 Vue3 + Element Plus 内联审批卡片 + 队列
H5 员工端 Vue3 + Vant4 分诊卡片 + 置信门控横幅
风格 企微浅色扁平 accent=#07C160

2.3 API 路由前缀

模块 前缀 说明
知识迭代管理 /api/admin/knowledge-iteration/* 12 条路由
独立审批队列 /api/admin/approval-queue/* 3 条路由
会话管理 /api/conversations/* 含结单触发

3. 各功能模块技术方案


3.1 分诊交互

功能描述

AI 分诊式回复,将复杂 IT 问题拆分为分步选择题(是/否/含概率推荐),卡片置顶悬浮展示,支持专家模式切换。

当前状态:仅前端组件(TriageCard.vue),未接入后端 API。

数据模型

classDiagram
    class TriageStep {
        +String question
        +List~TriageOption~ options
        +List~String~ collectedContext
    }

    class TriageOption {
        +String label
        +Boolean selected
        +Number probability
        +Boolean recommended
        +Boolean excluded
    }

    class TriageCard {
        +Boolean visible
        +Number step
        +Number total
        +List~TriageStep~ steps
        +Number confidence
        +toggleCollapse()
        +selectOption(idx)
        +handleConfirm()
        +handleSkip()
        +setExcludedOptions(labels)
        +setRecommendedOption(label)
    }

    TriageCard --> TriageStep : contains
    TriageStep --> TriageOption : contains

API 接口设计(前瞻 — 未实现)

方法 路径 请求 响应 说明
POST /api/h5/triage/start {conversation_id, question} {steps: TriageStep[], total: int} 发起分诊,AI 拆分复杂问题为分步选择题
POST /api/h5/triage/step {conversation_id, step_index, selected_label} {next_step: TriageStep, collected_context: string[]} 提交当前步骤选择,获取下一步
POST /api/h5/triage/skip {conversation_id, step_index} {next_step: TriageStep} 跳过当前步骤
POST /api/h5/triage/transfer {conversation_id, context: string[]} {conversation_id, status: "waiting_agent"} 分诊上下文转人工

核心流程(前瞻设计)

sequenceDiagram
    participant H5 as H5 员工端
    participant API as FastAPI 后端
    participant Dify as Dify AI
    participant DB as PostgreSQL

    H5->>API: POST /api/h5/triage/start {conversation_id, question}
    API->>Dify: 调用 Dify 分诊 prompt(拆分复杂问题为分步)
    Dify-->>API: 返回 steps[] (question + options + probability)
    API-->>H5: {steps, total}

    loop 每一步
        H5->>H5: 展示 TriageCard,员工选择选项
        H5->>API: POST /api/h5/triage/step {step_index, selected_label}
        API->>DB: 记录已收集上下文
        API->>Dify: 根据选择动态调整后续步骤
        Dify-->>API: 返回 next_step
        API-->>H5: {next_step, collected_context}
    end

    alt 所有步骤完成
        H5->>API: POST /api/h5/triage/complete
        API->>Dify: 根据收集的上下文生成最终答案
        Dify-->>API: 返回最终回复
        API-->>H5: 返回 AI 回复
    else 转人工
        H5->>API: POST /api/h5/triage/transfer {context}
        API->>DB: 会话状态 → waiting_agent
        API-->>H5: 转人工成功
    end

前端交互设计

组件文件frontend-h5/src/components/TriageCard.vue

交互元素 说明
置顶悬浮 position: sticky; top: 0; z-index: 100
步骤进度 "第 X/Y 步" 显示在标题栏
选项列表 单选模式,点击选中/取消
概率展示 百分比标签(≥70% 绿色高亮),不披露原始 confidence
推荐标记 推荐 标签(坐席侧设置)
排除标记 已排除 标签 + 灰显 + 不可点击
专家模式 van-switch 开关,开启后展示后续步骤预览
折叠/展开 点击标题栏切换
底部操作 "跳过" + "下一步/完成"

关键设计约束(D4 硬约束)

  • 一次给几步由 AI 判复杂度自适应
  • 概率展示为百分比(不披露原始 confidence 给员工)
  • 专家模式默认关(分步),老手可开一把梭
  • 卡片置顶/悬浮

技术选型与依赖

依赖 版本 用途
Vue3 ^3.4 响应式框架
Vant4 ^4.8 移动端 UIvan-switch, van-button, van-tag

部署状态

未实现 — 前端组件已开发(530 行),但后端 API 未实现,Dify 分诊 prompt 未配置。


3.2 置信门控

功能描述

当 AI 回复的 confidence 低于全局阈值 0.7 时,在 H5 前端渲染"转人工"入口并附已收集的上下文快照。门控阈值可通过 settings.confidence_gate_threshold 配置。

当前状态:生产在线。后端配置项 + 前端组件 + composable 逻辑封装。

数据模型

classDiagram
    class ConfidenceGateConfig {
        +Float confidence_gate_threshold = 0.7
        +String source = "settings.confidence_gate_threshold"
    }

    class ConfidenceGateResult {
        +Boolean triggered
        +Number displayProbability
        +String severity
        +Boolean shouldShowTransfer
    }

    class useConfidenceGate {
        +Ref~Float~ gateThreshold
        +Ref~Number~ lastConfidence
        +Ref~String[]~ contextSnapshot
        +Computed~ConfidenceGateResult~ gateResult
        +Computed~Boolean~ showGateBanner
        +evaluateConfidence(confidence, context)
        +addContext(items)
        +prepareTransferToHuman() String[]
        +reset()
        +updateThreshold(newThreshold)
    }

    class ConfidenceGateBanner {
        +Boolean visible
        +Number confidence
        +String[] contextSnapshot
        +String reason
        +displayProbability
        +severityClass
        +handleTransferToHuman()
        +handleContinueAI()
    }

    useConfidenceGate --> ConfidenceGateResult : produces
    ConfidenceGateBanner --> useConfidenceGate : consumes

配置项

配置项 默认值 来源 说明
confidence_gate_threshold 0.7 config.pyCONFIDENCE_GATE_THRESHOLD 环境变量 全局置信门控阈值
# backend/app/config.py
confidence_gate_threshold: float = 0.7

核心流程

sequenceDiagram
    participant H5 as H5 员工端
    participant Gate as useConfidenceGate
    participant Banner as ConfidenceGateBanner
    participant API as FastAPI 后端

    H5->>API: 发送问题
    API->>API: AI 回复 + confidence 值
    API-->>H5: {reply, confidence: 0.45}

    H5->>Gate: evaluateConfidence(0.45, context)
    Gate->>Gate: triggered = 0.45 < 0.7 = true
    Gate->>Gate: severity = "warning" (0.3 ≤ 0.45 < 0.5)
    Gate-->>H5: gateResult = {triggered: true, shouldShowTransfer: true}

    H5->>Banner: visible=true, confidence=0.45
    Banner->>Banner: displayProbability = 45%
    Banner->>Banner: severityClass = "warning"
    Banner-->>H5: 展示横幅 + "转人工" + "继续询问 AI"

    alt 员工点击转人工
        Banner->>Gate: prepareTransferToHuman()
        Gate-->>Banner: contextSnapshot[]
        Banner->>API: POST /api/conversations/transfer {context}
        API-->>Banner: 转人工成功
    else 员工点击继续询问 AI
        Banner->>Gate: dismissGate()
        Gate-->>H5: dismissed = true
    end

前端交互设计

组件文件frontend-h5/src/components/ConfidenceGateBanner.vue
逻辑封装frontend-h5/src/composables/useConfidenceGate.ts

严重程度 条件 配色 图标 文案
critical confidence < 0.3 红色背景 #fff0f0 + 红色左边框 #ee0a24 🚨 AI 非常不确定此回复,建议转人工处理
warning 0.3 ≤ confidence < 0.5 橙色背景 #fff7f0 + 橙色左边框 #ff976a ⚠️ AI 对此回复把握较低,可能需要人工协助
caution 0.5 ≤ confidence < 0.7 蓝色背景 #f0f7ff + 蓝色左边框 #1989fa 💡 AI 对此回复不太确定,你可选择转人工确认

展示元素

  • AI 把握度:百分比整数(如 "45%"),不显示原始 0.45
  • 已收集上下文快照:标签列表
  • 操作按钮:"转人工处理"danger+ "继续询问 AI"default
  • 反馈理由选项:答非所问/信息不完整/回答不准确/过于笼统/其他

技术选型与依赖

依赖 版本 用途
Vue3 ^3.4 Composition API
Vant4 ^4.8 van-button, van-tag

部署状态

生产在线 — 后端配置项 confidence_gate_threshold=0.7 已在 config.py 中定义,前端 ConfidenceGateBanner.vue + useConfidenceGate.ts 已部署。


3.3 内联审批卡片

功能描述

坐席在会话中直接审批知识建议的内联卡片,支持采纳/驳回/改写操作,展示拓扑预览、confidence、audience 下拉编辑。未处理的提案在会话关闭后进入独立审批队列。

当前状态:生产在线。后端 API + 前端组件完整实现。

数据模型

classDiagram
    class KnowledgeSuggestion {
        +String id
        +String suggestion_type
        +String status
        +String title
        +String content
        +String category
        +List~String~ tags
        +String source_type
        +List~String~ source_data
        +Float confidence
        +String audience
        +String issue
        +String action
        +String relation_type
        +String parent_issue
        +Dict graph_meta
        +String graph_sync_status
        +Boolean source_failed
        +DateTime queued_at
        +DateTime applied_at
        +String reviewer_id
        +DateTime reviewed_at
        +String reject_reason
    }

    class SuggestionStatusEnum {
        <<enumeration>>
        pending
        queued
        approved
        rejected
        applied
        graph_synced
        expired
    }

    class ApprovalInlineCard {
        +SuggestionData suggestion
        +Boolean readonly
        +DuplicateItem[] duplicates
        +handleApprove()
        +handleReject()
        +toggleRewrite()
        +submitRewrite()
        +onAudienceChange()
    }

    ApprovalInlineCard --> KnowledgeSuggestion : displays
    KnowledgeSuggestion --> SuggestionStatusEnum : status

状态机

stateDiagram-v2
    [*] --> pending : AI生成/手动录入

    pending --> queued : 会话关闭未处理
    pending --> approved : 内联审批通过
    pending --> rejected : 驳回
    pending --> expired : 超时

    queued --> approved : 队列审批通过
    queued --> rejected : 队列驳回
    queued --> expired : 超时

    approved --> applied : KB条目落库
    approved --> rejected : 撤销

    applied --> graph_synced : Neo4j写图成功

    rejected --> [*] : 终态
    graph_synced --> [*] : 终态
    expired --> [*] : 终态

合法状态转换表schemas/enums.py):

当前状态 允许转换到
pending queued, approved, rejected, expired
queued approved, rejected, expired
approved applied, rejected
applied graph_synced
graph_synced (终态)
rejected (终态)
expired (终态)

API 接口设计

方法 路径 请求体 响应 说明
POST /api/admin/knowledge-iteration/suggestions/{id}/approve {} {code:0, data: KnowledgeSuggestionResponse} 审核通过(触发 KB 落库 + Neo4j 写图)
POST /api/admin/knowledge-iteration/suggestions/{id}/reject {reject_reason: string} {code:0, data: KnowledgeSuggestionResponse} 审核拒绝
POST /api/admin/knowledge-iteration/suggestions/{id}/rewrite {title?, content?, category?, ...} {code:0, data: KnowledgeSuggestionResponse} 改写提案(重置为 pending
POST /api/admin/knowledge-iteration/suggestions/{id}/queue {code:0, data: KnowledgeSuggestionResponse} 放入独立队列
POST /api/admin/knowledge-iteration/suggestions/{id}/dequeue-approve {code:0, data: KnowledgeSuggestionResponse} 队列中审批通过
GET /api/admin/approval-queue/queued ?status=&audience=&page=&page_size= {code:0, data:{total, items[]}} 获取队列列表
GET /api/admin/approval-queue/queued/stats {code:0, data:{queued_total, pending_total, by_audience, by_source_type}} 队列统计
POST /api/admin/approval-queue/queued/{id}/dequeue-approve {code:0, data: KnowledgeSuggestionResponse} 队列审批通过

核心流程

sequenceDiagram
    participant AG as 坐席端 ApprovalInlineCard
    participant API as FastAPI
    participant Svc as KnowledgeIterationService
    participant DB as PostgreSQL
    participant Neo4j as Neo4j

    Note over AG: 提案 status=pending/queued

    alt 采纳
        AG->>API: POST /suggestions/{id}/approve
        API->>Svc: approve_suggestion(db, id, reviewer_id, neo4j_client)
        Svc->>Svc: 校验状态转换 pending/queued → approved
        Svc->>DB: 更新 status=approved, reviewer_id, reviewed_at
        Svc->>DB: 创建 KnowledgeBase 条目 → status=applied
        Svc->>Neo4j: sync_to_neo4j (merge_issue + merge_action + create_relation)
        alt 写图成功
            Svc->>DB: status=graph_synced, graph_sync_status=synced
            Svc->>DB: 回填 kb.graph_node_uuid
        else 写图失败
            Svc->>DB: graph_sync_status=failed
        end
        Svc-->>API: suggestion (graph_synced)
        API-->>AG: {code:0, data: suggestion}
    end

    alt 驳回
        AG->>API: POST /suggestions/{id}/reject {reject_reason}
        API->>Svc: reject_suggestion(db, id, reviewer_id, reason)
        Svc->>DB: status=rejected, reject_reason
        Svc-->>API: suggestion (rejected)
        API-->>AG: {code:0, data: suggestion}
    end

    alt 改写
        AG->>API: POST /suggestions/{id}/rewrite {title, content, ...}
        API->>Svc: rewrite_suggestion(db, id, reviewer_id, data)
        Svc->>DB: 更新字段 + status=pending (重置)
        Svc-->>API: suggestion (pending)
        API-->>AG: {code:0, data: suggestion}
    end

    alt 入队
        AG->>API: POST /suggestions/{id}/queue
        API->>Svc: queue_suggestion(db, id)
        Svc->>Svc: 校验 pending → queued
        Svc->>DB: status=queued, queued_at
        Svc-->>API: suggestion (queued)
        API-->>AG: {code:0, data: suggestion}
    end

前端交互设计

组件文件frontend-agent/src/components/chat/ApprovalInlineCard.vue

卡片区域 元素 说明
头部 类型图标 + 类型文本 💡新FAQ / 🔄内容更新 / 🔀合并去重
头部 置信度标签 ≥70% success / ≥50% warning / <50% danger
头部 状态标签 pending/queued/approved/rejected/applied/graph_synced
头部 重复标记 ⚠可能重复(danger, effect=dark
重复警告 重复项列表 名称 + 类型标签 + 相似度百分比
核心信息 标题 + 内容 内容截断 150 字符
拓扑预览 SVG 缩略图 parent_issue → issue → action 节点链
拓扑预览 文本流 蓝色 parent → 绿色 issue → 橙色 action
audience 下拉选择 employee_quick_reply / engineer_workguide
改写表单 标题/内容/分类输入框 展开时显示,提交后重置 pending
操作按钮 采纳(success) / 改写(warning) / 驳回(danger) readonly 时显示已处理状态

技术选型与依赖

依赖 版本 用途
Vue3 ^3.4 Composition API
Element Plus ^2.6 el-tag, el-select, el-input, el-button

部署状态

生产在线 — 后端 knowledge_iteration.py + approval_queue.py + 前端 ApprovalInlineCard.vue + ApprovalQueue.vue 均已部署。


3.4 拓扑预览

功能描述

在审批卡片中展示知识建议对应的图谱拓扑结构(Issue → Action 小缩略图),帮助训练师直观理解建议的图谱关系。

当前状态:仅前端 SVG 原型缩略图。后端 query_issue_subgraph 方法已实现但未通过 API 暴露给前端调用。

数据模型

拓扑预览数据来源于 KnowledgeSuggestion 的图字段:

classDiagram
    class TopologyPreview {
        +String parent_issue
        +String issue
        +String action
        +String relation_type
    }

    class MiniGraphNode {
        +Number x
        +Number y
        +String label
        +String type
    }

    class MiniGraphEdge {
        +Number x1
        +Number y1
        +Number x2
        +Number y2
    }

    TopologyPreview --> MiniGraphNode : generates
    TopologyPreview --> MiniGraphEdge : generates

已实现部分

前端 SVG 缩略图ApprovalInlineCard.vue):

  • 根据 suggestion.parent_issuesuggestion.issuesuggestion.action 三个字段生成节点
  • 节点颜色:parent=蓝色 #409eff、issue=绿色 #67c23a、action=橙色 #e6a23c
  • 节点间距 90px,半径 issue=12px / action=9px
  • 虚线连线 stroke-dasharray="4,2"
  • 标签超过 6 字符截断为 "前6字…"

后端子图查询neo4j_client.py):

  • query_issue_subgraph(issue_name, depth=1) 方法已实现
  • 以指定 Issue 为中心,向外扩展 depth 层关系
  • 返回 ECharts 格式的 {nodes, links}

API 接口设计(前瞻 — 需新增)

方法 路径 请求 响应 说明
GET /api/admin/knowledge-iteration/suggestions/{id}/topology {code:0, data:{nodes:[], links:[]}} 获取建议对应的图谱子图拓扑

前瞻设计方案

  1. 新增 API 端点:在 knowledge_iteration.py 中添加 /suggestions/{id}/topology 路由
  2. 调用链API → neo4j_client.query_issue_subgraph(issue_name, depth=1) → 返回子图 JSON
  3. 前端增强ApprovalInlineCard.vue 中将 SVG 缩略图替换为 ECharts mini graph(或保留 SVG + 可点击展开)
  4. 交互:点击缩略图弹出全屏子图预览 modal

部署状态

部分实现 — 前端 SVG 缩略图已实现(基于 suggestion 字段静态渲染),后端子图查询方法已实现但未通过 API 暴露。


3.5 重复检测

功能描述

在采纳知识建议前检测是否存在重复,利用 Neo4j 图结构(同名 Issue)+ SQL 文本相似(标题模糊匹配)双重检测,返回重复项列表供训练师参考。

当前状态:生产在线。

数据模型

classDiagram
    class DuplicateResult {
        +String type
        +String name
        +String suggestion_id
        +String suggestion_type
        +String issue
        +String action
        +String status
        +Float similarity
        +String source
    }

    class FindDuplicatesParams {
        +String issue_name
        +String title
        +String suggestion_id
        +Neo4jClient neo4j_client
    }

    class KnowledgeIterationService {
        +find_duplicates(db, issue_name, title, suggestion_id, neo4j_client) List~DuplicateResult~
        +_calc_similarity(a, b) Float
    }

    KnowledgeIterationService --> DuplicateResult : produces

重复检测类型

类型 来源 检测方式 相似度计算
same_issue Neo4j 同名 Issue 节点精确匹配 1.0
similar_issue Neo4j Issue 名称前缀匹配(前 10 字符) 公共前缀 / 最大长度
title_similar SQL 标题 ILIKE 模糊匹配(前 20 字符) 前缀匹配 + 长度比

相似度计算算法_calc_similarity):

  1. 完全匹配 → 1.0
  2. 包含匹配 → 0.5 + 0.5 × (shorter / longer)
  3. 公共前缀匹配 → common_prefix_len / max_len

API 接口设计

方法 路径 请求 响应 说明
GET /api/admin/knowledge-iteration/suggestions/{id}/duplicates {code:0, data:{suggestion_id, has_duplicates: bool, duplicates: DuplicateResult[]}} 检查指定建议是否存在重复

核心流程

sequenceDiagram
    participant ADM as 管理后台
    participant API as FastAPI
    participant Svc as KnowledgeIterationService
    participant DB as PostgreSQL
    participant Neo4j as Neo4j

    ADM->>API: GET /suggestions/{id}/duplicates
    API->>DB: 查询 suggestion (获取 issue, title)
    DB-->>API: suggestion

    API->>Svc: find_duplicates(db, issue, title, id, neo4j_client)

    rect rgb(245, 247, 250)
        Note over Svc,DB: 1. SQL 层面:标题模糊匹配
        Svc->>DB: SELECT * FROM knowledge_suggestions WHERE status IN (approved, applied, graph_synced) AND title ILIKE '%keyword%' AND id != suggestion_id
        DB-->>Svc: sql_duplicates[]
        Svc->>Svc: 计算 title_similar 相似度
    end

    rect rgb(232, 234, 246)
        Note over Svc,Neo4j: 2. Neo4j 层面:同名 Issue
        Svc->>Neo4j: find_issue_by_name(issue_name)
        Neo4j-->>Svc: existing_issue (含 source_suggestion_id)
        Svc->>DB: 查关联 suggestion
        Svc->>Svc: 记录 same_issue (similarity=1.0)
    end

    rect rgb(232, 234, 246)
        Note over Svc,Neo4j: 3. Neo4j 层面:相似 Issue(前缀匹配)
        Svc->>Neo4j: MATCH (i:Issue) WHERE i.name STARTS WITH $prefix AND i.name <> $exact_name
        Neo4j-->>Svc: similar_issues[]
        Svc->>Svc: 计算 similar_issue 相似度
    end

    Svc->>Svc: 按相似度降序排列
    Svc-->>API: duplicates[]
    API-->>ADM: {code:0, data:{has_duplicates, duplicates}}

前端交互设计

交互 说明
触发 详情弹窗中点击"检查重复"按钮
结果展示 弹窗显示重复项表格
无重复 绿色文字 " 未发现重复,可安全采纳"
有重复 橙色 Alert 警告 + 重复项表格
表格列 名称 / 匹配类型(同名Issue/相似Issue/标题相似)/ 相似度百分比 / 操作(合并)
合并操作 点击"合并"调用 merge API

部署状态

生产在线 — 后端 find_duplicates 方法 + API 路由 + 前端重复检查弹窗均已部署。


3.6 代答排除

功能描述

坐席在分诊卡片中排除某些选项,被排除的选项灰显且不可点击,引导员工选择更合适的路径。

当前状态:仅前端组件方法(setExcludedOptions),未接入后端。

数据模型

classDiagram
    class TriageOption {
        +String label
        +Boolean selected
        +Boolean excluded
        +Boolean recommended
    }

    class ExclusionRequest {
        +String conversation_id
        +List~String~ excluded_labels
        +String reason
    }

已实现部分

前端方法TriageCard.vue):

// 暴露方法供父组件调用
defineExpose({
  /** 设置坐席排除项 */
  setExcludedOptions(labels: string[]) {
    currentOptions.value.forEach(o => {
      if (labels.includes(o.label)) {
        o.excluded = true
        o.selected = false
      }
    })
  },
  /** 设置坐席推荐项 */
  setRecommendedOption(label: string) {
    currentOptions.value.forEach(o => {
      o.recommended = o.label === label
    })
  },
})

排除样式

  • 边框:#ebedf0(灰)
  • 背景:#f5f5f5(浅灰)
  • 透明度:0.5
  • 光标:not-allowed
  • 文字:删除线

API 接口设计(前瞻 — 未实现)

方法 路径 请求 响应 说明
POST /api/agent/triage/exclude {conversation_id, excluded_labels: string[]} {code:0, data:{excluded: true}} 坐席排除分诊选项
POST /api/agent/triage/recommend {conversation_id, recommended_label: string} {code:0, data:{recommended: true}} 坐席推荐分诊选项

前瞻设计方案

  1. 后端新增:在 conversations API 或新建 triage API 中添加排除/推荐端点
  2. WebSocket 推送:坐席排除选项后,通过 WS 实时推送到 H5 员工端
  3. Dify Prompt 增强:将排除的选项传入 Dify,影响后续步骤生成
  4. 审计日志:记录坐席排除/推荐操作

部署状态

未实现 — 前端 TriageCard.vuesetExcludedOptions / setRecommendedOption 方法已定义,但无后端 API 对接,无 WS 推送机制。


3.7 知识迭代管理

功能描述

管理后台的知识迭代提案管理页面,支持提案列表(含筛选/分页)、审阅提案详情、图字段编辑(issue/action/relation/parent)、训练师手动录入入口(通道 B)、触发分析。

当前状态:生产在线。47KB 服务 + 21KB API + 完整前端页面。

数据模型

classDiagram
    class KnowledgeSuggestion {
        +String id : UUID
        +String suggestion_type : "new_faq"|"update"|"outdated"
        +String status : "pending"|"queued"|"approved"|"rejected"|"applied"|"graph_synced"|"expired"
        +String title
        +String content
        +String category : "硬件"|"软件"|"网络"|"安全"|"账号"|"其他"
        +List~String~ tags : JSON
        +String source_type : "annotation"|"conversation"|"ai_uncertain"|"manual"|"document_ragflow"|"merge"
        +List~String~ source_data : JSON
        +String reason
        +Float confidence
        +String audience : "employee_quick_reply"|"engineer_workguide"
        +String issue
        +String action
        +String relation_type : "LEADS_TO"|"RELATES_TO"|"CAN_JUMP_TO"
        +String parent_issue
        +Dict graph_meta : JSON
        +String graph_sync_status : "pending"|"synced"|"failed"
        +Boolean source_failed
        +DateTime queued_at
        +DateTime applied_at
        +String reviewer_id
        +DateTime reviewed_at
        +String reject_reason
        +DateTime created_at
        +DateTime updated_at
    }

    class KnowledgeBase {
        +String id : UUID
        +String category
        +String title
        +String content
        +List~String~ tags : JSON
        +Integer view_count
        +Integer use_count
        +String graph_sync_status
        +String graph_node_uuid
        +DateTime created_at
        +DateTime updated_at
    }

    class KnowledgeIterationService {
        +Float confidence_gate_threshold
        +generate_knowledge_suggestion(db, source_type, source_data, reason) KnowledgeSuggestion
        +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
        +_build_context_from_source(db, source_type, source_data) List
        +_auto_tag_audience(db, source_type, source_data) AudienceEnum
        +_apply_confidence_gate(confidence) Boolean
        +_check_existing_suggestion(db, source_id) Boolean
        +approve_suggestion(db, id, reviewer_id, neo4j_client) KnowledgeSuggestion
        +reject_suggestion(db, id, reviewer_id, reason) KnowledgeSuggestion
        +rewrite_suggestion(db, id, reviewer_id, data) KnowledgeSuggestion
        +queue_suggestion(db, id) KnowledgeSuggestion
        +dequeue_approve(db, id, reviewer_id, neo4j_client) KnowledgeSuggestion
        +sync_to_neo4j(neo4j_client, suggestion) Boolean
        +get_suggestion_stats(db) Dict
        +get_queue_stats(db) Dict
    }

    KnowledgeIterationService --> KnowledgeSuggestion : manages
    KnowledgeIterationService --> KnowledgeBase : creates

ER 图

erDiagram
    knowledge_suggestions ||--o| knowledge_base : "approved → creates KB"
    knowledge_suggestions {
        string id PK
        string suggestion_type
        string status
        string title
        text content
        string category
        json tags
        string source_type
        json source_data
        float confidence
        string audience
        string issue
        string action
        string relation_type
        string parent_issue
        json graph_meta
        string graph_sync_status
        boolean source_failed
        datetime queued_at
        datetime applied_at
        string reviewer_id
        datetime reviewed_at
        text reject_reason
        text reason
        datetime created_at
        datetime updated_at
    }

    knowledge_base {
        string id PK
        string category
        string title
        text content
        json tags
        integer view_count
        integer use_count
        string graph_sync_status
        string graph_node_uuid
        datetime created_at
        datetime updated_at
    }

数据库索引

索引名 字段 用途
idx_suggestion_status status 按状态筛选
idx_suggestion_type suggestion_type 按类型筛选
idx_suggestion_created created_at 按时间排序
idx_suggestion_audience audience 按受众筛选
idx_suggestion_confidence confidence 按置信度范围筛选
idx_suggestion_graph_sync graph_sync_status 按图同步状态筛选

API 接口设计

方法 路径 请求参数 响应 说明
POST /api/admin/knowledge-iteration/analyze ?days=7 {code:0, data:{annotations_analyzed, conversations_analyzed, suggestions_generated}} 触发分析并生成建议
GET /api/admin/knowledge-iteration/suggestions ?status=&suggestion_type=&audience=&confidence_min=&confidence_max=&page=&page_size= {code:0, data:{total, items[]}} 获取建议列表
GET /api/admin/knowledge-iteration/suggestions/{id} {code:0, data: KnowledgeSuggestionResponse} 获取建议详情
POST /api/admin/knowledge-iteration/suggestions/{id}/approve {} {code:0, data: KnowledgeSuggestionResponse} 审核通过
POST /api/admin/knowledge-iteration/suggestions/{id}/reject {reject_reason} {code:0, data: KnowledgeSuggestionResponse} 审核拒绝
POST /api/admin/knowledge-iteration/suggestions/{id}/rewrite {title?, content?, ...} {code:0, data: KnowledgeSuggestionResponse} 改写提案
POST /api/admin/knowledge-iteration/suggestions/{id}/queue {code:0, data: KnowledgeSuggestionResponse} 放入独立队列
POST /api/admin/knowledge-iteration/suggestions/{id}/dequeue-approve {code:0, data: KnowledgeSuggestionResponse} 队列中审批
GET /api/admin/knowledge-iteration/stats {code:0, data: KnowledgeSuggestionStatsResponse} 获取统计
GET /api/admin/knowledge-iteration/graph ?limit=100&issue_name= {code:0, data:{nodes:[], links:[]}} 获取知识图谱数据
GET /api/admin/knowledge-iteration/suggestions/{id}/duplicates {code:0, data:{suggestion_id, has_duplicates, duplicates[]}} 检查重复
POST /api/admin/knowledge-iteration/suggestions/{id}/merge {duplicate_id} {code:0, data: KnowledgeSuggestionResponse} 合并重复建议

分析与生成流程

sequenceDiagram
    participant ADM as 管理后台
    participant API as FastAPI
    participant Svc as KnowledgeIterationService
    participant Wingman as WingmanService
    participant Dify as Dify AI
    participant DB as PostgreSQL

    ADM->>API: POST /analyze?days=7
    API->>Svc: analyze_and_generate_suggestions(db, days=7)

    rect rgb(255, 245, 230)
        Note over Svc,DB: 1. 分析标注数据(useless 标注 ≥3 次)
        Svc->>DB: SELECT * FROM conversation_annotations WHERE feedback='useless' AND created_at >= since
        DB-->>Svc: annotations[]
        Svc->>Svc: 按 message_id 分组统计高频错误
        loop 每个高频错误 (count ≥ 3)
            Svc->>Svc: _generate_update_suggestion()
            Svc->>Wingman: generate_knowledge_suggestion(context_messages)
            Wingman->>Dify: 调用 Dify API
            Dify-->>Wingman: {title, content, category, tags, confidence, issue, action, ...}
            Wingman-->>Svc: ai_result
            Svc->>Svc: 置信门控: confidence < 0.7 → source_failed=True
            Svc->>Svc: audience 自动标注
            Svc->>DB: INSERT knowledge_suggestion
        end
    end

    rect rgb(230, 245, 255)
        Note over Svc,DB: 2. 分析会话数据(waiting_agent/agentServing
        Svc->>DB: SELECT * FROM conversations WHERE status IN ('waiting_agent','agentServing') AND created_at >= since
        DB-->>Svc: conversations[]
        Svc->>Svc: 采样 min(20, len)
        loop 每个采样会话
            Svc->>Svc: 检查是否已有 pending 建议(避免重复)
            Svc->>Svc: _generate_new_faq_suggestion()
            Svc->>Wingman: generate_knowledge_suggestion(context_messages)
            Wingman->>Dify: 调用 Dify API
            Dify-->>Wingman: ai_result
            Wingman-->>Svc: ai_result
            Svc->>Svc: 置信门控 + audience 标注
            Svc->>DB: INSERT knowledge_suggestion
        end
    end

    Svc-->>API: {annotations_analyzed, conversations_analyzed, suggestions_generated}
    API-->>ADM: {code:0, data: result}

audience 自动标注规则(D8

source_type 判定逻辑 audience
manual 直接判定 engineer_workguide
document_ragflow 直接判定 engineer_workguide
annotation 查 Conversation → 默认 employee_quick_reply
conversation 查 Conversation → 默认 employee_quick_reply
ai_uncertain 查 Conversation → 默认 employee_quick_reply
其他/未知 保守默认 employee_quick_reply

置信门控逻辑(D3

# 置信门控:confidence < 0.7 → source_failed=True
if not source_failed and confidence < self.confidence_gate_threshold:
    source_failed = True
    logger.info(f"置信度 {confidence} 低于门控阈值 {self.confidence_gate_threshold},标记 source_failed")

门控效果

  • source_failed=True 的建议标题为 [生成失败] 新FAQ建议[生成失败] 优化建议
  • 前端卡片样式变红(approval-inline-card--failed
  • 不影响审批流程,训练师仍可手动改写后采纳

前端交互设计

页面文件frontend-admin/src/views/KnowledgeIteration.vue

页面区域 功能
页面标题 "📚 知识迭代管理"
视图切换 列表 / 图谱(el-button-group
操作按钮 手动录入(通道 B/ 触发分析
统计概要 待审核 / 队列中 / 已通过 / 已应用 / 已同步
筛选栏 状态 / 受众 / 置信度下限 / 置信度上限
提案表格 标题 / 类型 / 状态 / 置信度 / 受众 / 来源 / 创建时间 / 操作
操作按钮 采纳 / 驳回 / 详情
分页 el-pagination
详情弹窗 标题/内容/分类/受众编辑 + 图字段编辑(Issue/Action/关系类型/父Issue
重复检查 检查重复按钮 → 重复结果弹窗
手动录入 标题/内容/分类/受众/图字段 → 提交(confidence=1.0, source_type=manual

部署状态

生产在线 — 后端 12 条 API 路由已注册,47KB 服务文件完整实现,前端页面 980 行 Vue3 组件已部署。


3.8 图谱可视化

功能描述

管理后台使用 ECharts 力导向图可视化 Neo4j 知识图谱,支持全图查询和按 Issue 名称的子图查询。

当前状态Neo4j 运行中,ECharts 可视化已部署。

数据模型

classDiagram
    class IssueNode {
        +String uuid
        +String name
        +String category
        +DateTime created_at
        +DateTime updated_at
        +String source_suggestion_id
    }

    class ActionNode {
        +String uuid
        +String name
        +String description
        +DateTime created_at
        +String source_suggestion_id
    }

    class RelationEdge {
        +String from_uuid
        +String to_uuid
        +String type : "LEADS_TO"|"RELATES_TO"|"CAN_JUMP_TO"
        +Integer order
        +Float weight
    }

    class Neo4jClient {
        +String uri
        +String user
        +String password
        +String database
        +AsyncDriver _driver
        +initialize()
        +close()
        +health_check() Boolean
        +execute_write_query(cypher, params)
        +execute_read_query(cypher, params)
        +merge_issue(name, category, props) IssueNode
        +merge_action(name, props) ActionNode
        +find_issue_by_name(name) IssueNode
        +create_relation(from_uuid, to_uuid, rel) Boolean
        +query_full_graph(limit) Dict
        +query_issue_subgraph(issue_name, depth) Dict
    }

    Neo4jClient --> IssueNode : manages
    Neo4jClient --> ActionNode : manages
    Neo4jClient --> RelationEdge : manages
    IssueNode --> RelationEdge : from
    ActionNode --> RelationEdge : to

Neo4j 图 Schema

约束

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)
CREATE INDEX action_name IF NOT EXISTS FOR (a:Action) ON (a.name)

API 接口设计

方法 路径 请求参数 响应 说明
GET /api/admin/knowledge-iteration/graph ?limit=100&issue_name= {code:0, data:{nodes:[], links:[]}} 获取知识图谱数据

响应数据格式ECharts 力导向图兼容):

{
  "code": 0,
  "data": {
    "nodes": [
      {"id": "uuid", "name": "VPN问题", "category": "网络", "label": "VPN问题", "type": "issue"},
      {"id": "uuid", "name": "个人VPN开通", "category": "", "label": "个人VPN开通", "type": "action"}
    ],
    "links": [
      {"source": "issue_uuid", "target": "action_uuid", "type": "LEADS_TO", "weight": 1.0}
    ]
  }
}

核心流程

sequenceDiagram
    participant ADM as 管理后台
    participant API as FastAPI
    participant Client as Neo4jClient
    participant Neo4j as Neo4j

    ADM->>API: GET /graph?limit=200
    API->>Client: get_neo4j_client()

    alt Neo4j 不可用
        Client-->>API: None
        API-->>ADM: {code:0, data:{nodes:[], links:[]}, message:"Neo4j 不可用"}
    end

    alt 全图查询(无 issue_name
        Client->>Neo4j: MATCH (i:Issue) RETURN ... LIMIT $limit
        Neo4j-->>Client: issue_nodes[]
        Client->>Neo4j: MATCH (a:Action) RETURN ... LIMIT $limit
        Neo4j-->>Client: action_nodes[]
        Client->>Neo4j: MATCH (n)-[r]->(m) WHERE ... LIMIT $limit*3
        Neo4j-->>Client: relations[]
    else 子图查询(有 issue_name
        Client->>Neo4j: MATCH path = (center:Issue {name: $name})-[*0..1]-(neighbor) ...
        Neo4j-->>Client: subgraph_nodes[]
        Client->>Neo4j: MATCH (center:Issue {name: $name})-[r*1..1]-(neighbor) ...
        Neo4j-->>Client: subgraph_links[]
    end

    Client-->>API: {nodes, links}
    API-->>ADM: {code:0, data: graph_data}

前端交互设计

配置项 说明
图表类型 graph (force layout) ECharts 力导向图
Issue 节点 绿色 #67c23a, symbolSize=28 问题节点
Action 节点 橙色 #e6a23c, symbolSize=22 动作节点
连线颜色 #c0c4cc, curveness=0.3 曲线连线
连线宽度 max(0.5, weight * 1.5) 按 weight 粗细
排斥力 repulsion=300 力导向参数
重力 gravity=0.1 力导向参数
边长度 [100, 250] 边长度范围
缩放 roam=true 支持鼠标缩放平移
高亮 focus='adjacency' 悬停高亮相邻节点
筛选 按 Issue 名称筛选子图 留空查全图
节点/关系计数 实时显示 "节点: X
响应式 ResizeObserver 自动 resize

Neo4j 连接配置

配置项 默认值 环境变量
neo4j_uri bolt://localhost:7687 NEO4J_URI
neo4j_user neo4j NEO4J_USER
neo4j_password (无默认值) NEO4J_PASSWORD
neo4j_database neo4j NEO4J_DATABASE
neo4j_max_connection_lifetime 3600(秒)
neo4j_max_connection_pool_size 50
neo4j_connection_acquisition_timeout 30(秒)

部署状态

生产在线 — Neo4j 容器 wecom_it_neo4j 运行中,Neo4j 6.2.0 驱动已安装,API 路由已注册,ECharts 可视化已部署。


3.9 合并去重

功能描述

将重复的知识建议合并到主建议中,标签和元数据合并,重复建议标记为 rejected(合并归入)。

当前状态:生产在线。

数据模型

classDiagram
    class MergeRequest {
        +String primary_id
        +String duplicate_id
        +String reviewer_id
    }

    class MergeResult {
        +KnowledgeSuggestion primary
        +KnowledgeSuggestion duplicate
    }

    class KnowledgeIterationService {
        +merge_suggestions(db, primary_id, duplicate_id, reviewer_id) KnowledgeSuggestion
    }

    MergeRequest --> KnowledgeIterationService : input
    KnowledgeIterationService --> MergeResult : output

API 接口设计

方法 路径 请求体 响应 说明
POST /api/admin/knowledge-iteration/suggestions/{id}/merge {duplicate_id: string} {code:0, data: KnowledgeSuggestionResponse} 合并重复建议

核心流程

sequenceDiagram
    participant ADM as 管理后台
    participant API as FastAPI
    participant Svc as KnowledgeIterationService
    participant DB as PostgreSQL

    ADM->>API: POST /suggestions/{primary_id}/merge {duplicate_id}
    API->>Svc: merge_suggestions(db, primary_id, duplicate_id, reviewer_id)

    Svc->>DB: SELECT * FROM knowledge_suggestions WHERE id = primary_id
    DB-->>Svc: primary (主建议)

    alt 主建议不存在
        Svc-->>API: None
        API-->>ADM: {code:404, message:"主建议不存在"}
    end

    Svc->>DB: SELECT * FROM knowledge_suggestions WHERE id = duplicate_id
    DB-->>Svc: duplicate (重复建议)

    alt 重复建议存在
        Svc->>Svc: 合并标签: merged_tags = set(primary.tags + duplicate.tags)
        Svc->>Svc: 合并 graph_meta: primary.graph_meta.update(duplicate.graph_meta)
        Svc->>DB: UPDATE duplicate SET status='rejected', reject_reason='已合并至建议 {primary_id}(去重)', reviewer_id, reviewed_at
    end

    Svc->>DB: COMMIT
    Svc->>DB: REFRESH primary
    Svc-->>API: primary (合并后)
    API-->>ADM: {code:0, message:"建议合并完成,重复建议已标记为已驳回(合并归入)", data: primary}

合并规则

字段 合并策略
tags 并集去重:set(primary.tags + duplicate.tags)
graph_meta 深度合并:primary.graph_meta.update(duplicate.graph_meta)
status (duplicate) rejected
reject_reason (duplicate) 已合并至建议 {primary_id}(去重)
reviewer_id (duplicate) → 当前审核人
reviewed_at (duplicate) → 当前时间
primary 其他字段 保持不变

前端交互设计

交互 说明
触发入口 重复检测结果弹窗中每行的"合并"按钮
请求参数 suggestion_id(主建议,URL 路径参数)+ duplicate_id(重复建议,请求体)
成功反馈 关闭重复弹窗 + 刷新列表 + 刷新统计

部署状态

生产在线 — 后端 merge_suggestions 方法 + API 路由 + 前端合并操作均已部署。


3.10 会话关闭→建议→审核→写图

功能描述

全链路闭环:坐席结单 → 异步触发 AI 生成知识建议 → 训练师审核 → KB 落库 → Neo4j 写图。

当前状态:生产在线。全链路打通。

全链路数据流

flowchart LR
    A[坐席结单] --> B[异步触发\n知识建议生成]
    B --> C{Dify 可用?}
    C -->|是| D[调用 Wingman AI\n生成结构化建议]
    C -->|否| E[source_failed=True\n标题=生成失败]
    D --> F{confidence ≥ 0.7?}
    F -->|是| G[创建 KnowledgeSuggestion\nstatus=pending]
    F -->|否| H[source_failed=True\n标记低置信]
    E --> G
    H --> G
    G --> I{训练师审核}
    I -->|采纳| J[status=approved]
    I -->|驳回| K[status=rejected\n终态]
    I -->|改写| L[重置 status=pending\n重新审核]
    I -->|入队| M[status=queued\n独立队列]
    M --> N[队列审批\n→ approved]
    J --> O[创建 KnowledgeBase 条目\nstatus=applied]
    N --> O
    O --> P{Neo4j 写图}
    P -->|成功| Q[status=graph_synced\ngraph_sync_status=synced\n回填 kb.graph_node_uuid]
    P -->|失败| R[graph_sync_status=failed\n可重试]
    Q --> S[终态:知识图谱更新]
    R --> T[后续优化:\n重试队列]

    style A fill:#e3f2fd
    style Q fill:#e8f5e9
    style S fill:#c8e6c9
    style K fill:#ffebee

详细时序图

sequenceDiagram
    participant AG as 坐席端
    participant API_Conv as 会话 API
    participant Svc_KI as 知识迭代服务
    participant Wingman as Wingman AI
    participant Dify as Dify
    participant DB as PostgreSQL
    participant Neo4j as Neo4j
    participant ADM as 管理后台

    %% 阶段1:会话关闭 → 异步生成建议
    rect rgb(227, 242, 253)
        Note over AG,DB: 阶段1:会话关闭 → 异步生成建议
        AG->>API_Conv: POST /api/conversations/{id}/resolve (结单)
        API_Conv->>DB: 会话状态 → resolved/closed
        API_Conv-->>AG: 结单成功(不阻塞)

        API_Conv->>API_Conv: asyncio.ensure_future(_trigger_knowledge_suggestion())

        Note over API_Conv: 独立 db session 后台任务
        API_Conv->>Svc_KI: generate_knowledge_suggestion(db, "conversation", [conv_id], reason)
        Svc_KI->>Svc_KI: _check_existing_suggestion() — 避免重复
        Svc_KI->>Svc_KI: _build_context_from_source() — 获取消息历史
        Svc_KI->>Wingman: generate_knowledge_suggestion(context_messages)
        Wingman->>Dify: 调用 Dify API
        Dify-->>Wingman: {title, content, confidence, issue, action, ...}
        Wingman-->>Svc_KI: ai_result

        Svc_KI->>Svc_KI: 置信门控: confidence < 0.7 → source_failed
        Svc_KI->>Svc_KI: audience 自动标注
        Svc_KI->>DB: INSERT knowledge_suggestion (status=pending)
        Svc_KI-->>API_Conv: suggestion
    end

    %% 阶段2:训练师审核
    rect rgb(255, 243, 224)
        Note over ADM,DB: 阶段2:训练师审核
        ADM->>Svc_KI: GET /suggestions (查看待审核列表)
        Svc_KI->>DB: SELECT * FROM knowledge_suggestions WHERE status='pending'
        DB-->>ADM: suggestions[]

        ADM->>ADM: 训练师查看详情,编辑图字段

        alt 采纳
            ADM->>Svc_KI: POST /suggestions/{id}/approve
            Svc_KI->>Svc_KI: 校验 pending → approved (状态机)
            Svc_KI->>DB: UPDATE status=approved, reviewer_id, reviewed_at
        end
    end

    %% 阶段3KB 落库 + Neo4j 写图
    rect rgb(232, 245, 233)
        Note over Svc_KI,Neo4j: 阶段3KB 落库 + Neo4j 写图
        Svc_KI->>DB: INSERT knowledge_base (title, content, category, tags)
        Svc_KI->>DB: UPDATE suggestion status=applied, applied_at

        Svc_KI->>Svc_KI: sync_to_neo4j(neo4j_client, suggestion)

        rect rgb(232, 234, 246)
            Note over Svc_KI,Neo4j: Neo4j 写图步骤
            Svc_KI->>Neo4j: merge_issue(issue, category, props) — MERGE 幂等
            Neo4j-->>Svc_KI: IssueNode (uuid)

            opt 有父 Issue
                Svc_KI->>Neo4j: merge_issue(parent_issue, ...)
                Neo4j-->>Svc_KI: parent_node
                Svc_KI->>Neo4j: create_relation(parent → issue, type, weight)
            end

            opt 有 Action
                Svc_KI->>Neo4j: merge_action(action, props)
                Neo4j-->>Svc_KI: ActionNode (uuid)
                Svc_KI->>Neo4j: create_relation(issue → action, type, weight=confidence)
            end
        end

        alt 写图成功
            Svc_KI->>DB: UPDATE suggestion status=graph_synced, graph_sync_status=synced
            Svc_KI->>DB: UPDATE kb graph_sync_status=synced, graph_node_uuid=issue_node.uuid
        else 写图失败
            Svc_KI->>DB: UPDATE suggestion graph_sync_status=failed
            Svc_KI->>DB: UPDATE kb graph_sync_status=failed
        end

        Svc_KI->>DB: COMMIT
    end

    ADM->>Svc_KI: 响应 {code:0, data: suggestion (graph_synced)}

会话关闭触发点

文件backend/app/api/conversations.pyresolve_conversation 函数

关键代码

# 会话结单后异步触发知识建议生成
async def _trigger_knowledge_suggestion():
    """异步生成知识建议的后台任务(独立 db session)。"""
    from app.database import _get_session_factory
    from app.services.knowledge_iteration_service import KnowledgeIterationService

    factory = _get_session_factory()
    async with factory() as bg_db:
        knowledge_service = KnowledgeIterationService()
        suggestion = await knowledge_service.generate_knowledge_suggestion(
            db=bg_db,
            source_type="conversation",
            source_data=[str(conversation_id)],
            reason=f"会话'{conversation_id}'已结单,自动生成知识迭代建议",
        )
        if suggestion:
            bg_db.add(suggestion)
            await bg_db.commit()

# 创建后台任务(不阻塞结单响应)
_asyncio.ensure_future(_trigger_knowledge_suggestion())

设计要点

  1. 不阻塞结单:使用 asyncio.ensure_future 异步执行,结单响应立即返回
  2. 独立 db session:后台任务使用独立的 _get_session_factory() 创建新 session,避免与主请求 session 冲突
  3. 失败不影响主流程:知识建议生成失败时仅记录日志,不影响结单
  4. 避免重复_check_existing_suggestion 检查是否已有 pending 建议

Neo4j 写图逻辑(sync_to_neo4j

flowchart TD
    A[approve_suggestion 触发] --> B{suggestion.issue 存在?}
    B -->|否| C[return True\n无图字段不视为失败]
    B -->|是| D[merge_issue\nMERGE Issue 节点]

    D --> E{suggestion.parent_issue 存在?}
    E -->|是| F[merge_issue\nMERGE 父 Issue 节点]
    F --> G[create_relation\n父Issue → 当前Issue]
    E -->|否| H{suggestion.action 存在?}

    G --> H
    H -->|是| I[merge_action\nMERGE Action 节点]
    I --> J[create_relation\nIssue → Action\nweight=confidence]
    H -->|否| K[return True]

    J --> K
    K --> L[写图成功]

    style L fill:#c8e6c9

MERGE 幂等写入

  • Issue 节点按 name MERGE(同名不重复创建)
  • Action 节点按 name MERGE
  • 关系通过 MATCH + CREATE 创建

部署状态

生产在线 — 全链路已打通,从会话结单到 Neo4j 写图完整闭环。测试通过率 89/89。


4. 功能依赖关系图

graph TB
    subgraph "H5 员工端功能"
        F1[1.分诊交互]
        F2[2.置信门控]
        F6[6.代答排除]
    end

    subgraph "坐席端功能"
        F3[3.内联审批卡片]
        F4[4.拓扑预览]
    end

    subgraph "管理后台功能"
        F5[5.重复检测]
        F7[7.知识迭代管理]
        F8[8.图谱可视化]
        F9[9.合并去重]
    end

    subgraph "全链路功能"
        F10[10.会话关闭→建议→审核→写图]
    end

    subgraph "基础设施"
        NEO4J[Neo4j 图数据库]
        DIFY[Dify AI 平台]
        PG[(PostgreSQL)]
    end

    %% 依赖关系
    F2 -->|confidence < 0.7 触发| F10
    F1 -->|分诊上下文转人工| F10
    F6 -->|排除选项影响| F1

    F10 -->|生成 KnowledgeSuggestion| F3
    F10 -->|生成 KnowledgeSuggestion| F7

    F3 -->|展示拓扑| F4
    F3 -->|检查重复| F5
    F5 -->|发现重复| F9

    F7 -->|管理审核| F3
    F7 -->|查看图谱| F8
    F7 -->|检查重复| F5
    F7 -->|合并去重| F9

    %% 基础设施依赖
    F2 --> DIFY
    F10 --> DIFY
    F10 --> PG
    F3 --> PG
    F5 --> NEO4J
    F5 --> PG
    F7 --> PG
    F8 --> NEO4J
    F9 --> PG
    F10 --> NEO4J
    F4 --> NEO4J

    %% 样式
    style F1 fill:#fff3e0,stroke:#ff9800,stroke-dasharray: 5 5
    style F4 fill:#fff3e0,stroke:#ff9800,stroke-dasharray: 5 5
    style F6 fill:#fff3e0,stroke:#ff9800,stroke-dasharray: 5 5
    style F2 fill:#e8f5e9,stroke:#4caf50
    style F3 fill:#e3f2fd,stroke:#2196f3
    style F5 fill:#e8f5e9,stroke:#4caf50
    style F7 fill:#e8f5e9,stroke:#4caf50
    style F8 fill:#e8f5e9,stroke:#4caf50
    style F9 fill:#e8f5e9,stroke:#4caf50
    style F10 fill:#e8f5e9,stroke:#4caf50
    style NEO4J fill:#e8eaf6,stroke:#3f51b5
    style DIFY fill:#fce4ec,stroke:#e91e63
    style PG fill:#e8eaf6,stroke:#3f51b5

图例

  • 🟢 绿色边框:生产在线
  • 🟠 橙色虚线边框:未实现/仅前端组件
  • 🔵 蓝色:基础设施

核心依赖链

置信门控 → 会话关闭→建议→审核→写图 → 内联审批卡片 → 重复检测 → 合并去重
                                                              ↓
                                                          拓扑预览

5. 全链路数据流图

5.1 通道 A:会话自动生成(全链路闭环)

flowchart TD
    Start([员工提问]) --> AI_Reply[AI 回复]
    AI_Reply --> ConfCheck{confidence ≥ 0.7?}

    ConfCheck -->|是| Normal[正常回复]
    ConfCheck -->|否| GateBanner[置信门控横幅<br/>展示转人工入口]

    GateBanner --> Transfer{员工选择}
    Transfer -->|转人工| WaitingAgent[会话 → waiting_agent]
    Transfer -->|继续 AI| Normal

    Normal --> Resolved{问题解决?}
    Resolved -->|是| Close1[员工关闭]
    Resolved -->|否| WaitingAgent

    WaitingAgent --> AgentServe[坐席接管]
    AgentServe --> Close2[坐席结单]

    Close1 --> AsyncGen[异步触发<br/>知识建议生成]
    Close2 --> AsyncGen

    AsyncGen --> BuildCtx[构建对话上下文<br/>获取消息历史]
    BuildCtx --> CallAI[调用 Dify Wingman<br/>生成结构化建议]

    CallAI --> ConfGate{confidence ≥ 0.7?}
    ConfGate -->|是| CreateSuggestion[创建 KnowledgeSuggestion<br/>status=pending]
    ConfGate -->|否| MarkFailed[source_failed=True<br/>标题=生成失败]
    MarkFailed --> CreateSuggestion

    CreateSuggestion --> NotifyAgent[通知坐席<br/>内联审批卡片]
    CreateSuggestion --> NotifyAdmin[通知训练师<br/>管理后台列表]

    NotifyAgent --> Review{审核决策}
    NotifyAdmin --> Review

    Review -->|采纳| Approve[status=approved]
    Review -->|驳回| Reject[status=rejected 终态]
    Review -->|改写| Rewrite[修改字段<br/>重置 pending]
    Review -->|入队| Queue[status=queued<br/>独立队列]

    Queue --> QueueReview[队列审批]
    QueueReview -->|通过| Approve
    QueueReview -->|驳回| Reject

    Rewrite --> Review

    Approve --> CreateKB[创建 KnowledgeBase 条目<br/>status=applied]
    CreateKB --> WriteNeo4j[Neo4j 写图<br/>merge_issue + merge_action]

    WriteNeo4j --> SyncCheck{写图成功?}
    SyncCheck -->|是| GraphSynced[status=graph_synced<br/>回填 kb.graph_node_uuid]
    SyncCheck -->|否| SyncFailed[graph_sync_status=failed<br/>待重试]

    GraphSynced --> Done([知识图谱更新完成])

    style GateBanner fill:#fff3e0
    style AsyncGen fill:#e3f2fd
    style CreateSuggestion fill:#e8f5e9
    GraphSynced fill:#c8e6c9
    style Reject fill:#ffebee
    style Done fill:#c8e6c9

5.2 通道 B:训练师手动录入

flowchart LR
    A[训练师点击<br/>手动录入] --> B[填写表单<br/>标题/内容/分类/受众/图字段]
    B --> C[提交<br/>source_type=manual<br/>confidence=1.0]
    C --> D[创建 KnowledgeSuggestion<br/>status=pending]
    D --> E[审核流程<br/>同通道 A]

5.3 通道 CRAGFlow 文档 ETL(预留未实现)

flowchart LR
    A[RAGFlow 文档上传] --> B[ETL 处理<br/>文档→FAQ]
    B --> C[source_type=document_ragflow<br/>audience=engineer_workguide]
    C --> D[创建 KnowledgeSuggestion<br/>status=pending]
    D --> E[审核流程<br/>同通道 A]

5.4 三通道汇总

graph TB
    subgraph "通道 A:会话自动生成"
        A1[会话关闭] --> A2[Dify AI 生成] --> A3[KnowledgeSuggestion]
    end

    subgraph "通道 B:手动录入"
        B1[训练师录入] --> B2[confidence=1.0] --> B3[KnowledgeSuggestion]
    end

    subgraph "通道 CRAGFlow(预留)"
        C1[文档 ETL] --> C2[自动提取] --> C3[KnowledgeSuggestion]
    end

    A3 --> S[统一审核队列<br/>status=pending]
    B3 --> S
    C3 --> S

    S --> R{审核}
    R -->|采纳| AP[approved → applied → graph_synced]
    R -->|驳回| RJ[rejected]
    R -->|改写| RW[重置 pending]
    R -->|入队| Q[queued → 队列审批]

    style S fill:#e3f2fd
    style AP fill:#e8f5e9

6. 未实现功能设计

6.1 分诊交互 — 前瞻设计

当前状态

前端组件 TriageCard.vue 已完成(530 行),包含完整的 UI 交互:步骤进度、选项列表、概率展示、专家模式、折叠/展开、跳过/确认。但后端 API 未实现,Dify 分诊 prompt 未配置。

建议实现方案

后端新增

  1. 新增 API 文件backend/app/api/triage.py

    • POST /api/h5/triage/start — 发起分诊
    • POST /api/h5/triage/step — 提交步骤选择
    • POST /api/h5/triage/skip — 跳过步骤
    • POST /api/h5/triage/transfer — 转人工
  2. Dify Prompt 设计

    • 输入:员工问题文本
    • 输出:分步选择题数组 [{question, options: [{label, probability}], total_steps}]
    • 复杂度自适应:简单问题 1-2 步,复杂问题 3-5 步
  3. 数据模型

    • 复用 Conversation 表,增加 triage_steps JSON 字段存储分诊过程
    • 或新建 triage_sessions
  4. 集成点

    • H5 对话页面在 AI 回复前调用分诊 API
    • 分诊完成后将收集的上下文传入 Dify 生成最终回复

预估工作量

任务 工作量
后端 API + 服务 2 人日
Dify Prompt 调试 3 人日
H5 前端对接 1 人日
测试 1 人日
合计 7 人日

6.2 拓扑预览 — 前瞻设计

当前状态

前端 SVG 缩略图已实现(基于 suggestion 的 issue/parent_issue/action 字段静态渲染),后端 query_issue_subgraph 方法已实现但未通过 API 暴露。

建议实现方案

  1. 新增 API 端点

    @router.get("/suggestions/{suggestion_id}/topology")
    @require_admin
    async def get_suggestion_topology(suggestion_id: str, ...):
        # 查询 suggestion 获取 issue 名称
        # 调用 neo4j_client.query_issue_subgraph(issue_name, depth=1)
        # 返回 {nodes, links}
    
  2. 前端增强

    • SVG 缩略图保留为快速预览
    • 点击缩略图弹出 ECharts mini graph modal 展示完整子图
    • 子图支持节点点击跳转到图谱可视化页面
  3. 降级处理

    • Neo4j 不可用时回退到当前 SVG 静态渲染
    • suggestion 无 issue 字段时不展示拓扑

预估工作量

任务 工作量
后端 API 端点 0.5 人日
前端 ECharts modal 1 人日
测试 0.5 人日
合计 2 人日

6.3 代答排除 — 前瞻设计

当前状态

前端 TriageCard.vuesetExcludedOptions / setRecommendedOption 方法定义完成,但无后端 API 对接,无 WS 推送机制。

建议实现方案

  1. 后端新增

    • POST /api/agent/triage/exclude — 坐席排除选项
    • POST /api/agent/triage/recommend — 坐席推荐选项
  2. WebSocket 推送

    • 坐席排除/推荐操作后,通过 WS 实时推送到 H5 员工端
    • H5 端接收后调用 TriageCard.setExcludedOptions() / setRecommendedOption()
  3. Dify Prompt 增强

    • 将排除的选项作为上下文传入 Dify,影响后续步骤生成
    • 避免 AI 在后续步骤中再次推荐已排除的选项
  4. 审计日志

    • 记录坐席排除/推荐操作(操作人、时间、排除的选项、原因)

预估工作量

任务 工作量
后端 API + WS 推送 1.5 人日
坐席端前端对接 1 人日
H5 前端对接 0.5 人日
测试 1 人日
合计 4 人日

7. 已知问题与后续优化方向

7.1 已知问题

# 问题 影响 严重程度 当前处理
1 Neo4j 写图失败后无自动重试 graph_sync_status=failed 的建议停留在 applied 状态,图数据不完整 P1 人工触发重新审批
2 _analyze_conversation_data 采样限制 20 条 分析超过 20 条会话时仅采样前 20 条,可能遗漏 P2 可接受,后续调大采样
3 audience 自动标注默认 employee_quick_reply Conversation 模型无 session_type 字段,无法精确区分员工/工程师会话 P2 保守默认,训练师可手动修改
4 相似度计算为简单前缀匹配 无法检测语义相似但文字不同的重复 Issue P2 后续可引入向量相似度
5 会话关闭异步任务无重试机制 Dify 不可用时建议生成失败,无自动重试 P2 source_failed 标记,训练师可手动改写
6 过期状态 expired 无定时任务 设计中有 expired 状态(72h 超时),但无定时任务自动触发 P3 待实现定时任务
7 create_relation 使用 CREATE 而非 MERGE 重复审批同一建议可能创建重复关系边 P2 后续改为 MERGE
8 前端 createSuggestion 直接调用 POST /suggestions API 路由中无 POST /suggestions 创建端点(仅列表 GET P1 需补充创建 API 或使用其他路径

7.2 后续优化方向

短期(P0-P1

  1. Neo4j 写图重试队列

    • 新增定时任务扫描 graph_sync_status=failed 的建议
    • 自动重试写图,最多 3 次
    • 超过重试次数通知管理员
  2. 补充手动创建建议 API

    • 前端 createSuggestion 调用的 POST /suggestions 端点需补充
    • 或确认是否通过其他路由处理
  3. 关系边 MERGE 幂等

    • create_relation 改用 MERGE 替代 CREATE
    • 避免重复审批产生重复关系

中期(P2

  1. 向量相似度去重

    • 引入 embedding 模型计算 Issue 名称的语义相似度
    • 替代当前的前缀匹配算法
    • 提高重复检测准确率
  2. 过期定时任务

    • 实现 72h 超时自动 expired 的定时任务
    • 使用 APScheduler 或 Celery beat
  3. 分诊交互后端实现

    • 实现分诊 API + Dify Prompt
    • 打通 TriageCard 前后端
  4. 拓扑预览 API 对接

    • 暴露 query_issue_subgraph 为 API
    • 前端 ECharts mini graph 展示

长期(P3

  1. RAGFlow 通道 C 实现

    • 部署 RAGFlow 服务
    • 实现文档 ETL → KnowledgeSuggestion 自动生成
    • ragflow_ingestion_enabled 配置开关已预留
  2. 知识图谱推理

    • 基于 Neo4j 图结构进行路径推荐
    • 员工提问时推荐相关 Issue→Action 路径
  3. 全链路监控看板

    • 建议生成→审核→写图各阶段耗时统计
    • 转化漏斗:生成数 → 采纳数 → 写图成功数
    • Dify 调用成功率监控

附录

A. 数据库迁移

迁移版本 说明
043_knowledge_iteration 创建 knowledge_suggestions 表 + conversation_annotations 表
044_automation 自动化相关表(后续迁移)

B. 测试覆盖

测试层级 测试数 通过率 报告
Tier0 基础测试 41 100% docs/06-测试质量/Tier0-测试报告-20260708.md
Tier1 API 测试 34 100% 同上
CSV 验证 14 100% 同上
P2 可视化测试 docs/06-测试质量/P0串联+P2可视化-测试报告-20260708.md
合计 89 100%

C. 关键文件索引

文件 行数 说明
backend/app/api/knowledge_iteration.py 568 12 条 API 路由
backend/app/api/approval_queue.py 208 3 条队列 API 路由
backend/app/services/knowledge_iteration_service.py 1197 核心服务
backend/app/services/neo4j_client.py 759 Neo4j 异步客户端
backend/app/models/knowledge_suggestion.py 260 数据模型
backend/app/models/knowledge_base.py 143 数据模型
backend/app/models/neo4j_schema.py 115 图节点 Pydantic 模型
backend/app/schemas/enums.py 159 枚举 + 状态机
backend/app/schemas/knowledge_suggestion.py 208 请求/响应 Schema
backend/app/config.py 469 配置项
backend/app/api/conversations.py ~400+ 会话关闭触发点
frontend-admin/src/views/KnowledgeIteration.vue 982 管理后台页面
frontend-agent/src/components/chat/ApprovalInlineCard.vue 695 内联审批卡片
frontend-h5/src/components/TriageCard.vue 530 分诊卡片
frontend-h5/src/components/ConfidenceGateBanner.vue 332 置信门控横幅
frontend-h5/src/composables/useConfidenceGate.ts 181 置信门控逻辑

文档结束
本文档基于代码分析生成,已部署功能为回溯文档,未实现功能为前瞻设计。
如有疑问请联系架构组。