🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI
广告☁️ 云服务器特惠阿里云首购 8 折 · 腾讯云合作特惠
DeepSeek Harness Hub
← 返回列表

cwbcheng/dsh-knowledge-graph

DeepSeek 客户端兼容 / 相关生态spec-screened扫描:中风险在 GitHub 查看 ↗
✓ 可直接安装

DSHDeepSeek HarnessCordis 插件:把任意一段资料正文、包含文字 / 图示 /…

自动检查通过:npm 包已发布且 engines 声明满足基线(声明 Node >=22.13);该结论来自程序自动检查,未经人工实机验证。 · 最近上游提交 2026/9/23 · 已提供中文文档

DSH Cordis 插件:将任何源文本转化为 AI 知识图谱(事实/推论/概念/定义/示例/反例/规则),并实现图谱与原始文本之间的双向链接。

综合分
30.8
GitHub 分
30.8
用户评分
—
★ Stars
1
周下载量
—
兼容 / 相关生态插件(非 dsh 原生,请按其对应运行时安装)
git clone https://github.com/cwbcheng/dsh-knowledge-graph.git
信任档位:已验证本站已于 2 天前真实安装成功(L4 · 真实安装)
是什么
生态插件(可安装,未声明 dsh 能力)
装得上吗
本站已真实安装成功(L4 · 真实安装,非静态推断)
安全吗
本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
还在维护吗
活跃:最近一次提交在 3 天前

档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →

