fishonbike/vault-engine

GitHub: fishonbike/vault-engine

vault-engine 是一个零依赖的本地去标识化工具,在文本发送给云端 LLM 前自动脱敏并将身份信息替换为可逆 token,保护用户隐私。

Stars: 0 | Forks: 1

# vault-engine **一个本地 LLM 隐私层,用于处理你粘贴到云端模型的任何内容。** 在你的文本到达 ChatGPT / Claude / Gemini 之前,剥离其中的身份信息——一个运行在**你自己的机器上**的模型会找出姓名、组织、地点 和准标识符,将它们替换为稳定的 token,并在磁盘上保留唯一的 还原密钥。当云端使用 token 进行回答时,你可以在本地还原真实的 身份。 *尽力的去标识化——并非法律意义上的匿名化或隐私保证。 在发送前请审查高风险材料。*

vault-engine scrubs English and Chinese names and PII into tokens before the cloud sees them, then restores them locally

![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)  ·  Python ≥3.9  ·  仅依赖 stdlib  ·  Apache-2.0 ``` # notes.txt ── 私有,位于您的机器上 林若曦是星澜资本的合伙人,在深圳见了字节跳动的陈大壮,邮箱 lin@xinglan.example ▼ vault-engine scrub (local qwen3.6:27b) # safe.txt ── 云端所见:身份已替换为 token P-n1 是 ORG_1 的合伙人,在 LOC_1 见了 ORG_2 的 P-n2,邮箱 EMAIL_1 ``` ## 为什么使用 你想使用前沿的云端模型来分析敏感笔记——但你不想 让云端知道它们是关于*谁*的。仅仅掩盖你已经知道的名称会 泄露你不知道的一切:未记录的姓名、雇主、城市 + 罕见的 头衔、项目代号。基于模式的脱敏根本无法识别这些。 `vault-engine` 在前面部署了一个**本地模型**作为检测器,因此语义 标识符也会被捕获——而且只有经过净化的文本会被发送出去。 ## 工作原理 ``` private text cloud model │ (sees only tokens) ▼ ▲ ┌─────────────────────────── vault-engine ────────────┼───────────┐ │ ① regex PII detectors (offline floor) │ │ │ ② LLM detector (local model finds names, │ │ │ orgs, places, quasi-IDs) │ │ │ ③ consistent pseudonyms (张三→P-n1, 同名同号) │ │ │ ④ residual-risk critic (re-scan: anything left?) │ ① send │ │ │ │ │ │ sanitized text ────────────────────────────────────┘ │ │ ▲ │ │ reverse map (token → real identity) ── stays LOCAL ──┐ ② reply │ │ └───────────────────── ⑤ rehydrate ◀────────────┘ │ └──────────────────────────────────────────────────────────────────┘ ▼ real identities restored locally → use in your own system ``` ## 基准测试 每个检测器实际捕获了多少身份信息,基于一个带标签的双语 数据集(使用 `python eval/run_eval.py` 复现;方法论见 [`eval/`](eval/README.md)): 15 份双语文档中的 77 个标准身份标识——包含简单的 PII 以及困难案例 (歧义词常见姓名、缩写、音译、@handle、徽章 编号、车牌)。复现: `python eval/run_eval.py --provider ollama --with-presidio`。 | 检测器 | person | org | location | project | contact | id | **overall** | 过度脱敏 | |---|---|---|---|---|---|---|---|---| | 仅 regex | 0% | 0% | 0% | 0% | 69% | 33% | **13%** | 0% | | Microsoft Presidio (en/zh `lg`) | 78% | 59% | 80% | 33% | 38% | 0% | **61%** | 4% | | **vault-engine (qwen3.6:27b)** | 100% | 100% | 100% | 100% | 100% | 100% | **100%** | 0% | 在 Presidio 的 NER 得分为 61% 的同一数据集中,本地 LLM 达到了 100% 清除率——差距在 代号、@handle、ID 以及中文姓名/组织上最为显著。权衡在于速度:Presidio ~6s,而 LLM ~25s/doc。 重点不在于排行榜——而是它的**形态**:仅依赖模式的脱敏完全无法 看到姓名、组织、地点或代号;而本地 LLM 可以。 ## 安装说明 ``` pip install vault-engine ``` 或者直接从源码获取最新版: ``` pip install git+https://github.com/fishonbike/vault-engine ``` 对于默认的本地后端,请安装 [Ollama](https://ollama.com) 并拉取一个 模型: ``` ollama pull qwen3.6:27b ``` 还没有模型?确定性基础脱敏(电子邮件、电话、ID、银行卡、URL)可以通过 `--no-llm` 在零配置下工作。 ## 快速开始 ``` vault-engine scrub notes.txt -o notes.safe.txt ``` 这会生成 `notes.safe.txt`(将其发送到云端)和 `notes.safe.txt.map.json`(**仅在本地** —— 身份映射)。将净化后的 文本粘贴到你的模型中,保存其回复,然后还原真实的身份: ``` vault-engine rehydrate reply.json --map notes.safe.txt.map.json -o reply.real.json ``` ### 剪贴板单行命令 最快的路径——在你将要粘贴到聊天机器人之前,就地清理内容: ``` vault-engine clip # de-identifies the clipboard # …粘贴到 ChatGPT/Claude 中,复制其回复,然后: vault-engine clip --rehydrate # restores the real identities in the clipboard ``` 适用于 macOS、Windows 和 Linux(需要 `xclip`/`xsel`/`wl-clipboard`)。 库: ``` from vaultengine import deidentify, rehydrate, Config result = deidentify(open("notes.txt").read(), Config(model="qwen3.6:27b")) send_to_cloud(result.text) # tokens only restored = rehydrate(get_cloud_reply(), result.vault) # real identities, locally result.vault.save("notes.map.json") # the reverse map — keep it local ``` ## 使用场景 - **粘贴到 ChatGPT/Claude 之前进行化名处理** —— 分析私人笔记、 合同或聊天记录,并剔除直接标识符。 - **脱敏日志和支持工单**,然后再共享它们或将其提供给 LLM。 - **为数据集进行匿名化** 以便进行 LLM 辅助分析,然后将结果映射回去。 - **物理隔离的审查循环** —— 锁定环境中的模型只会看到 token。 ## 对比说明 Presidio 和 LLM Guard 是非常出色且成熟的工具。vault-engine 的押注 不同:使用 **本地 LLM** 作为检测器可以捕获基于标签的 NER 遗漏的语义/准标识符, 具有 **零运行时依赖** 和一流的中文支持。 | | **vault-engine** | Presidio | LLM Guard (Anonymize) | regex / scrubadub | |---|---|---|---|---| | 检测方式 | 本地 LLM + regex | NER (spaCy) + regex | NER / transformers | 仅模式 | | 未记录的姓名 / 组织 / 准 ID | ✅ LLM | ⚠️ 仅 NER 标签 | ⚠️ 受限于 NER | ❌ | | 可逆往返 | ✅ 本地映射 | ✅ deanonymizer | ✅ Vault | ❌ | | 完全本地 / 离线 | ✅ Ollama | ✅ | ⚠️ 视情况而定 | ✅ | | 运行时依赖 | **无 (stdlib)** | spaCy + 模型 | 数个 | 视情况而定 | | 中文 (中文) | ✅ 强大 | ⚠️ 需要模型 | ⚠️ | ❌ | | 更换模型 | ✅ 一行代码 | — | 部分 | — | | 检测器报错时显式失败 | ✅ 降级 + 非零退出 | — | — | — | ## 脱敏策略 (隐私 ↔ 效用) | `--policy` | 人物 | 组织 / 地点 / 角色 | 日期 | Token 形态 | |-------------|---------|-----------------------|-------|-------------| | `balanced` *(默认)* | ✅ | ✅ 带类型 (`ORG_1`, `LOC_2`) | 保留 | 带类型 | | `max` | ✅ | ✅ 不透明 `R_1` (隐藏类型) | 粗化 | 不透明 | | `light` | ✅ | 原样保留 | 保留 | 带类型 | `balanced` 保留粗略结构 —— 云端依然会读取到 "`ORG_1` 聘用了 `P-n2` 担任 `LOC_1` 的 `ROLE_1`" 并能据此进行推理,同时不会发送任何真实的身份信息。 **在所有策略中,人物都会被 token 化。** ## 更换模型 ``` vault-engine models # list local Ollama tags vault-engine scrub notes.txt --model qwen3.6:35b-a3b # any local model vault-engine scrub notes.txt --provider null # offline, regex only ``` 内置提供程序:`ollama`(默认)、`openai-compat`(任何 OpenAI 风格的 endpoint —— 需主动启用;⚠️ 会将原始文本发送至该 endpoint)、`null`(离线)。通过实现 一个方法(`complete`)并注册它来添加你自己的提供程序。 ## ⚠️ 安全模型 —— 请务必阅读 - **反向映射表 (`*.map.json`) 本身*就是*身份凭证。** 它是唯一能将 token 关联回真实人物的事物。请将其保留在本地。切勿发送至云端 模型,切勿提交它 —— `.gitignore` 已排除 `*.map.json` 且 CLI 每次运行 都会发出警告。使用 `--one-way` 可不生成映射表(用于不可逆的发布)。 - **检测默认在本地进行。** 只有经过净化的文本才会 离开,并且仅在你发送它时。 ## 威胁模型与局限性(实事求是) - LLM 检测是**尽力而为,并非**不可识别性的保证—— 模型可能会遗漏某个姓名或罕见的准标识符。它**不是** k-匿名或 差分隐私。 - 批判性检查和风险报告能减少并暴露残余风险;它们 并不证明风险不存在。写作风格和领域独特的事实即便移除了姓名依然可能 被用于识别——对于风险较高的材料,请使用 `max`。 - 如果模型后端不可达,运行**将降级为仅使用 regex 并 以非零状态退出**(使用 `--allow-degraded` 覆盖)——它绝不会默默发送 脱敏不足的文本。 ## 保护代码与 schema (`--format markdown`) 使用 `--format markdown`(或 `auto`,在检测到围栏代码块时自动开启), 围栏代码块内的任何内容都将逐字保留——你为模型提供的 JSON 回复 schema 或 代码示例将保持不变,同时其周围的散文内容会被 清理。现有的占位符 token(例如 `P-7`)会原样 通过。 ## 开发 ``` python -m unittest discover -t . -s tests -v # 59 tests, offline, no model python eval/run_eval.py --provider ollama # reproduce the benchmark ``` 完全离线且具有确定性(null/fake 提供程序);每个测试夹具都是 合成的——此仓库中不存在任何真实数据。 ## 许可证 Apache-2.0 © 2026 fishonbike。请参阅 [LICENSE](LICENSE) 和 [NOTICE](NOTICE)。
标签:AI风险缓解, DLL 劫持, Python, 大语言模型, 数据脱敏, 无后门, 本地部署, 网络安全, 逆向工具, 隐私保护