DeepSeek Harness 插件

JohnXu22786/docindex

Star 数 ★ 1 分类 工具与能力 收录于 2026-08-28

工作区文档的本地语义索引(MD/PDF/DOCX/TXT):FTS5 BM25 与本地嵌入混合检索、带行号命中引用、增量更新。

安装

# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)

dsh plugin --profile web add github:JohnXu22786/docindex

装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。

README

English

一个 dsh bundle:将工作区变为可检索的本地知识库。它会对本地的 Markdown / 纯文本 / PDF / DOCX / PPTX / XLSX 文档建立语义索引,并支持用自然 语言或关键词查询——返回命中文档、带精确行号的片段与相关度分数。

  • 词法检索:SQLite FTS5(node:sqlite,无原生依赖)+自研 CJK 分词器, 让中文搜索开箱即用。
  • 语义检索:provider 插槽——默认自带宽容零依赖的本地嵌入器,也支持按需 接入神经网络的 transformers provider。
  • 结果以 RRF(倒数排名融合) 融合。
  • 增量更新:仅对变更文件重索引(可选文件监听),并保留全量重建兜底。
  • 容量与排除规则可控,索引规模有界、目标明确。
  • 提供 dsh 服务(ctx.docIndex)+四个模型可调用工具(doc_scan、 doc_query、doc_reindex、doc_stats),同时提供独立 CLI(docindex)。

该 bundle 遵循 dsh 标准分发格式:package.json 声明 dsh.bundle.patch 指向 cordis.patch.yml,入口模块是带 static inject / static Config 的 Cordis Service——与 @deepseek-ai/dsh-session-query-sqlite 同形态,但为工作区文档 重新实现,并通过自有工具提供检索能力。


环境要求

  • Node.js >= 22.5(使用内置 node:sqlite)。
  • 要运行在 dsh 中,需要一个可提供 @deepseek-ai/cordis、 @deepseek-ai/dsh-tools 与 @deepseek-ai/schemastery 的 DeepSeek Harness 环境(这些被声明为 peer 依赖)。

说明: Node 将 node:sqlite 标记为实验特性,启动时会有提示(不影响功能)。 可用 --disable-warning=ExperimentalWarning 关闭。


安装接入 dsh

在 profile 目录(或 Harness 任意位置)添加 bundle 并通过补丁层挂载:

dsh plugin add <本包路径>

本包也已发布到 npm,可独立使用 CLI:

npm install -g dsh-doc-index   # 提供 `docindex` CLI
npm install dsh-doc-index      # 或作为项目依赖加入

自带的 cordis.patch.yml 只插入一行插件:

- insert:
    - id: doc-index
      name: dsh-doc-index

不额外配置时,它会把当前工作目录索引到 $DSH_HOME/doc-index/index.db (DSH_HOME 默认 ~/.dsh),并开始监听变更。

如需自定义,在 profile 的 cordis.patch.yml 里覆盖(后层补丁会整体替换 该行的 config,请把关心的键全部写上):

- id: doc-index
  config:
    roots:
      - /path/to/your/workspace
      - /another/vault
    dbPath: /path/to/index.db
    update: watch
    embedding:
      provider: transformers   # 需要 `npm i @huggingface/transformers`
    excludes:
      - vendor/
      - '*.tmp'

加载后,四个工具即可被模型调用,其他插件也可使用 ctx.docIndex 服务:

const hits = await ctx.docIndex.query({ query: 'RLHF and llama.cpp' })
// hits[0].path, hits[0].line, hits[0].snippet, hits[0].score

独立 CLI

同一套引擎也可以在命令行使用:

# 索引当前目录(可用 --root 多次;--db 指定库)
docindex scan
docindex scan --root ./docs --root ./specs

# 检索
docindex query "flux pipeline timeout" --top 5
docindex query "向量数据库" --mode semantic --json

# 重建
docindex reindex --full

# 查看统计
docindex stats

docindex --help 查看全部参数。环境变量:DOCINDEX_DB、DOCINDEX_ROOTS (按路径分隔符拆分)。


模型工具

工具 用途
doc_scan 增量扫描/刷新/清理工作区(可选 path 限定子树,force 忽略变更检测)。
doc_query 检索。query(必填)、topK、mode(auto/lexical/semantic)、highlight、snippetChars。每条命中返回 路径+行号+片段+分数。
doc_reindex 重建。full 先清空索引;path 限定范围重建。
doc_stats 索引统计(文档数、片段数、嵌入数、体积、根目录)。

配置参考

