知识库与嵌入调试接口.md 27 KB

知识库与嵌入调试接口

本文引用的文件

  • KnowledgeBaseController.java
  • EmbeddingDebugController.java
  • KnowledgeBaseService.java
  • KnowledgeDocService.java
  • SaveKnowledgeBaseDTO.java
  • KnowledgeBaseVO.java
  • KnowledgeDocVO.java
  • KnowledgeBase.java
  • KnowledgeDoc.java
  • EmbeddingDebugDTO.java
  • EmbeddingDebugVO.java
  • knowledgeApi.ts

目录

  1. 简介
  2. 项目结构与定位
  3. 核心组件总览
  4. 架构概览
  5. 知识库接口规范
  6. 嵌入调试接口规范
  7. 知识库与 Agent RAG 向量检索的关系
  8. 使用示例
  9. 常见问题排查
  10. 权限与隔离模型
  11. 结论

简介

本文档面向调用方和运维人员,系统化说明知识库管理接口与嵌入调试接口的行为、参数、响应、错误语义和排查方法。重点覆盖:

  • 知识库的创建、查询、更新、删除。
  • 知识库文档上传、下载、重试向量化、删除。
  • 嵌入调试接口对本地 ONNX 模型的批量文本嵌入与相似度计算。
  • 知识库与 Agent RAG 中向量检索的协作关系。
  • 文档解析失败、向量入库失败、相似度检索为空等典型问题的排查路径。

项目结构与定位

知识库接口位于后端 ai-server 模块的 com.zsjz.ai.module.knowledge.controller 包;嵌入调试接口位于 com.zsjz.ai.module.embedding.controller 包。前端 Electron 应用通过 ai-electron/frontend/src/ai/api/knowledgeApi.ts 封装知识库 API,包括登录态传递、文件下载处理等细节。

graph TB
    Client["调用方或前端"] --> Gateway["Sa-Token 鉴权<br/>x-token 头"]
    Gateway --> KB_Ctrl["KnowledgeBaseController"]
    Gateway --> Emb_Ctrl["EmbeddingDebugController"]
    KB_Ctrl --> KB_Service["KnowledgeBaseService"]
    KB_Ctrl --> Doc_Service["KnowledgeDocService"]
    Doc_Service --> Parser["文档解析器"]
    Doc_Service --> Indexer["知识索引器"]
    Doc_Service --> Storage["本地文件存储"]
    Emb_Ctrl --> Emb_Service["EmbeddingService"]
    Emb_Service --> Model["本地 ONNX 模型"]

图示来源

  • KnowledgeBaseController.java:1-122
  • EmbeddingDebugController.java:1-62
  • KnowledgeBaseService.java:1-200
  • KnowledgeDocService.java:1-200
  • knowledgeApi.ts:1-97

章节来源

  • KnowledgeBaseController.java:1-122
  • EmbeddingDebugController.java:1-62
  • knowledgeApi.ts:1-97

核心组件总览

组件 职责 关键行为
KnowledgeBaseController 暴露知识库 REST 接口 列表、新建、编辑、删除知识库;文档列表、上传、删除、重试、下载
KnowledgeBaseService 知识库生命周期与归属校验 内置库只读;自建库可编辑删除;级联清理文档、向量、方案绑定
KnowledgeDocService 文档上传、解析、审计下载、删除、重试索引 Tika 提取全文;异步向量化;PENDING/INDEXING/READY/FAILED 状态机
EmbeddingDebugController 嵌入调试入口 批量文本生成向量,返回维度、耗时、向量数组、两两余弦相似度矩阵
knowledgeApi.ts 前端知识库 API 封装 携带 x-token 下载文件、multipart 上传、统一错误提示

章节来源

  • KnowledgeBaseController.java:1-122
  • KnowledgeBaseService.java:1-200
  • KnowledgeDocService.java:1-200
  • EmbeddingDebugController.java:1-62
  • knowledgeApi.ts:1-97

架构概览

知识库流程分为两层:

  1. 元数据层:知识库表记录名称、描述、是否内置、创建者;文档表记录文件名、路径、字符数、块数、索引状态、失败原因。
  2. 向量层:文档解析后由索引器切分并写入向量数据库;RAG 检索消费 READY 文档对应的向量。

    flowchart TD
    Upload["上传文档"] --> Validate["校验类型、大小、数量上限"]
    Validate --> SaveFile["保存原件到本地存储"]
    SaveFile --> Extract["Tika 提取全文到 sidecar"]
    Extract --> Register["登记文档行"]
    Register --> Status{"提取成功?"}
    Status -->|是| Pending["索引状态设为 PENDING"]
    Status -->|否| Failed["索引状态设为 FAILED"]
    Pending --> Publish["发布索引事件"]
    Publish --> Vectorize["异步切分并向量化入库"]
    Vectorize --> Ready["索引状态变为 READY"]
    Failed --> Retry["重试索引后可重新抽取并入库"]
    

