cyber-self
mrlsss/cyber-self
Per-workspace personal knowledge base for DeepSeek Harness: each identity gets an isolated local library — import PDF, Word, Excel, Markdown, text, HTML and images, auto-chunk and embed into SQLite with FTS5 + vector hybrid retrieval, then ask questions in chat with numbered citations back to the source. Local-first, no cloud upload; vector embeddings need a local Ollama (default bge-m3), and without it retrieval degrades to FTS5 keyword search.
Install
dsh plugin --profile web add github:mrlsss/cyber-selfREADME
CyberSelf——赛博镜像
一个人可以有多重身份,每种身份一套只属于自己的资料库。把资料收进来,自动整理、建立索引,之后用说话的方式提问,回答会注明出处。
这是一个 DSH 插件:一个身份对应一个 DSH 工作区,工作区里挂着它自己的本地资料库。
适合什么场景
- 喜欢听歌的人(身份 A):录入歌单、乐评、歌词笔记。之后说"下雨天、一个人在家,想听安静的",从自己的资料里筛出符合的歌。
- 数据整理工作者(身份 B):录入工作中的数据。之后按条件让它整理出符合需求的条目。
- 学生(身份 C):录入各科资料、学习笔记。之后直接问某个知识点、某一道题。
- 销售、服务人员(身份 D):录入多名客户的聊天记录。之后问"某个客户推进到哪一步了"。
A、B、C、D 可以是同一个人的多重身份。身份之间互相隔离,互不影响。
实际的角色五花八门,但用法始终是同一条线:
- 收集这个身份的相关数据;
- 整理归纳、向量化、建立索引;
- 提问,复用这些数据。
身份怎么隔离
一个身份 = 一个 DSH 工作区 = 一个资料库。库文件就放在工作区目录里的 .cyberself/kb.db,全部内容只在本机。
检索只在当前工作区的库里进行,没有跨身份检索。删掉这个工作区,它的资料库也一起删掉。
安装
需要 Node.js 22.5 以上(资料库用 node:sqlite)、pnpm、DSH 0.2.1-rc 系列。向量化用本机的 Ollama;扫描件和图片转写需要一个能看图的对话模型。
ollama pull bge-m3
pnpm install
pnpm build
构建产物是 lib/index.js(Host 侧)和 lib/client.js(浏览器侧),仓库里带着构建好的文件,从 GitHub 安装时不需要再构建。
两种安装方式
| 应用内(desktop) | 命令行(自己建的 profile) | |
|---|---|---|
| 怎么装 | DSH Desktop 的插件市场 | dsh plugin add |
| 工作区 | 桌面应用里的全部工作区,挑需要的设为资料库 | 该 profile 下的工作区 |
| 其他工具 | 全部保留 | 可以关掉,只留资料库 |
| 适合 | 日常使用 | 只读资料库的专用入口、本地改代码调试 |
两个 profile 可以同时存在。资料库跟着工作区目录走,两个 profile 打开同一个工作区时用的是同一个库,不需要重新导入。
装进 DSH Desktop
桌面应用的 desktop profile 由应用自身管理,命令行的 dsh plugin 写不进去,会报 profile "desktop" is managed exclusively by the Electron application。在 DSH Desktop 的插件市场里搜索 cyber-self 安装。
也可以自己建一个命令行 profile,见下一节。
装进自己建的 profile
命令行 profile 有两种用法:市场还没收录时的安装方式,以及一个只让模型看到资料库的入口。后一种要在第 3 步关掉读文件、联网、执行命令。
1. 新建
dsh --profile kb --from-default-profile web
--from-default-profile 只接受 DSH 自带的模板(web、headless、tui)。desktop 由桌面应用自己管理,不能拿来当模板,也不能用 dsh plugin 往里写。
2. 装插件
dsh plugin --profile kb add github:MrLsss/cyber-self
改本地代码时在项目根执行 dsh plugin --profile kb add link:"$PWD",改完 pnpm build 再重启。
然后检查 ~/.dsh/profiles/kb/package.json,dsh.profile.bundles 里要有 cyberself:
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"cyberself"
]
}
}
3. 关掉不需要的工具
编辑 ~/.dsh/profiles/kb/cordis.patch.yml,按 id 把对应条目设为 disabled: true:
- id: tool-bash
disabled: true
- id: tool-pwsh
disabled: true
- id: tool-fs
disabled: true
- id: tool-fs-search
disabled: true
- id: tool-web
disabled: true
- id: tool-subagent
disabled: true
- id: tool-workflow
disabled: true
| id | 关掉的工具 | 作用 |
|---|---|---|
tool-bash | bash、后台任务 | 执行命令 |
tool-pwsh | pwsh | 在 Windows 上执行命令 |
tool-fs | read、write、edit | 读写工作区里的文件 |
tool-fs-search | glob、grep | 按文件名或内容搜索文件 |
tool-web | web_search、web_fetch | 联网搜索和抓取网页 |
tool-subagent | 子任务相关工具 | 另起一个助手干活 |
tool-workflow | 编排脚本 | 批量调度多个子任务 |
tool-todo、tool-goal、tool-skill、tool-result-pruner 不影响资料库的封闭性,可以留着。插件自己的 cyberself_search、cyberself_read 不受影响,资料库的读取走插件自己的工具。
4. 重启
dsh --profile kb
patch 层在启动时合成,改完 cordis.patch.yml 必须重启才生效。改 Host 代码也要重启;改客户端代码要重新 pnpm build 再刷新页面。
为什么关掉工具
「回答范围」里的「仅资料库」是提示词约束,模型手里仍然有 bash、read、web_search,只是被要求别用;在 profile 里关掉之后,这些工具根本不会出现在模型面前,问答只能围着资料库进行。
桌面应用里的日常对话不受影响,两边用的还是同一批工作区和同一份资料库。
使用四步
1. 收集录入
打开身份对应的工作区,点顶栏的「资料库」按钮(或右栏的「资料库」页签),点「设为资料库」,然后上传文件,或填入 Host 上的目录绝对路径整目录导入。
| 数据 | 格式 |
|---|---|
| 文档 | .pdf .docx(Word 内嵌的图片也会解析) |
| 表格 | .xlsx .xls .csv(每行一段,工作表名作为小节标题) |
| 笔记、纯文本 | .md .markdown .txt .text .log(自动识别 UTF-8 与 GBK) |
| 网页 | .html .htm(取正文、标题和表格) |
| 图片、扫描件 | .png .jpg .jpeg .webp .gif(视觉模型转写) |
| 聊天记录 | 从聊天软件导出为 txt、Markdown 或 html 后导入 |
单个文件最大 64 MB。目录导入会先递归扫描,列出文件数量、总体积、其中多少张图片要交给视觉模型,确认之后才开始导入;扫描时跳过隐藏目录和 node_modules、.git、.cyberself、dist、build、lib。.doc 不支持,先另存为 .docx 或 PDF。
2. 结构化整理(自动)
导入时自动完成:按格式解析出正文,按标题、表格行、段落切成块,按内容 hash 去重。同一份文件再导一次,直接提示「这个文件已经导入过」;换个文件名、内容一样,也认得出来。
3. 向量化、索引(自动)
切块进入 SQLite,同时建两份索引:全文索引(trigram)和向量(默认 Ollama bge-m3)。向量在后台补齐,面板上能看到「已向量化 K 段 / 共 M 段」。向量还没跑完也能提问,此时只按关键词匹配。
4. 资产复用
在对话里直接问。插件先检索资料,把命中的片段交给对话模型,回答里每句结论后面带 [1]、[2] 编号,编号对应面板里能查到的原文块。资料里没有的内容,回答会直说缺什么,不猜。
举个例子。身份 D 的「客户跟进」工作区里导入了 客户-林总.txt:
3月12日 林总:报价收到,内部还要过一遍采购流程。
3月20日 我:发了第二版方案,增加了分期付款。
3月27日 林总:方案可以,约下周三下午当面签合同。
问:「和林总推进到哪一步了?」
回答:
已到签约阶段。3 月 27 日林总确认第二版方案可行,约好下周三下午当面签合同。[1]
此前 3 月 12 日报价进入对方采购流程,3 月 20 日发出了增加分期付款的第二版方案。[1]
面板上的检索框可以只查资料、不调用模型,用来核对原文和分数。
面板功能
- 统计:几份资料、几段、已向量化几段、占用大小。
- 导入:上传文件,或填一个目录路径,扫描后先看数量、体积和图片张数,再决定是否导入。
- 文档列表:点开一份能看到每一段的原文、页码、小节标题,可以单独删除。
- 检索框:只查资料库,不调用模型。
- 操作:向量化全部、清空资料、删除数据。
「清空资料」删掉全部文档、分块和向量,保留资料库标记;「删除数据」删掉整个 .cyberself 目录,这个工作区不再算资料库。
回答范围
每个身份单独设置:
- 仅资料库:只依据检索到的原文回答,资料里没有就说明缺哪类资料。
- 允许补充:先查资料库,没覆盖的部分可以补充,补充内容单独成句并注明「(资料库外)」。
这是对模型的指令约束,模型手里仍然有其他工具。要让它在能力上就没有这些工具,按装进自己建的 profile 的第 3 步关掉。
设置
设置 → 资料库:
| 字段 | 说明 |
|---|---|
| 服务地址 | Ollama 地址,默认 http://127.0.0.1:11434 |
| 模型 | 嵌入模型名称,输入框会列出已安装的模型 |
| 单次超时 | 单次嵌入请求的超时,默认 120 秒 |
| 每批条数 | 每次送给模型的文本条数,默认 8 |
| 每块字符上限 | 0 表示整块送入;设小可以加快向量化,代价是每块后半段不参与语义匹配 |
| 表格分块去重 | 打开后,Excel 和 CSV 里只有数字不同的行共用一个向量 |
改动模型、每块字符上限或去重开关,会清空已有向量并在后台重新生成。保存之前先探测新的嵌入服务,连不上或者模型没装,设置不会保存,向量也不会被清掉。设置保存在 $DSH_HOME/cyberself/settings.json。
其余参数(分块长度、每次检索几条、回答温度等)写在 profile 的 cordis.patch.yml 里,全部字段和默认值见 src/host/config.ts:
- id: cyberself
config:
retrieval:
topK: 8
answer:
model: deepseek-chat
verify: true
数据
| 内容 | 位置 |
|---|---|
| 资料库数据库 | <工作区>/.cyberself/kb.db |
| 资料库标记与回答范围 | <工作区>/.cyberself/config.json |
| 嵌入服务设置 | $DSH_HOME/cyberself/settings.json |
资料库目录就在工作区里面,所以如果你会把这个工作区提交到 Git,记得把它加进自己的 .gitignore:
.cyberself/
开发
pnpm install
pnpm build # 生成 lib/index.js 与 lib/client.js
pnpm typecheck
pnpm test # node:test,94 个用例,需要本机 Ollama 与 bge-m3
其中两个用例要把问题真正发给对话模型(测试走 127.0.0.1:3425 的模型网关),CI 没有这个网关,会跳过这两个用例跑其余 92 个。
lib/ 跟着源码一起提交,安装侧不会执行构建。改完 src/ 记得重新 pnpm build 再提交,CI 会检查 lib/ 与源码是否一致。
| 目录 | 内容 |
|---|---|
src/host/ | 解析、分块、SQLite、检索、问答、HTTP 路由、模型工具、会话规则 |
src/client/ | 右栏面板、设置页、样式、数据请求 |
src/shared/ | 前后端共享的类型与路径 |
test/ | 测试用例、网关客户端、样例文件 |
test-docs/ | 各种格式的样本文件与测量脚本 |
限制
.doc不支持。- 扫描件和图片依赖能看图的模型,模型不支持图片时导入会失败。
- 扫描版 PDF 的页面要渲染成图片,依赖
@napi-rs/canvas的预编译包;平台没有预编译包时,这类页面会报错并说明原因,文字版 PDF 不受影响。 - 向量检索在 JavaScript 里逐块计算,耗时随分块数量线性增长,1 万段约 0.8 秒。
- Word 转出来的分块可能比章节更碎,检索粒度比 Markdown 差一些。
- 一个工作区一个库,没有跨身份检索。
- 同一时间每个库只跑一个向量化任务。
常见问题
连不上 Ollama。 先确认服务在跑:curl http://127.0.0.1:11434/api/tags。
提示 Ollama 里没有模型。 执行 ollama pull bge-m3,然后点设置页的「重新检测」。
导入成功但搜不到。 看面板统计里「已向量化」是不是 0。向量没生成时只按关键词匹配,可以换个更贴近原文的说法。
回答没有编号。 先确认 answer.verify 是打开的;重答一次仍无编号会附警告。也可以把 answer.model 换成更强的模型。