🟢实装验证通过· 2026/9/23
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/23(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
安装兼容性检查✓ 自动检查通过

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-knowledge-graph @ 0.1.3
✓Node 引擎要求 >=22.13 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后验证 2026/9/23 08:32:39

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

由 DeepSeek 最新模型翻译生成
dsh-knowledge-graph

| English

DSH(DeepSeek Harness)Cordis 插件:把任意一段资料正文、包含文字 / 图示 / 表格的图片——或一段 AI 会话执行轨迹——用 AI 拆解成一张知识图,并在知识图与原文之间双向定位。

贴原文 → AI 异步拆图 → 双向锚点定位。是 NovelStudio「资料 ⇄ 知识图」落地为独立、可复用插件的形态。

它能做什么

- AI 异步拆分:输入任意正文(章节、技术文档、学习笔记…),后台任务模式调用 LLM,约 15–40 秒返回一张知识图。支持最长约 100 万字符的书级正文;documentId 是随机稳定的逻辑文档 UUID,sourceId 是全文 SHA-256 的不可变版本身份,chunkId 绑定 sourceId + batch + paragraph range,因此不同文档/追加版本不会因局部 chunk-0001 重号而覆盖。常驻模式把全文、canonical graph 与无损 checkpoint 保存在 SQLite;刷新后浏览器只凭 documentId/runId 恢复,只有 Host 重启遗留的 running 任务才允许从 checkpoint 续跑,显式 failed/cancelled 任务绝不自动重试。
- PDF 直接生成知识图:工作台可直接上传不超过 15 MiB 的可搜索 PDF,本地有界解析正文后自动填入资料区并开始生成知识图;文件数据只用于本次解析,不写入浏览器草稿。复杂排版、特殊字体编码可能导致文本不完整;扫描版 PDF 当前不做 OCR,需先转换为可搜索 PDF。
- 图片直接生成知识图:工作台可一次上传 1–4 张 PNG / JPEG / WebP / GIF(单张不超过 6 MiB、合计不超过 16 MiB),支持纯文字截图、示意图 / 流程图 / 架构图、统计图、公式和表格,也可同时附带说明文字。Host 先把浏览器提交的有界 base64 图片交给 DSH attachments.saveImages() 验证并保存,再用多模态模型生成带图片范围的 canonical 视觉转写;现有文本抽取器只消费这份转写。结果页保留原图预览与 source.visualSource 回链,点击图片会定位对应转写段落。视觉转写会把箭头 / 连线、分组 / 包含、对象对应、顺序和具有图例语义的颜色 / 形状编码拆成独立关系单元,知识抽取后的覆盖复核会补回被首轮遗漏的图示关系;无法准确映射到内置 relation 的关系会保留为原子 fact / claim,而不会强套错误边。视觉转写是模型产物而非像素级确定性 OCR,关键文字、数值、表格单元和连线关系仍应对照原图复核;当前图片输入用于新建知识图,已有图的增量追加仍使用文字。
- 8 类节点 / 12 类关系:
- 节点:fact 事实 · claim 主张 · inference 推论 · concept 概念 · definition 定义 · example 例子 · counter_example 反例 · rule 规则。
- 关系:supports 支持 · example 例子 · counter_example 反例 · defines 定义 · infers 推断 · causes 因果 · is_a 属于 · contains 包含 · driven_by 受驱动于 · not_is 不是 · analogy 类比说明 · aims_at 旨在。
- 最小语义契约:一个节点只表达一个原子命题;作者的理论/经验概括用 claim 而不是 fact;保留“可能 / 多数 / 通常 / 必须 / 如果”等原文限定;存在更精确关系时不退化成 supports。
- 解释覆盖复核:首轮抽取通过后,仅在多步机制疑似欠覆盖,或原文明示纠偏/防误推理限定、留待后文回答的信息却未进入图时,执行一次受限复核;它也可恢复被多个核心命题反复引用的稳定概念锚点。调用可选复核器前,系统会先对原文明示且同句已命名的“某方法在明确条件下行不通/失效”原子结论做确定性、只增节点的补漏;相关关系仍必须由关系编织器依据直接原文证据审定,不会因端点同段出现而自动连边。复核通常只能补缺失节点及其必要关系;对于【图示关系】段落,若箭头、连线标签、分组、对应或图例直接证明允许 relation,也可只补两个已有节点之间的遗漏边;该例外仍要求同一条 evidence quote 同时包含 relation 专用显式词、两个端点及兼容方向。复核不能重写已有图,也不会为了连通率补知识。
- 《学习观》本体知识图(learning-view-v1):第二套抽取本体,不是对既有图的重切。节点类型与关系类型改为于建国《学习观》的本体:知识(concept 概念 / feature 特征 / rule 规律 / discrimination_model 判别模型 / connection_model 联结模型)与学习材料(intension_description 内涵描述 / feature_description 特征描述 / positive_example 正例 / negative_example 负例 / contrast_group 对比例组 / extension_contrast 外延对比 / relation_material 关系材料 / factor_material 因素材料 / property_material 性质材料 / segment_example_group 分段例组 / verification_material 验证材料 / data_or_experience 数据或经验 / memory_material 记忆材料)分开建节点,共 18 类节点 + 21 类关系。每份材料由两个正交坐标刻画:modelKind(判别 / 联结)与 layer(上料 / 下料),从而能诊断知识坍缩——上层丢失、下层丢失、下上错配、判联错配、联结空载、记言代学、言存义空、义存言空、验证复用旧例、缺验证、学习材料当记忆材料。抽取仍然只走 LLM,产出的仍是可存 / 可查 / 可导 / 可增补的知识图;未标注本体的既有文档一律按原来的命题本体处理,行为不变。怎么用:抽取表单右上角的「知识图模式」选《学习观》即可;默认仍是命题本体,且默认值不作为参数发送,老行为不变。一份文档按它自己被抽取时的本体显示(图上有模式徽章、图例、坐标网格、诊断条与边属性),已存在的老文档仍是命题图,要看《学习观》版本需重新抽取一次;模式只影响新抽取,不会改写文档的本体。边上的属性也来自本体:maps_between 的 role(输入/输出)、contrasts 的正负、compares_ 的 mode(对比/类比)都会拼进边的标签,值标签由本体下发,命题本体不声明属性也就不显示。布局也读本体:分层视图的主干道、卫星吸引与分支道改由该文档 relationTypes 的 family / weight 现算,所以《学习观》知识图按它自己的结构铺开,不会因为关系名不在命题表里而退化成毛线团。规范见 docs/learning-view-ontology.md。
- 关系感知分层布局:分层模式先对每个无向连通分量独立排层、消除重叠,再把组件矩形紧凑打包,避免无关子图共用全局层级而把直接相连节点拉远;层内排序按关系加权,以主干关系(命题本体为 causes/infers,各本体由 relationTypes[].family = backbone 声明)作为主路径,把卫星关系放成邻近分支,并将方向关系(family = directional)作为有界软邻近偏好。这些关系集合与权重全部来自当前文档的本体,不在客户端写死。多条边共享节点或行间通道时,箭头入口、水平通道和垂直走廊分别分轨,并为密集的水平轨道保留更高的层间通道;相邻关系标签发生碰撞时会在可读距离内确定性错位;极端拥挤且无可用位置时默认隐藏标签芯片,悬停或选中对应关系仍会显示,避免线段、标签及箭头挤在一起。新用户默认使用分层布局,已有本地布局偏好保持不变。
- 连通分量内的邻近压缩:换行只作为初始位置,不再把折行结果锁成不可跨越的层级。通过有轮数上限、确定性的二维优化,缩短按关系加权的边,同时保留推理顺序、主路径固定列、节点间距和行间布线通道,最后移除空行。垂直走廊按实际障碍区间搜索,不再依赖固定搜索半径。高连接度枢纽和跨分支关系仍可能需要较长的边;这只改变视图,不改写知识图数据和关系。
- 双向定位:
- 点击图中节点 → 弹出详情卡片(完整内容 + 原文摘录 + 定位按钮),并平滑滚动高亮到原文对应内容单元;
- 点击原文内容单元 → 图中居中聚焦并闪烁对应节点。
- 图中节点只展示前 4 行(超出以 … 省略),完整内容随时可在详情卡片中查看;
- 锚点以 AI 直接输出内容单元编号为主(确定性索引,长自然段会按句子边界切分成多个编号单元),quote 精确匹配与 token 重合度兜底;无法回链的节点不猜测偏移,统一进入诊断列表。
- 图渲染:SVG 画布 + 8 类配色 / 4 种可切换布局形态(图右上角下拉,选择记忆):力导向(d3-force 开源引擎内嵌零依赖:碰撞防节点重叠、边-节点排斥防箭头穿节点)、圆形、放射(中心枢纽 + BFS 环,边走折线:径向出线 → 外环弧 → 径向进线)、分层(边走直角正交折线:行间空通道 + 逐行避障走廊,线段保证不穿节点)/ 关系边带类型标签,且同源边按目标角度扇形弯曲(二次贝塞尔)/ 拖拽平移 / Ctrl+滚轮缩放 / 工具栏 − 100% +(50%–200% 步进 10%)/ 长按节点查看原文摘录 / 键盘可达。
- 验证与质疑知识图:生成图后可以检查它是否忠于原文——
- ⚡ 快速体检:本地规则即时检查(自环/悬空边、quote 能否在原文定位、段落编号与摘录位置是否一致、类型-关系语义规则、重复/疑似矛盾节点、孤立节点、覆盖统计),0 秒返回问题报告;
- 🤖 AI 深度审校:异步调用 LLM 逐节点/逐边找茬,所有 issue 必须以原文摘录为证据,标准档还会二次复核过滤误报;
- 人工闭环:问题按「错误 / 警告 / 建议」列出,点击问题 → 图中相关节点/边按严重度着色高亮并滚动定位原文;每条问题可采纳修复(改动立即应用并写入审计记录)或忽略;面板顶部提供一键修复,批量应用全部可自动修复的问题;修复记录逐条显示旧值 → 新值的具体差异;
- 主动质疑:节点详情卡可点「质疑此节点」,选中边后出现关系详情卡可点「质疑此关系」,也可在验证面板直接向整张图提问/质疑,AI 给出「图成立 / 质疑成立 / 证据不足 / 超出范围」判定与原文证据;
- 🔎 外部事实核查原文:把知识图中的 fact/claim/inference/rule/definition/counter_example 节点转为可核查断言,用 Wikipedia 等外部证据裁决原文是否可靠;面板支持粘贴领域规则来源(法条、制度、教材、标准),规则文本与 Wikipedia 证据共同参与裁决;判定为「支持 / 矛盾 / 部分支持 / 证据不足 / 无法核查 / 超出范围」,每条结论绑定证据链接与证据引文(引文必须能在检索结果中定位,编造引文会被自动降级);点击断言可回链图中节点与原文段落;
- 追加拆分后自动标记验证/核查结果过期,可重新验证或核查;轨迹知识图支持同样的全部验证/质疑/外部核查能力。
- 浮动工作台:窗口可拖动、可调整大小;原文与知识图的宽度比例、结果区高度均可拖拽调整并记忆。
- 划线拆分:在聊天消息里用鼠标选中任意一段文字,选区上方浮出「拆成知识图」按钮,点击即自动打开工作台并拆分所选文字;在结果页原文里划线选中可拆成子图;输入框里选中部分文字也可「拆分所选」。
- 追加拆分(增量合并):已有拆分结果后,输入区主按钮变为「追加拆分」——粘贴下一段/下一份资料,AI 只抽取新增内容,并自动与已有图建立跨段关系边(同一概念不重复建节点,直接连线到已有节点);结果原地合并、全文段落统一编号、历史记录原地更新。聊天划线选中文字时也会自动追加到当前图。
- 历史记录:每次成功拆分自动记录(最多 20 条、同文去重、可单删 / 清空);浏览器只保存 documentId、标题、计数等轻量索引,回看时从 Host/SQLite 重新载入正文与 canonical graph,避免把书级正文复制进 localStorage。
- 章节过滤与候选审核:结果区按章节筛选图节点和原文段落;候选实体 / 声明面板展示 evidence,可一键标记「待审核 / 已接受 / 已驳回」,状态通过 Host 同步到 SQLite(动态插件在 Host 会话中保留,失败时回退浏览器 localStorage),并可点击候选回链原文。
- 知识图消费层:正文图与轨迹图共用「使用这张知识图」面板,可按关键词、节点类型、章节、grounding / entailment 状态做有界结构化检索,并区分直接命中与关系邻居;「证据问答」只使用服务端加载的 canonical graph 和已认证原文,模型只能引用 Host 预分配的 evidenceId,每个被接纳的回答片段都必须有节点、关系或原文段落证据。点击检索结果或 citation 可回链图与原文;节点即使位于当前 800 节点渲染窗口之外,也会先按 node ID 加载 canonical 子图再定位。
- 知识图导出:结果工具栏可导出当前渲染图为高清 PNG 图片,也可导出完整 JSON(保留 source、chunk、evidence、验证报告和审计记录)以及节点 CSV、关系 CSV;数据导出的是完整图,不受当前章节筛选影响。轨迹知识图也支持相同导出。
- 常驻入口:每个对话的标题右侧常驻「知识图」按钮,一键打开;运行卡片内也有启动条。
- 轨迹知识图(会话视图标签页):对话区新增第三个标签页「轨迹知识图」(位于 对话 / 轨迹 旁),一键把当前会话的完整执行轨迹(用户消息、工具调用、工具结果、AI 回复)拆成知识图——可视化这个 Agent 查到了什么事实、做出了什么推论、用了什么方法,并在图与轨迹事件之间双向定位(点击节点滚动到对应事件,点击事件在图中聚焦对应节点)。结果按会话持久化到 Host/SQLite;浏览器仅保存 documentId/revision 引用,因此切换标签页或刷新页面后会从 canonical state 恢复,拆分进行中切走再切回会自动续接轮询;会话继续产生新事件后,可点 追加新事件 只拆解新增部分并在同一 revisioned document 上增量合并(跨事件建立关系边);轨迹事件列与图列的宽度、结果区高度均可拖拽调整并记忆。

界面一览

原文段落的类型标签旁有 × 按钮,可在确认后删除该段落、该类型在当前节点窗口中的对应节点,以及这些节点的全部关联关系(含跨窗口关系)。原文、其他段落和其他类型的节点保留。修改通过已有版本校验保存到 SQLite,刷新后不会恢复;生成任务进行中不允许此操作。适合手动清理被误识别为知识的目录、署名等内容。

┌─────────────────────────────── 浮动工作台 ───────────────────────────────┐
│ ● 知识库 · 资料 ⇄ 知识图                                      [ × ]        │
│ 知识库                                                                      │
│ 把任意资料用 AI 拆成「事实/主张/推论/概念/定义/例子/反例/规则」知识图… [历史][重新开始]│
│ [输入资料 ─────────── 收起 ▴]                                                │
│ [原文 ⇄ 知识图]                                                             │
│ 一句话总结:…                                                              │
│ N 节点 · M 关系 · 可回链 X/Y ─────────────────────────┐                    │
│ [原文段落…带类型徽标]  ‖  [知识图 SVG…]  [− 100% +]  │ ← 可拖宽竖条         │
│ ─────────────── 可拖高横条 ────────────────           │                    │
└─────────────────────────────────────────────────────────────────────────┘

对话区「轨迹知识图」标签页:

┌────────────────────────── 轨迹 ⇄ 知识图 ──────────────────────────┐
│ 拆解本会话轨迹:用户消息 / 工具调用 / 工具结果 / AI 回复            │
│ 一句话总结:…                                                     │
│ [轨迹事件…带类型徽章]  ‖  [知识图 SVG…]  [− 100% +]  ← 可拖宽竖条  │
│ ──────────── 可拖高横条 ────────────                              │
│ (切换标签页 / 刷新页面后结果自动恢复)                            │
└────────────────────────────────────────────────────────────────────┘

安装

这是一个 DSH 动态 Cordis 插件:一份 Host 代码(Node 进程)+ 一份 Client 代码(浏览器),纯 JS、零依赖、无需构建。通过 DSH Web 界面的 Cordis 插件机制加载,步骤适用于任何 DSH Web 会话。

0. 前置条件

- 已启动 DSH Web(dsh web)并进入任意会话;
- 环境中已配置 AI 模型提供方(设置 → 模型,或 agentDefaultModel)。插件默认跟随系统当前模型;工作台与「轨迹知识图」顶部均提供模型下拉框,可手动指定拆分、追加、AI 审校、质疑与外部核查使用的模型(选择会保存在浏览器本地);未配置时会给出明确的中文错误提示。图片抽取需要支持 image 输入的多模态模型;模型下拉框会标注已知的「图像 / 仅文本」能力,能力未知的模型允许尝试,但提供方拒绝图片时会以 model_image_unsupported 明确失败。

1. 获取源码

git clone https://github.com/cwbcheng/dsh-knowledge-graph.git
cd dsh-knowledge-graph

| 文件 | 作用 |
| --- | --- |
| src/index.host.js | Host 半:异步 AI 拆分任务引擎(图片 admission / 多模态视觉转写、段落编号、分批、schema 校验、typed 诊断、模型路由、会话轨迹序列化)+ 知识图验证/质疑引擎 + canonical 结构化检索与 evidence-ID 证据问答 |
| src/index.client.js | Client 半:浮动工作台 UI、图渲染、双向定位、共享检索/证据问答面板、验证与质疑面板、修复应用/审计、历史、宽高调节、轨迹知识图标签页 |
| src/kg-store.mjs | SQLite 持久化层:文档、内容块、节点、关系、证据、候选实体/声明、抽取 checkpoint 与大图有界消费查询 |

2. 安装(二选一)

方式 A:让 Agent 帮你安装(推荐)

在任意会话中把下面这句话发给 Agent(把路径换成你 clone 的位置):

请读取 dsh-knowledge-graph 仓库的 src/index.host.js 和 src/index.client.js,把这两个文件定义为 Cordis 插件的 Host 半和 Client 半,然后运行它。

Agent 会依次调用 cordis_define(定义)→ cordis_run(运行),并在界面上弹出运行审批卡片。

方式 B:自己复制源码定义

1. 在任意会话中发起一次 cordis_define(由 Agent 执行,或按你环境的 Cordis 工具流程操作);
2. Host 半粘贴 src/index.host.js 的内容,Client 半粘贴 src/index.client.js 的内容;
3. 注意粘贴的是函数体:去掉文件里的 export default function hostPlugin() { / export default function clientPlugin() { 这一行和文件末尾对应的 },保留中间的 return { ... }; 部分(文件头部注释可保留也可删掉)。

不熟悉 cordis_define 工具的话直接用方式 A,Agent 会自动处理好上面的取函数体步骤。

方式 C:常驻安装(推荐,重启不丢)

把本仓库安装为 web profile 的组合插件(与 dsh-hud 相同的社区插件包形态):Host 半走 webServer 路由、Client 半是 __ModuleLoader__ 浏览器模块,随 dsh web 启动自动加载,不需要每次重启后重新定义,也无需审批。

1. 在 profile 目录添加依赖与 bundle($DSH_HOME 默认 ~/.dsh)
cd ~/.dsh/profiles/web
在 package.json 的 dependencies 中加:
"dsh-knowledge-graph": "github:cwbcheng/dsh-knowledge-graph#main"
在 package.json 的 dsh.profile.bundles 中加:
"dsh-knowledge-graph"
pnpm install

2. 重启 dsh web(Ctrl+C 后重新 dsh web)

重启后:对话标题右侧出现「知识图」按钮。窗口位置、筛选和历史索引等轻量 UI 状态保存在浏览器 localStorage;正文、图、checkpoint 与 revision 由 Host/SQLite 持久化。

| 文件 | 作用(常驻包) |
| --- | --- |
| lib/index.js | Host 半:任务引擎 + /api/dsh-knowledge-graph 路由(抽取/追加、task status、document-load/canonical 来源成员校验 image-load/document-export、revisioned graph-commit、graph-query、answer-graph、安全 resume-extract、验证/质疑等)+ 自动 SQLite canonical graph / checkpoint 持久化 |
| lib/client.js | Client 半:__ModuleLoader__ 浏览器模块(fetch RPC + 手动样式注入) |
| cordis.patch.yml | bundle patch:向组合插入 dsh-knowledge-graph 行 |

src/ 与 lib/ 是同一插件的两种部署形态:src/ 供动态插件(方式 A/B)使用,lib/ 供常驻组合(方式 C)使用,逻辑保持一致。

3. 批准运行

定义成功后运行会进入 awaiting approval(等待批准) 状态:

- 插件面板(左下角 Cordis Plugin 按钮)会自动弹出并高亮待批准的行;
- 点 ✓(单勾):仅授权本次运行;点 ✓✓(双勾):同时授权该插件后续版本的自动运行(推荐);
- 批准后插件在浏览器中激活,面板状态变为 running。

4. 验证安装

- 任意对话的标题右侧(对话头部操作行)出现「知识图」按钮;
- 点击弹出浮动工作台,粘贴一段正文 → AI 拆分,约 15–40 秒后得到知识图;
- 对话区顶部出现第三个标签页「轨迹知识图」(对话 / 轨迹 / 轨迹知识图),点击 → 拆解本会话轨迹,约 15–40 秒后得到该会话的轨迹知识图。

5. SQLite 持久化与 CLI

CLI 使用 Node node:sqlite,要求 Node 22.13+(无需 experimental-sqlite 启动参数)。导入必须用 DSH_KG_DB 或 --db 显式指定目标数据库,包含完整 sourceText,并通过与 Host 相同的确定性验收;导入文件不能自行授予 entailment verified。默认只允许创建新文档,覆盖已有文档必须传 --expected-revision N。

初始化数据库
npm run kg -- init --db ./data/knowledge.sqlite

导入含完整 sourceText 的完整图(不可使用截断的 task/result 窗口)
npm run kg -- import-graph --db ./data/knowledge.sqlite --input ./graph.json

查看候选实体或声明
npm run kg -- list-candidates --db ./data/knowledge.sqlite --kind entity --status candidate
npm run kg -- list-candidates --db ./data/knowledge.sqlite --kind claim --status candidate

接受 / 驳回候选
npm run kg -- set-candidate --db ./data/knowledge.sqlite --kind entity --id ent_xxx --status accepted
npm run kg -- set-candidate --db ./data/knowledge.sqlite --kind claim --id clm_xxx --status rejected

查看已持久化文档与 checkpoint
npm run kg -- list-documents --db ./data/knowledge.sqlite
npm run kg -- show-document --db ./data/knowledge.sqlite --id document_xxx
npm run kg -- save-checkpoint --db ./data/knowledge.sqlite --input checkpoint.json --run-id run_xxx
npm run kg -- load-checkpoint --db ./data/knowledge.sqlite --run-id run_xxx

查看可恢复版本;恢复会用 CAS 产生新版本
npm run kg -- list-revisions --db ./data/knowledge.sqlite --id document_xxx
npm run kg -- restore-revision --db ./data/knowledge.sqlite --id document_xxx --revision 2 --expected-revision 5
常驻包的 lib/index.js 会在每个成功 chunk 和任务完成时自动写入 SQLite;数据库路径由 DSH_KG_DB 指定,未指定时为当前工作目录的 .dsh-knowledge-graph.sqlite。npm run test:kg 会在内存 SQLite 中验证文档、chunk、evidence、候选状态变更、checkpoint 保存与恢复;npm run test:kg-consumption 覆盖动态 RPC / 常驻 HTTP / SQLite 检索语义、800 节点窗口之外与 600+ 常见候选之后的精确召回、relation-only 查询、上下文预算、revision fence、非法过滤器、node/edge/source citation 认证、未知及「真实但无关」evidenceId 拒绝和共享前端入口;npm run test:kg-timeout 使用不合作 provider 回归真实 wall-clock deadline、晚到 iterator 清理与即时取消;npm run test:kg-image 覆盖动态 / 常驻图片 admission、多模态 content block、文字 / 表格 / 图示转写、颜色分组与对象对应关系遗漏补漏、text-only 模型 typed 拒绝、visual provenance、canonical 来源成员校验图片读取、伪造 visual checkpoint 拒绝、转写后即时 checkpoint / runId 恢复及 SQLite 不落原始 base64;npm run test:kg-performance 在 10000+ 节点 / 关系图上验证 keyset 分页和有界返回;npm run test:kg-candidates 额外验证候选列表和状态更新。常驻包构建时会同步生成 lib/kg-store.mjs。

覆盖图时会在同一事务中保存上一版图和原文单元快照。旧版本中只有计数、没有快照的历史明确不可恢复,不会凭空补回内容。快照随修改次数增长,应随数据库备份。浏览器的“移出历史 / 清空历史”只隐藏索引,不删除 SQLite 文档;“恢复历史”可重新显示这些文档。

npm test 还包含独立流水线、CAS 与历史异步竞态、模拟 OCR 中断恢复和 CRX 载荷校验。流水线的使用与安全边界见 OCR 流水线。

对着 dsh 源码跑

日常启动、关闭脚本位于 DSH 仓库 deepseek-harness/scripts/,不在本插件仓库中。在 WSL 中执行(需已安装下方的 systemd 用户服务):

cd /mnt/d/github/deepseek-harness
npm run dsh:start              # 等待知识图接口认证及就绪,打印本次地址
npm run dsh:stop               # 先暂停可恢复任务,再关闭服务
也可从任意目录直接执行:
bash /mnt/d/github/deepseek-harness/scripts/start-dsh.sh
bash /mnt/d/github/deepseek-harness/scripts/stop-dsh.sh

这两个入口管理同一个 dsh-kgsrc-web.service,重复启动不会新建实例,关闭后不会被守护器自动拉起。运行环境、解释执行参数、profile 和数据库沿用服务配置;不会设置开机自启、重新导入资料或自动解除崩溃重启限流。默认使用 /opt/node-v24.14.0/bin/node 执行控制脚本,可通过 DSH_DEV_NODE 指定其他 Node。

关闭前若有可恢复任务,会请求暂停并等待检查点落盘;不能暂停、状态查询失败或暂停未完成时会拒绝关闭。暂停的任务在下次启动后需要手动“继续任务”。确实要强制中断服务时使用 npm run dsh:stop -- --force,这可能丢失最后一个检查点之后的未保存工作,但不会删除已有图或检查点。

DSH_CONTROL_TIMEOUT_SECONDS 调整启动/暂停的等待时间(默认 90 秒)。控制器默认连接 127.0.0.1:3099,可读取 DSH_SERVICE_UNIT / DSH_DEV_PROFILE / DSH_DEV_PORT / DSH_DEV_LOG / DSH_DEV_PID 指向其他已安装服务;这些变量只选择控制目标,不会改写 systemd 服务配置,必须与目标服务一致。

想让它跑在 /mnt/d/github 里那份 dsh 源码构建上(而不是 npx 装的那份),用 scripts/dev-web.sh:

cd /mnt/d/github/dsh-knowledge-graph
npm run dev:web                 # 前台启动,Ctrl-C 结束
npm run dev:web -- --detach     # 后台启动并打印带 token 的地址
npm run dev:web:stop            # 停掉后台实例
npm run dev:web -- --rebuild    # 先 pnpm install + build(含本插件)

它沿用本地 DSH_REPO checkout,不会自动拉取或切换 Git 分支;缺少构建产物或显式 --rebuild 时安装依赖并构建。随后从随包 web 模板创建缺失的 profile,把本插件作为 bundle 层装进去,最后用独立端口和独立 profile 启动,不会碰其他实例。启动后会请求一次 ontology-list 确认插件真的回答了,因为插件加载失败时外壳照样能起来,「起来了」不等于「能用」。源码或构建脚本比 lib 新时会自动重建插件。端口被占用时直接报错退出,不抢端口。

可用 DSH_REPO / DSH_DEV_PORT / DSH_DEV_PROFILE / DSH_DEV_LOG 覆盖默认值(默认 /mnt/d/github/deepseek-harness、3099、kgsrc)。

启动器会打印实际 Node 路径和版本,优先使用 PATH 中的 Node 24+,也可用 DSH_DEV_NODE=/opt/node-v24.14.0/bin/node npm run dev:web 显式指定。只在此启动器内拒绝已观察到原生崩溃的 22.20.0,不修改 NVM 默认版本;这是运行时规避,不代表已经证明或修复了 V8/系统层崩溃根因。源码和构建脚本更新后自动重建插件。
每次启动先归档旧日志,再读取本次进程的 token,并用 token 换取 cookie 验证本体目录接口的 HTTP 状态和 JSON 内容。只输出 URL 不算就绪;检查失败或进程退出会返回非零状态并清理此次启动的进程。DSH_DEV_STARTUP_SECONDS 可调整就绪等待时间(默认 60 秒)。前后台均记录真实 Node PID 和启动时间;--stop 只停止匹配的进程,绝不按端口杀其他服务。旧格式 PID 文件不能用于停止进程。

原生崩溃与后台恢复

--detach 只负责脱离终端,不会在 Node 崩溃后重启。此机器的 Node 24.14.0 也曾在 Builtins_RegExpPrototypeTestFast 路径发生 SIGSEGV,升级版本不能视为根治。npm run dev:web -- --safe-runtime 可作为诊断性规避:只对 DSH 服务使用 --no-opt --no-maglev --no-sparkplug --regexp-interpret-all,禁用 JavaScript 优化/基线编译和正则 JIT,保留 WebAssembly,不改变全局 Node 配置或构建进程。代价是 JavaScript 更慢;它不能排除原生扩展、WSL 或硬件故障。不要替换为 --jitless:此版本 Node 的原生 fetch 依赖 WebAssembly,完全禁用会导致模型请求立即失败,即使服务入站健康检查仍能通过。

长任务可以使用 scripts/dsh-kgsrc-web.service 提供的 systemd 用户服务,安装前检查里面的仓库与 Node 路径。不要与同端口的前台/脱离终端实例同时启动:

2026-09-18 实测:解释执行模式下仍发生过原生崩溃,但守护服务与页面检查点恢复成功。这个模式不是“防崩溃保证”,也不能代替底层故障排查。证据与验证边界见 运行时故障记录。

mkdir -p ~/.config/systemd/user
cp scripts/dsh-kgsrc-web.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user start dsh-kgsrc-web
systemctl --user status dsh-kgsrc-web
journalctl --user -u dsh-kgsrc-web -n 50
停止必须是有意操作,正在执行的模型请求会中断:
systemctl --user stop dsh-kgsrc-web

服务每次异常退出后等待 10 秒重启,5 分钟内最多启动 3 次,超过后保持失败状态,不无限重试。故障日志保留在 journal 和轮转后的 /tmp/dsh-kgsrc-web.log.previous.;就绪通过前 systemd 的 active 仅表示启动器存活。需要看到日志中的认证健康检查成功才算插件可用。服务使用原 profile、DSH_HOME 和数据库,不重建任务;已保存的检查点仍由插件自己的恢复规则处理。不设置登录/开机自启,避免未经确认恢复付费模型请求。修复反复崩溃的原因后,才使用 systemctl --user reset-failed dsh-kgsrc-web 和 start。

隔离的服务恢复对抗测试:KG_TEST_SYSTEMD=1 npm run test:dev-web。它对临时假服务注入不可捕获的 SIGKILL,验证进程重建、接口重新就绪、重启限流及主动停止;不杀真实 DSH,也不调用模型或读写知识图数据库。

冻结质量回归门禁

kg:quality-regression 固定使用 2844 字的 world-recognition 原文与 calibrated-v2 的 25 个 QA case。修复后观察基线为 24/25;默认门禁要求 trusted QA 至少 23/25(最多退化 1 case)、score 至少 92、节点至少 20。节点下限只是 catastrophic-collapse sentinel,不能替代 QA 分数。--graph 模式也会先校验 graph.sourceText 的字符数和 SHA-256;缺少原文或换了文章时返回 frozen_source_missing / frozen_source_mismatch,不会输出误导性分数。

检查已有 graph(不会调用模型)
npm run kg:quality-regression -- --graph ./graph.json

调用当前 DSH Host 做真实抽取,再检查并保存结果
npm run kg:quality-regression -- \
--base-url http://127.0.0.1:3080 \
--provider codex-proxy \
--model gpt-5.6-sol \
--output ./quality-run.json

CI 也可以设置 DSH_KG_QA_BASE_URL、DSH_KG_QA_PROVIDER、DSH_KG_QA_MODEL 后直接运行 npm run kg:quality-regression。门禁同时校验冻结原文的字符数与 SHA-256,防止通过改评测原文或 QA 尺子掩盖回归。

更新插件

- 动态安装(方式 A/B):仓库有更新后重复方式 A——让 Agent 重新读取两个源文件并 cordis_define(在同一个插件下追加新 Package),再 cordis_run(update 模式)切换到新版本;若你之前点了双勾,新版本会自动运行。
- 常驻安装(方式 C):更新后重新 pnpm install(拉取最新 #main)并重启 dsh web 即可。

卸载插件

- 动态安装:打开 Cordis Plugin 面板 → 在插件行点击 停止(Stop) 暂停使用;需要彻底删除定义时使用 cordis_undefine。
- 常驻安装:从 profile 的 package.json 移除依赖与 bundles 条目,pnpm install 后重启。

窗口布局、历史索引等轻量 UI 数据保存在浏览器 localStorage;书级正文、canonical graph、checkpoint 与 graph revision 在常驻模式保存在 Host/SQLite。卸载前如需长期保留知识内容,请保留对应 SQLite 数据库或先导出 JSON/CSV。

注意事项
- 动态插件运行在 DSH 进程内:进程重启后插件会消失,需要重新安装(方式 A 或改用常驻方式 C,历史数据仍保留在浏览器里);常驻插件随服务启动自动加载,不受重启影响;
- Host 半依赖可用的 LLM(见前置条件);AI 调用只发生在你自己的 DSH 环境内,是否外传取决于你配置的模型提供方。图片抽取会把已由 DSH 附件服务接纳的原图发送给所选多模态模型,敏感图片请先确认提供方的数据政策;
- 本项目不含付费 / 配额功能:拆分、历史、双向定位全部在本地完成。

使用

1. 点击对话标题右侧的「知识图」按钮,打开浮动工作台;
2. 在「输入资料」粘贴正文,或点 上传图片 选择包含文字、图示或表格的图片(可同时输入说明文字、可选填标题);选择支持图片的模型后点 AI 拆分 / 图片生成知识图。图片生成后,原文栏顶部会显示可点击的原图画廊与视觉转写风险提示(输入区可收起;结果区高度、原文/图宽度比例均可拖拽调整并记忆);
3. 摘要 / 图出现后,点图中节点查看详情卡片(完整内容)并定位原文,或点原文段落聚焦图中节点;
4. 在 「使用这张知识图」 面板切换「结构化检索 / 证据问答」:按关键词、类型、章节找节点,或直接向 canonical graph 提问;点击结果/citation 可回链节点、关系与原文证据;
5. 点 ⚡ 快速体检 立即拿到确定性问题报告,或点 🤖 AI 深度审校 让 LLM 以原文为证据逐节点找茬;点 🔎 外部事实核查 则用外部证据核查原文本身;点击问题/断言行高亮图中相关节点/边并定位原文,采纳修复或忽略;在节点详情卡「质疑此节点」、选中边后「质疑此关系」,或在验证面板底部直接向整张图提问/质疑;
6. 在「章节与候选审核」面板选择章节,只查看该章节的图和原文;对候选实体 / 声明点「已接受」或「已驳回」,点击候选卡可回链原文证据;
7. 想继续扩展图:在输入区粘贴下一段资料,点 追加拆分(或直接选中聊天消息里的文字自动追加)——新增节点与已有节点自动建立跨段关系,全文段落统一编号,历史记录原地更新;此前验证结果会自动标记为过期,可重新验证;
8. 用「历史」回看之前的拆分(自动保存最近 20 条,可单删 / 清空);任务进行中关窗或刷新,重开窗口会自动恢复轮询;
9. 对话区切换到「轨迹知识图」标签页,点 拆解本会话轨迹 生成会话轨迹知识图;轨迹图也提供相同的结构化检索与证据问答入口;点击轨迹事件在图中聚焦节点,点击节点查看完整内容并滚动到对应事件;结果在切换标签页 / 刷新后自动恢复,拖拽中间竖条调两列宽度、拖拽下方横条调结果区高度。

暂停与继续任务

常驻 Web 插件中,有持久化检查点的资料拆分、追加拆分和轨迹拆分任务提供 暂停任务,包括拆分后的关系补全与审校阶段。暂停会中断当前模型请求,保留已经落盘的内容块、并发待合并结果与关系候选;未完成的请求在继续时重试。

- 收尾期间显示「暂停中」,检查点保存并释放运行锁后才显示「已暂停」。保存失败会明确报错,不把未保存的结果当作成功暂停。
- 刷新页面或重启 DSH 后仍保持暂停,可在「未完成任务」列表点击 继续任务;后台自动恢复逻辑不会唤醒主动暂停的任务。继续仍校验原文、本体与知识图版本,不覆盖已被其他操作修改的图。
- 暂停与取消、删除相互独立。无持久化检查点的任务,以及最终结果正在提交的短暂阶段,不显示暂停按钮。已有图上的独立「持续补全关系」任务仍使用下节的「停止补全」和已保存游标恢复机制。

持续补全关系

工作台的 生成并发 统一控制正文拆分、关系补全和关系审校,支持 1、2、4 路,默认 2 路;轨迹拆分仍保持串行。关系补全按固定分组顺序合并,每组完成即保存检查点;关系审校继续逐条验收完整证据,每批最多 16 条。遇到模型限流后,本次任务后续关系请求会降为串行,不通过缩减覆盖范围或跳过审校来提速。进度区显示后处理的并发上限、执行中请求数,以及已有的保存和审校进度。

未完成任务列表支持逐条删除:确认后清除该任务的拆分检查点和待合并结果,不删除已保存的知识图、原文或其他任务。删除不可撤销;后台任务运行或收尾时不允许删除,列表版本过期时需刷新后再次确认。

已有正文知识图至少包含两个节点时,可点击 持续补全关系。默认勾选「持续到本轮完成」:Host 自动检索未覆盖节点、独立审校候选关系,并分批保存结果,无需前端反复发起请求。取消勾选则只检索一批;图已经连通也可以继续检索。

- 每批最多检索 4 组候选节点,通过原文证据检查和语义审校后,将关系和检索游标一起保存。进度同时显示当前检索覆盖与已落盘覆盖、已保存批数、本次已接纳关系数。
- 关闭窗口或刷新页面不会停止 Host 中的任务,重开工作台会恢复进度。点击「停止补全」保留此前已保存的批次,当前未提交批次不会写入。
- 常驻插件使用 SQLite 保存游标。DSH 进程重启后,打开该历史知识图,再点击补全即可接着已保存进度执行;不会自动恢复付费模型调用。动态插件没有 SQLite 时,进程内状态不能跨进程恢复。
- 本轮所有目标节点检索完即停止。覆盖完成不代表所有可能关系都已找到;只有再次点击「再检索一轮」才会开启新一轮模型调用。合法的空关系结果也计入检索覆盖,不为凑数添加关系。
- 模型失败、审校未完成或知识图版本冲突会停止任务并提示原因。已经保存的结果保留,不会覆盖其他操作的修改,也不会跳过独立审校直接接纳候选。
- 审校遇到明确的传输中断或临时服务错误时,等待 3 秒后重试原批次一次(限流等待 30 秒),等待期间可取消。仍失败则保存待审候选并显示实际原因;继续时先审这些候选,再检索剩余节点。认证失败不自动重试,语义驳回也不会通过反复重试变成接纳。

两种 Host 入口的 relation-retry 均接受布尔参数 continuous,省略时维持单批行为;仍须传入 documentId 和当前 expectedRevision。

知识图消费层

前端使用

生成正文知识图或轨迹知识图后,下方会出现共享的 「使用这张知识图」 面板:

1. 结构化检索:输入关键词,并可叠加节点类型与章节筛选;返回列表只表示直接命中,关系邻居保留在响应子图中作为上下文,不会伪装成直接命中。
2. 证据问答:输入自然语言问题,Host 先做有界节点召回、最多两跳关系扩展和原文段落 fallback,再调用当前选择的模型;answered、insufficient、out_of_scope 都是成功的语义结果。
3. 点击检索结果或回答 citation 会同时聚焦节点与原文。若目标节点不在当前 800 节点窗口,Client 会调用 document-load({ query: nodeId }) 加载该节点及其邻居后再定位,而不是把“当前没渲染”误判为“图中不存在”。
4. 面板的错误、任务轮询与取消状态独立于抽取/验证面板,不会覆盖父工作台的错误提示。

graph-query:有界结构化检索

动态插件调用 host.call('graph-query', body);常驻包调用 POST /api/dsh-knowledge-graph/graph-query。公开请求以 logical document 为边界:

{
"documentId": "document_xxx",
"expectedRevision": 4,
"query": "断点恢复",
"nodeIds": [],
"types": ["fact", "rule"],
"relations": ["supports", "causes"],
"sectionIds": ["section-2"],
"groundingStatuses": ["grounded"],
"entailmentStatuses": ["verified", "uncertain", "unverified"],
"limit": 20,
"hops": 1,
"direction": "both",
"maxNodes": 80,
"maxEdges": 240
}

- nodeIds / types / sectionIds / groundingStatuses / entailmentStatuses 是 hard filter;非法枚举返回 typed invalid_input,不会静默丢弃后退为全图查询。
- relations 限制返回/扩展的关系类型;direction 为 both | in | out。relations 也可单独作为 selector:Host/SQLite 会先从匹配关系的端点播种直接候选,而不是从文档开头任取节点。
- matches 只包含直接命中;graph.nodes/edges 还可包含 0–2 跳邻居。直接命中的原文单元优先于邻居证据进入预算,预算截断量通过 metrics.sourceRefsOmitted 暴露。
- 响应包含 documentId、revision、matches、有界 graph、可回链 sourceUnits 和 metrics,不返回完整 sourceText。动态与常驻模式都对公开 node/edge/evidence 做字段与长度投影,sourceUnits 不再重复携带 quote 数组,并对聚合上下文设置硬 envelope;metrics.contextChars/contextBudget 可用于观测。
- 当前硬上限:查询 600 字、直接命中 40、节点 160、关系 480、跳数 2、原文单元 80、原文文本 24000 字;graph context 另有约 384000 字 envelope。调用者给出更小的 maxNodes/maxEdges 时也会严格遵守。
- 常驻模式在 SQLite 中一次查询就完成候选排名、关系扩展、精确 document_units 回填和可选 source fallback,不再先查 SQLite、再把结果交给 Host 做第二次检索/重组。词汇候选和 source fallback 使用 keyset 分页,避免随页码增长的 OFFSET 重扫;queryId 包含全部规范化 selector 与有效预算。
- expectedRevision 与 canonical revision 不一致时返回 revision_conflict,避免把旧 UI 状态与新图混用。抽取、重新抽取、追加与 checkpoint 恢复也会记录启动时 revision,并在发布 canonical replacement 时执行同样 fencing。

answer-graph:canonical graph + 原文证据问答

answer-graph 是异步任务,复用既有 task-status / task-cancel:

{
"documentId": "document_xxx",
"expectedRevision": 4,
"question": "为什么检查点能够支持断点续跑?",
"types": [],
"sectionIds": [],
"hops": 1,
"model": { "provider": "...", "model": "..." }
}

启动响应:

{ "taskId": "kg_xxx" }

任务完成后的核心结果:

{
"status": "answered",
"answer": "由 Host 拼接的已接纳回答",
"parts": [
{ "id": "part-1", "text": "一个独立回答命题", "evidenceIds": ["ev3"] }
],
"citations": [
{
"id": "ev3",
"targetKind": "node",
"targetId": "n12",
"nodeId": "n12",
"paragraph": 8,
"quote": "canonical 原文逐字摘录",
"groundingStatus": "grounded",
"entailmentStatus": "unverified"
}
]
}

安全与可信边界:

- 图片请求在 Client 与 Host 双侧限制为最多 4 张、单张 6 MiB、合计 16 MiB,并只接受 PNG / JPEG / WebP / GIF。Host 在任务发布前解码 canonical base64 并调用 DSH attachments.saveImages();之后任务、checkpoint、canonical graph、task-status 与 SQLite 都只保留不可变 attachment ref / 元数据,不持久化原始 base64。
- 插件会在调用 saveImages() 前预检已明确声明为仅文本的模型,避免这类确定性失败写入附件。DSH 当前公开附件契约是持久化、内容寻址存储且没有插件可调用的删除 API;因此能力未知的模型、模型超时或视觉 schema 失败发生在 admission 之后时,底层附件的保留周期由所配置的 DSH attachment backend 决定。对敏感图片应同时遵循该 backend 的留存 / 清理策略。
- image-load 不接受任意 attachment id:它先按 documentId(及可选 expected revision)加载 canonical source,再确认 imageId 确实属于 source.visualSource.images,最后才读取有界图片字节。公开 graph 可包含 attachment ref 以保留证据来源,但不直接包含像素字节。
- 图片证据的可回链文本来自模型生成的 immutable 视觉转写。Host 仍会对节点 quote 与该 canonical 转写做确定性认证,但这只能证明节点忠于“转写”,不能证明转写忠于像素;UI 因此同时展示原图、图片段落范围和风险提示,要求人工复核关键证据。
- image-load 与其他 canonical document API 一样依赖 DSH Web 的同源 / 工作区信任边界;documentId 是高熵随机 UUID,但不是多租户授权令牌。不要把同一 DSH Web origin 暴露给互不信任的租户;Chrome 扩展的 /dsh-kg allowlist 不开放 image-load。
- 对带 documentId 的请求,Host/SQLite 只从服务端加载 canonical graph 与 source;客户端提交的 graph / text 不会成为事实源。
- Host 在调用模型前,从已认证 node evidence、edge evidence 和 source paragraph fallback 中预分配最多 24 个 evidenceId。模型只能返回 parts[].evidenceIds,不能自行声明 nodeId/paragraph/quote。
- Host 丢弃未知 evidenceId、真实但与命题词汇无关的 evidenceId,以及没有合法证据的 answered part;candidate/unverified/uncertain 证据还要求回答显式使用“资料表述/可能/未验证”等限定措辞,unsupported 证据不能被包装成已证实结论。若所有 part 都被丢弃,结果自动降级为 insufficient。即使 part 通过准入,模型原始 part.text 也不会直接展示:Host 会从已认证 node/edge/source evidence 确定性渲染 part,再拼接最终 answer;insufficient/out_of_scope 也只返回 Host 固定语义文案且不返回 follow-up;answered 的 follow-up 由 citation target ID / paragraph 确定性生成,因此模型自由文本无法借回答或可点击追问混入结果。
- targetKind=node | edge | source 分别支持节点命题、关系命题和图覆盖不足时的原文段落证据。关系结论可直接引用 edge evidence,而不是只拿端点节点充当关系证明。
- groundingStatus=grounded 只表示 quote 可回到 canonical 原文,不等价于外部事实已证实;外部真实性仍应使用「外部事实核查」。entailmentStatus 会原样进入 citation,UI 不会把 unverified/uncertain/unsupported 包装成已验证事实。
- 原文中的 prompt injection 文本在问答提示中明确标记为待分析数据;输出仍经过严格 JSON 解析、evidence-ID admission、长度和数量上限。
- 每次模型调用都执行真实 wall-clock deadline,计时覆盖 llm.stream() 建立连接和完整异步迭代;超时以 typed timeout 失败,取消以 cancelled 结束。即使 provider 忽略 AbortSignal 或 iterator.return() 不返回,任务也会立即释放前台 busy 状态,晚到 iterator 会在进入 next() 前被幂等关闭,部分输出不会发布。运维/回归可用 DSH_KG_MODEL_TIMEOUT_CAP_MS(最小 20ms)把各调用点原有 deadline 统一下调;未设置时保留各阶段 60–360 秒的既有预算。

Chrome 扩展(划线拆图)

在任意网页上选中文字,点浮动按钮「拆成知识图」,一键调用本机 DSH 服务生成知识图(弹窗内可直接拆分、看图、回链原文)。

- 源码在仓库 extension/ 目录,零依赖打包:viewer.js 由 scripts/build-viewer.mjs 从 src/index.client.js 切片生成(d3/.js 为内嵌 d3 模块的独立文件——MV3 扩展页禁止 eval,popup 用  预载后 viewer 自动走全局 d3 快速路径),修改源文件后运行 node scripts/build-viewer.mjs 重新生成。
- 安装(二选一):
1. 拖一个文件(推荐):Chrome 打开 chrome://extensions → 开启右上角「开发者模式」→ 把 dist/dsh-knowledge-graph.crx 直接拖进页面 → 点「添加扩展程序」。首次会提示"Chromium 无法验证此扩展程序的来源",属正常(未上架商店),照常使用。
2. 加载文件夹:「加载已解压的扩展程序」→ 选择本仓库 extension/ 目录。
- 注意 Chrome 137+ 品牌版不支持 --load-extension 命令行加载(Chrome for Testing / Chromium 等未品牌化构建仍支持)。
- 重新打包(源码更新后想继续用 crx 分发):扩展私钥不能放在仓库里。将它保存在仓库外(默认建议 ~/.config/dsh-knowledge-graph/extension-signing.pem,权限 0600),然后通过环境变量传给打包脚本:
npm ci --prefix scripts/signing --ignore-scripts
export DSH_KG_EXTENSION_KEY="$HOME/.config/dsh-knowledge-graph/extension-signing.pem"
npm run pack:extension

私钥必须已经存在;脚本不会在缺失时自动生成新密钥。扩展 ID 由它派生,换密钥会改变 ID 并使旧安装失效。不要把私钥复制到 dist/ 或提交到 Git。脚本写入 dist/dsh-knowledge-graph.crx 和 dist/extension-release.json,逐文件校验 CRX 内部载荷与 extension/ 一致。CI 用 Python 3 复核载荷、版本和 SHA-256 发布记录,不需要私钥。
- 依赖:本机需运行 dsh web 且插件版本包含 /dsh-kg 扩展端点(常驻安装需先更新插件并重启 dsh web)。端点默认只接受本项目新 CRX 的扩展来源 chrome-extension://kffpcpfkpmfkicdnlckdphiplnhlbkof;若使用「加载已解压」导致扩展 ID 不同,启动 dsh web 前设置 DSH_KG_EXTENSION_ORIGINS=chrome-extension://你的扩展ID。只有显式设置 DSH_KG_ALLOW_LOCAL_ORIGIN=1 时才额外允许 localhost/127.0.0.1 来源,并返回 PNA 预检头;空 Origin 和任意其他扩展来源都会被拒绝。扩展路由还使用 endpoint allowlist,只开放 extract / task-status / task-cancel / list-models,不会暴露 document-load / graph-query / answer-graph / graph-commit 等 canonical 文档接口。
- 数据流:内容脚本(任意页面)→ chrome.runtime.sendMessage → Service Worker 写入 chrome.storage.session 并 chrome.action.openPopup()(Chrome 127+);弹窗读取选中文本后调用 http://127.0.0.1:3080/dsh-kg/extract,轮询 task-status 渲染知识图。DSH 服务地址可在弹窗底部修改并记忆(chrome.storage.local 的 kgBase)。

架构

┌─────────────── Host(Node 进程) ───────────────┐   ┌────────── Client(浏览器)──────────┐
│ extract / append-extract / task-status /        │   │                                      │
│   trajectory-extract / trajectory-status        │   │  浮动窗口(shell.overlay)           │
│   verify-graph (quick/standard)                 │   │    输入区(可收起)                  │
│   question-graph (node/edge/graph)              │   │    原文 ⇄ 知识图(宽高可拖)         │
│   fact-check (quick/deep, wikipedia evidence)   │   │    验证与质疑面板 / 修复应用 / 审计   │
│   graph-query / answer-graph (evidence IDs)    │   │    结构化检索 / 证据问答消费面板       │
│   split paragraphs (numbered)  ───────────────►│   │    外部事实核查面板                  │
│   serializeTrace(会话事件) ───────────────────►│   │    历史 / 诊断 / toast(悬浮)         │
│   append: 已有图节点清单注入提示词 ────────────►│   │  对话头部「知识图」按钮 + run 卡片启动条│
│   batches → llm.stream (typed retry ×2)        │   │  会话标签页「轨迹知识图」                 │
│   schema validate → merge (dedupe/warnings)    │   │    轨迹 ⇄ 知识图双向定位            │
│   task Map; busy lock; 2h purge                │   └──────────────────────────────────────┘
└────────────────────────────────────────────────┘

关键设计

- 内容单元编号即锚点:Host 与 Client 用同一算法先把每个空行块做结构分类(标题 / 列表 / 对话 / 表格 / 代码 / 引用 / 普通叙述),再按结构切分编号单元——标题与列表项各自成单元、对话每轮成单元、引用与代码按行组织;普通叙述按话题转换标记(但是/因此/例如…)与词汇话题漂移分组,组满约 120 字、单句超 180 字时按句边界/软标点继续拆,避免一个长单元挂太多节点标签。提示词要求每个节点直接汇报出处的单元编号;客户端据此确定性映射内容单元,不再依赖 LLM 逐字复述原文。
- 多批次全局重编号:每个批次的 AI 都从 n1 开始命名节点,Host 在合并前无条件重编号冲突 id 并同步重写边,避免长文档后续批次的节点被当成重复 id 丢弃。
- Evidence 自带 provenance,且关系证据必须证明关系本身:节点与关系的 canonical evidence 统一为 evidence[{ documentId, sourceId, chunkId, paragraph, quote }]。Host 在写入门重新验证 quote 确实存在于对应 source unit,并按 paragraph 对应的 source-version/chunk 补齐 provenance;无法认证的 quote 不会被包装成 evidence。相同 Node/Edge 在后续 source-version 再次出现时会合并 evidence,而不是丢掉后来的证据。仅仅证明两个端点分别出现过,不足以证明 supports / causes / infers 等 relation。
- 消费 API 只读 canonical、单次查询、输出有界:带 documentId 的检索/问答请求由 Host memory 或 SQLite 加载 canonical state,并用 expectedRevision 做 fencing;SQLite 一次完成 type/section/status/text 预过滤、全候选评分、有索引的 from/to relation 扩展、精确 source-unit 回填与可选 fallback,不再进行 SQLite → Host 双重检索。词汇候选按 (paragraph,node_id)、原文单元按 paragraph 做 keyset 分页并只保留 bounded top set,因此不会因为前 600 个常见词候选遮住后文精确命中,也不会因越来越大的 OFFSET 反复跳过旧页。响应把直接 matches 与扩展 graph 分开,优先保留直接证据,并限制节点、关系、evidence、原文及聚合 context envelope。
- 回答按 evidence ID 逐片段准入:Host 先认证节点、关系和 source fallback evidence,再分配不可由模型伪造的 evidenceId;模型输出 parts[{ text, evidenceIds }],Host 逐 part、逐句过滤未知/空引用,并用确定性词汇支撑、否定极性与 authority-status gate 拒绝「真实 ID + 无关/反向命题」、跨句限定词泄漏及未限定的未验证声明;通过后也不采用模型自由文本,而是从认证证据确定性渲染 part,再自行拼接最终 answer。这样 citation 不是事后给整段自由文本挂一个装饰性链接,而是每个被接纳命题的结构化准入条件。
- 生成即验收(Generate → Verify → Repair → Accept):validateGraphInvariantsHost() 是生成与快速体检共用的 deterministic truth gate。每个 batch 在 merge 前都会经过 schema normalize + invariant 检查;blocking invariant 会把 typed 错误回灌给模型做定向重试(最多 3 次),paragraph 等可确定问题由 Host 安全修复,最终仍不合格的边可安全省略,但无法安全修复/锚定的节点会让任务以 invariant_violation 显式失败。所有 batch merge 完成后还会再做一次整图 gate,只有 invariantErrors=0 才能写入 canonical graph / SQLite。生成审计同时统计 evidence-backed / candidate / unsupported claim;没有可认证 quote 的声明不会被标成 grounded。
- Anchor / Evidence / Semantic Entailment 明确分层:paragraph 只是 anchor,不能等价于 claim evidence。可在 source 中认证的 quote 才使节点进入 groundingStatus=grounded;只有 anchor、没有 evidence 的节点为 candidate,伪造/无法认证的 quote 为 unsupported。语义蕴含另由 entailmentStatus=verified|unsupported|uncertain|unverified 表示;当前 deterministic gate 只认证 provenance,不会因为 quote 存在就声称“节点 text 已被语义证明”。快速体检分别显示锚点覆盖、证据覆盖和语义已验证比例。
- typed 失败、不静默:CLI/进程失败、非 JSON、schema/invariant 不合法、队列忙碌、无模型等情况都有明确原因码与中文文案;无法安全修复的语义状态不会伪装成成功。
- 不猜偏移:锚点解析失败时节点在图/原文间不可回链,但绝不臆造偏移,统一暴露在诊断列表(anchor_unresolved:node:...)中。
- 轨迹图与正文图共用同一 canonical 生命周期:会话执行轨迹序列化为编号内容单元(用户消息 / 工具调用 / 工具结果 / AI 回复),每个事件记录 [start, end) 偏移。轨迹首次拆解产生 documentId/revision/sourceId;后续 append 只提交 sessionId + documentId + expectedRevision,Host/SQLite 读取完整 canonical graph 与持久化的 traceText/traceEvents 后增量追加。浏览器 localStorage 只保存轨迹 documentId/revision 引用,不保存整图/全文,因此 >800 节点重复追加也不会把不可见节点当作不存在。
- 增量合并(追加拆分):追加时把已有图的节点清单注入提示词,AI 只产出新节点、并通过引用已有节点 id 建立跨段关系边;宿主负责新 id 重编号(避开已有)、单元号偏移(对齐全文编号)与语义去重。同一 canonical Node/Edge 再次出现时会合并新的 provenance-rich evidence;append 始终受 base revision fence 保护。
- 验证以原文为唯一事实源:快速体检在 Host 本地执行(与 Client 同一套锚点匹配算法);深度审校按内容单元分批、每批只审相关子图,标准档先产生候选问题再由复核员二次过滤;无原文证据、置信度不足或目标不存在的 issue 在 Host 层直接丢弃;验证/质疑输入限制最多 800 个节点,避免恶意大图拖垮 Host。
- 修复不静默、可审计:AI 只提建议,用户点「采纳」才应用补丁;一键修复批量应用全部可自动修复项;每次应用写 graph.verification.auditLog。窗口化以后浏览器不再分配连续 canonical node id:新增节点使用 node_,Host/SQLite 仍会拒绝不可见节点 ID 碰撞。merge_nodes 通过 semantic operation merge_node(from→into) 交给 Host 在完整 canonical graph 上执行,因此窗口外 incident edges 会被重定向而不是静默删除。所有提交都受 expectedRevision + invariant gate 保护;blocking 修改返回 invariant_violation,并发冲突返回 revision_conflict。
- 任务可观测、有 deadline、可即时取消:进度实时可见(阶段 / 已运行时长 / 已接收字符 / 警告),所有长任务都有取消按钮。模型调用的 wall-clock deadline 同时覆盖 stream acquisition 与完整 iteration;timeout 与 cancelled 使用独立 typed 状态。取消 hook 在操作完成后移除,各 runner 在 finally 清理 activeTask;即使 provider 不合作,前台任务也不会被永久占住。
- 逐内容块无损 checkpoint:每个成功 chunk 都保存 nextBatchIndex、截至当前的完整语义图和任务启动时冻结的 baseRevision;append 还保存 baseSource / baseStaging。trajectory checkpoint 额外保存 traceEvents 与追加时的 baseTraceText/baseTraceEvents。无论通过 /extract 提交 checkpoint,还是 Host 重启后走 /resume-extract,恢复前都必须确认 canonical revision 仍等于该 frozen base;旧 checkpoint 不会被重新绑定到新 revision。常驻 /extract 还会在异步 revision lookup 前原子占用 busy slot,两个并发请求不能同时入场。已完成 batch 不重跑;checkpoint v2 不按 800 节点截断,并由 Host/SQLite 持久化;确定性失败不会自动续跑。
- 拆分后关系补全逐组恢复:每个通过确定性检查的关系组(包括有效空结果)保存到独立的 checkpoint.relationWeave 候选记录,绑定原文、基础图、本体与分组计划。Host 重启后按 runId 恢复,只重试未保存的组;写入失败立即终止,不把内存进度显示成已落盘。候选不会提前覆盖正式图,恢复后仍需独立语义审校。进度区和未完成任务列表显示已落盘组数。旧检查点兼容,但无法追溯修复前从未保存的关系候选。scripts/kg-weave-recovery-smoke.mjs 使用真实子进程强制终止、SQLite 写入失败及检查点篡改验证这些边界。已生成图上的持续补全仍按检索与审校完成的轮次提交正式图。
- 800 是视图预算,不是知识上限:Host/SQLite 保存全量 canonical graph;常驻模式的 document-load 直接在 SQLite 执行 LIMIT/OFFSET,子图查询只读取直接命中节点、bounded incident edges 与一跳邻居,不再先把整图 materialize 到 Node 内存。浏览器一次最多加载 800 个节点,提供上一页 / 下一页 / 指定页跳转与按节点 ID、文本、类型或章节查询。JSON/CSV 完整导出仍显式读取 canonical graph。
- 章节 / 候选审核视图:章节筛选只改变当前浏览器结果视图,不修改原始图;候选状态以 documentId | kind | nodeId 稳定键保存,保留原文 evidence 和回链能力。
- SQLite 候选层:src/kg-store.mjs 把图结果写入文档 / chunk / node / edge 表,并按节点类型生成带 evidence 的候选实体与候选声明;canonical revision 提交时会删除已经失效的候选,同时用稳定 candidate id 保留仍存在候选的 accepted/rejected 状态。用户也可以通过 CLI 更新审核状态。
- 可插拔声明抽取器:Host 可选读取 kgExtractor 服务;它实现 extractChunk(input),输入一个自有 JSON 内容块和已有节点 id,返回标准图对象或 JSON 文本。未提供时自动回退到当前 LLM 路径,因此动态插件和常驻包都不增加硬依赖。

数据契约

KnowledgeGraphDto { summary: string, source?, staging?, nodes[], edges[], warnings[], generation?, verification? }
GenerationAudit { invariantVersion, status: 'succeeded' | 'succeeded_with_warnings', invariantErrors: 0, sourceAudit, retryCount, collapseRetryCount, autoRepairCount, autoRepairs[], initial: { nodes, edges }, coverage: { attemptedBatches, repairedBatches, addedNodes, addedEdges, prunedNodes }, connectivity?, grounding: { groundedNodes, candidateNodes, unsupportedNodes, evidenceBackedClaims, candidateClaims, unsupportedClaims, entailmentVerifiedNodes, entailmentStatus } }
Source { id, documentId, title, chars, paragraphCount, chunkCount, sectionCount, sections[] }
Staging { sourceId, documentId, chunkCount, chunks[] }
Evidence { documentId, sourceId, chunkId, paragraph, quote }
Checkpoint { version: 2, taskKind, sourceId, documentId, baseRevision?, baseSource?, baseStaging?, traceEvents?, baseTraceText?, baseTraceEvents?, nextBatchIndex, totalBatches, graph / 无损 */, staging }
GraphView { nodes[ KnowledgeGraphBatch | JSON }
Node  { id, type, typeLabel?, text, quote?, paragraph?, evidence?: Evidence[], groundingStatus: 'grounded'|'candidate'|'unsupported', entailmentStatus: 'verified'|'unsupported'|'uncertain'|'unverified', documentId?, sourceId?, chunkId?, sectionId?, sectionTitle? }
Edge  { fromNodeId, toNodeId, relation, relationLabel?, evidence?: Evidence[], documentId?, sourceId?, chunkId? }

GraphVerification {
lastReport?: VerificationReport,
stale?: boolean,
auditLog?: [{ ts, action, targetId, detail, reportId, before?, after? }]
}
VerificationReport {
reportId, mode: 'quick' | 'standard' | 'question',
createdAt, model?, scope: { kind: 'full' | 'node' | 'edge' | 'graph', ids[] },
summary, metrics: { checkedNodes, checkedEdges, errorCount, warningCount,
suggestionCount, anchorCoverage, evidenceCoverage,
entailmentCoverage, paragraphCoverage },
issues: Issue[]
}
Issue {
id, source: 'local' | 'ai' | 'question',
severity: 'error' | 'warning' | 'suggestion',
category: 'grounding' | 'type' | 'relation' | 'duplicate' | 'contradiction'
| 'completeness' | 'summary' | 'other',
targetKind: 'node' | 'edge' | 'graph', targetId: string | null,
title, detail, evidence: [{ paragraph?, quote? }],
confidence: 0..1,
proposedFix: { action: 'none' | 'update_node' | 'delete_node' | 'add_node'
| 'update_edge' | 'delete_edge' | 'add_edge' | 'merge_nodes'
| 'update_summary', nodePatch?, edgePatch?, mergeIntoId?, summaryPatch? },
status: 'open' | 'accepted' | 'rejected' | 'applied'
}

FactCheckState { lastReport?: ExternalFactCheckReport, stale?: boolean }
ExternalFactCheckReport {
reportId, mode: 'quick' | 'deep', createdAt, model?,
summary, metrics: { totalClaims, supported, contradicted,
partially_supported, insufficient, unverifiable,
out_of_scope, supportedRate },
claims: ExternalClaim[], warnings?
}
ExternalClaim {
id, nodeId?, kind, paragraph?, quote, claim,
checkworthy: 0..1,
verdict: 'supported' | 'contradicted' | 'partially_supported'
| 'insufficient' | 'unverifiable' | 'out_of_scope',
confidence: 0..1, rationale?, correction?,
evidence: [{ id, provider: 'wikipedia' | 'rules', url?, title?,
snippet, domainAuthority }],
evidenceQuote?, status: 'open' | 'accepted' | 'rejected'
}

- 8 类节点 wire 类型与 12 类关系边见上文。
- 每节点优先携带 paragraph(段落编号,确定性回链)与 quote(原文逐字摘录)。
- verification / factCheck 可选,旧版本生成的历史数据没有这些字段时按未验证/未核查处理,完全向后兼容。

许可

MIT © cwbcheng

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入社群

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

DPharness QQ 群二维码,QQ 扫码进群
QQ 扫码进群
DPharness 飞书群二维码,飞书扫码进群
飞书扫码进群