图示来源

  • KnowledgeDocService.java:1-200
  • KnowledgeDoc.java:1-81

知识库接口规范

公共约定

  • 基础路径:/knowledge-bases
  • 登录要求:所有接口依赖 Sa-Token 登录态,从请求头 x-token 获取当前用户 ID。
  • 返回值包装:除下载接口外,其他接口均返回统一结果对象,包含业务数据和状态信息。
  • ID 传递:前端使用字符串 ID,后端按 Long 处理;跨语言调用时注意数字精度。

1. 列出知识库

  • HTTP 方法:GET
  • URL:/knowledge-bases
  • 请求参数:无
  • 权限要求:已登录
  • 行为:
    • 返回内置知识库与当前用户自建知识库。
    • 内置库全局可见;自建库仅创建者可见。
    • 返回列表项包含知识库标识、名称、描述、是否内置、是否属于当前用户、我的文档数、待索引文档数。

章节来源

  • KnowledgeBaseController.java:34-43
  • KnowledgeBaseService.java:53-74
  • KnowledgeBaseVO.java:1-31

2. 新建知识库

  • HTTP 方法:POST
  • URL:/knowledge-bases
  • 请求体:
    • name:必填,长度不超过 100。
    • description:可选,长度不超过 500。
  • 权限要求:已登录
  • 行为:
    • 新建的是非内置知识库,归属当前用户。
    • 返回新建知识库 VO。

章节来源

  • KnowledgeBaseController.java:45-49
  • SaveKnowledgeBaseDTO.java:1-22
  • KnowledgeBaseService.java:108-116

3. 更新知识库

  • HTTP 方法:PUT
  • URL:/knowledge-bases/{id}
  • 路径参数:
    • id:知识库主键。
  • 请求体:同新建知识库 DTO。
  • 权限要求:
    • 必须是当前用户自建的库。
    • 内置知识库拒绝更新。
  • 行为:
    • 更新名称与描述。
    • 返回最新知识库 VO。

章节来源

  • KnowledgeBaseController.java:51-55
  • KnowledgeBaseService.java:118-126

4. 删除知识库

  • HTTP 方法:DELETE
  • URL:/knowledge-bases/{id}
  • 路径参数:
    • id:知识库主键。
  • 权限要求:
    • 必须是当前用户自建的库。
    • 内置知识库拒绝删除。
  • 行为:
    • 删除该知识库下全部文档原件与 sidecar。
    • 删除向量数据。
    • 删除下载记录与文档行。
    • 解绑所有引用该知识库的研判方案。

章节来源

  • KnowledgeBaseController.java:57-63
  • KnowledgeBaseService.java:128-152

5. 列出“我的上传文档”

  • HTTP 方法:GET
  • URL:/knowledge-bases/{id}/docs
  • 路径参数:
    • id:知识库主键。
  • 权限要求:
    • 必须能访问该知识库。
    • 列表只返回当前用户上传的文档,不返回其他用户的文档。
  • 行为:
    • 返回文档标识、知识库标识、文件名、MIME、大小、字符数、已向量化块数、索引状态、失败原因、下载次数、创建时间。

章节来源

  • KnowledgeBaseController.java:65-69
  • KnowledgeDocService.java:63-79
  • KnowledgeDocVO.java:1-38

6. 上传文档

  • HTTP 方法:POST
  • URL:/knowledge-bases/{id}/docs
  • 路径参数:
    • id:知识库主键。
  • 请求体:multipart/form-data,字段名 file
  • 权限要求:
    • 自建库:库主人可上传。
    • 内置库:仅平台管理员(固定用户 ID 为 1)可维护上传。
  • 行为:
    • 校验文件是否为空、类型、大小、用户在当前库下的文档数量上限。
    • 保存原件到本地存储。
    • 尝试提取全文到 sidecar;提取失败不阻断登记,文档状态设为失败。
    • 提取成功后登记为 PENDING,并异步触发向量化。
    • 返回文档 VO,前端应轮询 indexStatus。

