Files
knowledge-adapter-service/docs/frontend-api-guide.md
T
姚章浩 693cd952cd feat(asset): 清理被截断的结尾图片引用,修复整单 502
仓库首次入库(此前仅存在于本地工作区与测试服构建产物中,未上传)。

改动(src/knowledge_adapter/asset_content_processor.py):
- 新增 _TRUNCATED_TRAILING_MARKDOWN_RESOURCE_IMAGE 规则,清除 chunk 末尾被截断的
  ![](resource://xxxx 残片(WeKnora 分块在图片引用中间截断时产生,旧逻辑无法匹配完整引用,
  残留 resource:// 触发 ContentProcessingError,导致整单 502)
- 回归测试 tests/test_asset_content_processor.py::
  test_truncated_trailing_markdown_resource_image_is_removed

验证证据:
- 测试服 120.76.217.51,镜像 knowledge-adapter-service:reviewed-test-aeab4b5fca2d
  (release aeab4b5fca2d8661):KB d015d05c-25c8-4d63-b2ab-e8590d3c2dfb 5 个查询全部
  http=200、records=5、残留 resource:// = 0;KB b9dacd62 无退化;容器日志无 error/exception
- 本地:pytest 141 项全通过、ruff 全通过
- 该文件与 258c31e0fe07fd08 源码的差异经逐文件 md5 比对,为唯一变更文件
2026-09-16 10:01:27 +08:00

8.9 KiB
Raw Blame History

测试环境 WeKnora 检索 API 调用说明

1. 当前状态

公网HTTPS链路已经通过真实验收:

Dify/业务后端
  → https://weknora-api-test.dobot.cn/retrieval
  → 公网测试入口
  → 测试ECS Nginx:80
  → Knowledge Adapter:18080
  → WeKnora knowledge-search

真实验收结果:

检索:HTTP 200
records:5
稳定图片UUID:15
图片:稳定UUID 302 → 私有OSS签名取图 HTTP 200

完整且已脱敏的真实请求与响应:

docs/test-api-request-response.txt

2. 接口地址与安全边界

检索地址

POST https://weknora-api-test.dobot.cn/retrieval

这是服务端到服务端接口:

Dify可以直接调用
业务后端/BFF可以直接调用
浏览器前端不能携带Adapter API Key直接调用

浏览器推荐链路:

浏览器前端
  → 业务后端/BFF
  → Adapter
  → WeKnora

禁止把真实API Key写入:

  • 前端JavaScript或打包产物;
  • Git仓库;
  • URL查询参数;
  • LocalStorage或SessionStorage;
  • 普通日志、埋点或错误上报。

3. 请求方法

Headers

Authorization: Bearer [TEST_DIFY_KEY]
Content-Type: application/json
Accept: application/json
X-Request-ID: <可选,建议使用UUID>

对外调用使用的是Dify Bearer Key。WeKnora API Key和OSS凭据只由Adapter内部使用,不能提供给Dify或浏览器。

Body

{
  "knowledge_id": "b9dacd62-87eb-4b38-a6b6-85f68e144796",
  "query": "接线",
  "retrieval_setting": {
    "top_k": 5,
    "score_threshold": 0.2
  }
}

字段说明

字段 类型 必填 说明
knowledge_id UUID字符串 是 测试环境“对外知识库”固定为 b9dacd62-87eb-4b38-a6b6-85f68e144796
query 字符串 是 用户问题;去除首尾空格后不能为空,最多2000字符
retrieval_setting.top_k 整数 是 至少为1,当前上限为5
retrieval_setting.score_threshold 浮点数 是 范围0至1;业务建议初始使用0.2,排查召回问题时可临时使用0
metadata_condition 对象 否 当前不支持非空过滤条件,调用方应省略

knowledge_id应由Dify或业务后端固定,不能接受浏览器任意指定。

4. 应答格式

成功响应:

{
  "records": [
    {
      "content": "Markdown格式的知识片段",
      "score": 0.82,
      "title": "文档标题",
      "metadata": {
        "knowledge_base_id": "知识库UUID",
        "knowledge_id": "文档UUID",
        "chunk_id": "Chunk UUID",
        "chunk_index": 1,
        "chunk_type": "text"
      }
    }
  ]
}

真实公网响应节选(content为缩写,完整正文见TXT样本):

{
  "records": [
    {
      "content": "<Markdown知识片段,包含稳定的 /i/<UUID> 图片地址>",
      "score": 0.5314404987902756,
      "title": "Dobot Magician Go用户手册V1.1_20240624_cn.pdf",
      "metadata": {
        "knowledge_base_id": "b9dacd62-87eb-4b38-a6b6-85f68e144796",
        "knowledge_id": "3c878f4e-bfea-4c5c-b122-b63ba9db4e34",
        "chunk_id": "d674ba02-7769-4e9a-8596-961cb50e1f75",
        "chunk_index": 53,
        "chunk_type": "text"
      }
    }
  ]
}

字段说明:

字段 类型 说明
records 数组 检索结果;没有命中时为空数组
records[].content 字符串 Markdown知识片段,不是大模型生成的最终答案
records[].score 浮点数 当前检索相关度分数;不要跨模型或跨版本硬编码绝对含义
records[].title 字符串 来源文档标题
records[].metadata 对象 知识库、文档和Chunk审计标识

该接口只负责检索。Dify拿到records后,再将知识片段交给大模型生成最终回答。

5. curl调用示例

真实Key应由运行环境或密钥系统注入,不要直接写进脚本:

curl --request POST \
  'https://weknora-api-test.dobot.cn/retrieval' \
  --header "Authorization: Bearer ${WEKNORA_ADAPTER_API_KEY}" \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header "X-Request-ID: $(python3 -c 'import uuid; print(uuid.uuid4())')" \
  --data '{
    "knowledge_id": "b9dacd62-87eb-4b38-a6b6-85f68e144796",
    "query": "接线",
    "retrieval_setting": {
      "top_k": 5,
      "score_threshold": 0.2
    }
  }'

