DeepThink v1.8.0 发布说明
自托管的多用户本地 AI Agent Loop Engineering 系统(支持桌面端 + 浏览器 + 移动端)
Powered By AI Genius Institute,AI 光剑
发布日期:2026-10-17
v1.8.0 是一个能力边界扩张版本,主轴是全新模块知识库(Knowledge Base):把腾讯开源的 WeKnora 知识库内核整体复刻到 DeepThink 原生的 TypeScript / React 栈上——文档切分为带原文绝对字符偏移的分块、分块级向量化、向量 + 关键词双路 RRF 融合检索,以及带引用溯源的 RAG 问答;并在同一版本内补齐扫描件 OCR与系统内置开源向量模型服务。
在此之前,DeepThink 的 Agent 能写代码、能跑 Loop、能被监控,但它读不了企业自己的文档:没有文档入库,没有检索,没有引用。Agent 的"知识"只能来自上下文窗口和它自己爬到的网页。企业最需要 Agent 掌握的那部分知识——制度、临床方案、运维手册、历史项目文档——恰恰都在本地。
本版本共33 个 commit,Schema v72 → v73(新增知识库 6 张实体表 + 4 张 FTS5 / vec0 虚拟表),无破坏性 API 变更。
🎯 新能力:知识库子系统(WeKnora 复刻)
需求与技术方案见docs/prd/2026-10-16-weknora-full-replica/、docs/tech_solution/2026-10-16-weknora-full-replica/;导航入口「知识库」→/knowledge-bases。
1. 检索内核:让「引用哪一个字的哪一段」可验证
复刻的核心约束不是"能搜到",而是每一条引用都能回到原文的确切位置:
text.slice(chunk.startAt, chunk.endAt) === chunk.content这条不变式写在分块器里、被单测与端到端用例逐块断言。它换来的能力是:检索结果里的引用可以按偏移回源到原文高亮,而不是给用户一段"大致在这里"的文字。没有它,文档 ID + 页码这种粗粒度引用在大纲结构的中文文档上基本无法核验。
| 层 | 实现 |
|---|---|
| 分块 | src/kb/chunker.ts:heading/heuristic/recursive三策略 +父子分块(父块只用于命中后回溯上下文,不进向量索引) |
| 融合 | src/kb/fusion.ts:RRF,K=60,向量 0.7 / 关键词 0.3 |
| 检索 | src/kb/search.ts:keyword/vector/hybrid三模式,双路得分与诊断信息原样返回给「检索测试台」 |
| 重排 | src/kb/rerank.ts:可选 cross-encoder,默认关闭;未配置即不改动融合顺序 |
| 问答 | src/kb/rag.ts:流式 / 非流式,回答带编号引用,引用可展开看原文 |
父子分块的口径(容易误读,已在文档中明示):当某个 section 的正文小于子块尺寸时,“父块 == 唯一子块”,不产生父行——这不是漏做,是 WeKnora 的语义。实测bodyRepeat=150的 6693 字夹具切出 42 块(14 父 + 28 子),bodyRepeat=40的 2073 字夹具切出 14 块(0 父 + 14 子),两条都用独立用例锁定。
2. 检索增强:把"问不准"拆成五个可单独关闭的开关
| 子项 | 能力 | 默认 |
|---|---|---|
| 查询改写 / 扩展 | 纯本地生成变体,只作用关键词臂(向量臂不动),变体命中给救援分 | 关 |
| 查询理解 | 改写 + 意图识别,意图决定走 FAQ 桶还是文档桶 | 开 |
| FAQ 索引 | 标准问 / 相似问分别建向量,检索时分桶;相似问带负向否决(问的是相似问,不能把整条 FAQ 当答案给出去) | 库类型为 FAQ 时 |
| 预生成问题(Doc2Query) | 为分块预生成可能的提问并一并向量化,弥补"用户问法"与"文档写法"的措辞鸿沟 | 关 |
| 重排 | 可选 cross-encoder,候选上限 50 | 关 |
默认关闭的项不是半成品:全部有单测与 UI 验收,"关闭时不改变任何既有结果"本身也是被断言的。
3. 文档接入:11 种格式 + 四条入口
| 入口 | 说明 |
|---|---|
| 单文件上传 | 单文件 ≤ 100MB;pdf / docx / pptx / xlsx / epub / xmind / html / csv / json / markdown / text |
| URL 抓取 | 走 SSRF 防护链(字面量校验 → DNS 解析校验 → 逐跳重定向校验) |
| 手写 Markdown | 直接写正文,与上传共用同一条入库链路,内容哈希判重口径一致 |
| 整目录 / 整包 | 目录选择(webkitdirectory)与拖拽目录(webkitGetAsEntry递归);zip整包走服务端解包,逐条回执 |
zip 容器格式(pptx / xlsx / epub / xmind)共用src/document-parser-zip.ts:
- pptx按 rels 页序输出(不是文件名序,实测夹具
slides-reordered.pptx的文件名序与真实页序相反) - xlsx表头与行绑定成 Markdown 表格——按"单元格平铺"切块会一落刀就把剂量和药名拆开
- epub按
spine序(toc顺序才与阅读顺序一致) - xmind层级转标题层级,游离主题(
children.detached)不渲染
三条安全闸:条目数 ≤ 5,000、解压前按uncompressedSize累计 ≤ 200MB、拒绝路径穿越(../ 绝对路径 / NUL)。老二进制格式(.doc/.xls/.ppt,magicD0 CF 11 E0)给出明确的"请另存为"提示,而不是笼统的"不支持"。
4. 扫描件 OCR + 系统内置开源模型服务
需求原文:「扫描件要支持,9999 那个实例要配向量模型,直接系统内置部署使用开源的向量模型服务。」
内置模型服务(src/local-model.ts):探测 / 拉起 / 流式拉取 / 维度探测。维度是问出来的而不是硬编码——vec0建表时固定维度,写错要等第一次检索失败才暴露。
扫描件 OCR(src/ocr.ts+src/kb/ocr-ingest.ts):纯图片 PDF 渲染成 PNG 交给视觉模型转写,表格按 Markdown 保留行列。光栅化用pdfjs-dist+@napi-rs/canvas——两者都是既有依赖,本轮没有新增任何 npm 依赖。
三个必须踩过的坑,全部用实测数据定方案:
| 坑 | 实测 | 处理 |
|---|---|---|
| 思维链视觉模型烧光上下文 | qwen3-vl:8b单页 51s~>300s,3 页夹具丢 1 页,287 页估算 6–12 小时 | 默认改用qwen2.5vl:7b(单页 14–20s,3 页全中,287 页约 38 分钟) |
Ollama 的 OpenAI 兼容端点静默忽略options.num_ctx | /v1/chat/completions传 16384,/api/ps仍是 4096 | 改走原生/api/chat |
| 「截断」被当成「空白页」 | done_reason=length+ 空正文被记为emptyPages,不报错 | 截断与空白分开判定,失败在正文留痕 |
OCR 必须后台跑(287 页 × 十几秒),但上传当场会校验"开关 / 服务 / 模型是否就绪",不满足直接 400 指路设置页——不让用户等半小时才看到失败。
5. Agent 真正用得上:三个内置工具
kb_search/kb_read_document/kb_list_documents注册进 Agent 运行时。知识库不是给人在网页上搜着玩的——它要能被 Agent 在任务执行中直接调用,否则仍然只是另一个文档管理后台。
6. 落地取舍(Think Before Coding:显式暴露)
| 决策 | 取舍 |
|---|---|
| 引用以字符偏移为准,不以页码为准 | 中文大纲文档的"第 3 段"无法核验;代价是分块器必须严格维持偏移不变式,任何后处理(如去空白)都不能偷偷改 content |
| 父块不进向量索引 | 检索单元是子块(更小、更准),父块只在命中后回溯上下文;代价是一次完整问答要读两次分块表 |
| FAQ 与文档分桶 | FAQ 问的是"标准答案能不能命中",文档问的是"正文哪一段相关",混在一个桶里向量相似度会互相污染;相似问另做负向否决 |
| OCR 只支持 PDF | 光栅化依赖"页"的模型;epub / xmind / xlsx 没有页,强行走 OCR 只会得到一个错误——如实暴露边界 |
| 关键词臂是子串/短语语义(FTS5 trigram) | 中文整句在纯 keyword 模式不命中,靠向量臂覆盖。这是已知边界,不是缺陷 |
| 失败分类要可见 | 目录 / 整包上传绝不静默吞条目:隐藏项、不支持格式、超上限,每一条都带 reason 出现在回执里 |
🐛 知识库线修复的缺陷(全部按 issue 工作流沉淀)
本版本新增19 篇issue 复盘文档(docs/issues/2026-10-1*.md,8 节完整结构)。其中影响最大的几条:
| # | 现象 | 根因 | 为什么单测没拦住 |
|---|---|---|---|
| 1 | 「上传文档」按钮点了完全没反应(用户上线实例上报) | <button>被包在<label>里,规范要求 label 对 interactive content 后代的点击"什么都不做" | Playwright 的setInputFiles()直接给 input 赋值,绕过了"点按钮"这一跳 |
| 2 | PDF 上传 100% 失败:pdfParse is not a function | pdf-parsev2 改成具名类导出,旧写法退化成模块命名空间对象 | PDF 解析此前零覆盖 |
| 3 | 扫描件"上传成功、状态就绪"却检索不到任何东西 | pageJoiner默认值给每页伪造-- n of 287 --标记,空值守卫永远不触发 | 与 #2 同一函数,同样零覆盖 |
| 4 | 长文档尾部内容永远检索不到 | embedding 层对超长文本静默截断8000 字符 | 用例都用短文档 |
| 5 | 中文关键词检索恒为 0 命中 | FTS5unicode61+ 整句短语匹配语义 | 用例用英文 token |
| 6 | 分块偏移与内容对不上,引用无法回源 | 分块后做了文本整理,offset 未同步 | 只断言了"块数 > 0" |
| 7 | 删除知识库必然 500 | DELETE语句上误用.all() | 删除路径无覆盖 |
| 8 | FAQ 条目建完不被向量化 | POST / PUT 未触发起始嵌入,FAQ 库也没有"重建索引"入口 | 只验了条目 CRUD 返回 200 |
| 9 | 纯标题文档(如 xmind)入库失败:Chunking produced no chunks | heading 分块逐段跳过空 body,整篇只剩标题时一块不剩 | 被 xmind 解析器放大成必现 |
| 10 | 切一次页签后「上传目录」静默退化成普通文件框 | webkitdirectory只在首次挂载的节点上打补丁,条件渲染会换节点 | 探针恰好跑在首屏 |
| 11 | .html上传与 URL 抓取 100% 失败:require is not defined | ESM 运行时里用了require | vitest / tsx 的转换层会注入require兼容对象,测试永远是绿的 |
| 12 | 重建索引后列表仍显示「已向量化 0」 | 冗余计数列只由 ingest 管线维护,rebuild 绕过了它 | 接口返回的attempted/success全都是对的 |
| 13 | URL 入库存在 SSRF,可被诱导读取云元数据 | fetch只判了^https?://,且redirect: 'follow' | 安全用例此前没有 |
| 14 | make start-prod服务的是桌面版内置前端 | Makefile 启动路径优先用了桌面端 dist | 静态检查看的是源码,不是启动脚本 |
| 15 | make stop-prod报「已停止」,几秒后旧看门狗又拉起来 | 停止时未先停看门狗 | 没人测过"停两次" |
共性:这 15 条里没有一条是靠"再读一遍代码"发现的。它们长在单测够不到的地方——用户点得到吗、真实 ESM 运行时跑得通吗、接口返回 200 之后数字对不对。这也直接改变了本版本的验收口径:
e2e 必须打在
dist编译产物上,并且「用户点得到」一律用waitForEvent('filechooser')真实点击,不用setInputFiles()绕过按钮。
🐛 其余修复(不在知识库线上)
| 项 | 根因 | 修复 |
|---|---|---|
| WebSearch 长期静默失效 | resolveZhipuApiKey()硬编码/home/me/...(最初那台开发机的路径),且能力绑死单一付费后端 | 新增shared/web-search.ts,5 个可插拔后端(zhipu / tavily / bocha / serper / 免 key Bing 抓取),四级优先级 + 设置页连通性自检;顺带修掉filterByDomain的endsWith缺陷(notexample.com不再越权放行) |
| 容器构建 Go 工具链下载单点失败 | dl.google.com国内解析到一组 GGC 节点,部分 443 不响应,--retry打的是同一个坏 IP | 多源按序回退(阿里云 → 南大 → 官方),先落盘 +gzip -t校验再解包 |
| macOS 桌面版单实例静默退出 | 残留挂载 + 单实例锁 | 已沉淀排查文档(docs/issues/2026-10-15-desktop-pack-launch-single-instance.md) |
✅ 验证
单元 / 集成测试
npx vitest run Test Files 183 passed | 4 skipped (187) Tests 2477 passed | 16 skipped (2493)较 v1.7.0(161 文件 / 2082 条)+26 文件 / +411 条,0 失败。
跳过 16 条,全部来自 5 个环境条件跳过的用例组(ISOLATED/RUN/dbAvailable未满足);这 5 个文件自 v1.7.0 起未改动,本轮也没有新增任何skip标记(git diff v1.7.0..main -- tests/中+.*skip为 0 条)。v1.7.0 记录的是 14 条,差值来自两次测量时的环境条件不同,不是本轮新增。
真实浏览器 UI 验收(Playwright + 本机 Chrome,非 mock)
| 轮次 | 范围 | 结果 |
|---|---|---|
| P1 内核 | 父子分块 / FAQ / Doc2Query / 查询改写 / 查询理解 | 18/18 |
| P1 PDF | 用户真实文件、真实点击拿filechooser | 10/10 |
| 内置模型服务 + OCR | 隔离实例:9898,真 Ollama、预置关键词夹具 | 21/21 |
| P2 文档接入 | 打在dist产物上,10 种格式矩阵 + 目录 + 整包 | 35/35 |
| 9999 生产实例 | 部署后复跑,含用户上报的那个库(只读) | 14/14 |
P2 验收的关键数值:格式矩阵 10 种全部「就绪」且已向量化 == 分块;目录上传3/3 · 成功 3,保留dirtree/protocol/visit.md相对路径,.draft.md与.cache/未入库;整包 zip解包后:入库 3 · 跳过 3 · 失败 0,跳过项逐条给理由。
截图全部归档在docs/test_report/2026-10-16-weknora-full-replica/screenshots*/。
生产实例 9999
- 部署链路:
npm run build+npm run build:web→make stop-prod→make start-prod PORT=9999→ 上线自检 - 模型服务:本机 Ollama 0.40.3,向量
bge-m3(1024 维)、OCRqwen2.5vl:7b,不依赖任何外部 API Key - 上线自检脚本:
tests/e2e/kb-9999-livecheck.mjs(可复跑)
已知缺口(如实列出,不声称解决)
| 缺口 | 状态 |
|---|---|
| 图片类文档(png/jpg)没有独立入库通道 | P2 只做到"识别并拒绝/按文本吃下";真正的图片通道属 P3 |
| 拖拽上传路径无 e2e 覆盖 | 只有间接覆盖(目录选择走的是同一套collectDroppedFiles纯函数) |
ParserEngineRules的 OCR 通道只有单测覆盖 | 未做真实 UI 端到端 |
| 关键词臂对中文整句不命中 | 设计边界(FTS5 trigram 子串语义),靠向量臂覆盖 |
| 「重建索引」单次最多嵌 200 分块、前端只调一次 | 分块多的库需点多次才补齐 |
| 向量维度在建表时固定 | 换模型且维度变化必须「重建索引」 |
| P3(rerank 深化 / Wiki / GraphRAG)、P4(fork/rewind / artifacts / steering)、P5(SSO / 多租户 / Langfuse) | 未启动 |
📦 升级说明
- Schema 自动迁移 v72 → v73:启动时创建知识库 6 张实体表 + 4 张 FTS5 / vec0 虚拟表,无数据改写、无破坏性变更。
- 新增路由族
/api/paas/knowledge-bases/*(34 个端点:库 / 文档 / 分块 / FAQ / 检索 / 问答)。 - 新增页面:「知识库」→
/knowledge-bases与详情页(文档 / 分块 / 检索测试台 / 问答 / FAQ 五个页签)。 - 新增 Agent 工具:
kb_search/kb_read_document/kb_list_documents(随 Agent 运行时自动注册)。 - 向量化需要模型配置:在「设置 → 模型服务」配置向量模型。推荐直接用系统内置的开源模型服务(本机 Ollama
bge-m3),不需要任何外部 API Key。 - 扫描件 OCR 需要视觉模型:同样是内置服务提供(
qwen2.5vl:7b),配置ocr.json即可;未配置时上传扫描件会在上传当场被拒绝并指路设置页,不会静默入库噪声。 - SQLite 需启用 sqlite-vec:向量索引依赖
sqlite-vec扩展(启动日志出现vector index enabled即正常)。 - 既有链路零改动:知识库是完全新增的子系统,不影响对话 / 图编排 / Loop / 监督者 / 开放平台 / 运行监控。
📦 获取方式
- AtomGit:
git@atomgit.com:AIGeniusInstitute/deepthink.git - GitHub:
git@github.com:AIGeniusInstitute/deepthink.git - 桌面端安装包:见各平台 Release 资产(macOS .dmg / Windows .exe / Linux AppImage)
gitfetch--tagsorigingitcheckout v1.8.0# 或直接拉取 main 分支(已包含 v1.8.0 全部内容)📊 版本统计
| 项 | 值 |
|---|---|
| Commit | 33 |
| 文件变更 | 219 files changed, 34059 insertions(+), 582 deletions(-)(新增文件 194 个,含验收截图) |
| Schema | v72 → v73(知识库 6 张实体表 + 4 张虚拟表) |
| HTTP 端点 | 34(/api/paas/knowledge-bases/*) |
| 支持格式 | 11(pdf / docx / pptx / xlsx / epub / xmind / html / csv / json / markdown / text) |
| 测试 | 187 文件 / 2493 用例(2477 passed / 16 skipped),较 v1.7.0 +26 文件 / +411 条 |
| 新增需求文档 | 知识库复刻 + 内置模型服务 的 意图 / PRD / 技术方案 / 执行状态 / 带截图测试报告 |
| 新增 issue 复盘 | 19 篇(8 节完整结构) |
| UI 验收 | 18/18(P1 内核)+ 10/10(PDF)+ 21/21(OCR)+ 35/35(P2)+ 14/14(9999 上线) |
🙏 致谢
让每一家企业都拥有一支永不停歇、持续进化的 AI 超级研发团队——从工具使用者,到代码创造者,最终成长为可自我繁衍的超级智能体。让我们在通往 AGI 的道路上一起前行。