章节来源

  • KnowledgeBaseController.java:71-75
  • KnowledgeDocService.java:81-157
  • KnowledgeBaseService.java:160-166

7. 删除文档

  • HTTP 方法:DELETE
  • URL:/knowledge-bases/{id}/docs/{docId}
  • 路径参数:
    • id:知识库主键。
    • docId:文档主键。
  • 权限要求:只能删除自己上传的文档。
  • 行为:
    • 删除原件与 sidecar。
    • 删除对应向量。
    • 删除下载记录。
    • 删除文档行。

章节来源

  • KnowledgeBaseController.java:77-81
  • KnowledgeDocService.java:171-186

8. 重试文档索引

  • HTTP 方法:POST
  • URL:/knowledge-bases/{id}/docs/{docId}/reindex
  • 路径参数:
    • id:知识库主键。
    • docId:文档主键。
  • 权限要求:只能重试自己上传的文档。
  • 行为:
    • 将文档状态重置为 PENDING,清空失败原因。
    • 重新发布索引事件,由索引器执行幂等重放。
    • 适用于提取失败、sidecar 缺失、嵌入服务临时不可用等情况。

章节来源

  • KnowledgeBaseController.java:83-87
  • KnowledgeDocService.java:188-206

9. 下载文档

  • HTTP 方法:GET
  • URL:/knowledge-bases/{id}/docs/{docId}/download
  • 路径参数:
    • id:知识库主键。
    • docId:文档主键。
  • 权限要求:只能下载自己上传的文档。
  • 响应特点:
    • 不是普通 JSON,而是裸文件流。
    • 响应头包含附件文件名。
    • 前端必须通过带 x-token 的请求下载,否则会被视为未登录。
  • 行为:
    • 校验文档归属。
    • 从本地存储读取原件流。
    • 写入下载审计记录。
    • 原子增加下载次数。

章节来源

  • KnowledgeBaseController.java:89-108
  • KnowledgeDocService.java:159-169
  • knowledgeApi.ts:67-97

嵌入调试接口规范

1. 嵌入调试

  • HTTP 方法:POST
  • URL:/embedding/debug
  • 请求体:
    • texts:字符串数组,必填,最多 16 条。
  • 权限要求:依赖登录态;主要用于人工验证本地嵌入模型。
  • 行为:

    • 调用本地嵌入服务批量生成向量。
    • 记录本次嵌入耗时。
    • 计算每两条文本之间的余弦相似度,保留四位小数。
    • 返回向量维度、耗时、向量数组、相似度矩阵。

      sequenceDiagram
      participant Caller as "调用方"
      participant Ctrl as "EmbeddingDebugController"
      participant Service as "EmbeddingService"
      Caller->>Ctrl: POST /embedding/debug
      Ctrl->>Service: 批量嵌入 texts
      Service-->>Ctrl: 向量数组
      Ctrl->>Ctrl: 计算两两余弦相似度
      Ctrl-->>Caller: 维度、耗时、向量、相似度矩阵
      

图示来源

  • EmbeddingDebugController.java:19-62

章节来源

  • EmbeddingDebugController.java:1-62
  • EmbeddingDebugDTO.java:1-19
  • EmbeddingDebugVO.java:1-24

知识库与 Agent RAG 向量检索的关系

知识库不是直接参与 RAG 检索的唯一通道,而是 RAG 的上游数据来源之一。其关系如下:

  1. 知识库负责文档入库:上传文档后,系统提取全文、切分、生成向量并写入向量数据库。
  2. 索引状态决定能否被检索:只有索引状态为 READY 的文档才会产生可用向量;PENDING、INDEXING、FAILED 的文档自然无法被检索命中。
  3. RAG 检索消费向量:Agent RAG 在执行检索时,会基于问题生成查询向量,并在向量数据库中查找相似片段。知识库中的 READY 文档是这些相似片段的重要来源。
  4. 文档层隔离不影响 RAG 全量检索:“我的上传文档”只对上传者开放,但 RAG 检索绑定知识库时会扫描该知识库下的全部文档向量,而不是只扫描上传者本人上传的部分。

    flowchart LR
    KB["知识库文档"] --> Parse["文档解析"]
    Parse --> Chunk["文本切分"]
    Chunk --> Vector["向量嵌入"]
    Vector --> Store["向量数据库"]
    Query["Agent RAG 查询"] --> QVector["查询向量"]
    QVector --> Search["相似度检索"]
    Search --> Store
    Store --> Context["召回上下文"]
    Context --> LLM["大模型生成回答"]
    

