跳到正文
GitHub·· 8 天前AI 评分38

DSH(DeepSeek Harness)Cordis 插件:把资料与 AI 轨迹拆解为双向定位知识图

cwbcheng/dsh-knowledge-graph

AI 导读

DSH(DeepSeek Harness)Cordis 插件可将任意正文、含文字/图示/表格的图片或 AI 会话执行轨迹用 AI 拆解成知识图,并在知识图与原文之间双向定位。它支持最长约 100 万字符书级正文、不超过 15 MiB 的可搜索 PDF 及 1–4 张图片上传,采用 8 类节点/12 类关系,并新增《学习观》本体(18 类节点+21 类关系)。

正文

中文 | English

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

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


它能做什么

  • 后台生成知识图:输入任意正文(章节、技术文档、学习笔记…),后台任务模式调用 LLM,完成后保存知识图。支持最长约 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。
  • 图片直接生成知识图与已有 Markdown 插图解读:工作台可一次上传 1–4 张 PNG / JPEG / WebP / GIF(单张不超过 6 MiB、合计不超过 16 MiB),支持纯文字截图、示意图 / 流程图 / 架构图、统计图、公式和表格,也可同时附带说明文字。Host 把图片交给 DSH attachments.saveImages() 验证并保存,再用多模态模型生成带图片范围的视觉转写;知识抽取器只消费这份转写。对于已导入 Markdown 文件夹且保留附件的知识图,在「解读与核对图片」中可搜索、筛选并勾选任意 1–4 张未解读图片,将转写追加为有来源标记的段落与候选节点,不覆盖原始 Markdown 或旧节点内容。逐图查看原图、转写、识别疑点与全图关联节点;超出当前渲染窗口的节点也可点击定位。结果页保留原图预览与 source.visualSource 回链。视觉转写可把箭头 / 连线、分组 / 包含、对象对应、顺序和具有图例语义的颜色 / 形状编码拆成独立关系单元;无法准确映射到内置 relation 的关系保留为原子 fact / claim,不强套错误边。AI 转写不是原书文字,也不能单凭文字引用证明像素内容正确;新增节点保持待复核,关键文字、数值、表格和连线关系须对照原图。
  • 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)作为有界软邻近偏好。这些关系集合与权重全部来自当前文档的本体,不在客户端写死。多条边共享节点或行间通道时,箭头入口、水平通道和垂直走廊分别分轨,并为密集的水平轨道保留更高的层间通道;相邻关系标签发生碰撞时会在可读距离内确定性错位;极端拥挤且无可用位置时默认隐藏标签芯片,悬停或选中对应关系仍会显示,避免线段、标签及箭头挤在一起。新用户默认使用分层布局,已有本地布局偏好保持不变。
  • 连通分量内的邻近压缩:换行只作为初始位置,不再把折行结果锁成不可跨越的层级。通过有轮数上限、确定性的二维优化,缩短按关系加权的边,同时保留推理顺序、主路径固定列、节点间距和行间布线通道,最后移除空行。垂直走廊按实际障碍区间搜索,不再依赖固定搜索半径。高连接度枢纽和跨分支关系仍可能需要较长的边;这只改变视图,不改写知识图数据和关系。
  • 双向定位:
    • 点击图中节点 → 弹出详情卡片(完整内容 + 原文摘录 + 定位按钮),并平滑滚动高亮到原文对应内容单元;
    • 点击原文内容单元编号或在编号上按 Enter → 图中居中聚焦并闪烁对应节点。大图中若节点不在当前窗口,会按已保存的段落编号读取目标所在分页,沿用每窗节点上限;工作台与轨迹页都支持,无需手动翻页。目标不在关系聚拢结果中时,返回主图窗口定位。定位前核对文档版本与原文摘录,后续选择会取消旧响应;没有对应节点时保留当前图。
    • 图中节点只展示前 4 行(超出以 … 省略),完整内容随时可在详情卡片中查看;
    • 锚点以 AI 直接输出内容单元编号为主(确定性索引,长自然段会按句子边界切分成多个编号单元),quote 精确匹配与 token 重合度兜底;无法回链的节点不猜测偏移,统一进入诊断列表。
  • 图渲染:SVG 画布 + 8 类配色 / 4 种可切换节点布局(图右上角下拉,选择记忆):自由布局(d3-force 开源引擎内嵌零依赖:碰撞防节点重叠、边-节点排斥防箭头穿节点)、环形布局、中心布局(中心枢纽 + BFS 环,边走折线:径向出线 → 外环弧 → 径向进线)、层级布局(边走直角正交折线:行间空通道 + 逐行避障走廊,线段保证不穿节点)/ 关系边带类型标签,且同源边按目标角度扇形弯曲(二次贝塞尔)/ 拖拽平移 / Ctrl+滚轮缩放 / 工具栏 − 100% +(50%–200% 步进 10%)/ 长按节点查看原文摘录 / 键盘可达。
  • 大图浏览性能:普通布局的平移与缩放复用节点及文字;「全部节点」总览按空间索引更新可见区域,可见范围改变时继续复用仍在视口内的节点、文字和完整摘录,只构造新进入的节点,适合画布仍显示全部节点。总览放大到 35% 起显示节点文字与原图预览;节点查找与原文定位覆盖完整图。加载时只统计一次关系度数,供所有节点测量批次复用;统计与文本测量均分批让出执行,保留取消响应。搜索面板关闭或查询为空时不提前规范化全部名称与摘录;首次文本查询只为所选类型的节点建立缓存,后续查询复用,图谱更换后失效。超过 200 节点的文本搜索按 8 ms 预算分批执行,期间显示「正在查找…」;改词、改类型、关闭搜索或更换图谱会取消旧任务,完成当前查询后才显示可定位的结果。继续缩小关键词或类型范围时只检查上次完成的匹配节点;删词、改变关键词或放宽类型时恢复完整搜索范围,取消中的部分结果不会进入候选缓存。切换节点通过相邻关系索引显示相关边;选中同一节点对的任一并行关系都会保持共享线条高亮。连续切换选中时复用显示状态不变的节点外框与完整可访问摘录;更换图谱、布局、来源图片、锚点或审校结果会更新对应内容,缓存仅覆盖当前视口。运行 node scripts/kg-graph-viewport-reuse-benchmark.mjs 1116e2d 可对照 12,000 节点在三种缩放下的跨界拖动、往返、窗口调整和缩放;比较完整节点内容,并报告包含缓存维护的元素创建、摘录读取及 Map 操作数。耗时包含计数开销,不含 DOM 与绘制,不作为 CI 速度门槛。
  • 图片来源查找性能:含图知识图按原图节点编号和视觉转写的段落范围查找来源,原文列表按段落查找插图,不再为每个节点或段落重扫图片清单。重叠转写范围仍采用原清单中第一张图片;跨段表格汇集各段插图,按原清单顺序保留独立来源记录。替换图片说明或转写状态后会刷新标记、插图与详情;段落编号、原文和来源对象保持不变。索引按范围边界及明确的段落引用存储,不展开长转写区间。可运行 node scripts/kg-graph-image-benchmark.mjs [基线提交] 和 node scripts/kg-source-image-performance.mjs [基线提交],分别对比首次场景与原文列表构造的图片记录读取次数和耗时;耗时包含计数器开销,确定性回归检查来源对应及只读性。原文浏览器回归可用 node scripts/kg-verification-ui-fixture.mjs --source-image-performance 启动隔离的 12,000 段 / 200 图样本。
  • 原文跨页定位性能:SQLite 用“无段落编号节点数 + 更早段落节点数”确定目标所在页,通过既有段落索引的两个范围计数;同段第一个节点、NULL 优先、分页上限及版本快照保持一致,不另建索引。运行 node scripts/kg-paragraph-rank-performance.mjs 可与原排名条件对照,--smoke 检查普通分页及随机、同段、稀疏编号数据的一致性。计时只覆盖排名 SQL,不包含窗口读取、诊断、HTTP、视图构造或浏览器绘制。
  • 长原文的窗口关联性能:翻页时按有序段落范围查找节点锚点,避免每个节点从原文第一段开始扫描;段落编号、空白间隙、段尾边界与完整摘录保持一致。「全部节点」也使用同一查找。可运行 node scripts/kg-paragraph-window-benchmark.mjs [基线提交] 对比 12,000 段的四个尾部窗口与全部节点,检查完整视图结果一致性,并分别报告未插入计数器的中位耗时和段落边界读取次数;耗时只涵盖视图建立,不含网络、布局或浏览器绘图。浏览器回归可用 node scripts/kg-verification-ui-fixture.mjs --paragraph-window-lookup 启动隔离样本。
  • 旧引用的关联性能:旧记录没有段落信息且引用无法直接定位时,前缀与后缀匹配先检查最长及最短片段,再按嵌套片段的长度二分查找,避免逐长度重扫原文;仍优先前缀,采用原来的最长命中和首个偏移,准确/规范化匹配及模糊回退不变。词语回退首次沿用原扫描,每段只分词一次;第二次回退将词语集合转换为词语到段落的索引并释放集合,后续按词语更新匹配段落的分数。单段词直接存段号,多段词存段号列表,每次查询清零并复用分数缓冲。直接引用不建立词语集合或索引;重复查询词权重、最小分数和同分采用首段的规则保持一致,状态不跨视图或文档保存。运行 node scripts/kg-legacy-token-benchmark.mjs [基线提交] 对比 12,000 段的 200/800 个旧引用、稀疏词、单条冷启动、前后缀命中和直接引用窗口,核对完整视图一致,分别报告未插入计数器的 5 次中位耗时及分词、匹配和分配次数;计时不含 HTTP、布局或浏览器绘制。单独运行 node --expose-gc scripts/kg-legacy-token-benchmark.mjs [基线提交] --memory-only 可比较第二次评分后的存活词语状态增量,显式 GC 的诊断不代表整页内存或瞬时峰值。node scripts/kg-verification-ui-fixture.mjs --legacy-token-lookup 提供尾部 200 个旧引用的隔离浏览器样本;--legacy-fragment-lookup 混合前缀、后缀及词语回退样本。
  • 引用规范化性能:空白或标点不一致的引用仍按原来的顺序匹配,规范化文本按连续保留片段复制,并保留每个 UTF-16 单位的原文偏移。空白只处理空格、换行、Tab 和全角空格;CR、其他 Unicode 空白、原标点集合及前导/尾随行为保持一致。每个视图最多建立三种原文形式,直接引用跳过规范化,已有段落信息时优先局部匹配。运行 node scripts/kg-anchor-normalization-benchmark.mjs [基线提交] 对比 12,000 段的三种规范化、中文/补充字符、单条/两条/200/800 条旧引用及局部/直接引用,核对完整视图和偏移一致;分别报告五次未插桩中位耗时及原文输出片段、映射单位和逐字符标点查询数,计时不含 HTTP、布局或浏览器绘制。node scripts/kg-verification-ui-fixture.mjs --normalized-anchor-lookup 提供三种规范化混合的浏览器样本。
  • 原文表格预处理性能:没有完整表格或表格超过原有长度上限时,跳过全文代码区域扫描;首次表格定位沿用原查找;第二次需要定位时,只检查一次段落范围是否有序且不重叠,随后用二分查找。单张表格不增加段落检查。异常或无序范围沿用首个重叠段落的旧规则。跨段表格、代码中的字面示例、原文偏移及段落锚点保持一致。运行 node scripts/kg-source-table-performance.mjs [基线提交] 对比 12,000 段、400 张表格及混合代码示例,核对完整分组及解析调用;七次未插桩中位耗时与边界读取/代码扫描计数分开报告。计时不含原生 HTML 解析、分段、HTTP 或 React/DOM 绘制。node scripts/kg-verification-ui-fixture.mjs --source-table-lookup 提供 400 张跨段表格和各 400 个行内/缩进示例的浏览器样本。
  • 轨迹原文关联性能:轨迹页为当前事件清单建立一次范围查找,选中节点或闪烁更新时复用;一个长事件拆成多段时,仍显示原事件类型和序号。替换事件清单时重建,空白间隙及旧记录的段落索引回退保持一致;无序或重叠的导入范围沿用原清单首个匹配。可运行 node scripts/kg-trajectory-event-performance.mjs [基线提交] 对比 12,000 段/事件的首次行构造及四次选中更新,计数器与计时分开,检查完整行内容一致。耗时不含 HTTP、知识图准备或 React/DOM 更新。node scripts/kg-verification-ui-fixture.mjs --trajectory-event-lookup 提供隔离的 12,000 段样本,首个事件跨三段,事件序号独立于段落编号。
  • 验证与质疑知识图:生成图后可以检查它是否忠于原文——
    • ⚡ 规则检查:本地规则即时检查(自环/悬空边、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 引用,因此切换标签页或刷新页面后会从已保存的知识图恢复,拆分进行中切走再切回会自动续接轮询;会话继续产生新事件后,可点 追加新事件 只拆解新增部分并在同一 revisioned document 上增量合并(跨事件建立关系边);轨迹事件列与图列的宽度、结果区高度均可拖拽调整并记忆。

新功能怎么用

先从左侧栏的「知识图」打开工作台,生成知识图,或从历史记录打开已保存的图。工作台分为四区,切换时保留草稿、查找结果和正在运行的任务:

  • 阅读知识图:对照原文与图,使用阅读导航,解读和核对图片。展开「阅读书签」可保存浏览位置;导出和知识图状态也在这里。
  • 查找与学习:查找知识、根据原文问答、对照跨书概念、完成学习练习。点击查找结果或引文,会回到阅读区并定位来源。
  • 检查与修正:检查当前窗口或全图、核对变化部分、复核问题并确认修复。章节候选确认和外部事实核查各自折叠。问题行的「查看图文」回到阅读区;节点详情的「质疑此节点」进入问题输入框。
  • 导入资料:输入或追加正文、图片、PDF、Markdown 文件夹。尚未生成图时直接显示输入区。

AI 模型在页头选择,知识分类方案和同时生成批数在「生成设置」中调整。AI 核对进度在各区均可查看;完成后点「查看检查报告」进入检查区。完整用语对照及维护要求见界面文案规范。

功能 入口与操作 会发生什么
核对变化部分 在「检查与修正」点「核对变化部分」,核对弹窗中可复用批次、待审批次、模型和最低请求数,再确认。 仅复用输入、原文、模型及审校规则依赖均未变化且已保存的历史批次;变化部分重新调用 LLM,本地规则仍检查全图。与「AI 全图原文核对」的全新审校不同。复用不等于免费或零请求,也不会自动采纳修复。需要已保存的 canonical 图和可复用的历史审校批次;没有可复用批次时计划会显示仍需全部审校。
问题组与批量修复 在「检查与修正」的「批量复核问题」中,保留「显示全部问题」可跨组核实当前筛选的下一批;也可按问题类型或原文选择一组。核实后先点「检查冲突与修改」,逐项查看判定及修改前后,最后点「确认保存本批处理」或「确认保存本组处理」。 同组共享图与原文上下文,但每个问题独立核实;批量仅接纳原文逐字支持的安全修复,其他结论留待单独处理。冲突项不会强行写入。保存是一次带版本校验的提交;若此后没有其他图修改,可撤销上一批/组保存,不能覆盖后续编辑。核实会调用所选模型,建议先用小批量。
阅读导航 在结果区点「阅读导航」,按来源章节进入,按「图中概念线索」筛选条目;点条目或「原文 P…」引文定位图与原文,可翻页或跳页。 给大图提供「章节 → 知识条目 → 可核对原文」的阅读路径。「概念线索」和阅读起点是从图派生的候选组织方式,不是作者亲自标出的核心论点;没有可核对引文的条目会明确提示。打开地图不改图、不调用 LLM。
联结模型工作台 在「阅读知识图」点「联结模型」,从全图目录按章节、关键词、概念作用或待核对状态筛选。查看输入、映射与条件、输出,以及规律、例子和原文。方向修改需先预览,再明确确认保存。 使用已有 connection_model、maps_between 及用户确认的可选模型结构。旧模型不会自动转换;未定角色、异常关系和错误示例保持可见,不从节点顺序或名称猜方向。阅读不修改图,保存有版本校验。
独立槽位、分支与配对实例 在模型详情点「核对结构」,分别整理槽位的概念、输入输出角色、单位和时间状态;同一概念可作为多个独立槽位。填写条件、映射、边界的来源身份与引文,按槽位和分支记录情境、状态及推测过程。「下上对照」按分支浏览实例,点击实例状态高亮对应槽位。原有图谱端点可另行展开,差异和异常不会被新槽位遮住。 每项更改须预览修改前后并确认,只更新该模型的 modelStructure,不自动添加关系边。原文引用必须匹配已存来源;用户整理、AI 建议与待核对内容明确区分。配对完整性与分支覆盖不代表规律已验证;映射是结构化文本,不执行公式或推测链。失败、切换与版本变化保留草稿,旧版本不能覆盖新图,删除被引用概念会被阻止。
待补充内容与原文选取 在模型详情点「待补充内容」,查看缺少的输入输出、分支条件、配对状态和来源记录;点击缺口进入对应草稿字段。尚无实例绑定时,先明确「补齐输入变量」或「补齐输出变量」,再填写空状态。分支字段可「从原文选取」连续片段,保留限定语与出处,预览后确认保存。 诊断覆盖该模型的全部已记录分支与实例,分页显示;不是正确性或学习掌握度评分。候选原文包含模型及相关材料上下文,不保证支持所选字段。原文选取不调用 AI、不自动补全或写图;替换现有内容须确认,编辑后旧预览失效。读取和提交均沿用已存段落身份,不因新版全文切分改变引用编号。旧 Host 缺少能力标记时明确禁用诊断与原文选取。
模型比较 在模型详情点「模型比较」,明确选择第二个模型;默认筛选共享概念端点,也可取消筛选搜索全图。并列核对输入、输出、完整联结表述、条件、材料和引文;「查看模型 A/B」打开完整材料,「挑战模型 A/B」进入对应模型的反例练习。 相同概念身份、已记录角色、单位与时间状态是结构比较依据,不是模型等价或矛盾的判定。同名但不同身份的端点单列,未定或重复关系不会被算作完整方向。已整理的条件分支可并排阅读,旧模型显示未结构化;不自动推断适用性,不建立类比边或推测链。
两步推测草稿 在模型详情点「两步推测」,明确选择第二个模型和两个分支,填写全部已知输入、预测、条件及应用过程;按独立槽位选择承接上一步的输出,分别记录含义、单位口径、时间状态与对象范围的核对依据。「检查推测缺口」标明停在哪一步,草稿可导出 JSON。 候选覆盖全图,仅按概念身份与已记录的输出→输入方向筛选,不代表相容、因果或可迁移。缺少任一输入、方向不明、单位或时间状态未定或冲突、错误示例、类型说明及已驳回模型会阻断;上一步有缺口时,其手填输出不能供给下一步。同名异身份不能直接承接,不自动换算、逆推、执行公式或合成概率。完整状态仅说明字段齐备,含义、对象与适用性仍是未独立核验的用户自述;限定语、字段来源与循环风险保留。仅缓存当前标签页的个人草稿,不写正式图谱或长期学习记录;切换第二模型需确认,旧版本保留文字但暂停检查,必须明确对照后换基准。
草稿导回继续编辑 已选择两模型的草稿即使尚未检查或仍有缺口,也可导出 JSON。「导入推测草稿」读取文件后先预览文档、模型、来源版本、情境和槽位数量,再明确确认替换当前文字;兼容已有检查结果导出文件。 文件最多 2 MiB;错误格式、文档或模型身份不匹配、未来版本及缺失模型不覆盖当前草稿。文件中的旧检查结果和模型快照不作为当前依据;只恢复可编辑文字,旧版本仍须明确对照后换基准。读取期间编辑或切换范围会取消过时导入,不自动检查、保存长期学习记录或修改图谱。
情境预测与反例挑战 在联结模型详情点「情境预测」,选择新情境预测或反例挑战。后者先写基准情境与预测,再写只改变的一项、保持不变的条件、改变后的预测和能反驳联结的观察。保存预测后显式展开原文,填写并保存复盘。 学习记录独立于正式图谱,保留当时模型与引文快照,最初预测和已完成复盘不可覆盖;两类练习的历史和标签页草稿分别保存。仅改标点或排版的情境变化会被拒绝,是否真正受控、是否构成反例仍未核验;边界外不适用不是边界内被反驳。不会自动打分、声称掌握或修改图谱。常驻 Host 支持持久保存,临时动态 Host 会明确提示持久化不可用。
我的理解 在联结模型详情点「我的理解」,独立填写输入判别、联结规律、输出判别、条件、边界与疑问,对照原文模型后保存;可关联已有预测或复盘,填写修改理由,追加修订版本。 复用学习记录存储,不另建个人图数据库;保留当时模型、字段来源与练习快照,不覆盖正式图谱、旧表述或练习。并发修订和图谱版本变化阻止旧草稿直接保存,重读后草稿仍在,须明确对照新基准。无来源或表述不完整仍可作为个人记录,不自动评对错、掌握或新颖性。历史与各类可选练习展示最近 100 条,最多关联 10 条。
渐构靶图 在「阅读知识图」切换「渐构靶图」,从概念、判别模型或联结模型建立个人靶图。上层整理输入内涵、规律与输出内涵,下层配对具体情境、全部输入、推测过程和输出;支持多个必要输入、多例指向同一输出,以及尚无例子指向的陪域取值。 表述、例子和修订独立保存为个人记录,不写正式图谱。预测须先保存再填写对照,保存后不能事后改写;可查看预测时的上层快照。草稿按文档、节点身份及图谱版本隔离,旧版草稿可重新打开但不能覆盖新版。个人判断、资料答案、观察记录和 AI 建议均不是独立核验或掌握证明。详见 渐构靶图。
验证结果记录 打开已保存的预测或反例挑战,记录真实观察、参考资料、公式或规则推导、AI 建议或个人复盘;填写实际条件、比较依据与自述诊断。真实观察须确认已发生并记录日期和时区;原文引用须先显式展开当时对照。结果可追加更正,修订个人理解时冻结关联预测的最近 5 条结果。 复用学习记录,绑定最初预测、来源版本与当时练习版本;所有来源仍未独立核验,不是自动判分、外部证实或掌握证明。更正不计作另一份独立证据;并发更正须明确改用最新基准,保存回应丢失可按同一请求恢复。来源更新后仍可补记旧预测的观察,但不算当前模型的验证,旧引文不能定位到新来源。外部链接不自动读取,AI 不自动调用;每次预测展示最近 100 条结果,有限快照明确标注。新前端连接旧 Host 会阻止结果写入。
模型学习记录 在模型详情点「学习记录」,查看按来源分开的比较计数,按情境预测/反例挑战、来源、比较或诊断环节筛选,逐页打开最初预测和具体结果。 统计完整历史,先折叠更正链再筛选与分页,每格按预测去重;不同来源和多个比较列可能重叠,不合计为独立证据、正确率或掌握分数。一致与不同并存时不选胜者。旧图谱版本与当前版本分开计数,自述未见不证明新情境。列表每页 20 次预测,结果预览最多 5 条;筛选命中的更早结果可直接定位,不受最近 100 条历史窗口限制。
诊断对应材料 在已保存结果点「查看诊断对应材料」,对照输入/输出角色、条件与边界或规律的当时材料,再点「带这次预测修订我的理解」,明确关联后编辑和保存个人修订。 按快照中的角色、材料类型与来源选取,不推断错误原因;尚未展开原文时引用仍隐藏,旧引文无法定位新来源。缺失材料明确提示,不自动补公式、调用 AI 或生成正确答案。关联不会替换已有草稿,也不静默保存;仍最多关联 10 次练习。
阅读书签 先调整当前搜索词、筛选、章节、关注节点、关系聚拢、布局或阅读地图,再回到「阅读知识图」展开「阅读书签」,输入名称并点「另存书签」。以后从下拉框选择并点「打开书签」;「更新书签」用当前状态覆盖它。 相当于当前文档的浏览书签,不是待办任务或另一张图。每张图最多保存 20 个;保存的是视图状态,不复制节点或原文。「删除」只删除书签,不删除知识图。图更新后重新打开会核查节点和章节,已失效的位置会清除并提示。
跨书概念档案 在「查找与学习」点「跨书概念档案」,选当前图的概念,查看同名候选或输入关键词点「查找对照概念」。核对各书的来源与原文引文后,勾选「纳入对照」,标注「相关,待辨析 / 不同用法、分歧 / 可能同义」,填写适用条件、时间及说明,再点「保存候选对照」。 保存一个可重开、编辑、删除的对照档案,不合并各书节点;同名只产生候选,不自动判为同义。来源表述是否忠实与现实中是否正确是两件事。来源图变化时档案会标记过期,需重新核对。
学习练习 在「查找与学习」点「学习练习」,选择「概念辨析」「机制解释」或「新情境应用」,阅读带原文定位的题目,填写回答;新情境题还需写一个不能照搬原文的具体场景。选自评后点「保存练习与自评」,可在「学习记录」中复盘。 练习从现有图和可定位引文派生,不是原文,也不自动判对错或证明掌握。缺少依据时对应题型不可用。回答、自评与原文知识图分开保存;图更新后旧练习保留但标为旧版。

联结模型目录的关键词也覆盖通过当前 canonical 概念与原文引用校验的已记录条件、规律和边界。新增字段搜索按同一字段内的完整短语筛选,只规范化全角、大小写与空白,保留运算符和箭头,不把 x > 3 与 x < 3 合为同一命中,也不把分散在不同字段或分支的词拼成一个条件。目录保留原文顺序、全图数量和既有章节/概念/角色筛选;响应中的 modelFieldMatches 最多列出 8 个分支/字段位置与声明的来源身份,余量明确,依据是 recorded_text_not_applicability,不代表适用性、正确性或掌握度。来源备注和实例不在这个目录搜索范围内;无效结构仍可按模型身份或标题找到并核对。

历史恢复、canonical 导出、联结模型目录、阅读地图和关系聚拢按完整 documentId 定位,不截取前缀、不去除首尾空白,也不合并全角或同名标识。这组只读入口的标识上限为 4096 个 JavaScript 字符,仍受各路由原有请求体预算限制;超限或类型错误明确拒绝,找不到完整标识时不会回退到前缀文档或客户端提供的图。候选列表也保留完整文档标识。本轮涉及的图提交、抽取、审校和个人学习记录入口没有扩大文档标识范围,仍限制为 160 字且无首尾空白;不支持的标识拒绝或报告未找到,不能截断后修改另一份文档。长标识文档的个人记录保存、任务视图和图片读取等其他入口尚未扩展,不应把只读恢复成功当作整个编辑流程已支持,也不能外推其他接口的身份契约。

以上视图、档案和练习都要求当前资料已保存为 canonical 文档。结构核对还要求 Host 返回对应版本的能力标记;新前端连接旧 Host 时保留阅读入口,明确提示版本尚未就绪并阻止结构写入,不把仅加载新前端当作完整部署。审校、核实和修复有模型费用或修改风险,先读计划与预览;阅读地图、任务视图、概念档案候选检索和现有图派生练习不需要模型调用。开发者另有审校质量基准和全图发现基准:样本由 Codex 复核,不是独立人工真值。隔离环境曾用 DeepSeek V4.1 Flash 对合成案例和一段公版原文实际运行并保留结果;这些小规模样本不能代表真实书籍的准确率,也不能把模拟预测当作模型成绩。

关系聚拢的文档版本、中心、各层邻接、分页顺序、节点内容和关联边来自同一 SQLite 读取快照。读取期间的更新或删除不会把新内容标成旧版本,也不会因另一份去空白后同名文档的版本而误报冲突;后续查询仍严格核查 expectedRevision,旧版分页不能接到新版图上。方向与层数仅表示已记录边的浏览范围,不认证因果、可逆性、条件成立或模型真伪。

界面一览

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

以下为早期图文对照截图,当前工作台入口按上面的四个工作区组织。

早期图文对照界面

┌─────────────────────────────── 浮动工作台 ───────────────────────────────┐
│ ● 知识图工作台                                                [ × ]        │
│ 知识图                                                                      │
│ 当前资料标题                          [AI 模型] [历史记录] [新建知识图]     │
│ [生成设置]                                                                │
│ [阅读知识图] [查找与学习] [检查与修正 · 待处理数] [导入资料]                 │
│ [原文与知识图]                                                             │
│ N 节点 · M 关系 [阅读导航] [阅读书签] [导出]                                 │
│ 原图 N 张 · 未解读 M 张 [打开图片节点] [解读与核对图片]                       │
│ [原文段落…带类型徽标]  ‖  [知识图 SVG…]  [− 100% +]  │ ← 可拖宽竖条         │
│ ─────────────── 可拖高横条 ────────────────           │                    │
└─────────────────────────────────────────────────────────────────────────┘

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

image

┌────────────────────────── 轨迹 ⇄ 知识图 ──────────────────────────┐
│ 拆解本会话轨迹:用户消息 / 工具调用 / 工具结果 / 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. 验证安装

  • 左侧栏底部、设置上方出现「知识图」按钮,无需打开对话;
  • 点击弹出浮动工作台,粘贴一段正文 → 生成知识图,任务完成后可阅读知识图;
  • 对话区顶部出现第三个标签页「轨迹知识图」(对话 / 轨迹 / 轨迹知识图),点击 → 生成会话知识图,任务完成后可阅读该会话的知识图。

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 新时会自动重建插件。端口被占用时直接报错退出,不抢端口。

每次启动会将插件的 lib 运行模块、package.json 和 bundle patch 固定到 $DSH_HOME/plugin-artifacts/dsh-knowledge-graph/<构建哈希>,profile 通过本地 link: 指向该份快照。正在运行的实例不再因开发目录的后续构建而提前更换客户端;只有下一次明确启动才同时加载新的 Host 和客户端。相同构建复用,旧快照保留,不自动清理。复制期间产物变化、既有快照校验失败或安装后未指向预期快照,均拒绝启动,不以包管理器退出 0 代替安装验证。

快照只固定本插件的构建代码,不复制资料库、学习记录、凭据、源码或整个 node_modules;已安装依赖通过链接复用,因此不是整个 Harness 与依赖的可复现发布包。安装需要 PATH 中的 pnpm;仅有 Corepack 时,启动器使用其已有 pnpm shim,不改全局安装。此保护须在使用新版启动器启动后才生效,已经运行的源码链接实例不会被自动迁移或重启。

可用 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. 在「导入资料」粘贴正文,或点 上传图片 选择包含文字、图示或表格的图片(可同时输入说明文字、可选填标题);选择支持图片的模型后点 生成知识图。图片生成后,原文栏顶部会显示可点击的原图画廊与视觉转写风险提示(输入区可收起;结果区高度、原文/图宽度比例均可拖拽调整并记忆); 对已导入的 Markdown 文件夹,在「阅读知识图」打开 解读与核对图片,选择支持图像输入的模型,勾选 1–4 张未解读图片并点 解读所选图片;不必按原书顺序处理。可按名称 / 图注搜索,或筛选「未解读」「已转写 · 待核对」。「选择本页未解读图片」选中本页前四张未处理图片,不会自动提交或连续跑完全部图片。此操作会追加 canonical 图版本并使旧审校报告过期,不会改写原始 Markdown;PDF 中未作为附件保存的图片不在本功能范围内。
  3. 摘要 / 图出现后,点图中节点查看详情卡片(完整内容)并定位原文,或点原文段落聚焦图中节点;
  4. 在 「查找与学习」 选择「查找知识」或「证据问答」:按关键词、类型、章节找节点,或根据已保存的知识图和原文提问;点击结果或引文会回到阅读区,定位节点、关系与原文证据;
  5. 在 「检查与修正」 点「当前窗口规则检查」检查当前节点窗口,或点「AI 全图原文核对」以原文为证据审校全部节点与关系;「外部事实核查」另用外部证据核查原文本身。问题清单可跨组分批核实、预览后保存安全修复;「查看图文」回到阅读区核对。节点详情的「质疑此节点」和关系详情的「质疑此关系」直接进入对应提问框;
  6. 在「检查与修正」展开「章节筛选与候选确认」,选择章节以筛选阅读区的图和原文;对候选实体 / 声明点「已接受」或「已拒绝」,点击候选卡可回链原文证据;
  7. 想继续扩展图:在「导入资料」粘贴下一段资料,点 追加资料(或直接选中聊天消息里的文字自动追加)。新增节点与已有节点建立跨段关系,全文段落统一编号,历史记录原地更新;此前验证结果会自动标记为过期,可重新验证;
  8. 用「历史记录」回看之前的拆分(自动保存最近 20 条,可单删 / 清空);任务进行中关窗或刷新,重开窗口会自动恢复轮询;
  9. 对话区切换到「轨迹知识图」标签页,点 生成会话知识图 生成会话轨迹知识图;轨迹图也提供相同的结构化检索与证据问答入口;点击轨迹事件在图中聚焦节点,点击节点查看完整内容并滚动到对应事件;结果在切换标签页 / 刷新后自动恢复,拖拽中间竖条调两列宽度、拖拽下方横条调结果区高度。

核对图片解读结果

原图本身也是知识图节点。新生成的图片知识图或 Markdown 图会保存 image 来源节点;旧资料在「阅读知识图」点击 打开图片节点,即可把已保留的图片加入 canonical 图并显示图片子图,不调用模型。重复打开不会重复建节点或增加图版本。第一次入图会增加版本,已有审校报告的版本状态随之更新,但不会改写原文或已有知识节点。

图片节点直接显示原图缩略图,可以放大查看;在图片详情中点击 定位图片节点,可聚焦该图片及其关联节点。视觉转写产生的内容节点通过 解读自图片(visual_source)连接到原图。未解读图片也能独立入图,但不会把附近正文自动认作图片内容。同名文件不是同一图片,不能按名称自动合并。

在「查找与学习」的节点类型筛选中选择 图片,可以检索全图中的图片节点并点击定位,不受当前图窗口限制。

image 和 visual_source 是受管理的来源记录,不扩大模型可生成的语义本体。来源连线不表示支持、因果或真实性认证,不能通过普通命题编辑、删除标签或关系合并来改写;内容节点改换转写来源后,对应连线会同步更新。图片节点和来源引用随完整 JSON 导出保留,图片字节仍由附件服务保存,不内嵌进 JSON。PNG 导出会嵌入已加载的图中缩略图;未加载的图片会明确阻止导出,需先查看相关图片子图。

在 解读与核对图片 点击一张图片,可放大原图、查看带段落编号的完整转写与识别疑点,再点击关联节点回到图文对照。节点数量来自完整 canonical 图,不受当前 800 节点窗口限制;没有抽出节点时明确显示「已保留转写,但没有关联节点」,不会把转写成功等同于建图成功。直接上传的图片也可在此核对。

  • 「已转写 · 待核对」不代表图片内容已经正确识别,更不是人工确认。原图中的否定、脚注、单位、箭头方向和分组边界仍需核对。
  • 在图片详情点击 核对转写,对照原图和完整转写,选择 与原图一致 或 发现转写问题,填写核对备注,再勾选 已对照原图检查转写内容 并点击 保存核对。发现问题时备注必填;原图未加载成功时不能确认。核对不会调用模型,也不会自动修正转写或节点。
  • 图片清单和筛选会区分 待核对、人工核对一致 和 有转写问题。常驻 Web 的记录保存在独立 SQLite 表中,刷新后保留;动态 Host 的记录随当前 Host 生命周期保留。可点击 撤销核对 恢复待核对状态。原图、转写、图注或识别疑点变化后,旧核对会失效;其他节点的编辑不会把图片核对结果改成语义验证。
  • 图片核对只记录用户对照原图后的判断,不等于节点或关系的真实性认证,不更改 canonical 图、原文、审校报告或图版本。不同窗口同时保存时会拒绝覆盖较新的记录;可点 刷新核对状态 后重新确认,未保存的备注会保留。
  • JSON 语法错误、重复 / 缺失图片编号、非法内容单元、超出长度或数量限制、输出 token 耗尽及只有思考没有结果时,本次转写会整批拒绝。运行中的任务会带着校验反馈重新提交同一组原图,转写最多尝试 3 轮;每轮均计入模型用量,不会靠补标点、拼接残缺结果或静默截断来伪装成功。只有完整结果通过校验后才开始生成节点。
  • 连续失败后会显示「图片视觉解读失败」及尝试次数,已有图、图片解读状态和勾选保持不变,可再次提交,或减为单张后重试。鉴权错误、不支持图片和任务取消不会因格式重试而重复调用。终态失败任务不会自动重启;运行期间刷新只重新连接原任务,不额外提交任务。读取图片结果失败时,可点「重试读取」;该操作不调用模型。
  • 对已有知识图解读图片时,顶部显示任务进度,图文阅读、原图放大、检索和旧审校报告仍可浏览;「运行详情」保留完整进度和暂停操作。任务进行中或暂停时,改图、追加和新 AI 请求暂不可用,避免与待合并结果冲突。完成后自动更新已保存的图,不强制切换当前标签页。正文追加和关系补全也遵循这一方式;首次建图尚无内容时仍显示进度页。
  • 放大原图后的「定位原书插图」返回原图在书中的位置,而不是追加的 AI 转写段落;查看转写时则使用其段落编号。

暂停与继续任务

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

  • 收尾期间显示「暂停中」,检查点保存并释放运行锁后才显示「已暂停」。保存失败会明确报错,不把未保存的结果当作成功暂停。
  • 刷新页面或重启 DSH 后仍保持暂停,可在「未完成任务」列表点击 继续任务;后台自动恢复逻辑不会唤醒主动暂停的任务。继续仍校验原文、本体与知识图版本,不覆盖已被其他操作修改的图。
  • 暂停与取消、删除相互独立。无持久化检查点的任务,以及最终结果正在提交的短暂阶段,不显示暂停按钮。已有图上的独立「持续补全关系」任务仍使用下节的「停止查找关系」和已保存游标恢复机制。
  • AI 原文核对也可暂停:已完成的批次及其独立复核结果逐批落盘;暂停中止在途请求,重启后只有点击「继续检查」才会重跑未完成批次。继续时沿用原模型和审校输入,并检查知识图版本。取消审校不会伪装成暂停,也不能从已取消任务继续。
  • 若审校完成时浏览器已关闭,报告仍保存在任务检查点中。「可恢复任务与报告」会显示尚未附加到知识图的报告,点击「保存检查报告」即可按原图版本提交;图已被修改时明确拒绝自动覆盖。已成功附加的报告不再出现在恢复列表。

持续补全关系

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

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

已有正文知识图至少包含两个节点时,可点击 继续查找关系(最多 N 批)。默认勾选「连续查找关系」,预算为 3 批,可改为 1–20 的整数。Host 检索未覆盖主目标、独立审校候选关系,并分批保存;达到本次预算或本轮覆盖完成即停止,不再默认承诺持续到本轮完成。取消勾选则固定只检索 1 批;图已经连通也可以继续检索。

  • 建图表单中的「查找关系批数上限」也约束首次抽取、正文追加和图片追加之后的关系检索,UI 默认 3 批;它不限制正文拆分或视觉转写等步骤。非法、空白、非整数或越界输入会提示并禁用对应提交按钮,提交回调也会在发请求前拒绝,而不是静默截断或修正预算。
  • 一批不等于一次模型请求。 每批最多检索 4 组候选节点,可能另有重试、证据检查与逐条语义审校请求。批次预算不是 token、总模型请求次数或费用上限。
  • 已有图的补全任务通过原文证据检查与独立语义审校后,将关系和检索游标一起保存。首次抽取/追加的候选检查点不等于正式图已保存:进度区明确区分「已记录检查点批次」与审校后提交的批次。
  • generation.relationCompletion 与运行中的 progress.completion 记录 maxBatches、completedBatches 和 stopReason。budget_exhausted 表示达到本次预算,不表示本轮查找完成;coverage_complete 仅表示本轮主目标已经覆盖;single_batch 表示单批停止。旧记录缺少预算或停止原因时会明确标为未记录,不推断为完成。
  • 关闭窗口或刷新页面不会停止 Host 中的任务,重开工作台会恢复进度。点击「停止查找关系」保留此前已保存的批次,当前未提交批次不会写入。
  • 常驻插件使用 SQLite 保存游标。DSH 进程重启后,打开该历史知识图,再点击检索即可接着已保存进度执行;不会自动恢复付费模型调用。动态插件没有 SQLite 时,进程内状态不能跨进程恢复。
  • 本轮主目标检索完即停止。覆盖完成不代表所有可能关系都已找到,也不证明哲学或其他语义正确;只有再次点击 新一轮查找(最多 N 批) 才会开启新一轮模型调用。合法的空关系结果也计入检索覆盖,不为凑数添加关系。
  • 模型失败、审校不可用/未完成或知识图版本冲突会停止任务并提示原因。已经提交的结果保留,不会覆盖其他操作的修改;未通过独立检查的发现候选不进入已保存的图,不能仅发一条 warning 就保留为正式关系。
  • 首次建图的关系组若返回非法/未完成结果,会保留 v3 关系检查点并以 relation_weave_failed 停止任务,不能跳过缺失组进入后处理或发布正式图。恢复时只重试未完成的发现组,不重新支付已缓存成功组的发现请求;缓存候选仍须接受独立语义审校。合法 edges: [] 与真正孤立的有效事实不因此失败。
  • 审校遇到明确的传输中断或临时服务错误时,等待 3 秒后重试原批次一次(限流等待 30 秒),等待期间可取消。仍失败则保存待审候选并显示实际原因;继续时先审这些候选,再检索剩余节点。认证失败不自动重试,语义驳回也不会通过反复重试变成接纳。
  • 输出截断不原样重试,也不接纳半截 JSON。 关系发现遇到 output_truncated 时,将该组的有向端点/关系类型输出域确定性二分;子请求保留原组的完整节点、上下文和证据,结果必须属于该子域并继续通过证据与独立语义审校。只在原组所有子任务完整完成后增加该组的主目标覆盖;合法空结果也可完成子任务,部分成功不伪报整组完成。独立关系审校遇到截断则有限拆分候选批次,不能跳过审校入库。
  • 每次显式任务由 Host 发起的关系发现与独立关系审校合计最多 128 次请求,拆分深度最多 20;实际调用前共享扣减,真实 LLM 路径的内部停滞重试也逐次计入,认证缓存回放不扣额度。额度耗尽只停止新请求,已预约的并发请求可在完整验收与版本检查后保存候选缓存,再以额度耗尽结束本次任务;用户取消、持久化失败或版本冲突仍中止请求,不接受晚到结果。达到机制上限或最小子任务仍截断时明确停止,并保留可恢复记录。这是请求安全上限,不是 token 或费用预算,也不约束正文抽取等其他模型调用或外部适配器自行发起的隐藏请求;不会自动增加模型输出上限或更改模型设置。
  • 常驻 SQLite Host 另外保存当前版本的关系补全子任务与审校恢复记录,绑定正文、本体、基础图和 revision。后续手动继续时只请求缺失子任务;已有正式关系和覆盖游标不回滚。正式批次提交与对应恢复记录清除在同一事务中校验,取消、检查点保存失败或版本冲突不会覆盖用户的新修改。存在未消费的发现检查点时,普通补全先恢复原发现,再统一审校旧待审候选与新候选;显式 reviewPendingOnly: true 则拒绝跨过该检查点,不会静默扩大付费请求范围或清掉已付费缓存。动态 Host 未提供可信存储适配器时明确标为进程内暂存,不能宣称跨进程恢复。旧 v1/v2 组检查点和 v3 批检查点仍先验证绑定、完整性与证据再回放,不因降低全局分组常量而失效。
  • 已认证的最小域或深度上限截断在下次默认继续时不会重新付费发送同一载荷。若提高本次 relationSplitDepth 后可继续拆分,直接沿已知截断生成子域,不重付父请求;仍不可拆分时需要主动选择另一 model,或在 relation-retry 明确传入布尔值 retryTruncatedLeaf: true 承认可能重付该叶。该参数不绕过请求/深度上限、证据检查或独立审校,也不是自动续跑许可。

两种 Host 入口的 extract、append-extract 与 relation-retry 接受数值参数 relationBatchBudget(整数 1–20,非法值在模型调用前拒绝)。省略时,初始抽取/追加 API 默认 1 批;relation-retry 的 continuous: true 默认 3 批,其余默认 1 批。UI 显式传入所选整数,取消连续模式时传入 1。relation-retry 仍须传入 documentId 和当前 expectedRevision,省略 continuous 时保留单批默认行为。API 可用 relationRequestBudget(整数 1–128)和 relationSplitDepth(整数 0–20)调低本次关系请求或拆分上限,不能突破 Host 的硬上限;省略时分别使用 128 和 20。这两个新安全参数显式填写时必须为数值整数,null、字符串、分数和越界值均在创建任务/调用模型前拒绝。仅 relation-retry 的 retryTruncatedLeaf 接受可选布尔值(默认 false);true 是针对已知截断叶的有意识新尝试,不是清除全部成功缓存。

无密钥截断回归见 kg-relation-truncation-smoke.mjs:使用 mock 模型、临时 SQLite 和生产 HTTP 入口,不连接实际图或真实模型。旧 v1/v2/v3 检查点回放由 kg-relation-budget-smoke.mjs共同验证。

npm run test:kg-relation-truncation
# 仅执行源 Host,不要求先构建 lib:
node scripts/kg-relation-truncation-smoke.mjs --dynamic-only

结构质量诊断与只读内容层

结果上方非折叠区域显示 图的连接情况:正文节点/关系数、孤立节点及比例、最大连通簇大小及比例、孤立概念锚点、背景说明节点数和本轮关系检索覆盖。孤立概念可定位回原文核查。这里有三类不同问题,不能互相代替:

  1. 确定性抽取验收:节点与边的格式、引用、证据定位等机器可检验约束。
  2. 结构质量:图是否碎片化、概念锚点是否孤立、重点检索主目标是否尚未覆盖。
  3. 语义正确性:命题与关系是否确实由原文支持,是否把同主题、类比或条件规则误当作互推或物理因果。

因此,「格式与引用错误 0」不意味着图结构健康;「暂无结构警报」不是语义认证;「本轮查找已覆盖」也不等于所有关系已找到。结构提示是建议,不阻止合法独立事实保存,不要求强行连通,不按同主题自动添加边。正文至少 8 个知识节点时,孤立比例达到 40% 或最大连通簇不足 20% 会提示碎片化;孤立概念锚点另行提示。这些阈值不是验收门槛。

诊断来源明确区分:

  • graph.graphStructureQuality 是 Host 对当前载入版本的 完整知识图生成的诊断;历史转发为 graph.view.graphStructureQuality 的形态也兼容。它不受 800 节点窗口、章节筛选或画布显示层影响。
  • generation.structureQuality 是生成时快照,不是编辑后的当前图实时诊断。旧 Host 未提供全图诊断时,只有确实完整加载的图才能在客户端只读计算;截断窗口或查询子图只显示快照标签,或明确提示全图尚未评估,不用窗口中的孤立比例评价全图。
  • 检索覆盖中的 totalTargets、searchedTargets、remainingTargets 指被作为重点检索主目标的记录,不是曾进入模型上下文的节点数;旧记录可能包含背景说明目标,不能直接等同于正文节点数量。缺少/不一致的覆盖记录表示未评估,未知计数不是 0;complete 仍不证明语义正确。

画布上方的 图谱显示层(只读) 提供「全部」「正文内容」「版本与来源」,默认全部。仅筛选 GraphCanvas 的展示,不改变原文、本体、检索/编辑使用的 canonical 数据,不把投影写回知识图;边的选择、质疑和删除仍映射回原来的边对象及索引。正文与背景间的跨层边只在全部层同时呈现两端时显示。图像节点不参与知识结构连通性指标,但显示层保留属于该层的原图节点对象。原文点击、外部定位或定位被筛选隐藏的节点会恢复全部层;普通可见画布节点选择不会重置所选层。

内容层优先使用合法 contentLayer: "main" | "source_context"。旧图没有显式标记时,按所属章节与明确的编辑说明标题保守识别,例如「版本说明」「底本说明」「校勘说明」「转写说明」「来源说明」;普通正文中出现「版本」「来源」「年代」等词,以及笼统的「序言」,不自动归入背景说明。旧图默认全部展示,不自动迁移、删节点或改正文/本体。

无密钥 UI 回归见 kg-generation-structure-ui-smoke.mjs:直接读取客户端源码,用 stub h、只读 source helper 和 inert Host 执行快照与回调断言,不依赖生成 bundle、模型密钥或真实模型调用。

node scripts/kg-generation-structure-ui-smoke.mjs

知识图消费层

前端使用

生成正文知识图或轨迹知识图后,下方会出现共享的 「查找与问答」 面板:

  1. 查找知识:输入关键词,并可叠加节点类型与章节筛选;返回列表只表示直接命中,关系邻居保留在响应子图中作为上下文,不会伪装成直接命中。
  2. 证据问答:输入自然语言问题,Host 先做有界节点召回、最多两跳关系扩展和原文段落 fallback。模型先写简洁解释,Host 逐句检查证据 ID、词汇与数值,再单独调用模型核对每个命题是否被所引原文支持;未通过的句子退回原文摘录。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,不会静默丢弃后退为全图查询。
  • types / relations 按文档自身的 canonical 本体校验。《学习观》文档可筛选 connection_model / factor_material 等 18 类材料及 maps_between / states_mapping 等 21 类关系;未标本体的旧文档仍使用命题本体。受管理的 image / visual_source 在两种模式均可筛选。请求自带的 ontology / graph 不能替换已保存文档的本体;常驻校验与检索共用同一个 SQLite 读取快照,非法值或超过 40 项的列表整体拒绝。
  • relations 限制返回/扩展的关系类型;direction 为 both | in | out。relations 也可单独作为 selector:Host/SQLite 会先从匹配关系的端点播种直接候选,而不是从文档开头任取节点;没有匹配关系时返回空结果。存储边方向不等于模型输入/输出角色:maps_between 的角色仍由 role 记录,缺失角色不会被推测补齐。
  • matches 只包含直接命中;graph.nodes/edges 还可包含 0–2 跳邻居。直接命中的原文单元优先于邻居证据进入预算,预算截断量通过 metrics.sourceRefsOmitted 暴露。
  • 关键词也检索 connection_model.modelStructure 已记录分支的 condition / mapping / boundary 文本,不要求把条件复制到模型标题。只解析通过形状契约的上述文本,不搜索来源备注、实例、任意扩展字段或 JSON 序列化内容;未知角色、假设、错误示例和冲突来源仍可被发现,不因此获认证。命中记录的 modelFieldMatches 最多给出 8 个分支/字段位置及声明的来源种类,余量明确,basis: recorded_text_not_applicability;部分关键词跨字段命中不变成完整短语或条件满足证明。现有客户端可以据关键词找到模型,但本轮没有新增字段命中高亮界面。
  • 响应包含 documentId、revision、matches、有界 graph、可回链 sourceUnits 和 metrics,不返回完整 sourceText。动态与常驻模式都对公开 node/edge/evidence 做字段与长度投影,sourceUnits 不再重复携带 quote 数组,并对聚合上下文设置硬 envelope;metrics.contextChars/contextBudget 可用于观测。
  • 检索中的文档、节点、端点、来源、块及章节 ID 是不透明身份,完整保留,不按 160 字前缀合并或定位。超长身份使直接记录、来源元信息或公开响应超过既有预算时返回 limit_exceeded,不改变正式存储,也不返回看似可用的截断身份。此保证限于消费检索与问答读取,不扩大其他学习或写入 API 的身份长度契约。
  • 引用及后续问题也保留完整目标 ID;问题中的 ID 以 JSON 字符串表示,不删除中文或特殊字符。完整身份不能放入 600 字问题预算时,省略这条后续问题,不使用短前缀或无法绑定目标的相对指代。
  • 当前硬上限:查询 600 字、直接命中 40、节点 160、关系 480、跳数 2、原文单元 80、原文文本 24000 字;graph context 另有约 384000 字 envelope。调用者给出更小的 maxNodes/maxEdges 时也会严格遵守。
  • modelContexts 是单独的有界模型记录,最多检查已返回节点中的 8 个模型,合计不超过 48000 字且不扩大原有总 envelope。recorded_core 仅表示记录的独立槽位和全部条件分支已读取、身份与引文可在同一 canonical 快照内匹配,不是语义正确、事实成立或掌握证明。同一概念的多个槽位、未知角色、单位、时间状态、内容身份、限定语和 source/user/AI/unknown 来源保持原样;概念引用不占用或扩大 graph.nodes 的窗口。具体实例不在这个核心投影内,examplesIncluded: 0 / examplesOmitted 只说明核心范围,完整实例仍从模型详情读取。
  • modelExampleContexts 单独读取已返回完整核心的成对实例,最多 8 条,每个模型按存储顺序检查前 2 条;合计最多 12000 字,与核心共用原有总预算。情境、独立槽位绑定、分支、过程和来源整条保留,单条超过 8000 字或预算不足则整条省略,不裁掉必要输入。全局与分模型计数区分包含、省略、实际检查、无效引用和预算省略;未检查的实例不能假定有效、覆盖全部分支或不存在。核心未读取时不返回无法解释角色的实例。
  • 实例 fieldCheck 只报告缺失绑定、未知角色、未指定分支和过程是否已有文字,basis: recorded_fields_not_applicability,不判断条件满足、单位相容、计算正确或事实成立。source/user/AI/unknown 是声明的材料来源,不是观察结果认证;source 引文也必须在同一快照的实际原文中完整匹配才有引用入口,超出引用长度的引文不经截断获权。问答把实例与其完整核心作为一条 JSON 接纳,若放不下可保留完整核心并明确省略实例,不混配模型;这些已含输出的材料不是未见题或新情境验证,也不自动写学习记录。
  • 单个核心超过 12000 字、引用失效或整体预算不足时,不裁掉必需输入、分支或限定语:分别返回 omitted_budget / invalid,没有结构则为 not_recorded;超过 8 个的模型通过 omittedModels 报告。字段来源引文补入实际原文读取,只有 source 身份及当前返回原文中的匹配引文可进入问答引用目录。个人或 AI 字段不能独立成为来源证据。问答的 24000 字提示词预算也按整条模型 JSON 接纳或省略,并单独说明省略量,不执行公式、逆推或模型链。
  • 常驻模式在 SQLite 中一次查询就完成候选排名、关系扩展、精确 document_units 回填和可选 source fallback,不再先查 SQLite、再把结果交给 Host 做第二次检索/重组。词汇候选和 source fallback 使用 keyset 分页,避免随页码增长的 OFFSET 重扫;queryId 包含全部规范化 selector 与有效预算。
  • 结构化分支搜索用同一快照内的分批模型候选和有界排名;不把仅被检查、没有文本命中的模型计入词汇候选总数。整图搜索及 canonical 类型/章节/状态筛选保持,超过首个候选页的精确匹配仍可排在前面;不新增数据库迁移或长期索引副本。
  • expectedRevision 与 canonical revision 不一致时返回 revision_conflict,避免把旧 UI 状态与新图混用。抽取、重新抽取、追加与 checkpoint 恢复也会记录启动时 revision,并在发布 canonical replacement 时执行同样 fencing。
  • 新 SQLite 连接若未设置锁等待,默认提供 2000 ms 的有限 busy_timeout,在建表与迁移前生效;调用者明确设置的非零超时保持不变。短时独立读写锁可等待释放,但持续锁仍报错并回滚,原始 revision 条件不自动刷新,不在应用层反复重放写入;不更改日志模式或降低持久化门禁。

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": "根据这份资料:\n恢复要依靠检查点。",
  "answerStyle": "natural",
  "parts": [
    { "id": "part-1", "text": "恢复要依靠检查点。", "evidenceIds": ["ev3"], "mode": "natural" }
  ],
  "citations": [
    {
      "id": "ev3",
      "targetKind": "node",
      "targetId": "n12",
      "nodeId": "n12",
      "paragraph": 8,
      "quote": "恢复依赖检查点。",
      "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 以保留证据来源,但不直接包含像素字节。
  • image-inspect 是只读接口,必须提交匹配的 expectedRevision,并检查图片的文档归属。它返回该图片的转写和每页最多 50 个关联节点,不包含原始图片字节,不调用模型,也不改变图谱或审校状态;版本冲突时拒绝混合旧图片与新节点结果。
  • 图片证据的可回链文本来自模型生成的 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。通过初筛的草稿会接受一次单独的逐句语义核验:核验输入只含问题、草稿和对应的已认证原文 quote;只有核验明确判为 supported 且返回的 evidenceId 属于该草稿时,模型写的自然解释才会展示。核验缺失、格式错误、拒绝或超时时,该 part 只展示 Host 从已认证引文生成的原文摘录,标记为 extractive;所有 part 都无法准入时降级为 insufficient。answerStyle 区分 natural、mixed 和 extractive,每个 part 保留 mode 与回链引文。Host 在回答外统一注明“根据资料”,不把 grounded 或模型自评置信度当作外部事实验证。insufficient/out_of_scope 只返回固定语义文案;追问查询由 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 统一下调;未设置时保留各阶段既有预算。

Chrome 扩展(划线拆图)

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

  • 源码在仓库 extension/ 目录,零依赖打包:viewer.js 由 scripts/build-viewer.mjs 从 src/index.client.js 切片生成(d3/*.js 为内嵌 d3 模块的独立文件——MV3 扩展页禁止 eval,popup 用 <script src> 预载后 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                │   └──────────────────────────────────────┘
└────────────────────────────────────────────────┘

关键设计

  • 层级布局先检查节点原位置:固定推理主干后,若节点原位置满足行间距,直接保留,不再创建和排序备选位置;冲突时按原顺序查找备选,并复用同次占位不变期间的失败原位检查。非有限坐标或尺寸保持原查找,行成员、固定主干、严格 18 间距与更新顺序不变。node scripts/kg-layered-row-origin-benchmark.mjs [--smoke] 用冻结的 8243d4a 重排算法对照当前完整布局:800 节点树图该阶段排序 64 → 0、链图 47 → 0;拥挤多分量图 3 → 3。直接输入的 800 节点无冲突行候选值 639,999 → 0,碰撞访问仍为 319,600。计数包括准备和新增判断,仅表示行重排工作量,不推断整体时延或内存收益。187 组直接对照验证异常尺寸、混合 / 重复 ID、符号零、严格间距和连续移动;完整引擎核对坐标、分量成员身份及顺序、每次选择与原始进度,另检查实际 Worker、取消和其他布局不变。--smoke 接入完整测试与 CI;真实浏览器夹具为 node scripts/kg-verification-ui-fixture.mjs --layered-origin [--client-ref=8243d4a],包含连续推理主干与并行关系,可在相同字体和 Blob Worker 下比较。

  • 局部关系定位复用同层清单:例子、定义、包含与类比等关系尝试靠近锚点时,复用已建立的同层节点清单,避免每个候选位置扫描整个组件和复制数组;节点顺序、即时位置、边界与候选顺序保持,不新增索引或跨调用缓存。node scripts/kg-layered-local-benchmark.mjs ce6c56a 与当前版本对照:800 节点树形场景的节点访问(筛选加碰撞遍历)从 4,557,360 → 21,587,局部 Map 读取从 4,584,392 → 58,136;已有同层准备的 800 条记录、1,600 次读取和 800 次写入仍单独计入。脚本冻结完整几何、组件身份、原始进度、每次移动及每次碰撞判断,含宽图、多锚点、骨干、无局部关系控制及 12,000 节点场景(--large),CI 使用 --smoke。真实浏览器可运行 node scripts/kg-verification-ui-fixture.mjs --layered-local,加 --client-ref=ce6c56a 对照原客户端。访问量是局部定位阶段指标,不代表完整布局或浏览器时延、内存收益。

  • 选择时复用关系路径:关系路径、箭头端点和标签几何按当前图与布局惰性缓存;选中、高亮、问题标记与操作回调仍实时更新。总览只计算曾显示的相邻关系,替换节点、关系、位置、尺寸或准备好的几何时释放旧缓存。node scripts/kg-graph-edge-geometry-benchmark.mjs ce6c56a 与当前版本对照:800 节点、1001 条关系连续四次选择,径向绕行角计算 4796 → 0、节点访问 3,836,800 → 0,全部连线和标签几何哈希一致。首次计算保持不变,模拟 hooks 的计数不代表浏览器延迟;--smoke 在回归中验证失效边界和总览惰性计算。真实工作台可运行 node scripts/kg-verification-ui-fixture.mjs --edge-geometry-performance,加 --client-ref=ce6c56a 对照旧客户端;选择中心布局后重置可见计数,再实际选择节点或关系。

  • 中心布局使用实际节点宽度:各 BFS 环按节点 ID 读取测量尺寸计算半径,保留中心节点、层级、次序、最小环距和缺失尺寸回退。node scripts/kg-radial-width-benchmark.mjs ce6c56a 与当前版比较真实布局引擎:固定 800 个 200×100 节点的星形图,最终重叠对数 512 → 0、角度避让轮数 160 → 1、节点对检查 51,136,000 → 319,600。计数包含原避让过程,不代表浏览器延迟;混合尺寸图仍由现有避让规则处理,不保证任意矩形都无重叠。--smoke 回归宽度响应、多环、缺失尺寸、断连节点及后台/本地几何一致性。真实工作台可运行 node scripts/kg-verification-ui-fixture.mjs --radial-widths,加 --client-ref=ce6c56a 对照旧版后选择中心布局。

  • 角度避让复用位置和尺寸引用:环形/中心布局在单次避让开始时按 ID 读取每个节点的位置对象和尺寸,至多各一次;每对节点仍读取调整后的坐标并按原顺序计算距离、半径和角度。引用只在本次调用内保留。node scripts/kg-angle-lookup-benchmark.mjs 4e6c12c --smoke 与当前版比较:80 个混合尺寸节点的 160 轮避让,Map 读取 2,022,400 → 160;省略 --smoke 使用 800 节点,读取 204,544,000 → 1,600。完整坐标、节点对检查和调整次数相同;计数包含准备,不代表浏览器延迟。回归冻结原引擎完整几何,覆盖图片高度、多环、缺失输入、后台/本地一致性与重新布局。

  • 自由布局的连线排斥复用点和尺寸引用:每次排斥准备当前节点的引用,仍在每轮重新计算连线路径,逐段读取当前坐标、累计推力后按原顺序限幅移动;无关系时直接完成该阶段。node scripts/kg-force-repulsion-benchmark.mjs 847e882 与当前版对照真实完整 force:两组 800 节点 / 101 关系的排斥阶段 Map 读取各 12,921,499 → 17,763,240 节点 / 363 关系样本 13,787,723 → 58,855;包含准备、弯曲排序、路径端点和轮末读取。每次动态路径、排斥后及最终完整坐标、推动次数和进度均冻结且相同,不声称浏览器时延收益。--smoke 使用三组 80 节点并进入性能回归;默认两组 800 和一组 240 较密关系样本,覆盖并行、自环、缺失端点及尺寸、退化路径、逐轮坐标和限幅、新调用和输入只读;实际 worker / 回退与取消沿用完整 force 回归。浏览器复用 --force-overlaps 夹具,旧客户端加 --client-ref=847e882。

  • 自由布局的重叠处理复用位置和尺寸引用:d3-force 结束后的两段中心线避让分别准备当前节点的引用,每个阶段按 ID 各读取一次位置和尺寸;保留逐对最新坐标、推动顺序、连线排斥、分量整理和进度消息。node scripts/kg-force-overlap-benchmark.mjs ce6c56a --smoke 与当前版比较真实生成引擎:80 节点两段各 120 轮,Map 读取合计 3,033,600 → 320;省略 --smoke 使用 800 节点,306,816,000 → 3,200。两个规模均冻结第一段及最终完整坐标、推动次数和进度序列。计数包含准备,不代表浏览器延迟。回归覆盖混合尺寸、断连/并行关系、重布局、缺失输入、后台/本地几何一致性及进度取消。真实工作台运行 node scripts/kg-verification-ui-fixture.mjs --force-overlaps,旧客户端加 --client-ref=ce6c56a 后选择自由布局。

  • 层级布局复用当前调用的连通分量:整理画布使用刚发现的有序分组,保留包围盒、排序、平移、分量元数据和进度;自由布局继续自行发现分量。node scripts/kg-layered-component-reuse-benchmark.mjs [ce6c56a] [--smoke] 对照真实完整引擎:12,000 节点 / 10,503 关系样本在分量发现、关系分配和整理阶段的关系记录检查 31,509 → 21,006,BFS 取出节点及邻接集合构造各 24,000 → 12,000,同时计入新增的 12,000 次节点 ID 复制。保留每个分量内部布局及其关系扫描,不声称浏览器时延收益。默认覆盖 800 节点宽层图、12,000 节点小分量和孤立图,--smoke 使用三组 80 节点;冻结完整坐标、所有分量成员与顺序、原始进度,并验证实际 worker 元数据、节流进度完成消息、取消、新拓扑 / 尺寸、引用身份和缺失输入。真实浏览器运行 node scripts/kg-verification-ui-fixture.mjs --layout-components [--client-ref=ce6c56a]。

  • 完全连通的层级图直接保留布局结果:只有一个分量时不需整理画布,也不复制分组 ID 或建立整理排序表。相对于首版分量复用 63f90d8,800 节点宽层 / 链 / 循环图的两项准备各 800 → 0;node scripts/kg-layered-component-reuse-benchmark.mjs [63f90d8] --large-connected 用真实完整引擎验证 12,000 节点链和循环,各 12,000 → 0。多分量仍沿用原整理规则,自由布局发现路径保留;默认和 --smoke 另外覆盖三种连通图的完整几何、共享成员顺序和原始进度,实际 worker 与连接 / 断开 / 改尺寸再连接保持一致。浏览器 node scripts/kg-verification-ui-fixture.mjs --layout-connected [--client-ref=63f90d8] 使用 800 节点单连通图。计数只针对整理准备,不代表整个布局时延。

  • 层级布局直接用 ID 选择起点:已有度数表按分量 BFS 顺序比较节点 ID,保留严格大于的同度数选择规则,省去每个候选再在节点数组中查找。真实完整生成引擎 node scripts/kg-layered-hub-benchmark.mjs [ce6c56a] [--smoke|--large] 对照:800 节点宽层 / 链 / 循环各 320,401 次查找比较 → 0;12,000 节点链 / 循环各 72,006,001 → 0,候选度数比较仍各 800 / 12,000 次,无新增索引或复制。冻结完整坐标、分量元数据 / 成员顺序 / 引用身份和原始进度;验证 BFS 同度数、数字 / 字符串 ID、推理链与循环回退、实际 worker、取消及新拓扑和尺寸。计数限于起点查找,不代表整个布局时延。浏览器 node scripts/kg-verification-ui-fixture.mjs --layered-hub [--client-ref=ce6c56a] 使用 800 节点。

  • 层级布局行压缩复用几何与临时区间:既有原坐标表同时保留当前位置和固定尺寸引用,各行按原顺序保存相同条目;位置改变后仍读取即时坐标,推理约束仍用原始坐标。候选行的碰撞区间即时消费,每次重写全部边界,惰性复用本分量的临时数组和区间对象。节点始终落在行网格上,按最高节点的严格竖直碰撞边界跳过不可能相交的行。实际完整引擎 node scripts/kg-layered-row-benchmark.mjs [ce6c56a|60642a3|2582f32|0dedb9c] [--smoke|--large] 对照:800 节点宽层图的整个行压缩阶段 Map 读取(包含准备)29,044,927 → 313,797,混合推理树 1,802,966 → 169,814;12,000 节点循环 2,923,556 → 1,413,109,多分量 2,193,268 → 948,120。宽层图行成员访问 14,286,594 → 6,312,458、碰撞区间对象 4,729,161 → 94、合并副本 100,207 → 0、临时数组 188,206 → 3;12,000 节点循环行成员访问 650,989 → 261,033、区间对象 97,503 → 2,数组 195,018 → 3。32 个以上的区间若按原顺序持续严格重叠,可直接求单段并集;相切、断开、无效首段或小数组沿用稳定排序,失败试探不改变输入。800 宽层图对照 0dedb9c,排序调用 94,103 → 39,431,比较 20,188,961 → 8,922,601;计入新增长度检查、失败试探、重叠及端点判断和 Math.max 的排序 / 合并运算 29,452,987 → 24,270,604(约 17.6%),区间遍历 4,729,161 → 4,919,780;每分量一个新 helper 也单独计数,不宣称整体时延或内存收益。冻结全部坐标、成员顺序、原始进度、每次移动及每个候选行的原始 / 合并区间;候选顺序、实际碰撞区间和更新顺序保持。引用与临时存储限于本次调用,无新增 ID 索引;严格高度边界、高节点、重复 ID、缺失尺寸、实际 worker、取消和新拓扑 / 尺寸有回归;另冻结 2,016 个连续复用候选的完整并集结果,覆盖符号零、非有限值、退化区间与严格相切,320 节点真实 Worker 确实执行快路径。浏览器夹具使用 node scripts/kg-verification-ui-fixture.mjs --layered-rows [--client-ref=ce6c56a|60642a3|2582f32|0dedb9c]。

  • 层间排序复用相邻节点均值:单次排序内位置和方向筛选固定,四个以上节点的层复用原索引条目保存均值,平局仍使用原序号;小层保持原计算路径,每次排序重新计算。node scripts/kg-layered-sweep-benchmark.mjs ce6c56a 与省略提交参数的当前版本对照:800 节点树图相邻节点访问 59,314 → 7,677,含原索引准备与缓存读取的 Map 访问 130,641 → 52,860;宽图相邻访问 4,791 → 2,400。加 --large 验证 12,000 节点,多分量相邻访问 54,003 → 31,503,循环图与链图保留原访问量。脚本计数实际均值条目分配,冻结完整几何、每次移动及原生排序比较轨迹,覆盖混合与重复 ID、非有限均值、位置和方向变化、实际 worker 与取消;npm run test:kg-performance 包含 --smoke。真实浏览器使用 node scripts/kg-verification-ui-fixture.mjs --layered-sweeps,加 --client-ref=ce6c56a 对照原客户端。计数是排序阶段的确定性工作量,不代表整体布局时延或内存收益。

  • 普通节点选择复用:工作台更新时创建新的图片渲染回调,只有实际显示原图预览的节点依赖它;普通文字节点和总览中隐藏的预览复用视觉状态未变的外框。显示或更新预览仍使用最新回调,节点操作也使用当前回调,缓存仍限于当前视口。node scripts/kg-graph-node-selection-benchmark.mjs f710ff5 --replace-image-renderer 与省略提交参数的当前版本对照:12,000 个文字节点连续四次选择,实际外框重建 48,000 → 16;保留完整证据。这是生产场景的确定性构造计数,脚本中的模拟 hooks 耗时不代表浏览器延迟或绘制收益。

  • 分层连线复用行边界:单次绘制准备中,一次组件扫描建立行边界和最高层索引,层间通道与同层关系直接复用,避免每条关系或每个新通道扫描组件;路径、标签避让及隐藏规则保持。索引随本次准备结束释放,新尺寸、新位置或取消后重试会重新计算。npm run test:kg-performance 核对冻结几何、组件隔离、空行与非有限值回退和实际节点访问次数;node scripts/kg-layered-channel-benchmark.mjs 68270e9 可对照逐通道缓存版本,f710ff5 可对照原始实现。基准分别报告含索引建立的路径计算及包含分轨、固定宽度标签测量与标签避让的整理连线阶段,不相加,不包含真实文字测量、后台布局、原文、HTTP 或绘制,也不设 CI 时延门槛。真实浏览器可运行 node scripts/kg-verification-ui-fixture.mjs --window-query-count --window-response-performance;加 --client-ref=68270e9 可只读取该提交的客户端,在相同宿主和数据夹具下交替对照,不改工作区。

  • 标签避让只检查邻近矩形:分层准备为整个当前布局建立空间索引,节点和成功放置的标签共同参与避让,保留原候选顺序、边界相交规则及隐藏行为。每个矩形最多占 64 个网格;超大、非有限或倒置范围使用原碰撞判断回退,不跨准备保留索引。性能回归覆盖边界差分、实际碰撞次数、存储上界及取消重试;node scripts/kg-layered-channel-benchmark.mjs 55efef0 比较标签索引前后的完整几何和整理连线阶段,并报告计时外的实际矩形检查及网格引用数。浏览器夹具的 --client-ref=55efef0 可用于相同宿主与数据下的交替对照。

  • 复用标签候选偏移:原点冲突后,同次分层准备按实际间距、轴向和同分方向复用已排序的候选偏移,位置与占位仍逐次检查。最多保留 16 个列表、每列表 256 个候选;容量满、过大列表或异常间距保持原计算并不缓存。原点可用时不建候选。node scripts/kg-layered-channel-benchmark.mjs a2fe94d 对照复用前的真实实现,统计实际候选构造、对象分配和排序比较次数;计数与计时用独立引擎,几何、模板容量、参数差分和取消重试由性能回归核对。

  • 内容单元编号即锚点: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 层直接丢弃。常驻 Web 插件的审校请求在较大时用 gzip 传输,不丢弃节点或关系;Host 分别限制压缩请求与解压后的 JSON 大小,并对超限返回明确错误。单次验证最多接纳 2000 个节点。

  • 修复不静默、可审计:AI 只提建议,用户点「采纳」才应用补丁;一键修复批量应用全部可自动修复项;每次应用写 graph.verification.auditLog。窗口化以后浏览器不再分配连续 canonical node id:新增节点使用 node_<UUID>,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。

  • 翻页复用全图结构诊断:常驻 SQLite Host 首次读取完整图计算诊断,连续翻页、改变窗口预算和子图查询复用最近一份结果;诊断仍描述同一版本的完整图。缓存绑定文档、版本、纯诊断函数和同一快照内的 SQLite 变更标记,本连接及其他连接写入(包括来源更新、删除重建)后重新计算;外层事务绕过缓存,返回值与缓存隔离,只保留诊断而非完整图。可运行 node scripts/kg-document-window-diagnostics-benchmark.mjs eed57e6 比较:12,000 节点 / 35,904 关系首次打开后连续翻四个 800 节点页,载入节点 51,200 → 3,200,重复全图读取 4 → 0。计时含 HTTP、JSON 和仪表开销,不含浏览器绘制;冷打开仍须完整诊断,不把窗口连通性当作全图指标。

  • 翻页复用准确的全图总数:连续窗口读取复用同一份结构诊断保存的节点与关系总数,避免每次重扫两个全图索引;SQLite data_version、total_changes()、文档版本和纯诊断函数都须吻合。本连接或其他连接写入、删除重建、切换文档或诊断函数都会失效;外层事务、不可克隆的诊断及缺少事务状态接口的旧运行时仍执行完整计数。只在已有单文档诊断中增加两个数字,返回总数与截断语义不变。node scripts/kg-document-window-totals-benchmark.mjs f710ff5 验证完整窗口与其余 SQL/参数/Native 记录一致,并对照 64 / 12,000 / 96,000 节点、不同摘录、窗口预算、子图和无诊断/事务控制;计时为完整 Store 窗口,包含真实诊断检查器及返回值克隆,不含 HTTP 或绘制,不作为 CI 门槛。

  • 稀疏窗口关系查询:普通分页和子图查询在同一读取快照内,根据整图关系数与实际窗口节点组合数选择索引查询策略;整图保守界不足且窗口至少有 64 个节点时,先用既有出向索引有限探测,最多计 2049 个候选,不读取完整关系载荷。至多 2048 条出向关系才启用已有的布尔成员检查,避免稀疏小窗逐对探测;小于 64 节点、密集或高连接度选择保留原双端点查找,后两者会增加一次有限探测。关系两端仍须在窗口内,TEXT 身份、完整证据、顺序、预算与快照不变,不增加索引、迁移或缓存。node scripts/kg-document-window-edges-benchmark.mjs 82d96ce 独立对照普通/深页、63/64/65 节点、少/满匹配、2048/2049 边界、密集/高连接度/20 万条窗外关系和 ANALYZE 控制,严格比较完整 Store 窗口、Native 关系、全部无关 SQL/参数/记录/顺序,分别计时整窗及探测/关系阶段;两种范围不相加,不含 inspector、HTTP 或浏览器绘制,也不作为 CI 性能门槛。历史关系基准仍为 node scripts/kg-document-window-diagnostics-benchmark.mjs 515825b --edge-shapes;后续改动可能贡献历史整窗耗时,已有统计信息时原查询可能已选中较优计划,收益依数据和计划而异。

  • 深页节点读取:跳过至少四个窗口的普通分页先按原有段落和节点编号顺序选出本页内部行编号,再在同一 SQL 中读取完整记录并恢复原排序,减少跳过旧页时排序携带的节点内容。浅页和子图查询沿用原路径;内部行编号不返回、不缓存或保存。没有新增索引或迁移,NULL 优先、BINARY 顺序、窗口预算及读取快照保持一致;OFFSET 仍须遍历前面的排序项。可运行 node scripts/kg-document-window-nodes-benchmark.mjs 与 b389b313 的原节点查询作 12,000 / 96,000 节点、不同摘录长度和同段节点数的独立对照。计时仅节点 SELECT/all,不包括 JSON 解析、其余窗口查询、诊断、HTTP 或绘制,不作为 CI 门槛。

  • 省略原文的窗口读取:严格指定 includeSourceText: false 的分页和子图查询只从文档行读取所需身份、来源元数据和版本,在 SQLite 返回 Node 字符串前省略 source_text。显式或默认请求原文、首次完整图诊断和完整导出仍读取原文;图元数据与 staging chunks 保持完整,其中已有的原文内容不会删减。没有跨请求原文缓存或存储迁移。可运行 node scripts/kg-document-window-source-benchmark.mjs cce0a3e,独立对照文档 SELECT/get 与完整 store 窗口,原文读取计数在计时外测量;不包括 HTTP 或浏览器绘制,不承诺磁盘 I/O 为零或峰值内存下降。

  • 子图查询保留符号:持久化 SQLite 窗口中的 %、_ 按字面子串匹配节点 ID、类型、正文、摘录及章节,不再删除这些字符;node_17 与 node17、100% 与 100 分别查找。其他查询沿用原有 LIKE 路径,大小写规则、邻居扩展、来源、排序、窗口预算及快照保持。可用 node scripts/kg-document-window-query-benchmark.mjs b967b9f 比较真实旧/新 Store 窗口;符号查询修正命中结果,不能把不同结果的计时当作同结果提速。计时不包含完整图诊断、HTTP 或绘制;普通查询作为结果与 SQL 一致性控制。

  • 少量子图匹配省去重复计数:普通 LIKE 与符号字面查询都先读取有预算的直接匹配节点;少于预算(含零)时已取得全部匹配,直接用其数量,避免再次扫描六个字段。恰好或超过预算仍执行完整 COUNT;匹配结果、参数、大小写、排序、邻居、原文、元数据及快照保持,不增加索引、缓存或中间匹配表。node scripts/kg-document-window-ordinary-query-benchmark.mjs 942ca9a 以已有符号优化为基线,对照 12,000 / 96,000 节点、短/长引用、少/空/满匹配、199/200 直接候选及大批查询,验证完整窗口、Native 关系批次、候选/剩余预算及其余无关 SQL/参数/记录/顺序一致,分别计时完整 Store 和匹配阶段。历史脚本支持 --validate-only 做结果/SQL 验证而不计时;后续关系与匹配优化可能叠加在历史完整 Store 耗时中,隔离原匹配阶段收益须使用对应测量版本。计时不含 inspector、HTTP 或绘制,不作为 CI 门槛。

  • 普通搜索省去重复小写转换:每次普通 LIKE 查询先检测当前连接是否保留 SQLite 的默认 ASCII 大小写行为,再直接匹配转为 TEXT 的六个字段,省去逐行 LOWER 的转换与复制;保留历史 BLOB/数值转换、NULL、NUL 和 Unicode 语义。显式大小写敏感或非默认 Unicode 转换继续使用原 LOWER;连接行为不缓存,普通分页与含 %、_ 的字面查询不增加检测。不加索引、迁移或字段缓存,匹配总数、排序、预算、邻居、来源和快照保持。node scripts/kg-document-window-fold-benchmark.mjs f710ff5 对照 64 / 12,000 / 96,000 节点、短/长摘录、少/无/满命中及 199/200 分界,含字面查询、普通页和敏感模式控制,验证完整窗口及 Native 记录/参数/总数/顺序和其余 SQL 一致。完整 Store 与包含行为检测的实际匹配阶段分别计时,不相加,不含 inspector、HTTP 或绘制,不作 CI 时延门槛;历史基准仅允许这六处有行为检测的 SQL 转换差异,单独校验原生结果,其余 SQL 仍逐项比较。

  • 按编号定位子图邻居:补入一跳邻居时先用已有文档/节点编号索引取得本批内部行编号,再在同一 SQL 中读取完整记录并恢复段落/节点编号顺序,避免为少量编号按段落索引扫描整份文档。每批最多 400 个编号,原有去重、批次顺序、预算、完整证据与读取快照保持;内部行编号不返回、缓存或保存,不新增索引或迁移。可运行 node scripts/kg-document-window-neighbor-nodes-benchmark.mjs 567f1b0,以完整窗口一致、普通分页和空查询作控制,分别测量完整 Store 与邻居 SELECT/all;计时不含 inspector、HTTP 或绘制,不作为 CI 门槛。

  • 稀疏相邻关系按端点定位:大图(至少 4096 条关系)先有限探测已有出向/入向索引,不读取完整关系载荷。至多 64 个节点的批次保留 64 条候选预算,65~300 节点的批次使用 2048 条预算;都取其与剩余关系预算的较小值,两方向合计达到预算加一就停止。含重复端点的保守总数在预算内时,才在同一 SQL 合并内部行编号、读取完整记录并恢复原顺序;密集、高连接度与小图保留原有 OR/LIMIT 查询。原 300 节点批次、去重、并行关系、证据、预算与快照保持;不新增索引、迁移或缓存。node scripts/kg-document-window-large-incident-benchmark.mjs d7bcc43 以既有小批次优化为基线,对照 12,000 / 96,000 节点、短/长引用、65/199/200 候选及多批查询、密集/高连接度/小图控制,验证全部 Native 批次及其他 SQL/参数/记录/顺序一致,分别计时完整 Store 与实际有限探测/关系查询阶段。历史小批次基准仍为 node scripts/kg-document-window-incident-benchmark.mjs 71d5102,支持 --validate-only;后续改动可能影响历史完整 Store 耗时。计时不含 inspector、HTTP 或绘制,不作为 CI 门槛。

  • 章节 / 候选审核视图:章节筛选只改变当前浏览器结果视图,不修改原始图;候选状态以 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[<=800], edges[], view: { kind: 'window' | 'query', nodeOffset, nodeLimit, totalNodes, totalEdges, truncated, query?, matchedNodes? } }
GraphQueryResult { documentId, revision, query, matches[{ nodeId, score, reasons[] }], graph /* 有界直接命中 + 邻居 */, sourceUnits[], metrics }
GraphAnswerResult { status: 'answered'|'insufficient'|'out_of_scope', answer, parts[{ id, text, evidenceIds[] }], citations[{ id, targetKind: 'node'|'edge'|'source', targetId, paragraph, quote, ...provenance }], supportingNodeIds[], retrieval }
GraphOperation { kind: 'merge_node', fromNodeId, intoNodeId }
EntityCandidate { id, documentId, nodeId?, text, type, status: 'candidate' | 'accepted' | 'rejected', evidence[] }
ClaimCandidate { id, documentId, nodeId?, text, type, status: 'candidate' | 'accepted' | 'rejected', confidence?, evidence[] }
ExtractionRun { runId, documentId?, sourceId?, status, nextBatchIndex, totalBatches, checkpoint }
GraphExtractorService { extractChunk({ title, chunk, paragraphOffset, existingNodeIds, prompt, attempt }) -> 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 可选,旧版本生成的历史数据没有这些字段时按未验证/未核查处理,完全向后兼容。

手工导入联结模型

在知识图工作台的“联结模型”目录点击“导入联结模型”,粘贴 { "graph": { "nodes": [], "edges": [] } } 格式的 JSON,先“校验并预览”,再“保存导入”。也可以直接粘贴含 nodes、edges 的对象。只允许新增联结模型、概念、规则,原有节点和关系保留。新增内容统一进入待审校、未验证状态。

aggregate-v1 的自动抽取词表继续使用原有 8 类节点和 12 类关系;手工图层额外支持 connection_model、maps_between(role: input | output)和 has_rule。modelStructure 记录模型身份、输入输出槽位、条件分支、解释边界与配对例子。AI 归纳应使用 identity: hypothesis 及 provenance.kind: ai;逐字摘录才使用 source。摘录与从零开始的段落索引必须对应现有原文,概念槽位必须指向图中的概念节点。

预览不写库。保存采用当前文档版本的原子提交;内容或版本变化后须重新预览。服务端校验来源、结构、重复身份及版本,失败时不导入部分数据。每批最多新增 300 个节点和 1,000 条关系。

node scripts/kg-aggregate-model-import-smoke.mjs 覆盖经典图层兼容、原图保留、过期版本拒绝、错误摘录拒绝以及 SQLite 重开后的模型与方向保留。

许可

MIT © cwbcheng

来源:GitHub · github.com