Back to Weknora

@wxg-prc-cpg/dsh-weknora

packages/dsh-weknora/README_CN.md

0.8.09.1 KB
Original Source

@wxg-prc-cpg/dsh-weknora

English | 简体中文

npm

一个 DeepSeek Harnessdsh)插件,让 harness 里的 Agent 直接用上 WeKnora 知识库:混合检索、按文档通读、以及 WeKnora 自己带引用的成稿答案。

dsh 本身没有任何检索、向量或知识库能力——它的 grepglob 只看工作区文件,web_search 只看互联网。这个插件把缺的这一 块换成你自己的文档。

安装

sh
# 从 npm 安装(推荐:装到的是构建产物,用户无需授权执行构建脚本)
dsh plugin --profile web add @wxg-prc-cpg/dsh-weknora

# 或者从本仓库的检出目录安装
dsh plugin --profile web add ./packages/dsh-weknora

然后把它指向你的部署。插件自带的配置层会读环境变量,所以最快的起步方式是:

sh
export WEKNORA_BASE_URL=https://weknora.example.com   # 或 http://localhost:8080
export WEKNORA_API_KEY=sk-...                          # 需要 `retrieve` 能力(用 ask 还需要 `chat`)
export WEKNORA_KNOWLEDGE_BASE_IDS=kb-123,kb-456        # 可选的默认知识库范围
export WEKNORA_RESOURCE_URLS=public                    # 默认;改成 `handle` 则保留内部文件引用
dsh web

超出这个范围的配置,在 profile 自己的 cordis.patch.yml$DSH_HOME/profiles/<name>/cordis.patch.yml)里覆盖这一行:

yaml
- id: weknora
  config:
    baseUrl: https://weknora.example.com
    apiKey: !!js process.env.WEKNORA_API_KEY
    knowledgeBaseIds:
      - kb-product-docs
    agentId: ''            # 填 WeKnora 自定义 Agent id,`weknora_ask` 就走 ReAct 流水线
    maxResults: 8
    maxChunkChars: 1200
    requestTimeoutMs: 30000
    chatTimeoutMs: 300000
    resourceUrls: handle   # 默认是 `public`,引用里的图片给可直接加载的直链;`handle` 保留内部引用
    toolPrefix: weknora    # 重命名工具,例如同时挂两个部署时
    tools:
      listKnowledgeBases: true
      search: true
      readDocument: true
      ask: true

patch 是整块替换该行的 config,所以要保留的字段需要一并写出。配置不合法会在插件加载阶段失败,并逐条列出问题,而不是等到 模型第一次调用工具时才报错。

同时挂两个部署,就是两行加两个前缀:

yaml
- insert:
    - id: weknora-internal
      name: "@wxg-prc-cpg/dsh-weknora"
      config: { baseUrl: https://kb.internal.example.com, toolPrefix: internal_kb }
    - id: weknora-public
      name: "@wxg-prc-cpg/dsh-weknora"
      config: { baseUrl: https://kb.public.example.com, toolPrefix: public_kb }

工具

工具WeKnora 接口模型拿到什么
weknora_list_knowledge_basesGET /knowledge-bases知识库名称与 id,用于说明有哪些库,或为后续检索缩小范围
weknora_searchPOST /knowledge-search + GET /knowledge/search原文片段与排序,每条带 knowledge_id、得分、分块序号,外加查询点名的文档
weknora_read_documentGET /chunks/:knowledge_id + GET /knowledge/:id单个文档按序拼回的正文,开头给出标题与摘要,支持翻页
weknora_askPOST /sessions + POST /knowledge-chat/:idPOST /agent-chat/:idWeKnora 自己的答案、引用、服务端用过的工具,以及可续聊的 session_id

weknora_search 是主力:它把原文交给 Agent 自己推理,Agent 的结论因此是可审计的。它在同一次调用里同时匹配片段内容和 文档名,因为模型常常分不清自己要找的是「哪里讲了这件事」还是「那份叫 X 的文档在哪」。当查询读起来像个标题时,结果里会额外 列出被点名的文档——这样即便某份文档的正文用词与标题完全不同,也依然够得着。

范围不需要配置。没有指定知识库的调用,检索接口会直接拒绝,RAG 接口则会在什么都没检索到的情况下作答,因此当 knowledgeBaseIds 为空时,插件会自己解析出该凭据可见的全部知识库并一并使用;这份清单每个进程只解析一次,且由 weknora_searchweknora_ask 共用。让模型先去挑反而更糟:知识库的命名往往糟糕到无从选择。

weknora_ask 把整个问题委派给 WeKnora。它适合跨多篇文档、需要综合的宽泛问题,也就是自己检索要来回好几轮的场景;它在服务端 再跑一个模型,所以慢,而且返回的是结论而非支撑结论的证据。配了 agentId 时它不会自己填范围:自定义 Agent 会按自己的知识库 选择模式在服务端解析范围,从这里传 id 反而会把它覆盖掉。

weknora_read_document 的存在是因为检索返回的是碎片:一旦某个片段看起来对,Agent 通常还需要它的上下文。每条检索结果都带 着这次调用需要的 knowledge_id;第一页会先给出文档标题和 WeKnora 生成的摘要,长文档不必翻完才知道自己拿到的是什么。

Code Mode 下,同样的工具 可以写成 await tools.weknora_search({ query }),特别适合多跳检索:一段程序里扇出十个子问题,而不是十次模型往返。

权限与数据流

插件只读。它不会写 WeKnora:不入库、不改分块、不删除。四个工具里有三个只需要 retrieve 能力的 API Key;weknora_ask 额外需要 chat,因为它要创建会话并流式取回答案。

Key 通过 X-API-Key 发送。如果用的是平台级 API Key,还需要配 tenantId,它会作为 X-Tenant-ID 选择工作空间。报错信息 只包含 HTTP 状态码和 WeKnora 自己给出的原因,不会带上 Key。

片段内容在进入模型前会按 maxChunkChars 截断,避免一份超大文档吃掉整个上下文窗口;截断这件事会明确告知模型 (truncated: true),而不是悄悄丢文本。

默认 resourceUrls: public 时,WeKnora 会把片段里的 resource:// 图改写成可直接加载的 http(s) 直链——把这些 Markdown 图片写进回复,dsh 网页端就会把图画出来。限定知识库的 API Key 拿不到直链(WeKnora 会 403),插件会把这次调用改回 handle 模式,之后也一直用 handle。

配置层还会读 WEKNORA_RESOURCE_URLSpublichandle)。

配置项

字段默认值说明
baseUrlhttp://localhost:8080/api/v1缺少 /api/v1 时自动补全
apiKey未设置X-API-Key;不设表示部署无鉴权
tenantId未设置X-Tenant-ID,平台级 Key 必填
knowledgeBaseIds[]调用未指定范围时的默认值;留空表示检索该凭据可见的全部知识库
agentId未设置weknora_ask 走 ReAct 流水线
maxResults8同时是 max_results 与引用条数的上限
maxChunkChars1200单个片段的字符预算
requestTimeoutMs30000检索与读文档
chatTimeoutMs300000weknora_ask,要等 WeKnora 自己的模型调用
resourceUrlspublicpublic 返回可直接加载的文件直链;handle 保留内部 resource:// 引用。限定知识库的 API Key 会自动回退到 handle。可用 WEKNORA_RESOURCE_URLS 覆盖。
toolPrefixweknora工具名前缀,需匹配 ^[a-z][a-z0-9_]*$
tools.*全部 true少注册几个工具就少占几分 prompt

开发

sh
npm install
npm test          # 先构建,再跑单元测试与契约测试
npm run typecheck

端到端检查会把这个包装进一个临时 dsh profile,用 mock 的 WeKnora 后端和一个确定性的 OpenAI 兼容模型启动 headless profile,并断言 harness 真的调用了工具、并且答案来自工具返回的内容:

sh
npm run build
node test/e2e/run-in-dsh.mjs                        # 首次运行会从 npm 装一个 dsh
DSH_BIN=/path/to/dsh node test/e2e/run-in-dsh.mjs   # 或者复用已有安装

dsh 的会话持久化需要带 zstd 的 Node(≥ 22.15 或 ≥ 24),并且 PATH 上要有 pnpm ≥ 10——dsh plugin add 通过 pnpm 装进 profile,而它写出的 profile 把设置放在 pnpm-workspace.yaml 里。插件自身只要求 Node ≥ 20.11,两者都不需要。

test/fixtures/api-contract.json 记录了本插件发出的每一个 WeKnora 调用。test/contract.test.mjs 断言插件仍然只发这些 调用,contract/contract_test.go 断言 WeKnora 真实的 Go 请求/响应类型仍然接受并提供这些字段——任何一侧改名都会在 CI 挂掉, 而不是在用户的 Agent 里挂掉。

兼容性

已针对 dsh 0.1.0-rc.8 与 WeKnora 0.8.0 验证。dsh 处于 developer preview 并明确会有破坏性变更;本包因此没有任何运行 时依赖,交给 ctx.tools.register() 的只是一个普通对象,不锁定任何 harness 包版本。如果 harness 的工具定义契约发生变化, 请在本仓库提 issue。

许可

MIT,与 WeKnora 和 dsh 一致。