图示来源

  • KnowledgeDoc.java:1-81
  • KnowledgeDocService.java:1-200

章节来源

  • KnowledgeDoc.java:1-81
  • KnowledgeDocService.java:1-200

使用示例

以下示例以 curl 形式展示常见调用方式。实际使用时需替换 {host}、{kb_id}、{doc_id}、{token} 等占位符。

列出知识库

curl -H "x-token: {token}" \
  http://{host}/knowledge-bases

新建知识库

curl -X POST -H "Content-Type: application/json" \
  -H "x-token: {token}" \
  -d '{"name":"测试知识库","description":"用于验证知识库接口"}' \
  http://{host}/knowledge-bases

更新知识库

curl -X PUT -H "Content-Type: application/json" \
  -H "x-token: {token}" \
  -d '{"name":"更新后的知识库","description":"描述已更新"}' \
  http://{host}/knowledge-bases/{kb_id}

删除知识库

curl -X DELETE -H "x-token: {token}" \
  http://{host}/knowledge-bases/{kb_id}

列出我的上传文档

curl -H "x-token: {token}" \
  http://{host}/knowledge-bases/{kb_id}/docs

上传文档

curl -X POST -H "x-token: {token}" \
  -F "file=@/path/to/document.pdf" \
  http://{host}/knowledge-bases/{kb_id}/docs

删除文档

curl -X DELETE -H "x-token: {token}" \
  http://{host}/knowledge-bases/{kb_id}/docs/{doc_id}

重试文档索引

curl -X POST -H "x-token: {token}" \
  http://{host}/knowledge-bases/{kb_id}/docs/{doc_id}/reindex

下载文档

curl -H "x-token: {token}" \
  -o downloaded_file.pdf \
  http://{host}/knowledge-bases/{kb_id}/docs/{doc_id}/download

嵌入调试

curl -X POST -H "Content-Type: application/json" \
  -H "x-token: {token}" \
  -d '{
    "texts": [
      "今天天气很好",
      "明天可能下雨",
      "北京今天的温度很高"
    ]
  }' \
  http://{host}/embedding/debug

常见问题排查

文档解析失败

现象

  • 上传后文档状态为 FAILED。
  • 文档列表中显示失败原因。
  • RAG 检索不到该文档相关内容。

可能原因

  • 文件格式不被支持。
  • 文件损坏或编码异常。
  • 文件大小超过配置上限。
  • Tika 解析抛出异常。

排查步骤

  1. 检查上传响应中的文档状态,确认是否为 FAILED。
  2. 查看文档列表中的失败原因字段。
  3. 确认文件后缀是否在允许的可解析文本类型范围内。
  4. 确认文件大小没有超过系统配置的最大值。
  5. 使用重试接口重新触发索引;若 sidecar 缺失,索引器会重新抽取。
  6. 若仍失败,检查日志中“文档提取失败”相关记录。

章节来源

  • KnowledgeDocService.java:81-157
  • KnowledgeDocService.java:188-206

向量入库失败

现象

  • 文档状态长期停留在 PENDING 或 INDEXING。
  • 文档状态变为 FAILED,失败原因与嵌入服务相关。
  • 知识库中有文档,但 RAG 检索结果为空。

可能原因

  • 嵌入服务暂时不可用。
  • 本地 ONNX 模型初始化失败。
  • 向量数据库连接异常。
  • 文本切分后向量维度异常。

排查步骤

  1. 查看文档 indexStatus 与 failReason。
  2. 调用嵌入调试接口,验证本地模型是否能正常输出向量。
  3. 检查返回结果的 dimension 是否符合预期。
  4. 检查返回的向量数组是否为空。
  5. 检查向量相似度矩阵是否合理。
  6. 如果嵌入服务只是临时故障,使用重试接口重新触发索引。
  7. 如果向量维度异常,优先检查嵌入模型配置和输入文本。

章节来源

  • KnowledgeDocService.java:188-206
  • EmbeddingDebugController.java:19-62
  • EmbeddingDebugVO.java:1-24

相似度检索为空

现象

  • 知识库有文档且状态为 READY。
  • 调用 Agent RAG 检索后,没有找到相关知识片段。

可能原因

  • 文档虽为 READY,但向量质量差,语义表达弱。
  • 查询语句与文档内容差异过大。
  • 向量检索阈值过高。
  • 文档被切分成过细或过粗的片段。
  • 使用了错误的知识库。