6. Node.js服务端调用示例

下面代码只能运行在Node.js服务端或BFF,不能放入浏览器包:

import { randomUUID } from "node:crypto";

const ADAPTER_URL = "https://weknora-api-test.dobot.cn/retrieval";
const KNOWLEDGE_ID = "b9dacd62-87eb-4b38-a6b6-85f68e144796";

export async function retrieveKnowledge(query) {
  const apiKey = process.env.WEKNORA_ADAPTER_API_KEY;
  if (!apiKey) {
    throw new Error("WEKNORA_ADAPTER_API_KEY is not configured");
  }

  const response = await fetch(ADAPTER_URL, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "Content-Type": "application/json",
      Accept: "application/json",
      "X-Request-ID": randomUUID(),
    },
    body: JSON.stringify({
      knowledge_id: KNOWLEDGE_ID,
      query,
      retrieval_setting: {
        top_k: 5,
        score_threshold: 0.2,
      },
    }),
    signal: AbortSignal.timeout(25000),
  });

  if (!response.ok) {
    throw new Error(`Knowledge retrieval failed: HTTP ${response.status}`);
  }

  const body = await response.json();
  if (!body || !Array.isArray(body.records)) {
    throw new Error("Invalid knowledge retrieval response");
  }
  return body.records;
}

日志中只建议记录:

X-Request-ID、HTTP状态、耗时、records数量

不要记录:

Authorization、API Key、完整问题、完整知识正文、图片302 Location

7. 浏览器调用BFF示例

浏览器只调用业务后端,不携带Adapter API Key:

const response = await fetch("/api/knowledge/retrieve", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ query: userInput }),
});

if (!response.ok) {
  throw new Error(`检索失败:HTTP ${response.status}`);
}

const { records } = await response.json();

业务后端负责补充:

Authorization
knowledge_id
retrieval_setting
X-Request-ID

8. Dify配置

在Dify外部知识库API中填写:

Endpoint:
https://weknora-api-test.dobot.cn/retrieval

API Key:
测试环境Adapter原始Key

External Knowledge ID:
b9dacd62-87eb-4b38-a6b6-85f68e144796

不要把Dify直接指向WeKnora原生/api/v1/knowledge-search。协议转换、知识库白名单、响应裁剪和图片稳定URL都由Adapter负责。

9. 图片调用方法

检索结果中的图片使用稳定地址:

https://weknora-api-test.dobot.cn/i/<UUID>

真实样例:

https://weknora-api-test.dobot.cn/i/02e269e8-c4f0-4b3f-a41e-82f5b222a31f

前端直接将稳定地址作为图片地址:

<img src="https://weknora-api-test.dobot.cn/i/<UUID>" alt="知识图片">

图片访问不需要Bearer Key:

浏览器GET /i/<UUID>
→ Adapter查询有效映射
→ HTTP 302
→ 私有OSS 10分钟签名URL
→ 图片HTTP 200

注意:

  • 保存和渲染稳定/i/<UUID>地址;
  • 不保存、不打印、不缓存302后的OSS签名地址;
  • 10分钟过期的是OSS签名地址,不是稳定UUID地址;
  • 稳定UUID属于能力链接,不应进入无关日志或公开页面;
  • OSS Bucket继续保持Private。

真实图片验收:

稳定UUID:HTTP 302
Cache-Control:no-store
Referrer-Policy:no-referrer
私有OSS匿名访问:HTTP 403
短期签名取图:HTTP 200
类型:image/jpeg
大小:56,025 bytes
JPEG结构:有效

10. 错误码

HTTP状态 含义 调用方处理
200 成功 读取records,允许空数组
400 请求格式错误或知识库未授权 不重试;检查请求字段和固定knowledge_id
401 API Key缺失或错误 不重试;检查服务端Secret配置
403 请求方法被Nginx拒绝 不重试;确认使用POST /retrieval或GET /i/<UUID>
404 路径或图片UUID不存在 不重试;检查地址
502 WeKnora响应异常或内容处理失败 记录Request ID,有限重试并告警
503 WeKnora超时、暂时不可用或图片签名失败 建议退避重试1至2次,仍失败则降级

不要自动重试400、401、403和404。

11. 联调检查表

  • 公网HTTPS回源测试ECS Nginx 80;
  • 保留Host、Authorization、Content-Type和X-Request-ID;
  • 无Key请求返回401;
  • 正确Key请求返回HTTP 200和records;
  • 有图结果返回稳定UUID,图片302和最终下载通过;
  • 前端构建产物中确认不存在Adapter API Key;
  • 业务日志中确认没有Authorization、完整正文和OSS签名URL;
  • 生产环境使用独立域名、独立Key和独立知识库白名单。