键 默认值 含义
roots [] → process.cwd() 扫描的工作区根目录。
dbPath '' → $DSH_HOME/doc-index/index.db SQLite 路径(可用 :memory:)。
openAt startup 打开库的时机:startup / first-use / never。
update watch watch(fs.watch+防抖)或 manual。
watchDebounceMs 1500 监听重扫的防抖毫秒。
excludes [] 额外的 gitignore 风格排除规则(见下)。
includeHidden false 是否索引点号开头的文件/目录。
followSymlinks false 是否跟随目录符号链接(自动断环)。
maxDocs 20000 最大文档数。
maxSegments 300000 最大文本片段数。
maxEmbeddedSegments 50000 最多获得向量的片段数。
maxFileBytes 5 MB 大于此字节数的文件跳过。
maxDepth 64 根目录下最大目录深度(0 表示不限制)。
maxWalkedFiles 200000 单次扫描最多收集的候选文件数(内部检查文件预算为其 4 倍)。若因此被截断,则本次扫描不做删除。
tokenizer.cjkN 2 CJK n-gram 深度:1(一元)/2(+二元)/3(+三元)。
segmentChars 400 单个索引片段约最大字符数。
snippetChars 240 每条命中的最大片段长度。
textExtensions [] 额外按纯文本处理的扩展名(如 .csv)。
search.topK 10 每次查询默认命中数(1–50)。
search.minScore 0 过滤低于此归一化分数的结果。
search.mode auto auto / lexical / semantic。
search.highlight true 是否对命中词加 **…** 标记。
search.matchOp and 查询各「组」之间用 and 还是 or。
search.rrfK 60 RRF 常数。
search.semanticWeight 0.5 语义列表在 RRF 中的权重(词法为 1 - w)。
embedding.provider ngram none / ngram / transformers。
embedding.dim 256 ngram 嵌入器维度。
embedding.model '' transformers 模型 id(默认多语言 MiniLM)。
embedding.device / cacheDir / quantized auto / HF 缓存 / true transformers 相关选项。
journalMode wal SQLite 日志模式。

语义嵌入(provider 插槽)

DeepSeek 未提供官方 embedding API,因此本插件内置可插拔的 EmbeddingProvider 插槽:

  • ngram(默认,零依赖):基于 CJK n-gram +拉丁词的确定性特征哈希嵌入器, 完全离线、无需下载模型,提供一个「共享 token 越近」的向量空间,作用相当于 重排序器:语义候选被限定为与查询有 token 重合的片段,因此无匹配的查询 会返回空结果而非“噪声命中”。需要真正学到语义(含跨语言召回)时切换 provider。
  • transformers(可选):通过 @huggingface/transformers 加载小型 ONNX 编码器。安装后设置 embedding.provider: 'transformers';默认模型为多语言, 中文可直接使用。
  • none:关闭语义路径(仅词法)。
  • 宿主应用也可自实现并注入自定义 provider(例如远程 HTTP embedding 接口)。

若请求的 provider 无法构建(例如缺少可选的 @huggingface/transformers), 引擎会优雅降级:记警告并以纯词法继续。doc_query 会在「需要语义但不可用」 时把结果标记为 degraded。


检索原理

  1. 片段:每篇文档按约 segmentChars 切分为若干片段,每个片段记录起始的 1 基行号,因此每条命中都可定位到行。
  2. 分词:拉丁词统一小写;CJK 连续段展开为 n-gram(深度 2 时 你好世界 → 你 好 世 界 你好 好世 世界)。索引侧与查询侧使用同一套 分词,中文关键词检索开箱即用。查询时,一个表意字串内部用 OR 匹配其 n-gram(于是“苹果手机”也能命中只含“苹果”或“手机”的文档),字串/词之间用 AND(或 OR)组合。
  3. 词法:FTS5 bm25() 排序命中。
  4. 语义:查询向量与库内片段向量做余弦相似度(受 maxEmbeddedSegments 约束;向量存于 SQLite)。
  5. 融合:两份排序结果用 RRF 合并,并归一化到 [0, 1]。

排除规则、二进制与容量

  • 默认排除表:node_modules/、.git/、.svn/、.hg/、.cache/、 .next/、.nuxt/、.output/、dist/、build/、coverage/、 .DS_Store、*.pyc/pyo、*.exe/dll/so/dylib/o/obj、Thumbs.db、 .docindex/。excludes 追加 gitignore 风格规则(支持 **、*、?、 [...]、! 取反前缀、目录尾 /、锚定前缀 /)。
  • 未知扩展名按内容嗅探,疑似二进制则跳过(binary)。无文本层的 PDF 以 no-text-layer 跳过(需 OCR)。空文件以 empty 跳过。
  • 达到 maxDocs/maxSegments 后新文档会以 max-docs/max-segments 跳过, 并在 doc_scan 输出中报告。

开发

npm install          # 仅安装 TypeScript 与 dsh 类型包(dev)
npm run build        # tsc -> dist/
npm test             # 构建并运行完整测试(node:test,无额外依赖)

核心(src/engine.ts、src/db.ts、src/embedding.ts 等)零运行时依赖, 并有完整单元测试覆盖:分词、忽略规则、抽取(文本/PDF/OOXML)、发现、增量 更新、中文检索、RRF 排序、片段高亮、容量限制,以及「无嵌入模型时优雅降级」。

示例工作区见 example/。

许可证

MIT

遇到问题或希望支持新的文档类型?欢迎在 github.com/JohnXu22786/docindex 提交 issue。

内容来自项目 README(GitHub)↗

链接

同类插件

查看整个分类 →

社区评论

评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。