排查步骤

  1. 确认文档索引状态是 READY。
  2. 使用嵌入调试接口输入相同或相近文本,观察相似度矩阵。
  3. 如果相似度矩阵对角线接近 1、其他位置接近 0,说明向量区分度正常。
  4. 如果多条不同文本之间相似度也很高,说明嵌入质量可能存在问题。
  5. 调整查询语句,使其更接近文档语义。
  6. 检查知识库是否正确绑定到 Agent 或相关检索流程。
  7. 检查向量检索配置中的相似度阈值。

章节来源

  • KnowledgeDoc.java:1-81
  • EmbeddingDebugController.java:19-62

下载失败或未登录

现象

  • 浏览器地址栏直接访问下载链接返回未登录。
  • 前端下载报错,提示未登录或 token 失效。

可能原因

  • 下载请求缺少 x-token。
  • 使用了 <a href> 直链而非带鉴权的 fetch。
  • token 过期或被清除。

排查步骤

  1. 确保下载请求携带 x-token。
  2. 不要使用普通超链接直接跳转。
  3. 前端应使用带 token 的 fetch 或封装好的下载函数。
  4. 如果后端返回 JSON 而不是文件流,说明鉴权失败,需要刷新 token。

章节来源

  • KnowledgeBaseController.java:89-108
  • knowledgeApi.ts:67-97

无权操作知识库或文档

现象

  • 更新或删除知识库返回权限错误。
  • 删除或下载文档提示只能操作自己上传的文档。

可能原因

  • 知识库是内置库,不允许编辑或删除。
  • 自建知识库不属于当前用户。
  • 文档不是当前用户上传的。
  • 内置知识库仅管理员可上传。

排查步骤

  1. 确认知识库是否内置。
  2. 确认当前用户是否为知识库创建者。
  3. 确认当前用户是否为平台管理员。
  4. 确认文档的 userId 是否与当前登录用户一致。

章节来源

  • KnowledgeBaseService.java:154-174
  • KnowledgeDocService.java:208-218

权限与隔离模型

系统采用双层隔离:

层级 控制点 规则
知识库层 KnowledgeBaseService.requireVisible、requireOwned 内置库全局可见;自建库仅创建者可见;内置库不可编辑删除
文档层 KnowledgeDocService.requireOwnedDoc 文档列表、下载、删除、重试仅上传者本人可操作
上传权限 KnowledgeBaseService.requireUploadable 自建库=库主人;内置库=平台管理员
向量检索 RAG 侧消费知识库向量 不按上传者过滤,按绑定知识库的全量向量检索
classDiagram
    class KnowledgeBase {
        +Long id
        +Long userId
        +Integer isBuiltin
        +String name
        +String description
        +boolean isBuiltin()
    }

    class KnowledgeDoc {
        +Long id
        +Long kbId
        +Long userId
        +String fileName
        +String filePath
        +String sidecarPath
        +String indexStatus
        +String failReason
        +Integer chunkCount
        +Integer downloadCount
    }

    class KnowledgeBaseService {
        +list(userId)
        +create(userId, dto)
        +update(userId, id, dto)
        +delete(userId, id)
        +requireVisible(userId, kbId)
        +requireUploadable(userId, kb)
    }

    class KnowledgeDocService {
        +listMine(userId, kbId)
        +upload(userId, kbId, file)
        +download(userId, docId)
        +delete(userId, docId)
        +reindex(userId, docId)
        -requireOwnedDoc(userId, docId)
    }

    KnowledgeBaseService --> KnowledgeBase : "读写"
    KnowledgeDocService --> KnowledgeDoc : "读写"
    KnowledgeDocService --> KnowledgeBaseService : "校验知识库"

图示来源

  • KnowledgeBase.java:1-57
  • KnowledgeDoc.java:1-81
  • KnowledgeBaseService.java:1-200
  • KnowledgeDocService.java:1-200

结论

知识库接口提供完整的文档生命周期管理能力,并通过内置库与自建库、知识库层与文档层的权限模型,兼顾共享性与隐私性。嵌入调试接口则专注于本地 ONNX 模型的质量验证,帮助快速定位向量维度、归一化、语义区分度等问题。在实际使用中,应重点关注文档索引状态、失败原因、嵌入调试结果和 RAG 检索阈值,形成从上传、向量化到检索的完整排查闭环。