From 468cf0483f7a0c19b052e36069c4fcfe7d9c6b98 Mon Sep 17 00:00:00 2001 From: mesalogo Date: Thu, 3 Sep 2026 16:29:51 +0800 Subject: [PATCH] docs: design external knowledge providers --- docs/features/knowledge-base/README.md | 20 +- .../external-knowledge-logic-design.md | 343 +++++++++++ .../knowledge-base/external-knowledge-prd.md | 254 ++++++++ .../external-knowledge-technical-design.md | 580 ++++++++++++++++++ .../external-knowledge-ui-design.md | 401 ++++++++++++ .../external-knowledge-user-stories.md | 212 +++++++ 6 files changed, 1808 insertions(+), 2 deletions(-) create mode 100644 docs/features/knowledge-base/external-knowledge-logic-design.md create mode 100644 docs/features/knowledge-base/external-knowledge-prd.md create mode 100644 docs/features/knowledge-base/external-knowledge-technical-design.md create mode 100644 docs/features/knowledge-base/external-knowledge-ui-design.md create mode 100644 docs/features/knowledge-base/external-knowledge-user-stories.md diff --git a/docs/features/knowledge-base/README.md b/docs/features/knowledge-base/README.md index 4ef53c97..c712cf7b 100644 --- a/docs/features/knowledge-base/README.md +++ b/docs/features/knowledge-base/README.md @@ -1,6 +1,7 @@ # 知识库 -知识库负责资料导入、解析、分块、索引、检索、图谱和带来源的知识问答。 +知识库负责资料导入、解析、分块、索引、检索、图谱和带来源的知识问答,也负责将 +Dify、FastGPT 和 RAGFlow 中已有的知识库接入同一检索范围。 ## 文档导航 @@ -10,5 +11,20 @@ | [User Stories](./user-stories.md) | 知识使用者、维护者和调试者场景 | | [本地文本向量技术设计](./local-embedding-technical-design.md) | 本地与兼容向量连接、模型包、索引和进程边界 | | [知识检索评估](./retrieval-evaluation.md) | 检索质量评估方法、数据集、指标和门槛 | +| [外部知识库接入 PRD](./external-knowledge-prd.md) | 外部实例、知识库绑定、检索范围和产品验收 | +| [外部知识库 User Stories](./external-knowledge-user-stories.md) | 实例配置、添加、使用和故障恢复场景 | +| [外部知识库逻辑设计](./external-knowledge-logic-design.md) | 状态、不变量、配置优先级和失败规则 | +| [外部知识库 UI 设计](./external-knowledge-ui-design.md) | 知识库页面、外部实例管理和创建向导交互 | +| [外部知识库技术设计](./external-knowledge-technical-design.md) | Provider Adapter、凭据、持久化、IPC 和检索标准化 | -当前尚未拆出统一功能逻辑、UI 设计和功能进度文档。 +## 术语 + +- **外部实例**:一个由用户配置的 Dify、FastGPT 或 RAGFlow 服务地址及其认证信息。 +- **外部知识库绑定**:GoodBuddy 中的知识库记录与外部实例内一个远端知识库 ID 的只读关联。 +- **Provider 配置**:某一 Provider 检索接口独有的设置,例如 RAGFlow 图谱检索。 + +外部知识库只提供检索结果。GoodBuddy 不接入外部 App、Chat、Assistant、Workflow +或 Agent,也不在外部实例中创建、修改、上传或删除知识库内容。远端资料不会批量同步 +或进入本地索引;实际用于回答的有界片段会随引用保存在本地会话中。 + +当前尚未拆出覆盖整个知识库功能家族的统一逻辑、UI 设计和功能进度文档。 diff --git a/docs/features/knowledge-base/external-knowledge-logic-design.md b/docs/features/knowledge-base/external-knowledge-logic-design.md new file mode 100644 index 00000000..16c6b5cf --- /dev/null +++ b/docs/features/knowledge-base/external-knowledge-logic-design.md @@ -0,0 +1,343 @@ +# 外部知识库逻辑设计 + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 状态 | 设计稿 | +| 版本 | 0.1 | +| 日期 | 2026-09-03 | +| 关联需求 | [外部知识库接入 PRD](./external-knowledge-prd.md) | +| 关联场景 | [外部知识库 User Stories](./external-knowledge-user-stories.md) | + +## 1. 不变量 + +### EK-I-01 单一知识库身份 + +本地知识库和外部知识库都使用 GoodBuddy `knowledgeBaseId` 参与聊天范围、检索模式、 +工具授权和活动记录。Provider、实例 ID 和远端知识库 ID 不能替代该授权单位。 + +对应:`EK-FR-10`、`EK-FR-11`、`EK-US-C1`。 + +### EK-I-02 外部绑定只读 + +GoodBuddy 对外部实例只执行连接测试、目录读取、详情读取和检索。添加、编辑、移除 +均只修改本机记录,不调用远端创建、更新、上传或删除接口。 + +对应:`EK-FR-15`、`EK-US-A3`。 + +### EK-I-03 凭据不离开 Main + +API Key 明文只在 Main 内完成解密并短暂进入请求头。Renderer、Preload 返回值、Runtime、 +Provider 配置、知识库元数据、诊断、日志和错误只能获得凭据状态。 + +对应:`EK-FR-02`、`EK-FR-11`。 + +### EK-I-04 Provider 不能定义界面 + +远端响应只提供数据和能力证据。可显示字段、字段类型、范围、默认值和请求映射均来自 +GoodBuddy 内置、版本化的 Provider Adapter。 + +对应:`EK-FR-09`、`EK-US-D1`。 + +### EK-I-05 无静默切换 + +请求固定使用绑定保存的实例、远端知识库和 Provider 配置。失败时不切换实例、公共云 +地址、认证方式或其他知识库。 + +对应:`EK-FR-14`、`EK-FR-16`、`EK-US-C4`。 + +### EK-I-06 零结果与失败分离 + +成功响应经过过滤后没有片段才是零结果。超时、认证、权限、限流、目标不存在、服务错误 +和响应无效均为失败,不能折叠成零结果。 + +对应:`EK-FR-14`、`EK-US-D4`。 + +### EK-I-07 外部证据不可信 + +Provider 返回的名称、内容、元数据、URL 和错误均视为不可信输入,经过长度、数量、类型 +和 URL 校验后才能显示或进入 Runtime。内容中的指令不能改变系统或工具权限。 + +对应:`EK-FR-12`。 + +### EK-I-08 Provider 配置不跨类型复用 + +Dify、FastGPT 和 RAGFlow 使用各自的判别配置。切换知识库类型或实例 Provider 时,旧类型 +配置不参与新请求,也不能按同名字段自动迁移。 + +对应:`EK-FR-06`、`EK-FR-09`。 + +## 2. 对象关系 + +```text +ExternalKnowledgeInstance 1 ─── n ExternalKnowledgeBinding + │ + │ 1:1 + ▼ + KnowledgeBase +``` + +- 实例可以没有绑定。 +- 外部知识库只能绑定一个实例和一个远端知识库 ID。 +- 同一实例的同一远端知识库默认只允许存在一个绑定,避免重复选择和重复检索。 +- 允许不同实例绑定同名或相同远端 ID,因为实例边界不同。 +- 本地知识库不存在 `ExternalKnowledgeBinding`。 + +## 3. 实例状态 + +实例状态由启停、凭据和最近探测三个维度组成,不能用一个布尔值代替。 + +### 3.1 持久状态 + +| 维度 | 值 | +| --- | --- | +| 启停 | `enabled`、`disabled` | +| 凭据 | `configured`、`missing`、`unavailable` | +| 探测 | `untested`、`catalog-ready`、`healthy`、`list-restricted`、`auth-failed`、`unreachable`、`incompatible`、`failed` | + +`unavailable` 表示系统安全存储当前无法解密或保存凭据,与用户尚未配置的 `missing` 分开。 + +### 3.2 派生可用性 + +| 条件 | 目录读取 | 已绑定知识库检索 | 页面状态 | +| --- | --- | --- | --- | +| disabled | 禁止 | 禁止 | 已停用 | +| missing / unavailable | 禁止 | 禁止 | 缺少凭据 / 凭据不可用 | +| auth-failed | 禁止 | 禁止 | 认证失效 | +| unreachable | 可重试 | 可重试 | 无法连接 | +| incompatible | 禁止 | 禁止 | 接口不兼容 | +| list-restricted | 禁止 | 允许按 ID 验证与检索 | 需手工指定知识库 | +| catalog-ready | 允许 | 创建绑定时验证 | 目录可用,检索待验证 | +| healthy | 允许 | 允许 | 正常 | +| untested | 允许测试 | 已有绑定可尝试检索 | 未测试 | + +保存新实例要求至少完成服务可达和认证验证。目录受限可以保存;检索接口尚未通过时, +实例不能用于创建绑定。 + +## 4. 连接测试状态机 + +```text +idle + └─ test → connecting + ├─ network failure → unreachable + └─ connected → authenticating + ├─ 401 → auth-failed + ├─ incompatible response → incompatible + └─ authenticated → listing + ├─ 403 / unsupported → list-restricted + └─ success + ├─ no target → catalog-ready + └─ target selected → probing-retrieval + ├─ success / empty → healthy + └─ failure → failed +``` + +检索探测需要一个目标知识库。新增实例尚未选择目标时,目录成功即可把实例保存为“目录可用, +检索待绑定验证”;创建绑定时补做真实检索。手工模式必须先填写目标 ID,再执行检索探测。 +检索请求正常完成但返回零条结果时,说明接口和目标可访问,可继续创建绑定;失败状态按错误 +分类处理。 + +每次测试拥有 request ID 和取消信号。用户修改 Provider、地址、凭据或实例后,旧 request ID +的结果作废。 + +## 5. 目录读取规则 + +1. 只有选定、启用且凭据可用的实例可以读取目录。 +2. Provider 列表接口按适配器定义分页,Main 最多向 Renderer 返回 500 个目录项。 +3. FastGPT 列表中的文件夹和知识库必须按类型区分;文件夹不可作为绑定目标。 +4. 列表搜索优先使用 Provider 支持的服务端过滤,不支持时只过滤已经有界加载的当前结果。 +5. 下拉列表以远端 ID 为值,以远端名称为标签;重名时追加短 ID 或父级名称。 +6. 已经绑定的目标显示“已添加”并禁止重复添加。 +7. 远端列表项名称变化不自动修改 GoodBuddy 显示名称,只更新远端名称快照。 +8. 刷新失败时可以保留上次成功目录供查看,但不得用旧目录完成新绑定,直到目标重新验证。 + +## 6. 创建向导状态 + +### 6.1 类型 + +```text +local | dify | fastgpt | ragflow +``` + +`local` 使用现有字段和验证。外部类型使用以下步骤状态: + +```text +provider selected +→ instance selected +→ catalog loading / manual ID +→ remote target selected +→ configuration valid +→ retrieval verified +→ binding created +``` + +前置字段变化时,后续状态按下表失效: + +| 变化 | 必须清除或重新验证 | +| --- | --- | +| 类型 | 实例、远端目标、全部 Provider 配置、测试结果 | +| 实例 | 远端目标、能力快照、Provider 配置、测试结果 | +| 远端目标 | 远端详情、能力适用性、测试结果 | +| 通用或 Provider 配置 | 测试结果 | +| 显示名称 | 不清除测试结果 | + +## 7. 配置模型 + +### 7.1 通用配置 + +| 字段 | 范围 | 默认值 | 语义 | +| --- | --- | --- | --- | +| `resultLimit` | 1 至 20 | 6 | Provider 结果标准化后最多保留的片段数 | +| `requestTimeoutMs` | 1,000 至 60,000 | 15,000 | 单次远端请求总时限 | +| `maxSnippetCharacters` | 500 至 8,000 | 4,000 | 单片段进入 IPC 和 Runtime 前的字符上限 | + +Provider 请求仍使用自己的候选数量或 Token 预算。`resultLimit` 只定义 GoodBuddy 最终保留 +上限,不改写 Provider 字段的单位。 + +### 7.2 Dify 配置 + +| 字段 | 初始范围 | 说明 | +| --- | --- | --- | +| `useDatasetDefaults` | boolean,默认 true | 开启时不发送 `retrieval_model` 覆盖 | +| `searchMethod` | keyword / semantic / full-text / hybrid | 对应 Dataset Retrieve 检索方式 | +| `providerTopK` | 1 至适配器上限 | Dify 返回候选数量 | +| `scoreThresholdEnabled` | boolean | 是否向 Dify 发送分数阈值 | +| `scoreThreshold` | 0 至 1 | 开启阈值后生效 | +| `rerankingMode` | weighted-score / reranking-model | 覆盖检索配置时必填 | +| `rerankingProvider`、`rerankingModel` | 受支持的远端标识 | 选择模型重排时必填 | +| `keywordWeight`、`vectorWeight` | 0 至 1,总和为 1 | 加权混合模式时生效 | +| `embeddingProvider`、`embeddingModel` | 受支持的远端标识 | Dify 要求时从知识库详情选择或填写 | + +`useDatasetDefaults` 开启时,其余覆盖字段隐藏且不发送。关闭后必须收集当前 Dify 接口 +构造 `retrieval_model` 所需的完整字段,缺少 Provider 或模型标识时不能保存。 + +### 7.3 FastGPT 配置 + +| 字段 | 初始范围 | 说明 | +| --- | --- | --- | +| `searchMode` | embedding / fullTextRecall / mixedRecall | 搜索方式 | +| `tokenLimit` | 适配器限制,最高 20,000 | Provider 返回内容预算,不等同结果条数 | +| `similarity` | 0 至 1 | 最低相关度 | +| `usingRerank` | boolean | 使用 FastGPT 重排 | + +初始版本不开放 FastGPT 查询优化字段,避免把查询发送给 FastGPT 配置的 LLM。检索和重排 +仍可能产生远端 Embedding、Rerank 用量及 API 审计记录,测试与保存配置时必须说明。 + +### 7.4 RAGFlow 配置 + +| 字段 | 初始范围 | 说明 | +| --- | --- | --- | +| `similarityThreshold` | 0 至 1 | 最低综合相似度 | +| `vectorSimilarityWeight` | 0 至 1 | 向量分数权重 | +| `knnTopK` | 1 至适配器上限 | KNN 候选数量,不使用已弃用 `top_k` | +| `rerankCandidatesCount` | 0 或正整数 | 重排候选数量,实例支持时显示 | +| `rerankId` | 可选受限字符串 | 远端重排模型 ID | +| `useKg` | boolean,默认 false | 仅在已有图谱证据成立时允许开启 | +| `includeKnowledgeCompilation` | boolean,默认 false | 实例支持时显式发送,禁止依赖服务端默认 true | +| `metadataCondition` | 后续受控编辑器 | 初始版本不接受任意 JSON 文本 | + +`parser_config.graphrag.use_graphrag` 描述构建状态,不是检索参数。只有列表、详情或受控 +探测提供已有图谱的证据时,界面才允许开启 `useKg`。Knowledge Compilation 是另一项 +检索能力,必须与旧 GraphRAG 分别显示和保存。 + +## 8. 配置优先级 + +生效请求由以下信息组成: + +```text +GoodBuddy 固定安全上限 +∩ 当前 Adapter 支持矩阵 +∩ 当前绑定保存的通用配置和 Provider 配置 += 本次请求配置 +``` + +- 固定安全上限不可被实例或用户扩大。 +- 远端知识库自身默认值只用于创建表单的建议值,不在每次请求时覆盖本地已保存值。 +- Provider 增加新字段不会自动启用。 +- 当前实例版本离开 Adapter 支持矩阵,或 Adapter 新版本无法解析已保存配置时,绑定标记 + 配置失效;用户确认前不重写配置。 +- 服务端忽略未知字段不能视为成功。Adapter 只发送已知且受支持的字段。 + +## 9. 绑定状态 + +| 状态 | 条件 | 可进入聊天范围 | +| --- | --- | --- | +| `ready` | 实例可用,目标最近验证成功,配置有效 | 是 | +| `untested` | 迁移或新增后尚未完成真实检索 | 否 | +| `instance-disabled` | 实例停用 | 否 | +| `credential-error` | 凭据缺失、不可用或认证失败 | 否 | +| `remote-missing` | 远端目标返回不存在 | 否 | +| `config-invalid` | 已保存配置不再受支持 | 否 | +| `temporarily-unavailable` | 超时、限流或服务错误 | 是,但本次显示失败并允许重试 | + +短暂故障不立即永久禁用绑定;认证失败、目标不存在和配置失效会改变持久状态。 + +## 10. 多知识库检索 + +1. 读取请求冻结的 GoodBuddy 知识库 ID 集合。 +2. 本地库进入本地检索,外部库按实例和绑定构造独立请求。 +3. 同一请求最多选择现有契约允许的 20 个知识库,并遵循全局并发上限。 +4. 每个库单独记录成功、零结果、失败、耗时和截断。 +5. 成功结果按知识库保留来源,不比较不同 Provider 的原始分数。 +6. 上下文拼装使用现有总字符预算,在各成功知识库间采用确定性配额。 +7. 全部失败时返回检索失败;至少一个成功时返回证据和部分失败诊断。 + +初始版本不对跨 Provider 结果运行统一学习型重排。后续如增加,必须保留原始 Provider +分数和重排来源,且单独定义评估数据。 + +## 11. 错误分类 + +| 稳定错误码 | 用户状态 | 持久影响 | +| --- | --- | --- | +| `EXTERNAL_KB_NETWORK` | 无法连接实例 | 无 | +| `EXTERNAL_KB_TIMEOUT` | 检索超时 | 无 | +| `EXTERNAL_KB_AUTH` | 认证失效 | 实例标记认证失败 | +| `EXTERNAL_KB_FORBIDDEN` | 没有访问权限 | 目录或绑定按操作标记受限 | +| `EXTERNAL_KB_NOT_FOUND` | 远端知识库不存在 | 绑定标记目标不存在 | +| `EXTERNAL_KB_RATE_LIMITED` | 请求过于频繁 | 无,可显示建议等待 | +| `EXTERNAL_KB_INCOMPATIBLE` | 接口或配置不兼容 | 实例或绑定标记不兼容 | +| `EXTERNAL_KB_INVALID_RESPONSE` | 返回内容无法读取 | 无,记录脱敏诊断 | +| `EXTERNAL_KB_SERVER` | 外部服务处理失败 | 无 | +| `EXTERNAL_KB_CANCELLED` | 已取消 | 无 | + +Provider 原始正文不能直接成为用户错误。Adapter 将其映射为稳定错误码和有界短消息。 + +## 12. 删除规则 + +| 操作 | 无绑定 | 有绑定 | +| --- | --- | --- | +| 停用实例 | 直接停用 | 允许;绑定变为不可用 | +| 清除凭据 | 直接清除 | 需要确认;绑定保留但不可用 | +| 删除实例 | 直接删除 | 阻止直接删除,要求同时移除本地绑定 | +| 移除绑定 | 删除本地绑定 | 不影响实例和远端知识库 | + +删除确认不得使用“删除远端知识库”等文案。 + +## 13. 需求追踪 + +| 需求 | 主要逻辑 | User Story | +| --- | --- | --- | +| `EK-FR-01` 至 `EK-FR-03` | 实例状态、连接测试状态机 | `EK-US-A1`、`EK-US-A2` | +| `EK-FR-04`、`EK-FR-05` | 目录读取规则、手工目标验证 | `EK-US-B1`、`EK-US-B2` | +| `EK-FR-06`、`EK-FR-07`、`EK-FR-08`、`EK-FR-09` | 创建向导状态、配置模型和优先级 | `EK-US-B3`、`EK-US-B4`、`EK-US-D1`、`EK-US-D3` | +| `EK-FR-10` 至 `EK-FR-13` | 单一身份、多知识库检索和引用规则 | `EK-US-C1` 至 `EK-US-C3`、`EK-US-D2` | +| `EK-FR-14` | 绑定状态、错误分类和部分失败 | `EK-US-C4`、`EK-US-D4` | +| `EK-FR-15` | 对象关系和删除规则 | `EK-US-A3` | +| `EK-FR-16` | 无静默切换、请求冻结和传输风险确认 | `EK-US-C2` | + +## 14. 逻辑完整性 + +已确定: + +- 产品入口、对象关系、只读边界和凭据边界。 +- 目录读取与手工 ID 的切换条件。 +- 三种 Provider 的初始配置范围和 RAGFlow 图谱语义。 +- 多知识库部分失败、删除和版本变化规则。 + +实施前仍需技术验证: + +- 选定支持的 Dify、FastGPT、RAGFlow 最低版本,形成固定支持矩阵并保存真实响应 fixture。 +- 验证各版本检索探测的 API 审计、用量和内容修改行为。 +- 确定 Provider 返回 URL 的安全打开策略;未验证前只显示文本定位和远端 ID。 +- 依据真实延迟确定默认并发上限和跨知识库上下文配额。 diff --git a/docs/features/knowledge-base/external-knowledge-prd.md b/docs/features/knowledge-base/external-knowledge-prd.md new file mode 100644 index 00000000..072079f6 --- /dev/null +++ b/docs/features/knowledge-base/external-knowledge-prd.md @@ -0,0 +1,254 @@ +# 外部知识库接入 PRD + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 状态 | 设计稿 | +| 版本 | 0.1 | +| 日期 | 2026-09-03 | +| 适用产品 | GoodBuddy 桌面端 | +| 关联逻辑 | [外部知识库逻辑设计](./external-knowledge-logic-design.md) | +| 关联界面 | [外部知识库 UI 设计](./external-knowledge-ui-design.md) | +| 技术设计 | [外部知识库技术设计](./external-knowledge-technical-design.md) | + +## 1. 背景 + +不少企业已经在内网部署 Dify、FastGPT 或 RAGFlow,并在其中维护制度、产品、研发 +和客服知识。继续要求用户把相同资料导入 GoodBuddy,会产生重复存储、版本分叉和 +额外维护成本。 + +GoodBuddy 需要把这些已有知识库加入当前知识库列表和聊天检索范围。外部系统只 +承担知识存储与检索,问题理解、上下文组织、模型回答、Agent 和工具执行仍由 +GoodBuddy 负责。 + +## 2. 产品决策 + +1. 外部知识库属于现有“知识库”功能,不新增一级页面,也不放入全局设置中心。 +2. 知识库页面标题区增加“管理外部实例”;现有“新建知识库”向导增加知识库类型。 +3. 一个外部实例代表一个 Provider 服务地址和一组凭据,可绑定多个远端知识库。 +4. 一个外部知识库绑定在 GoodBuddy 中仍是一个 `KnowledgeBase`,可以进入现有聊天 + 范围、每次先检索、模型按需检索和检索测试流程。 +5. 外部知识库保持远端检索,不批量同步或本地索引远端文档、分块、向量和图谱,也不 + 显示“已同步”。实际进入回答的有界片段和引用随会话保存在本机,并遵循会话删除规则。 +6. Dify、FastGPT 和 RAGFlow 只使用知识库列表、详情和检索接口。App、Chat、 + Assistant、Workflow 和 Agent API 均不接入。 +7. 用户点击“添加”只创建本地绑定,不在外部实例中创建知识库;移除绑定也不删除 + 远端知识库。 +8. 通用配置只包含跨 Provider 语义一致的选项。检索算法、阈值、重排和图谱开关 + 由 Provider 配置承担。 +9. Provider 专属字段由 GoodBuddy 内置适配器定义。外部服务器不能下发任意表单、 + 脚本或字段 Schema。 +10. API Key 在用户输入表单和受限 IPC 中短暂存在,由 Main 进程加密保存并用于请求; + 保存后不回传 Renderer,也不进入 Runtime、日志、普通元数据和检索引用。 + +## 3. 目标 + +### 3.1 用户目标 + +- 在知识库页面配置企业现有的 Dify、FastGPT 或 RAGFlow 实例。 +- 新建知识库时选择 Provider、实例和远端知识库,不手工复制资料。 +- 在同一知识库列表和聊天选择器中使用本地与外部知识库。 +- 按 Provider 能力调整检索参数,例如 RAGFlow 图谱检索。 +- 明确看到查询发送到哪个实例、检索是否成功以及引用来自哪里。 +- 连接失效后能更新凭据、重试或更换远端知识库,不丢失其他知识库配置。 + +### 3.2 产品目标 + +- 保持现有知识库 ID 作为聊天和 Runtime 的统一授权单位。 +- 让三种 Provider 的结果进入同一有界证据与引用契约。 +- 保留每种 Provider 的有效检索能力,不用最低公共字段覆盖全部差异。 +- 将实例认证与知识库绑定分离,使一个实例可以服务多个绑定。 +- 对 Provider 版本差异、列表权限关闭和部分检索失败提供可诊断状态。 + +## 4. 非目标 + +本功能不包含: + +- 调用 Dify App、FastGPT 应用、RAGFlow Chat 或任何外部 Agent。 +- 使用外部系统生成最终回答或维护外部会话。 +- 在外部实例中创建、编辑、删除知识库、文档或分块。 +- 向外部实例上传文件、网页、剪贴板、完整会话或本地知识库内容。 +- 批量同步或本地索引外部文档、分块、Embedding、图谱或模型配置。回答实际引用的 + 有界片段仍会随会话保存在本机。 +- 跨实例复制、迁移或统一管理外部知识内容。 +- 企业 SSO、组织级凭据下发、文档级 ACL 映射或 ShareServer 管理策略。 +- 自定义脚本适配器和任意 HTTP 请求模板。兼容检索 API 需要独立设计。 +- 把不同 Provider 的原始分数解释成可直接比较的统一质量分数。 + +## 5. 核心对象 + +| 对象 | 定义 | 用户可执行操作 | +| --- | --- | --- | +| 外部实例 | Provider、服务地址、凭据和已探测能力 | 添加、测试、编辑、停用、删除 | +| 外部知识库目录项 | 实例列表接口返回的远端知识库摘要 | 刷新、选择 | +| 外部知识库绑定 | GoodBuddy 知识库与远端知识库的只读关联 | 添加、改名、配置、测试、移除 | +| Provider 配置 | 适配器支持的检索参数 | 查看、修改、恢复默认 | +| 标准化检索结果 | Provider 结果转换后的片段、来源和诊断 | 查看、引用、提供给 Runtime | + +## 6. 主要流程 + +### 6.1 管理外部实例 + +1. 用户在知识库页面点击“管理外部实例”。 +2. 页面列出实例名称、Provider、服务地址、状态和已绑定知识库数量。 +3. 用户添加实例,填写名称、Provider、服务地址和 API Key。 +4. “测试连接”分别验证服务可达、认证、知识库列表和检索能力。 +5. 用户保存后,API Key 被加密保存,列表只显示凭据已配置。 + +列表接口不可用但已知远端知识库 ID 可检索时,实例可以保存为“需手工指定知识库”。 +服务不可达或认证失败时不得保存为可用实例;用户可以保留表单并修正。 + +### 6.2 添加外部知识库 + +1. 用户点击现有“新建知识库”。 +2. 在“知识库类型”中选择“本地”、Dify、FastGPT 或 RAGFlow。 +3. 选择外部类型后,左侧选择同 Provider 的外部实例。 +4. GoodBuddy 自动读取远端知识库列表,并填入可搜索下拉框。 +5. 列表权限不可用时,用户可以手工填写远端知识库 ID。 +6. 用户选择一个远端知识库,填写 GoodBuddy 显示名称。 +7. 右侧展示通用配置和当前 Provider 的专属配置。 +8. 用户填写测试查询并执行一次有界检索;请求成功后创建本地绑定,零结果不算失败。 + +添加完成后沿用现有知识库规则,把新绑定加入当前聊天选择,但不会重新启用用户此前 +取消的其他知识库。 + +### 6.3 使用外部知识库 + +外部绑定出现在现有知识库列表和聊天知识范围中,持续显示 Provider 与实例名称。 +检索请求只发送本次查询文本和该绑定已保存的检索配置。返回片段经过 Main 校验、 +截断和标准化后,才作为不可信证据提供给 Runtime。 + +一次请求选择多个知识库时,本地与外部检索可以并行。单个外部知识库失败不扩大 +检索范围,也不切换其他实例;其他知识库成功时可继续回答,并显示部分失败。 + +### 6.4 编辑和移除 + +- 修改显示名称只影响 GoodBuddy 本地名称。 +- 修改 Provider 配置只影响后续检索,不写回远端知识库。 +- 更换远端知识库属于重新绑定,保存前必须重新测试。 +- 删除外部实例前必须处理其所有绑定:取消,或明确移除这些本地绑定。 +- 移除绑定只删除 GoodBuddy 中的绑定和检索配置,不调用远端删除接口。已经保存在历史 + 会话中的引用继续可读,但不再提供依赖当前实例的刷新操作。 + +## 7. 功能需求 + +### EK-FR-01 知识库页面入口 + +知识库页面必须同时提供“管理外部实例”和“新建知识库”。外部实例管理不得迁移到 +全局设置中心或创建新的一级导航。 + +### EK-FR-02 实例配置 + +实例必须包含唯一 ID、显示名称、Provider、规范化服务地址、凭据状态、启停状态、 +最近测试结果和适配器能力快照。用户可以使用 `keep`、`replace`、`clear` 语义更新凭据。 + +### EK-FR-03 分项连接测试 + +连接测试必须区分服务可达、认证、列表读取和测试检索。新增实例尚未选择知识库时, +测试检索显示“绑定知识库时验证”,不能伪装成已通过。测试错误应包含可处理原因, +不得返回凭据、Authorization、完整响应正文或内部堆栈。 + +### EK-FR-04 远端目录读取 + +选择实例后自动读取有界、可分页的远端知识库列表。列表支持加载、刷新、搜索、空结果、 +权限不足和失败状态,且异步旧响应不得覆盖当前实例结果。 + +### EK-FR-05 手工指定远端 ID + +列表接口不受支持或没有权限时,允许手工填写远端知识库 ID 和显示名称。保存前必须通过 +该 ID 的详情或检索验证;不能只验证字符串非空。 + +### EK-FR-06 知识库类型 + +新建向导必须提供“本地”、Dify、FastGPT、RAGFlow 四种类型。本地类型保持现有创建、 +存储模式、图谱和导入行为;外部类型不得显示本地分块、导入或索引设置。 + +### EK-FR-07 两栏配置 + +外部类型的创建向导在常规宽度使用左右两栏。左侧负责 Provider、实例、远端知识库和 +显示名称;右侧负责通用配置与 Provider 专属配置。窄窗口按来源、通用配置、专属配置 +顺序堆叠。 + +### EK-FR-08 通用配置 + +通用配置至少包含最终返回片段数、请求超时和单片段最大字符数。数值必须有固定范围, +由 Main 再次校验。Provider 的 Top K、Token 预算或 Page Size 不得冒充同一字段。 + +### EK-FR-09 Provider 专属配置 + +Provider 配置使用受版本控制的判别联合。界面只展示当前适配器和已确认实例版本支持的字段; +不支持的已保存字段必须明确显示为失效配置并阻止静默提交。 + +### EK-FR-10 统一知识库列表 + +外部绑定与本地知识库出现在同一列表,但必须显示 Provider、实例和“远端检索”状态。 +外部绑定不得显示本地文档数、同步、分块、向量覆盖率或本地图谱状态。 + +### EK-FR-11 统一检索范围 + +现有聊天知识范围、多选上限、`auto` 和 `always` 模式继续以 GoodBuddy 知识库 ID 工作。 +Runtime 只能获得标准化后的有界证据,不能获得实例地址、API Key 或 Provider 原始响应。 + +### EK-FR-12 引用来源 + +每条外部结果必须保留 Provider、实例 ID、远端知识库 ID、文档名称和片段。远端文档 ID、 +远端片段 ID、页码、URL、分数及其他定位只在 Provider 实际返回时保存,不得补造。 + +### EK-FR-13 检索测试 + +现有检索测试入口支持外部绑定。页面显示生效配置、总耗时、Provider 耗时、返回数量、 +截断状态和脱敏错误。外部测试不创建聊天、调用 GoodBuddy LLM 或修改远端内容。 + +### EK-FR-14 故障隔离 + +认证失败、超时、限流、目标删除、版本不兼容和响应无效必须分别报告。多知识库检索中, +单项失败不得改写为零结果,也不得阻止已成功证据进入回答。 + +### EK-FR-15 生命周期边界 + +删除实例、移除绑定、清除凭据和更换远端目标必须经过明确确认。任何操作都不得调用 +Provider 的远端创建、更新、上传或删除接口。 + +### EK-FR-16 网络与数据说明 + +界面必须说明查询会发送到所选实例,并列出不会发送的内容。请求遵循用户配置的服务地址 +和当前内网兼容模式,不自动切换地址、Provider 或公共云端点。HTTP 或放宽证书校验会 +传输 API Key,测试和保存实例前必须显示风险并取得针对当前地址的明确确认。 + +## 8. Provider 初始范围 + +| Provider | 目录能力 | 检索能力 | 首批专属配置 | +| --- | --- | --- | --- | +| Dify | 知识库列表与详情 | Dataset Retrieve | 使用知识库默认配置,或完整覆盖检索方式、Top K、Score 阈值及 Rerank 模式 | +| FastGPT | 知识库层级列表与详情 | Dataset Search Test | 搜索模式、Token 上限、相似度、Rerank | +| RAGFlow | Dataset 列表与详情 | Retrieval | 相似度、向量权重、KNN Top K、Rerank、图谱检索、Knowledge Compilation | + +“首批专属配置”表示适配器允许表达的字段,不保证每个实例版本都支持。具体显隐由能力 +探测和[逻辑设计](./external-knowledge-logic-design.md)共同决定。 + +## 9. 产品验收 + +1. 用户可以在知识库页面完成三种 Provider 的实例添加、连接测试、编辑和删除。 +2. 每种 Provider 至少通过一个真实自部署实例完成列表读取、绑定和检索。 +3. 列表权限关闭时,可以通过手工 ID 添加并验证一个可检索知识库。 +4. 本地与外部知识库可以同时进入一次聊天检索,引用来源可区分。 +5. RAGFlow 支持时可以开启图谱检索;不支持时不发送该字段。 +6. 外部知识库详情不出现本地导入、同步、分块和索引操作。 +7. 删除绑定或实例不会改变远端知识库和文档。 +8. 保存完成后的 Renderer 状态、Runtime、SQLite 普通元数据、日志和错误中均找不到明文 + API Key。 +9. 超时、401/403、404、429、5xx 和响应格式错误都有独立测试并显示准确状态。 +10. 中断、切换实例或关闭向导后,过期列表与测试响应不会写入当前表单。 +11. FastGPT 页面说明检索会记录远端 API 使用情况,并可能产生 Embedding 或 Rerank 用量。 +12. HTTP 或放宽证书校验的实例未经明确确认不能保存或发送 API Key。 + +## 10. 外部资料 + +以下链接用于核对初始适配范围,实施时仍须用受支持版本的真实实例和响应 fixture 验证: + +- [Dify Knowledge API](https://docs.dify.ai/en/guides/knowledge-base/knowledge-and-documents-maintenance/maintain-dataset-via-api) +- [Dify Retrieve Chunks](https://docs.dify.ai/en/api-reference/knowledge-bases/retrieve-chunks-from-a-knowledge-base-test-retrieval) +- [FastGPT 知识库接口](https://doc.fastgpt.io/zh-CN/openapi/dataset) +- [RAGFlow HTTP API](https://ragflow.io/docs/dev/http_api_reference) +- [RAGFlow Release Notes](https://ragflow.io/docs/dev/release_notes) diff --git a/docs/features/knowledge-base/external-knowledge-technical-design.md b/docs/features/knowledge-base/external-knowledge-technical-design.md new file mode 100644 index 00000000..7bb6cf7c --- /dev/null +++ b/docs/features/knowledge-base/external-knowledge-technical-design.md @@ -0,0 +1,580 @@ +# 外部知识库技术设计 + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 状态 | 设计稿 | +| 版本 | 0.1 | +| 日期 | 2026-09-03 | +| 产品需求 | [外部知识库接入 PRD](./external-knowledge-prd.md) | +| 逻辑设计 | [外部知识库逻辑设计](./external-knowledge-logic-design.md) | +| UI 设计 | [外部知识库 UI 设计](./external-knowledge-ui-design.md) | + +## 1. 设计约束 + +1. 外部知识库扩展现有知识库领域,不建立独立检索工具、聊天范围或 Runtime 权限模型。 +2. 外部绑定使用远端检索,不落地远端文档、分块、向量和图谱。 +3. 所有网络、凭据、Provider 响应校验和结果标准化都在 Main 完成。 +4. Renderer 只能通过受限 IPC 管理实例、读取目录、保存绑定和发起测试。 +5. Dify、FastGPT、RAGFlow 使用独立 Adapter 和判别配置,不通过任意 JSON 请求模板实现。 +6. 首次实现只调用无内容修改语义的列表、详情和检索接口。 +7. Provider API 变化通过真实 fixture、Adapter 版本和能力快照处理,不通过猜测字段兼容。 + +## 2. 现有代码边界 + +当前实现中的主要扩展点: + +| 边界 | 现有位置 | 需要的变化 | +| --- | --- | --- | +| 共享知识契约 | `src/shared/knowledge-contracts.ts`、`src/shared/contracts.ts` | 增加实例、绑定、Provider 配置和外部引用判别联合 | +| IPC 名称 | `src/shared/ipc-channels.ts` | 增加实例和目录操作通道 | +| Preload | `src/preload/index.ts` | 暴露受限、类型化的外部知识库 API | +| Main IPC | `src/main/ipc.ts` | 校验输入、调用服务、投影脱敏结果 | +| 知识服务 | `src/main/knowledge/knowledge-service.ts` | 按知识库来源分派本地或外部检索 | +| 数据库 | `src/main/knowledge/knowledge-database.ts` | 增加实例、绑定和迁移 | +| 内部类型 | `src/main/knowledge/types.ts` | 增加 Provider、实例、绑定和标准化结果类型 | +| 知识页面 | `src/renderer/src/KnowledgeWorkspace.tsx` | 实例管理、创建向导类型和外部详情 | +| 检索测试 | `src/renderer/src/KnowledgeRetrievalWorkbench.tsx` | 支持本地与外部诊断判别联合 | +| 聊天预检索 | `src/main/ipc.ts` | 统一调用 Provider-aware 检索编排 | +| Agent 知识工具 | `src/main/agent/knowledge-mcp-gateway.ts` | 与预检索复用同一编排和引用标准化 | + +外部 Provider 不是 `KnowledgeSourceType`。现有 `file | directory | url` 表示会进入本地 +文档、分块和索引的资料来源;把远端绑定塞入该枚举会错误触发同步、分块和来源打开逻辑。 + +## 3. 模块设计 + +建议增加: + +```text +src/main/knowledge/external/ +├─ external-knowledge-service.ts +├─ external-knowledge-store.ts +├─ external-knowledge-errors.ts +├─ external-knowledge-http.ts +├─ external-knowledge-registry.ts +├─ external-knowledge-normalizer.ts +└─ providers/ + ├─ dify-adapter.ts + ├─ fastgpt-adapter.ts + └─ ragflow-adapter.ts +``` + +职责: + +- `ExternalKnowledgeService`:实例、目录、绑定、测试和检索编排。 +- `ExternalKnowledgeStore`:实例和绑定持久化,凭据加解密。 +- `ExternalKnowledgeHttp`:超时、取消、大小限制、地址和响应读取。 +- `ExternalKnowledgeRegistry`:按 Provider 返回内置 Adapter,不接受运行时插件注册。 +- `ExternalKnowledgeNormalizer`:统一结果边界、截断和引用。 +- Adapter:构造固定端点与请求,解析 Provider 响应,声明静态配置和能力条件。 + +`KnowledgeService` 继续作为聊天、检索测试和 MCP 网关的统一入口。它根据 +`KnowledgeBase.kind` 调用现有本地检索或 `ExternalKnowledgeService.retrieve`。 + +## 4. Provider Adapter + +```ts +type ExternalKnowledgeProvider = 'dify' | 'fastgpt' | 'ragflow' + +interface ExternalKnowledgeAdapter { + readonly provider: ExternalKnowledgeProvider + readonly configVersion: number + + normalizeBaseUrl(input: string): URL + testConnection(context: AdapterContext): Promise + listKnowledgeBases( + context: AdapterContext, + input: CatalogPageInput + ): Promise + getKnowledgeBase( + context: AdapterContext, + remoteKnowledgeBaseId: string + ): Promise + probeRetrieval( + context: AdapterContext, + input: ProviderRetrieveInput + ): Promise + retrieve( + context: AdapterContext, + input: ProviderRetrieveInput + ): Promise + parseCapabilities(input: unknown): CapabilitySnapshot + validateConfig( + input: unknown, + capabilities: CapabilitySnapshot + ): PersistedConfig +} +``` + +`probeRetrieval` 可以复用 `retrieve`,但必须使用用户在创建向导中明确输入的测试查询。 +不得生成会泄露组织信息的默认问题,不得调用 Provider 的 App 或模型问答接口,也不得 +修改远端知识内容。Provider 自身记录 API 审计或计算检索用量不属于内容修改,必须由界面 +提前说明。 + +Adapter 返回数据对象,不返回 React 组件、HTML 或远端 Schema。Renderer 中的配置定义 +由共享的 Provider 判别联合和本地字段描述生成。 + +## 5. 共享契约 + +### 5.1 实例 + +```ts +type CredentialMutation = + | { action: 'keep' } + | { action: 'replace'; value: string } + | { action: 'clear' } + +interface ExternalKnowledgeInstanceSummary { + id: string + name: string + provider: 'dify' | 'fastgpt' | 'ragflow' + baseUrl: string + enabled: boolean + credentialStatus: 'configured' | 'missing' | 'unavailable' + probeStatus: + | 'untested' + | 'catalog-ready' + | 'healthy' + | 'list-restricted' + | 'auth-failed' + | 'unreachable' + | 'incompatible' + | 'failed' + detectedVersion?: string + bindingCount: number + lastTestedAt?: string + lastErrorCode?: string +} +``` + +Renderer 输入使用 `CredentialMutation`,因此新密钥会在输入控件和该次 IPC 中短暂存在。 +Main 返回值永远没有 `credential`、`apiKey`、`authorization` 或加密 envelope。 + +### 5.2 绑定 + +```ts +interface ExternalKnowledgeBinding { + knowledgeBaseId: string + instanceId: string + remoteKnowledgeBaseId: string + remoteName: string + remoteDescription?: string + commonConfig: ExternalKnowledgeCommonConfig + providerConfig: DifyConfig | FastGptConfig | RagflowConfig + providerConfigVersion: number + adapterVersion: number + lastVerifiedAt?: string +} +``` + +`providerConfig` 必须带 `provider` 判别字段,且与实例 Provider 一致。`remoteName` 是用于 +显示和变化检测的快照,不是授权标识。 + +### 5.3 标准化结果 + +现有 `KnowledgeRetrievalResult` 假定结果映射到本地 `documentId/sourceId/chunkId`。需要改为 +引用定位的判别联合,同时保持现有调用方可按统一字段读取片段: + +```ts +type KnowledgeReferenceLocator = + | { + kind: 'local' + documentId: string + sourceId: string + chunkId: string + parentChunkId?: string + } + | { + kind: 'external' + provider: ExternalKnowledgeProvider + instanceId: string + remoteKnowledgeBaseId: string + remoteDocumentId?: string + remoteChunkId?: string + providerScore?: number + location?: string + sourceUrl?: string + metadata?: Record + } + +interface UnifiedKnowledgeRetrievalResult { + knowledgeBaseId: string + documentTitle: string + sourceDisplayName: string + snippet: string + relevance?: number + rank: number + locator: KnowledgeReferenceLocator +} +``` + +`remoteDocumentId` 和 `remoteChunkId` 只保存 Provider 实际返回的标识,缺失时不得从标题、 +序号或内容哈希推导。`providerScore` 保留原始值,但不改名为统一 `relevance`。只有经过 +单独定义和验证的归一化算法才能填写跨 Provider `relevance`。初始跨库拼装按结果配额和 +稳定 Provider 顺序工作,不按原始分数混排。 + +所有共享 Schema 使用严格对象并限制: + +- 查询不超过 4,000 字符;同时遵守 Provider 更小限制,例如 Dify 当前公开接口的 + 250 字符限制,超出时在发送前明确失败,不静默截断查询。 +- 单次目录页不超过 100 项,总目录最多 500 项。 +- 标准化结果最多 20 条,单片段最多 8,000 字符。 +- 标题、ID、定位、URL 和元数据键值均设独立上限。 +- Provider 原始响应总字节数设固定上限,超限立即取消读取。 + +## 6. 持久化 + +### 6.1 数据库变化 + +保留现有 `knowledge_bases` 表,增加: + +```sql +ALTER TABLE knowledge_bases + ADD COLUMN kind TEXT NOT NULL DEFAULT 'local' + CHECK (kind IN ('local', 'external')); +``` + +增加实例表: + +```sql +CREATE TABLE external_knowledge_instances ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + provider TEXT NOT NULL CHECK (provider IN ('dify', 'fastgpt', 'ragflow')), + base_url TEXT NOT NULL, + enabled INTEGER NOT NULL CHECK (enabled IN (0, 1)), + credential_envelope_json TEXT, + probe_status TEXT NOT NULL, + detected_version TEXT, + capabilities_json TEXT NOT NULL, + transport_security TEXT NOT NULL, + transport_risk_accepted_url TEXT, + transport_risk_accepted_at TEXT, + last_tested_at TEXT, + last_error_code TEXT, + created_at TEXT NOT NULL, + updated_at TEXT NOT NULL +); +``` + +增加绑定表: + +```sql +CREATE TABLE external_knowledge_bindings ( + knowledge_base_id TEXT PRIMARY KEY + REFERENCES knowledge_bases(id) ON DELETE CASCADE, + instance_id TEXT NOT NULL + REFERENCES external_knowledge_instances(id) ON DELETE RESTRICT, + remote_knowledge_base_id TEXT NOT NULL, + remote_name TEXT NOT NULL, + remote_description TEXT, + common_config_json TEXT NOT NULL, + provider_config_json TEXT NOT NULL, + provider_config_version INTEGER NOT NULL, + adapter_version INTEGER NOT NULL, + binding_status TEXT NOT NULL, + last_verified_at TEXT, + last_success_at TEXT, + last_error_code TEXT, + UNIQUE(instance_id, remote_knowledge_base_id) +); +``` + +已有知识库迁移为 `kind = 'local'`。外部知识库仍保留现有名称、描述和创建时间,但本地 +`storageMode`、图谱、分块和本地检索设置不进入外部请求;后续可以在数据库重构时再移除 +这些历史必填默认值,本功能不为此扩大迁移范围。 + +### 6.2 凭据 + +复用 `SettingsCredentialCipher` 和 Electron `safeStorage`: + +- `replace`:Main 加密新值后在一个事务中替换 envelope。 +- `keep`:不读取、不重写现有 envelope。 +- `clear`:确认后删除 envelope,并把实例凭据状态设为缺失。 +- 安全存储不可用时拒绝新增或替换,不降级为明文。 +- 解密只发生在发起请求前;请求结束后不缓存明文。 + +实例导出、诊断和数据库普通 JSON 视图均排除 `credential_envelope_json`。 + +## 7. IPC 设计 + +建议增加独立通道: + +```text +knowledge:external-instances:list +knowledge:external-instances:test +knowledge:external-instances:save +knowledge:external-instances:set-enabled +knowledge:external-instances:delete +knowledge:external-catalog:list +knowledge:external-catalog:get +knowledge:external-bindings:create +knowledge:external-bindings:update +knowledge:external-bindings:remove +knowledge:external-retrieval:test +``` + +所有 Handler 必须: + +1. `assertTrustedSender`。 +2. 用共享 Zod Schema 解析严格输入。 +3. 根据实例 ID 在 Main 读取地址和凭据,不接受 Renderer 在检索请求中重复传入。 +4. 使用稳定错误码返回脱敏错误。 +5. 对网络操作支持 AbortSignal、总超时和响应大小限制。 + +目录和测试请求返回 `requestId`。Renderer 仍需校验当前类型、实例和目标与响应关联,避免 +旧响应覆盖新表单。 + +## 8. HTTP 边界 + +### 8.1 服务地址 + +- 只接受 `http:` 和 `https:`。 +- 拒绝用户名、密码、查询和片段。 +- Adapter 负责规范化 Provider 所需 API 根路径,避免用户填写完整操作端点。 +- 请求只能拼接 Adapter 内置相对路径,远端目录项或错误不能改变目标 URL。 +- 重定向默认拒绝;若某 Provider 的受支持部署确需重定向,只允许同源且不得跨跳转发送 + Authorization。 +- 当前全局“内网兼容模式”决定是否允许 HTTP 和非标准 HTTPS 证书;操作开始后冻结该值。 +- HTTP 或实际使用证书例外时,Main 返回 `transportSecurity` 风险状态。用户必须针对规范化 + 后的当前地址明确确认,才能保存实例或发送 API Key;地址变化立即使旧确认失效。 +- 不进行公共云回退,不把自部署地址替换成 Provider 官方地址。 + +用户明确配置内网地址属于产品用途,因此不能采用禁止私网地址的通用 SSRF 规则。安全边界 +依靠显式实例配置、Main-only 请求、固定端点、无任意方法和无远端 URL 跟随。 + +### 8.2 请求限制 + +- 默认超时 15 秒,用户可在 1 至 60 秒内调整。 +- 目录、详情和检索分别设置响应字节上限。 +- JSON 解析后仍执行深度、数组数量、字符串长度和未知字段策略。 +- 默认不自动重试。用户重试或上层下一次检索会产生新请求。 +- 取消、应用关闭和实例删除立即终止相关请求。 +- 日志只记录 Provider、实例 ID、操作、状态码、稳定错误码、耗时和字节数。 + +## 9. Provider 映射 + +本节记录 2026-09-03 核对的初始公开接口。实施时应把每个受支持版本的真实响应保存为 +去敏 fixture,并以 fixture 和真实实例测试作为发布依据。 + +### 9.1 Dify + +| 操作 | 接口 | +| --- | --- | +| 列表 | `GET /v1/datasets` | +| 检索 | `POST /v1/datasets/{dataset_id}/retrieve` | +| 认证 | `Authorization: Bearer ` | + +Adapter 只接受 Knowledge Service API Key,不调用应用 `/info`、Chat 或 Workflow。默认不 +发送 `retrieval_model`,沿用远端知识库配置。用户选择覆盖时,Adapter 必须一次收集并验证 +当前接口要求的搜索方式、Top K、阈值、`reranking_mode`,以及相应的 Rerank Provider/模型 +或关键词/向量权重与 Embedding Provider/模型;缺少任何必填标识时不构造请求。响应从 +`records[].segment`、`score`、文档名称和元数据提取标准化引用。 + +Dify 当前文档限制查询不超过 250 字符。GoodBuddy 不静默截断;超出时检索测试和聊天 +诊断返回 Provider 限制,并允许后续单独设计查询压缩策略。 + +### 9.2 FastGPT + +| 操作 | 接口 | +| --- | --- | +| 列表 | `POST /api/core/dataset/list` | +| 详情 | `GET /api/core/dataset/detail?id=...` | +| 检索 | `POST /api/core/dataset/searchTest` | +| 认证 | `Authorization: Bearer ` | + +列表响应同时包含文件夹和知识库,只有 `type = dataset` 可以绑定。检索映射 `datasetId`、 +`text`、Token `limit`、`similarity`、`searchMode` 和 `usingReRank`。初始版本不发送查询优化 +字段,避免调用 FastGPT 配置的 LLM。 +响应从 `q`、`a`、`sourceName`、`sourceId`、`collectionId` 和 `score` 构造片段与引用。 + +FastGPT 4.15.0 起部署实例的 `/apidoc/devapi` 是接口事实来源,手工文档可能落后。支持矩阵 +必须按真实版本测试;不能因为健康页可访问就假定列表和检索 Schema 相同。`searchTest` +可能记录 `SEARCH_TEST` 等远端审计并更新 API Key 用量;Embedding 和 Rerank 也可能产生 +费用。GoodBuddy 将这些行为作为检索成本显示,不宣称该接口没有副作用。 + +### 9.3 RAGFlow + +| 操作 | 接口 | +| --- | --- | +| 列表/详情 | `GET /api/v1/datasets` | +| 检索 | `POST /api/v1/retrieval` | +| 认证 | `Authorization: Bearer ` | + +检索映射 `question`、`dataset_ids`、`page_size`、`similarity_threshold`、 +`vector_similarity_weight`、`knn_top_k`、重排、`use_kg` 和 +`include_knowledge_compilation`。不发送已弃用的 `top_k`。响应从 `data.chunks` 和 +`data.doc_aggs` 提取片段、文档、位置和原始相似度。 + +图谱规则: + +- `parser_config.graphrag` 或等价详情字段作为已有图谱的证据,不写回。 +- `use_kg` 是检索时开关,只在已有图谱和受支持版本均确认后发送。 +- Knowledge Compilation 与旧 GraphRAG 分别建模。 +- `include_knowledge_compilation` 使用本地保存的显式布尔值,初始默认 false;即使服务端 + 默认 true,也不依赖字段省略获得隐式行为。 +- Provider 没有返回图节点或路径证据时,GoodBuddy 不生成图谱引用。 + +## 10. 检索编排 + +```text +retrieveMany(knowledgeBaseIds, query, requestContext) + ├─ load and authorize GoodBuddy knowledge bases + ├─ partition local and external bindings + ├─ local: existing retrieval path + ├─ external: bounded concurrent adapter requests + ├─ validate and normalize each response + ├─ allocate deterministic context budget + └─ return evidence plus per-library diagnostics +``` + +预检索和 `knowledge_search` 工具必须调用同一个 `retrieveMany`。如果只修改聊天预检索而 +未修改 `KnowledgeMcpGateway`,`auto` 和 `always` 会产生不同能力,这是阻断发布的问题。 + +### 10.1 上下文预算 + +- 每个知识库先保留不超过其 `resultLimit` 的结果。 +- 先给每个成功知识库一个最小有界配额,再按稳定顺序分配剩余字符。 +- 不用不同 Provider 原始分数决定跨库优先级。 +- 片段截断在 Main 完成并在引用中标记。 +- 相同实例的多个绑定仍按绑定分别请求,除非 Provider 明确支持且 Adapter 实现等价的多 + Dataset 请求;合并不得改变每个绑定的配置和诊断。 + +### 10.2 失败结果 + +返回结构包含每个知识库的: + +```ts +interface KnowledgeRetrievalOutcome { + knowledgeBaseId: string + status: 'success' | 'empty' | 'failed' | 'cancelled' + durationMs: number + resultCount: number + errorCode?: ExternalKnowledgeErrorCode + truncated: boolean +} +``` + +至少一个 `success` 或 `empty` 表示检索编排完成;全部 `failed/cancelled` 时上层显示整体失败。 + +## 11. 引用与来源打开 + +外部结果不能进入依赖本地数据库的 `referenceContext` 和 `openSource` 路径。 + +- 引用详情直接使用请求时保存的标准化片段和定位。 +- Main 可以按远端片段 ID 提供一次只读重新读取,但初始版本不要求。 +- Provider 返回 URL 只作为不可信元数据保存。没有独立 URL 规则和真实实例验证前, + Renderer 不显示打开链接操作。 +- 活动和会话持久化保存标准化引用,其中包含实际用于回答的有界远端片段;这属于引用 + 留存,不是批量同步或本地索引。删除会话或对应活动时按现有生命周期删除该副本。 +- 实例删除后,历史引用仍显示 Provider、知识库、文档名称和已保存片段,但标记连接已移除。 + +## 12. 支持矩阵与版本变化 + +每个 Adapter 维护明确的最低版本、已验证版本和 `adapterVersion`。连接测试优先读取可靠的 +版本接口或响应头;无法识别版本时,只允许经真实请求验证过的基础列表和检索字段,高级字段 +保持不可用。 + +Adapter 可以保存少量受控事实,例如“目录接口可用”“详情表明已构建图谱”,但不尝试从 +远端拼出完整 capability manifest,也不计算 capability fingerprint。 + +- `adapterVersion` 相同且实例仍在支持矩阵内:解析已保存配置并执行。 +- Adapter 升级:使用明确的配置迁移或把绑定标记为 `config-invalid`,不猜测字段迁移。 +- 实例版本离开支持矩阵:停止发送高级字段,并要求重新测试和确认。 +- 新能力出现:保持默认关闭,用户主动配置后才发送。 +- RAGFlow `use_kg` 还要求当前远端知识库存在已构建图谱的证据。 + +## 13. 安全与隐私 + +- API Key 在用户输入和保存 IPC 中短暂存在,随后使用系统安全存储加密;保存后不返回 + Renderer,也不进入 Runtime、日志和普通元数据。 +- 请求不附带完整会话、附件、本地知识库证据、系统提示、模型配置或其他 Provider 结果。 +- Provider 结果使用与本地知识证据相同的不可信上下文标记。 +- Adapter 拒绝响应中的原型污染键、过深对象、超长数组和非有限数值。 +- 远端错误正文只用于 Main 内映射,日志与 UI 使用稳定错误码和短消息。 +- 外部知识库不能扩大当前对话显式选择的 GoodBuddy 知识库 ID。 +- Ask 与 Execute 对知识检索均为只读,Execute 不获得额外 Provider 权限。 +- Provider 配置中的模型 ID、背景文本和 Metadata 条件按独立长度限制验证,不能携带凭据。 +- HTTP 或证书例外需要按当前规范化地址确认凭据传输风险,地址变化后重新确认。 + +## 14. 测试 + +### 14.1 契约测试 + +- 每个 Provider 的列表、详情、检索成功和错误 fixture。 +- 未知字段、缺字段、错误类型、超长内容、非有限分数和超大响应。 +- Dify 查询长度、FastGPT 文件夹过滤、RAGFlow 图谱和 Knowledge Compilation 字段。 +- Provider 配置判别联合拒绝类型错配和未知字段。 + +### 14.2 安全测试 + +- 保存完成后的 Renderer 快照、IPC 返回值、日志、错误、活动和导出中不存在明文 API Key; + `replace` 输入只在当前表单和单次 IPC 请求中短暂存在。 +- `keep/replace/clear` 凭据语义和安全存储不可用路径。 +- 地址中的凭据、查询、片段、危险 scheme、跨源重定向和远端 URL 注入被拒绝。 +- 取消、超时、响应大小上限和应用关闭释放请求。 + +### 14.3 集成测试 + +- 实例保存、目录读取、手工 ID、绑定创建、编辑和本地移除。 +- 同一远端目标重复绑定被拒绝。 +- 删除实例的引用保护和级联本地移除确认。 +- 本地与外部 `retrieveMany` 部分成功、全部失败和确定性上下文预算。 +- 聊天 `always` 与 Agent `knowledge_search` 使用同一 Provider-aware 编排。 +- 历史引用在实例或绑定移除后仍可读。 + +### 14.4 UI 测试 + +- 类型切换、异步旧响应、目录搜索、刷新和手工模式。 +- 两栏与窄窗口堆叠、键盘、焦点恢复和离开保护。 +- Provider 字段显隐、失效配置、RAGFlow 图谱说明和恢复默认。 +- 外部详情不出现导入、同步、分块和本地图谱操作。 +- 错误、零结果、部分失败和 Provider 引用显示。 + +### 14.5 真实实例验收 + +每个 Provider 至少选择一个明确版本的自部署实例,记录: + +- 版本、部署方式和认证范围。 +- 列表与检索的请求/响应 fixture,移除凭据和业务正文。 +- 默认与专属配置是否真实生效。 +- 401、403、404、429、超时和取消行为。 +- 查询、片段、引用和诊断的实际上限。 + +Mock 或公开文档通过不能代替真实实例验收。 + +## 15. 实施顺序 + +这里的顺序只用于控制代码依赖,不裁剪产品设计: + +1. 建立共享判别契约、数据库迁移和凭据存储。 +2. 实现 HTTP 边界、错误映射和 Adapter Registry。 +3. 逐个实现三种 Provider,并用 fixture 完成契约测试。 +4. 实现实例管理和目录 IPC。 +5. 扩展创建向导、统一列表和外部详情。 +6. 扩展检索测试、引用和 `retrieveMany`。 +7. 接入聊天预检索与 `KnowledgeMcpGateway`。 +8. 完成真实实例、安全、响应式和跨平台验收。 + +## 16. 发布条件 + +- 三种 Provider 的受支持版本和限制已在产品界面或发布说明中可查。 +- 真实实例列表、绑定、检索和错误矩阵均通过。 +- 没有写入远端知识内容的代码路径。 +- API Key 泄漏测试、地址边界和响应大小测试通过。 +- 本地知识库创建、同步、检索、图谱和引用回归测试通过。 +- `auto`、`always`、检索测试和 MCP 知识工具得到一致的外部知识能力。 + +## 17. 需求追踪 + +| 需求 | 技术落点 | 验证 | +| --- | --- | --- | +| `EK-FR-01` 至 `EK-FR-03` | 实例契约、Store、实例 IPC、凭据和测试状态 | 实例集成测试、安全测试 | +| `EK-FR-04`、`EK-FR-05` | Adapter 目录与详情接口、目录 IPC | Provider fixture、手工 ID 集成测试 | +| `EK-FR-06` 至 `EK-FR-09` | Provider 判别联合、Adapter 配置版本、Renderer 本地字段定义 | 契约测试、UI 字段显隐测试 | +| `EK-FR-10`、`EK-FR-11` | `KnowledgeBase.kind`、绑定表、统一 `retrieveMany` | 本地与外部混合检索测试 | +| `EK-FR-12`、`EK-FR-13` | 引用定位判别联合、结果标准化、检索测试 IPC | 引用持久化与 UI 测试 | +| `EK-FR-14` | 稳定错误码、逐库 Outcome、取消和超时 | 错误 fixture、部分失败测试 | +| `EK-FR-15` | 外键限制、绑定本地删除、无远端写接口 | 删除生命周期测试 | +| `EK-FR-16` | Main-only HTTP、固定端点、传输风险确认 | 地址、证书和凭据泄漏测试 | diff --git a/docs/features/knowledge-base/external-knowledge-ui-design.md b/docs/features/knowledge-base/external-knowledge-ui-design.md new file mode 100644 index 00000000..28e44f0b --- /dev/null +++ b/docs/features/knowledge-base/external-knowledge-ui-design.md @@ -0,0 +1,401 @@ +# 外部知识库 UI 设计 + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 状态 | 设计稿 | +| 版本 | 0.1 | +| 日期 | 2026-09-03 | +| 产品需求 | [外部知识库接入 PRD](./external-knowledge-prd.md) | +| 行为规则 | [外部知识库逻辑设计](./external-knowledge-logic-design.md) | +| 全局规范 | [GoodBuddy UI 设计系统](../../../UI-DESIGN.md) | + +## 1. 信息架构 + +外部知识库不增加左侧主导航和知识库一级页签。现有知识库页面结构保持: + +```text +知识库 +├─ 页面标题区 +│ ├─ 管理外部实例 +│ └─ 新建知识库 +├─ 知识库列表 +└─ 当前知识库详情 +``` + +“管理外部实例”管理可复用连接;“新建知识库”负责创建本地知识库或添加一个远端绑定。 + +## 2. 页面标题区 + +常规宽度: + +```text +知识库 [管理外部实例] [新建知识库] +导入、检索并维护本地和企业现有知识 +范围:全局 +``` + +- “新建知识库”保持主按钮。 +- “管理外部实例”是带服务器图标的次按钮。 +- 沿用知识库页面的全局 `ScopeBadge`,创建和管理外部连接时持续可见。 +- 按钮使用文字和图标,不增加只含缩写的厂商快捷入口。 +- 窄窗口下两个按钮换到标题下方,保持同一行;空间不足时各占一半宽度。 + +对应:`EK-FR-01`。 + +## 3. 知识库列表 + +本地和外部知识库保留在同一主列表。条目采用现有列表密度,不增加卡片墙。 + +```text +研发规范 +RAGFlow · 研发知识平台 · 远端可检索 + +产品资料 +本地 · 12 个来源 · 全文与向量可用 +``` + +### 3.1 外部条目字段 + +- GoodBuddy 显示名称。 +- Provider 图标或文字徽标。 +- 外部实例名称。 +- “远端可检索”、认证失效、目标不存在等准确状态。 +- 最近一次成功检索时间;从未检索时显示“尚未检索”。 + +外部条目不显示来源数量、同步进度、向量覆盖率、本地图谱或导入失败数。 + +### 3.2 列表筛选 + +现有搜索同时匹配 GoodBuddy 名称、远端名称、Provider 和实例名称。来源筛选使用菜单: + +```text +全部来源 +本地 +Dify +FastGPT +RAGFlow +``` + +筛选不是新的页面页签。 + +## 4. 管理外部实例 + +点击“管理外部实例”打开大尺寸 Modal。Modal 使用标题、可滚动内容和固定操作区,遵循 +全局焦点陷阱、Escape、背景隔离和焦点恢复规则。 + +```text +┌──────────────────────────────────────────────────────────────┐ +│ 外部实例 [添加实例] [×] │ +│ 管理 Dify、FastGPT 和 RAGFlow 的连接 │ +├──────────────────────────────────────────────────────────────┤ +│ 名称 Provider 服务地址 状态 操作 │ +│ 研发知识平台 RAGFlow ragflow.example 正常 ⋯ │ +│ 客服知识平台 FastGPT fastgpt.example 认证失效 ⋯ │ +└──────────────────────────────────────────────────────────────┘ +``` + +### 4.1 实例行 + +显示: + +- 名称、Provider、脱敏后的主机名、状态。 +- 已绑定知识库数量。 +- 最近测试时间。 +- 行尾菜单:测试连接、编辑、停用或启用、删除。 + +服务地址可以显示 scheme、host 和非默认端口,不显示路径中的敏感信息、查询或凭据。 + +### 4.2 空状态 + +```text +尚未配置外部实例 +添加企业现有的 Dify、FastGPT 或 RAGFlow 服务。 +[添加实例] +``` + +筛选无结果和加载失败使用不同 `EmptyState` 变体。 + +## 5. 添加和编辑实例 + +实例表单在管理 Modal 内切换为编辑面板,不叠加第二层 Modal。 + +```text +添加外部实例 + +实例名称 [研发知识平台 ] +Provider [RAGFlow ▾] +服务地址 [https://ragflow.example ] +认证方式 API Key +API Key [•••••••••••••••• ] +凭据状态 尚未保存 + +连接测试 +服务连接 未测试 +身份认证 未测试 +知识库列表 未测试 +检索接口 绑定知识库时验证 + + [取消] [测试连接] [保存实例] +``` + +### 5.1 字段行为 + +- Provider 使用原生 Select;编辑已被绑定的实例时不可切换 Provider。 +- 服务地址只接受完整 HTTP(S) 地址。字段下方说明其受全局内网兼容模式影响。 +- API Key 使用密码输入和显示/隐藏图标。明文会在当前表单和保存 IPC 中短暂存在;编辑时 + 留空表示保留,不使用占位假密钥。 +- 已保存凭据旁提供“替换凭据”和“清除凭据”,清除属于需要确认的操作。 +- 地址使用 HTTP,或连接测试依赖放宽证书校验时,在测试和保存操作旁持续显示传输风险。 + 用户必须针对当前地址确认后才能保存;地址变化会清除该确认。 +- “测试连接”不保存草稿;测试期间按钮显示进度并提供取消。 +- 保存成功进入应用通知,Modal 返回实例列表并聚焦对应行。 + +### 5.2 测试结果 + +分项状态使用图标、文字和说明,不只依靠颜色: + +```text +服务连接 通过 183 ms +身份认证 通过 +知识库列表 受限 当前凭据不能读取列表,可手工填写知识库 ID +检索接口 待验证 添加知识库时执行 +``` + +长错误折叠显示,正文经过脱敏。失败后保留全部草稿和 API Key 输入。 + +FastGPT 实例额外显示:`检索会计入该实例的 API 使用记录,并可能产生 Embedding 或 +Rerank 用量。` + +## 6. 新建知识库向导 + +扩展现有页面内 `CreateLibraryWizard`,不改为新的全屏页面或 Modal。 + +### 6.1 类型选择 + +表单第一项使用单选卡片或共享 SegmentedControl: + +```text +知识库类型 +[本地] [Dify] [FastGPT] [RAGFlow] +``` + +只有选择本地时显示现有存储模式、图谱和本地说明。外部类型选中后显示两栏配置。 + +### 6.2 外部类型两栏布局 + +```text +┌──────────────────────────────┬──────────────────────────────┐ +│ 知识库来源 │ 检索配置 │ +│ │ │ +│ Provider RAGFlow │ 通用配置 │ +│ 外部实例 [研发平台 ▾] │ 返回片段数 [ 6 ] │ +│ 远端知识库 [研发规范 ▾] │ 请求超时 [15 秒] │ +│ [↻] │ 单片段上限 [4000] │ +│ [手工填写知识库 ID] │ │ +│ │ RAGFlow 配置 │ +│ 显示名称 [研发规范 ]│ 相似度阈值 [0.20] │ +│ 远端名称 研发规范 │ 向量相似度权重 [0.30] │ +│ 远端 ID 7f31…c902 │ KNN Top K [1024] │ +│ 测试查询 [部署网络要求 ]│ 图谱检索 [开关] │ +│ │ Knowledge Compilation [开关]│ +├──────────────────────────────┴──────────────────────────────┤ +│ 将向研发知识平台发送测试查询。不会上传文件或完整会话。 │ +│ [取消] [测试检索] [添加知识库] │ +└─────────────────────────────────────────────────────────────┘ +``` + +测试查询由用户填写,不自动生成,也不取用当前会话内容。“添加知识库”在真实检索请求 +成功前禁用;成功返回零条结果仍可添加,但界面显示“检索成功,未找到匹配片段”。验证结果 +在底部说明区展示,不用成功 Alert 撑高表单。 +添加成功后沿用本地知识库行为,把新绑定加入当前聊天选择,不重新启用其他已取消知识库。 + +### 6.3 目录下拉框 + +- 选择实例后自动打开加载状态,不要求再点击“读取”。 +- 使用可搜索 Select,选项显示名称、远端短 ID 和可用状态。 +- 右侧刷新使用刷新图标按钮,Tooltip 为“刷新知识库列表”。 +- 加载时保持控件稳定尺寸,显示“正在读取知识库…”。 +- 目录为空显示“当前实例没有可访问的知识库”。 +- 403 或不支持列表时显示原因和“手工填写知识库 ID”。 +- 列表失败后显示“重试”,不自动切换到手工模式。 + +### 6.4 手工模式 + +```text +远端知识库 ID [ ] +显示名称 [ ] +[验证知识库] +``` + +验证成功后显示远端名称和 Provider 返回的摘要。返回自动列表不会丢弃已输入 ID,切换前 +如有未保存输入须确认。 + +## 7. 配置面板 + +右侧配置固定分为“通用配置”和“{Provider} 配置”,不创建嵌套卡片。高级字段可以使用 +一个折叠区,但核心检索方式、阈值和 RAGFlow 图谱检索保持直接可见。 + +控件选择: + +- 开关:图谱检索、Score 阈值启用、Rerank、使用 Dify 知识库默认配置。 +- Select 或 SegmentedControl:少量固定检索方式。 +- 数字输入或 Stepper:结果数、Token、Top K、超时。 +- Slider 加数字输入:0 至 1 的阈值和权重,二者保持同步。 +- Metadata 条件:初始版本不提供自由 JSON 编辑器。 + +字段显隐由 GoodBuddy 内置 Provider 描述和 Main 返回的能力状态共同决定。服务端返回的 +任意字符串不得变成 HTML、控件标签或帮助链接。 + +### 7.1 RAGFlow 图谱文案 + +开关名称:`图谱检索` + +说明:`检索远端知识库已经生成的图谱内容,不会创建或更新图谱。` + +只有远端详情或受控探测表明图谱已经构建时,该开关才可用。证据缺失时显示“未确认远端 +图谱状态”并禁用。Knowledge Compilation 单独显示为 `包含 Knowledge Compilation`,默认 +关闭,不把它和旧 GraphRAG 合成同一开关。 + +## 8. 外部知识库详情 + +选中外部绑定后,现有详情区按来源类型裁剪: + +```text +研发规范 RAGFlow · 远端检索 +研发知识平台 / 远端知识库 7f31…c902 + +[概览] [检索配置] [检索测试] +``` + +### 8.1 概览 + +显示 Provider、实例、远端名称、远端 ID、连接状态、最近成功检索和数据位置。操作包括: + +- 刷新远端信息。 +- 更换远端知识库。 +- 编辑 GoodBuddy 显示名称。 +- 从 GoodBuddy 移除。 + +不显示导入文件、添加目录、添加网页、同步、分块、重建索引和本地图谱入口。 + +### 8.2 检索配置 + +复用创建向导右侧配置面板。存在失效字段时,页头显示“配置需要确认”,字段附近说明 +Provider 版本变化,保存按钮保持禁用直到用户处理。 + +### 8.3 检索测试 + +复用现有检索测试工作台的查询、结果和焦点行为,但外部结果采用 Provider 诊断: + +```text +RAGFlow · 研发知识平台 +总耗时 642 ms · 返回 6 条 · 保留 6 条 + +1 部署规范.pdf + 第四章 网络要求… + Provider 分数 0.82 · 文档 ID 98ab… +``` + +外部测试不显示 FTS/CJK/本地向量扫描等本地通道,也不提供依赖本地分块的“查看上下文”。 + +## 9. 聊天知识范围 + +现有多选列表保留一个选择面,只在每行增加来源: + +```text +[✓] 产品资料 本地 +[✓] 研发规范 RAGFlow · 研发知识平台 +[ ] 客服知识 FastGPT · 客服平台 +``` + +- 不按 Provider 创建多套选择器。 +- 不可用绑定保留显示但禁用勾选,并给出认证失效或目标不存在原因。 +- 当前会话已选绑定变为不可用时,不静默移除 ID;发送前提示该知识库本次无法检索。 + +## 10. 执行状态和引用 + +活动状态: + +```text +正在检索“研发规范” +RAGFlow · 研发知识平台 · 已发送当前检索词 +``` + +部分失败: + +```text +已检索 3 个知识库,2 个成功,1 个超时 +[查看详情] +``` + +引用: + +```text +部署规范.pdf / 网络要求 +研发规范 · RAGFlow · 研发知识平台 +``` + +引用详情显示远端文档名、ID、片段、Provider 分数和实际返回的定位。未完成 URL 安全设计前, +不显示“打开远端来源”。 + +## 11. 删除确认 + +移除绑定: + +```text +从 GoodBuddy 移除“研发规范”? +这会删除本机绑定和检索配置,不会删除 RAGFlow 中的知识库或文档。 + +[取消] [移除] +``` + +删除有绑定的实例: + +```text +“研发知识平台”仍被 3 个知识库使用 +删除实例会同时从 GoodBuddy 移除这些绑定。远端数据不会改变。 + +[取消] [查看知识库] [删除实例和本地绑定] +``` + +破坏性主操作使用 `danger-solid`,默认焦点放在“取消”。 + +## 12. 可访问性与响应式 + +- 常规宽度两栏使用稳定 Grid;小于 `960px` 时改为单栏,顺序为来源、通用配置、Provider 配置。 +- 小于 `720px` 时外部实例表格转为单列列表,行操作保留菜单按钮和完整可访问名称。 +- Modal、创建向导、下拉框和折叠区支持完整键盘操作。 +- 异步列表和测试状态使用 `aria-live="polite"`;错误使用与字段关联的 `role="alert"`。 +- 图标按钮必须提供 Tooltip 和 `aria-label`。 +- 状态不只靠颜色;加载、成功、受限和失败均包含文字。 +- 长实例名、地址、远端名称和 ID 使用单行省略,完整值可通过 Tooltip 或详情查看。 +- 切换类型、实例或退出时存在有效草稿,应按全局离开保护规则确认。 + +## 13. 文案表 + +| 场景 | 文案 | +| --- | --- | +| 页面操作 | 管理外部实例 | +| 创建类型 | 本地 / Dify / FastGPT / RAGFlow | +| 创建主操作 | 添加知识库 | +| 列表加载 | 正在读取知识库… | +| 列表受限 | 当前凭据不能读取知识库列表,可手工填写知识库 ID。 | +| 远端状态 | 远端可检索 | +| 移除操作 | 从 GoodBuddy 移除 | +| 图谱开关 | 图谱检索 | +| 测试说明 | 测试只发送当前查询,不会调用 GoodBuddy 模型或修改远端内容。 | + +产品文案不使用“同步外部知识库”“导入 Dify 知识库”或“创建远端知识库”,因为这些动作 +都不是本功能的实际行为。 + +## 14. 需求追踪 + +| UI 区域 | 需求 | 场景 | +| --- | --- | --- | +| 页面标题与统一列表 | `EK-FR-01`、`EK-FR-10` | `EK-US-C1` | +| 外部实例管理与表单 | `EK-FR-02`、`EK-FR-03`、`EK-FR-15`、`EK-FR-16` | `EK-US-A1` 至 `EK-US-A3` | +| 新建知识库向导 | `EK-FR-04` 至 `EK-FR-09` | `EK-US-B1` 至 `EK-US-B4` | +| 外部详情与检索测试 | `EK-FR-12`、`EK-FR-13` | `EK-US-C3`、`EK-US-D1` 至 `EK-US-D4` | +| 聊天范围、状态和引用 | `EK-FR-11`、`EK-FR-12`、`EK-FR-14` | `EK-US-C1` 至 `EK-US-C4` | diff --git a/docs/features/knowledge-base/external-knowledge-user-stories.md b/docs/features/knowledge-base/external-knowledge-user-stories.md new file mode 100644 index 00000000..98434d07 --- /dev/null +++ b/docs/features/knowledge-base/external-knowledge-user-stories.md @@ -0,0 +1,212 @@ +# 外部知识库 User Stories + +## 文档信息 + +| 项目 | 内容 | +| --- | --- | +| 状态 | 设计稿 | +| 版本 | 0.1 | +| 日期 | 2026-09-03 | +| 关联 PRD | [外部知识库接入 PRD](./external-knowledge-prd.md) | + +## 1. 角色 + +- **知识库使用者**:在聊天中选择已经添加的本地或外部知识库并查看引用。 +- **实例维护者**:持有外部知识库 API Key,负责配置实例、选择远端知识库和处理失效连接。 +- **RAG 调试者**:需要调整 Provider 参数并直接验证检索结果。 + +## 2. 实例管理 + +### EK-US-A1 添加外部实例 + +作为实例维护者,我希望在知识库页面保存一个外部实例,以便后续绑定其中的多个知识库。 + +验收: + +- Given 用户打开“管理外部实例”并选择 Dify、FastGPT 或 RAGFlow +- When 用户填写名称、服务地址和 API Key,并执行连接测试 +- Then 页面分别显示服务、认证、目录和检索检查结果 +- And 保存后只显示“凭据已配置”,不回显 API Key +- And 新实例可被同 Provider 的新建知识库向导选择 +- And 使用 HTTP 或放宽证书校验时,保存前明确提示 API Key 的传输风险 + +### EK-US-A2 修复失效凭据 + +作为实例维护者,我希望替换认证失效的 API Key,同时保留已有知识库绑定。 + +验收: + +- Given 实例因认证失败处于“认证失效”状态 +- When 用户选择“替换凭据”、测试并保存 +- Then 所有绑定继续引用同一实例 ID +- And 旧密钥不再使用 +- And 用户没有输入新密钥时可以取消且不清除旧密钥 + +### EK-US-A3 删除仍被使用的实例 + +作为实例维护者,我希望删除实例前看到受影响的知识库,以免留下无法解释的绑定。 + +验收: + +- Given 实例仍被一个或多个外部知识库绑定引用 +- When 用户点击“删除实例” +- Then 确认界面列出受影响数量和名称 +- And 用户可以取消,或明确同时移除本地绑定 +- And 确认后不向外部实例发送删除请求 + +## 3. 添加知识库 + +### EK-US-B1 从远端列表添加 + +作为实例维护者,我希望选择 Provider 和实例后自动看到远端知识库,以便避免手工复制 ID。 + +验收: + +- Given 至少存在一个可用的对应 Provider 实例 +- When 用户在“新建知识库”中选择外部类型和实例 +- Then GoodBuddy 自动读取有界知识库列表 +- And 下拉框支持按名称搜索与刷新 +- And 目录只显示当前凭据可见的知识库,不推断隐藏对象 +- And 切换实例后旧实例的异步响应不会覆盖新列表 + +### EK-US-B2 手工填写远端 ID + +作为实例维护者,我希望列表接口受限时仍可通过远端 ID 添加已有知识库。 + +验收: + +- Given 连接测试表明认证和检索可用,但目录读取无权限或不受支持 +- When 用户进入手工模式并填写远端知识库 ID +- Then GoodBuddy 使用详情或测试检索验证该目标 +- And 验证失败时保留输入并显示原因 +- And 未经真实验证不能完成添加 + +### EK-US-B3 配置 RAGFlow 图谱检索 + +作为 RAG 调试者,我希望在添加 RAGFlow 知识库时设置图谱检索,以便使用远端已经构建的图谱内容。 + +验收: + +- Given 适配器确认实例检索接口支持 `use_kg` +- When 用户选择一个具备相关能力的 RAGFlow 知识库 +- Then 右侧显示“图谱检索”开关并说明它只影响检索 +- And 开启后测试请求携带该选项 +- And 只有远端知识库存在已构建图谱的证据时才允许开启 +- And 页面不把该开关描述为构建或更新远端图谱 +- And 能力不明确时该开关禁用并说明原因 + +### EK-US-B4 保持本地创建流程 + +作为本地知识库用户,我希望新增外部类型后仍能按原流程创建本地知识库。 + +验收: + +- Given 用户在新建向导中选择“本地” +- When 用户填写名称、存储模式和图谱设置 +- Then 表单字段、默认值和创建结果与现有行为一致 +- And 外部实例、远端 ID 和 Provider 配置不出现 + +## 4. 检索和引用 + +### EK-US-C1 在聊天中选择外部知识库 + +作为知识库使用者,我希望外部知识库出现在现有知识范围选择器中,以便与本地知识库一起使用。 + +验收: + +- Given 外部知识库绑定处于可检索状态 +- When 用户打开聊天知识范围 +- Then 它与本地知识库出现在同一选择器中 +- And 条目持续显示 Provider 和实例名称 +- And 选择结果仍保存 GoodBuddy 知识库 ID +- And 新添加的绑定进入当前聊天选择,但不重新启用其他已取消知识库 + +### EK-US-C2 只发送检索查询 + +作为知识库使用者,我希望清楚知道哪些数据会发送到企业知识库。 + +验收: + +- Given 本次请求选择了外部知识库 +- When GoodBuddy 执行检索 +- Then 只发送本次检索查询、远端知识库 ID 和已保存检索参数 +- And 不发送完整会话、本地附件、其他知识库内容、系统提示或模型凭据 +- And 活动状态显示目标 Provider 和实例 + +### EK-US-C3 查看外部引用 + +作为知识库使用者,我希望回答中的引用标明外部来源,以便回到企业知识系统核验。 + +验收: + +- Given Provider 返回文档名、片段 ID、内容和分数 +- When GoodBuddy 展示引用 +- Then 引用显示 Provider、实例、知识库和文档名称 +- And 详情只显示 Provider 实际返回且通过校验的定位信息 +- And 缺失页码、链接或分数时不生成替代值 + +### EK-US-C4 多知识库部分失败 + +作为知识库使用者,我希望一个外部实例暂时失败时仍能使用其他成功结果。 + +验收: + +- Given 本次选择了本地知识库和两个外部知识库 +- When 一个外部请求超时,其他请求成功 +- Then 成功证据继续进入回答 +- And 页面显示一个知识库检索失败及其原因 +- And 超时不显示为“未找到相关内容” +- And GoodBuddy 不自动改用同 Provider 的其他实例 + +## 5. 配置与诊断 + +### EK-US-D1 调整 Provider 配置 + +作为 RAG 调试者,我希望只看到当前 Provider 支持的参数,以便理解设置会怎样影响远端检索。 + +验收: + +- Given 用户编辑一个外部知识库绑定 +- When 页面读取实例能力和已保存配置 +- Then 通用配置与 Provider 专属配置分区显示 +- And 每个字段显示范围、默认值和作用 +- And 不受支持的字段不会被静默发送 +- And 恢复默认只恢复当前绑定的 Provider 配置 + +### EK-US-D2 运行检索测试 + +作为 RAG 调试者,我希望在知识库页面直接测试外部检索,不经过聊天模型。 + +验收: + +- Given 当前选中一个外部知识库 +- When 用户输入查询并点击“测试检索” +- Then 页面显示 Provider 耗时、返回数量、片段、来源和截断状态 +- And 测试不创建聊天消息、不调用 GoodBuddy LLM、不修改远端内容 +- And 远端原始响应和凭据不进入界面或日志 +- And FastGPT 测试明确提示远端可能记录 API 使用并产生检索或重排用量 + +### EK-US-D3 Provider 版本变化 + +作为实例维护者,我希望升级外部系统后看到配置是否仍受支持。 + +验收: + +- Given 最近一次能力探测与已保存快照不同 +- When 用户测试实例或打开绑定设置 +- Then 页面指出新增、失效或行为变化的配置 +- And 失效配置不会静默删除或继续发送 +- And 用户确认有效配置后才更新绑定 + +### EK-US-D4 远端知识库被删除 + +作为实例维护者,我希望远端目标不存在时看到准确状态并重新绑定。 + +验收: + +- Given Provider 返回目标不存在 +- When 用户打开知识库或执行检索 +- Then 绑定状态显示“远端知识库不存在” +- And 聊天选择器不把它显示为可用 +- And 用户可以刷新目录并选择新的远端知识库 +- And 保存新目标前必须重新测试