工作区文档的本地语义索引(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
一个 dsh bundle:将工作区变为可检索的本地知识库。它会对本地的 Markdown / 纯文本 / PDF / DOCX / PPTX / XLSX 文档建立语义索引,并支持用自然 语言或关键词查询——返回命中文档、带精确行号的片段与相关度分数。
- 词法检索:SQLite FTS5(
node:sqlite,无原生依赖)+自研 CJK 分词器, 让中文搜索开箱即用。 - 语义检索:provider 插槽——默认自带宽容零依赖的本地嵌入器,也支持按需
接入神经网络的
transformersprovider。 - 结果以 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。
检索原理
- 片段:每篇文档按约
segmentChars切分为若干片段,每个片段记录起始的 1 基行号,因此每条命中都可定位到行。 - 分词:拉丁词统一小写;CJK 连续段展开为 n-gram(深度 2 时
你好世界→你 好 世 界 你好 好世 世界)。索引侧与查询侧使用同一套 分词,中文关键词检索开箱即用。查询时,一个表意字串内部用OR匹配其 n-gram(于是“苹果手机”也能命中只含“苹果”或“手机”的文档),字串/词之间用AND(或OR)组合。 - 词法:FTS5
bm25()排序命中。 - 语义:查询向量与库内片段向量做余弦相似度(受
maxEmbeddedSegments约束;向量存于 SQLite)。 - 融合:两份排序结果用 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/。
许可证
遇到问题或希望支持新的文档类型?欢迎在 github.com/JohnXu22786/docindex 提交 issue。
链接
同类插件
Tencent/WeKnora#dsh-weknora★ 33277
把 WeKnora 知识库接入 dsh 的四个只读工具:列出知识库、混合检索原文片段、按顺序还原单篇文档,以及直接取用 WeKnora 自己带引用的 RAG 或 ReAct agent 回答(含可续聊的 session id)。
superdesigndev/treg★ 4991
给 Agent 的工具目录:按「要做的事」检索约 2,600 个外部接口(SEO 与 SERP、外链、社交、人物与公司信息补全、广告库、抓取),查看参数与单次调用价格后直接调用,凭据由服务端注入。附带技能,MCP 行在未设置 TREG_TOKEN 前保持禁用。
TencentCloudBase/CloudBase-AI-Toolkit#dsh-plugin★ 1136
把腾讯云 CloudBase 后端接入 DeepSeek Harness——在对话里搭好并部署全栈应用,查询结果渲染为表格卡片(分页、排序、导出 CSV),部署后可预览真实域名,并提供 CloudBase MCP 工具集(`mcp__cloudbase__*`),登录走 device-code 流程。
gitroomhq/postiz-agent#dsh-postiz★ 511
通过 MCP 将 DeepSeek Harness 连接到 Postiz:列出已连接的社交媒体渠道、获取各平台发帖规则,并向 X、LinkedIn、Instagram、Facebook、Threads、TikTok、YouTube、Reddit、Bluesky、Mastodon、Discord、Slack、Telegram 等平台排期、存草稿或发布帖子;附带 postiz 工作流技能。
EthanYoQ/Invoice-Downloader#dsh-invoice-downloader★ 503
面向 DeepSeek Harness 的本地 IMAP 发票下载、OCR 识别、归档与 Excel 报销汇总。
anysearch-team/anysearch-dsh★ 458
基于 AnySearch 的实时网页与垂直搜索插件,为 DeepSeek Harness 提供搜索工具。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。