← 返回列表
未验证
dsh-deep-research · 一个 DeepSeek Harness 插件兼独立库 · 零运行时依赖
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/9 · 已提供中文文档
Kestrel——一个无法引用来源从未说过的话的研究引擎。只有当引文被机械地在来源中定位到时,引用才会被采纳;佐证以独立来源计数,而非来源数量。DeepSeek Harness 插件 + 独立库。零依赖。
综合分
29.6
GitHub 分
29.6
用户评分
—
★ Stars
1
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add grloper/dsh-deep-research该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/20(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools@deepseek-ai/dsh-llm@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-home-paths用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
kestrel
dsh-deep-research · 一个 DeepSeek Harness 插件兼独立库 · 零运行时依赖
License: MIT
Tests
Node
DSH Plugin
快速开始 · 运行演示 · 工作原理 · 工具 · 架构
问题所在
每一个 AI 研究工具都在为附带 URL 的貌似合理的文字做优化。这会产生四个失败,再多的提示词工程也无法修复:
| | 失败 | 现实 |
|---|---|---|
| F1 | 引用 ≠ 支持 | 被引用的页面往往并未陈述附于其上的那句话。没有人检查蕴含关系;一个靠近论断的 URL 就被当作证据。 |
| F2 | 虚假的相互印证 | “12 个来源一致”通常是一份新闻稿和十一次转载。来源数量被用作真相的代理指标;独立性从未被计算。 |
| F3 | 仅确认性搜索 | 查询由假设播种,因此智能体搜索支持性证据,而从不搜索反驳性证据。 |
| F4 | 垃圾内容污染 | AI 生成的联盟营销博客与一手来源排名相同,且没有可信度模型将它们区分开。 |
Kestrel 以机械方式攻击全部四个问题——用语言模型无法靠花言巧语绕过的代码。
两个关键理念
1. 伪造的引文无法通过 indexOf
每一条引用都必须携带一段逐字引文。在被接纳之前,Kestrel 会对存储的来源文本执行字面子串检查,然后将匹配结果映射回精确的字符偏移量。
quote ∈ document ? ✓ 引用被接纳,带有 [charStart, charEnd]
✗ ✗ 被拒绝 → 论断降级为 UNVERIFIED
不会去问模型这条引用好不好。让产生幻觉的东西去检查自己的幻觉是循环论证。String.indexOf 不是。
评判者必须返回一段引文,而这段引文随后由代码验证。一个不诚实的模型无法凭空制造支持——它只能在这道关卡前失败。
2. 相互印证按起源计数,而非按文档计数
MinHash → LSH 候选过滤 → 谱系 DAG → Tarjan SCC 缩点 → 统计根节点数。边的方向由 min(publishedAt, waybackFirstSeen) 固定,因为发布者会改写自己的日期,而存档是他们唯一无法控制的那个时间戳。
十二家媒体发布同一份通讯稿副本,只是一个见证者,Kestrel 就将其报告为一个。
看它运行(60 秒)
无需 API 密钥。无需网络。无需配置。
git clone https://github.com/grloper/dsh-deep-research.git
cd dsh-deep-research
npm run demo
该演示在一个固定语料库上运行真实流水线:一份新闻稿、六份逐字转载、四份衍生改写、一份独立监管申报文件,以及一份撤回标题数字的更正。
实际输出
1 · 捏造的引文无法通过
ADMITTED (genuine) "its Q3 revenue reached 42 million dollars"
kind=EXACT span=[40,81] · Quote appears verbatim in the source document.
REJECTED (fabricated) "its Q3 revenue reached 91 million dollars"
kind=FAILED span=[-1,-1] · Quote does not appear in the source document
(best token overlap 0.75 “深度研究:欧盟《人工智能法案》的基础模型规则在 2024 年三方会谈后是否发生了变化?”
“在我引用这篇文章之前,先核实一下。”
“这六个 URL 真的是独立来源吗?”
作为库使用
每个机制都是一个导出的、无依赖的模块:
js
import { anchorQuote, analyzeLineage, verifyText } from 'dsh-deep-research'
// Mechanical citation gate
const anchor = anchorQuote('revenue reached 42 million dollars', sourceText)
if (!anchor.ok) throw new Error(anchor.reason)
console.log(anchor.charStart, anchor.charEnd) // 精确、可重放的偏移量
// 独立性分析
const { ics, total, roots, circular } = analyzeLineage(documents)
console.log(${total} sources → ${ics} independent origins)
五种工具
自动注册到宿主 agent。
| 工具 | 功能 |
|---|---|
| verify_text | 逐条对任意文本块进行事实核查。提取原子化断言,搜索支持和反驳证据,只有当引文能在获取的源中被机械定位时,才承认该引用。 |
| deep_research | 完整的对抗式调查。分解问题,运行一个寻找反证的公诉方与一个辩护方,并通过针对缺口的后续追问迭代,直到发现收敛。模式:quick、standard、deep、forensic。 |
| compare_sources | 给定同一报道的多个 URL,判断其中有多少是真正独立的。检测逐字联合发布、衍生改写、引文传播和循环引用。 |
| check_source | 评估单个 URL:来源类型、带理由的可信度信号、内容质量信号,以及发布日期可靠性,包括改写日期检测。 |
| research_recall | 查询累积的证据图谱,排除在其波动周期内已过时的发现。在研究之前使用它,以避免重复工作。 |
六种机制
M1 · 机械式引用锚定
三个层级,从最严格开始:EXACT(字节完全相同)、NORMALIZED(在空白/标点折叠后相同,并投影回原始偏移量)和 FUZZY(token-Jaccard ≥ 0.85,单独报告,以便调用方可以严格处理)。短于 24 个字符的引文会被直接拒绝,因为短字符串会因巧合而匹配。
文档在获取时进行 SHA-256 哈希。如果存储的文本不再与其哈希匹配,则依赖它的每一条引用都会因完整性失败而被拒绝。
M2 · 独立佐证分数
3-gram shingles → 128 排列 MinHash → LSH 分带 → 成对 Jaccard。高于 0.85 的文档属于联合发布;高于 0.40 且共享 50+ 字符引文的文档属于衍生。Tarjan 算法压缩环,DAG 的根被计为真正的起源。循环引用环会被明确报告。
M3 · 对抗式法庭
对于每一条断言,一个公诉方生成寻求反驳的查询("" debunked OR false OR retracted),而一个辩护方寻求支持。双方的证据都通过同一道机械门。只有当辩护在公诉下仍然成立时,断言才会达到 SUPPORTED——并且一个活跃的矛盾会硬性限制置信度,无论有多少来源一致。
M4 · 日期解析
JSON-LD、Open Graph、meta 标签、HTTP 头和 URL 路径段会被交叉核对。页面自报日期与其归档首次出现时间之间的不一致会以警告形式呈现,从而挫败回溯性修改日期的行为。
M5 · 复合证据图
经过验证的断言会持久保存在本地存储中(可用时使用 node:sqlite,否则透明回退到 JSON),并采用 BM25 + 实体索引 + RRF 混合检索。新鲜度按波动性类别逐断言确定——数学常数和股票价格绝不能按同一时间表过期。
| 类别 | 时间范围 | 示例 |
|---|---|---|
| IMMUTABLE | 5 年 | 成立日期、定理、DOI |
| SLOW | 约 6 个月 | 公司结构、政策 |
| FAST | 24 小时 | 价格、民调、“现任 CEO” |
M6 · 确定性回退评判器——引擎绝不静默空操作
上述每个阶段都以评判器返回一段逐字引用为门槛,随后该引用会在来源中被机械地定位。这道门槛是正确的。危险在于没有可用语言模型时会发生什么。
一个对所有内容都返回 NEUTRAL 的评判器并不是优雅降级——裁判庭只接纳 SUPPORTED/PARTIAL/CONTRADICTED 证据,因此这样的桩会丢弃100% 的已检索文档。随后循环会耗尽全部轮次预算,按构造什么也找不到,并报告“0 resolved”。对用户而言,这与激活深度研究却什么也没发生无法区分。
因此,无 LLM 路径是一个真正的评判器,而不是桩:
1. IDF 加权句子选择,在文档自身的句子上进行,因此出现在每个句子中的词(通常是页面主题)权重很低,而罕见、具体的词权重很高。仅仅提及主题的页面,不会像论述该断言的页面那样得分。
2. 归一化数字匹配——8、8% 和 8.0 比较相等,而精确的数值一致会大幅提升相关性,远超词语重叠。
3. 立场检测,权衡否定线索(debunked、failed to replicate、found no)与肯定线索,从而捕捉反驳,而不是将其归并为支持。
4. 结构性诚实——引用是从文档中选取的,绝不是生成的,因此该评判器无法捏造引文。低于相关性下限时,它会返回诚实的 NEUTRAL。
与此同时,能力预检会报告实际接入了什么。没有搜索服务的运行会返回明确的“研究无法运行:无网络搜索能力”报告,而不是空报告——能力问题会被报告为能力问题,绝不会被报告为证据缺失。
架构
lib/
├── index.js 宿主插件:工具注册、服务适配器、harness RPC + /kestrel/api HTTP 桥接
├── client.js 浏览器端:Verify 操作、Deep Research 启动器、设置仪表盘(HTTP 桥接)
├── anchor.js M1 · 机械引文锚定 + 准入闸门
├── lineage.js M2 · MinHash/LSH/SCC 独立性分析
├── tribunal.js M3 · 控方/辩方裁定
├── dates.js M4 · 多信号发布日期解析
├── store.js M5 · 证据存储、波动性类别、新鲜度
├── graph.js M5 · BM25 + 实体 + RRF 混合召回
├── credibility.js 来源类型划分、可信度与低质信号
├── verify.js verify_text 流水线
├── judge.js M6 · 零 LLM 词汇蕴含判定器 + 能力预检
└── research.js 深度研究循环、覆盖度评估、缺口查询
刻意选择的设计约束:
- 零运行时依赖。 无需审计,无物可坏,无供应链。
- 每项能力均通过注入提供。 搜索、抓取和 LLM 均通过适配器接入,因此整个引擎可离线测试,并在宿主服务缺失时降级为启发式方法,而非崩溃。
- 浏览器从不进行裁定。 页面无法抓取并锚定来源,因此它从不渲染并非来自宿主引擎的裁决。当宿主不可达时,UI 会如实说明,而不是猜测。
验证
bash
npm test # 262 个测试
npm run demo # 端到端验证,离线运行
npm run bench # 吞吐量与扩展性基准测试
该测试套件覆盖锚定层级、谱系/SCC 凝聚、裁定庭裁决、日期解析、可信度评分、存储/新鲜度行为、图召回、RPC 契约,以及插件在宿主服务缺失、部分可用和恶意情况下的降级表现。
值得注意的回归防护:
- 即使判定器断言 SUPPORTED,伪造的引文也会被拒绝。
- NEUTRAL 来源永远不会成为引用 —— 未针对该主张作出回应的来源不构成其证据。
- 200,000 个不同 URL 产生零 ID 冲突,保护了为多年累积而设计的存储。
- 模糊锚定保持线性;增量滑动窗口取代了 O(文档 × 引文) 扫描,将 40k token 的匹配从约 290 ms 降至约 45 ms。
- 在完全没有 LLM 的情况下,研究运行仍能纳入真实锚定的证据 —— 防止了回退判定器丢弃所有文档、引擎静默地什么都不产出的回归。
- 回退判定器输出的每条引文都能通过机械锚定,因为它是从文档中选取的,而非生成的。
- 状态分桶之和始终等于子问题数量,因此报告永远不会对实际运行过的工作打印 0 resolved · 0 contested · 0 unresolved。
- 搜索服务缺失会产生明确的“无法运行”报告,而绝不是空的发现列表。
- 分解永远不会输出丢失谓词的片段 —— Compare Rust and Go for backend services 绝不能变成 ["Compare Rust", "Go for backend services"]。
如果测试运行需要避免逐文件生成进程(受限沙箱、某些 CI 镜像),请使用 npm run test:serial。
配置
js
apply(ctx, {
storePath: '~/.dsh/kestrel/evidence.db', // ':memory:' 用于临时存储
maxSources: 6, // 每个论断收集的来源数量
defaultMode: 'standard', // quick | standard | deep | forensic
localLlm: false, // 选择启用本地 sidecar 快速路径
localLlmModel: 'qwen2.5-coder',
})
本地模型快速路径默认关闭且会自动禁用:研究工具不应将提示文本发送到无人配置的本地端口,而且一次探测失败就会在该进程内将其锁定为关闭状态,而不是在每次调用时都付出超时代价。
局限性
坦率地说,因为一个自我吹嘘的验证工具是自相矛盾的:
- 锚定证明的是引用,而非真相。 一个来源可以被完美引用,但仍然是错误的。Kestrel 报告的是证据说了什么以及它有多独立,而非真相。
- 蕴含质量取决于宿主 LLM。 机械门控使伪造引用成为不可能;但它并不能使糟糕的判断成为不可能。在没有 LLM 的情况下,确定性词汇判断器(M6)仍然会接纳真正锚定的证据,但它是基于词汇重叠而非语义进行推理:它会漏掉不共享任何显著术语的转述,并且每份报告都会说明是由哪个判断器生成的。
- 独立性检测是基于文本的。 两家独立采访同一来源的媒体会产生不同的文本,并将被计为两个来源。
- 没有搜索服务,引擎根本无法运行,并且会明确说明这一点,而不是返回一份空报告。来源发现是唯一没有离线替代方案的能力。
名称
红隼通过悬停来捕猎——在空中保持定点,纹丝不动,直到它
看清那里究竟有什么。然后它一击而下,仅此一次。
这与研究智能体通常的行为方式恰恰相反:抓取前十个
结果,自信地总结,附上 URL。这个引擎的构建目的是在证据上方保持
定点,只有当引用确实存在时才出击。
其标志是一只红隼悬停在源文本行上方,用一个实心
点标记引用所锚定的确切字符偏移量。
许可证
MIT同作者(grloper)的其他插件
扫码进群