llm-wiki-compiler 安全模型深度解析:fail-closed 配置、路径限制与审查门如何构建可审计的 AI 知识库
【免费下载链接】llm-wiki-compilerThe knowledge compiler. Raw sources in, interlinked wiki out. Inspired by Karpathy's LLM Wiki pattern.项目地址: https://gitcode.com/gh_mirrors/ll/llm-wiki-compiler
llm-wiki-compiler(命令名llmwiki)是一个"知识编译器":把原始资料(笔记、论文、网页、PDF)一次性编译成带引用、带审查状态的互联 Wiki。而它最被低估的能力,是内建的安全模型——fail-closed 配置、路径限制、审查门三道防线,让 AI 生成的知识库在可审计的前提下运行。本文用通俗的方式带你拆解这套机制。
为什么 AI 知识库需要"安全模型"?
🤖 传统 RAG 工具每次提问都去翻原始文件;llmwiki 的思路是先编译、后复用——把知识固化为页面,积累结构、来源引用和审查状态(见 docs/concepts/karpathy-pattern.mdx)。
但"AI 写内容"本身就带风险:模型可能输出低置信度结论、伪造引用、甚至被恶意文件"夹带私货"。llmwiki 的应对哲学是一句话:规则由运行时强制执行,而不是写在提示词里做约定。违反规则的操作不是"警告后继续",而是直接失败。
Fail-closed 配置:出错就停下,绝不悄悄放行
Fail-closed(失败关闭)的意思是:当配置无法理解时,系统选择"拒绝工作",而不是"降低标准继续工作"。这在安全领域很常见(比如门禁读不懂卡片时应该关门,而不是开门)。
llmwiki 中几个典型的 fail-closed 场景:
- 审查策略配置:
.llmwiki/config.json中出现未知的拦截模式名、或配置文件损坏无法解析时,编译会直接报错中止,而不是静默禁用审查、把所有页面都写出去。这防止了一次手误悄悄绕过审查门(docs/configuration/review-policy.mdx)。 - 状态文件版本不匹配:如果
.llmwiki/state.json是更新版本写入的,命令会失败关闭,并提供state reset备份后重建的路径(docs/troubleshooting/state-recovery.mdx)。 - 生命周期配置文件:fail-closed 的
.llmwiki/profile.json一旦非法,声明的实体、关系、工作流全部拒绝生效,绕过声明门写入的操作同样失败(README.md 中 "Configurable Lifecycle Profiles" 一节)。
一句话总结:宁可不跑,也不带病跑。
路径限制:任何文件都不能"逃出"项目目录
🔒 这是 llmwiki 源码里着墨最多的一条防线。它要防的攻击很具体:假设wiki/或sources/下混进一个符号链接,指向项目外部的敏感文件(甚至/etc/passwd)。如果编译器"顺着链接读",外部内容就会被读进来、写进生成的页面、甚至塞进 LLM 提示词。
llmwiki 的解法集中在两个工具模块:
- src/utils/path-confine.ts:提供路径"围栏"判定——先解析真实路径(realpath),再确认它确实落在预期目录之内;对
sources/里的符号链接直接判定"不是合法源文件",读、列、写三条路径使用同一份定义,避免各说各话。 - src/compiler/confined-wiki-read.ts:编译时读 Wiki 页面用的是"精确目录围栏 + 不跟随符号链接 + 绑定已打开文件句柄"的读取方式。一旦路径逃出项目根目录,在读取发生之前就返回"丢弃",逃出去的内容一个字节都不会进入写入计划或模型提示词。
而且被丢弃不是静默的:文件真实存在却逃出围栏时,终端会打出醒目的黄色警告,点名是哪个文件、什么机器可读的原因——"逃逸链接永远不会被悄悄跟随"(src/compiler/confined-wiki-read.ts)。
这种"文件句柄绑定"还顺带防了一类更隐蔽的竞态:读取路径和解码内容之间文件被替换(TOCTOU 攻击),读到的字节永远属于你打开的那个文件(src/utils/confined-read.ts)。
审查门:AI 写的内容,人点过头才发布
🚦 第三道防线是审查门(review gate),由 src/trust/ 目录下的信任执行器统一落地。
默认行为下,compile会把生成的页面直接写入wiki/。你可以把"摩擦"加上去:
- 全量审查:
compile --review让每一页候选都进队列,批准前wiki/纹丝不动; - 按风险拦截:在配置里声明拦截模式,普通页面照常直写,只有命中风险条件的页面被"扣下"——低置信度(低于阈值)、与已有页面矛盾、违反 schema 链接规则、引用损坏(docs/cli/review.mdx)。
被扣下的页面不是"悬空"状态,而是进入.llmwiki/candidates/留档,附带上具体原因码;在线的旧页面保持原样,直到你执行review approve把它转正、或review reject归档丢弃。每次编译结束都会汇报"写了几篇、扣了几篇",队列随时可用review list清点(docs/configuration/review-policy.mdx)。
在 1.0 引入的可配置生命周期配置中,这种审查还能绑定到状态机迁移上:页面从 draft 到 published 的每次迁移都要满足配置声明的证据与信任门,写路径强制执行,事后由 standing lint 复查漂移(docs/concepts/configurable-lifecycle-profiles.mdx)。
可审计性:每个结论都能追到出处
✅ 三道防线之外,llmwiki 还让"审计"成为日常动作:
- 引用即证据:页面中的段落与论断引用源文件的文件名和行号范围,
llmwiki lint校验链接与引用有效性(docs/concepts/citations.mdx); - 质量记分:
llmwiki eval输出健康分、逐页健康分布、引用覆盖率与精度,最差的页面会被点名(docs/cli/lint-eval.mdx); - 变更留痕:信任层的日志(journal)记录迁移前置状态、恢复与回滚,src/trust/journal.ts 让"谁在什么时候改了什么、依据是什么"可回放(docs/guides/ci-quality-gates.mdx 展示了如何在 CI 中把 lint/eval 变成质量门)。
小结:三条防线一张表
| 防线 | 防什么 | 行为 |
|---|---|---|
| fail-closed 配置 | 配置错误/损坏被静默绕过 | 直接中止,绝不降级运行 |
| 路径限制 | 符号链接逃逸、外部文件混入 | 围栏外内容不读、不写、不进模型提示词 |
| 审查门 | 低置信度/矛盾/引用损坏的内容入库 | 扣入候选队列,人工批准后发布 |
对新手来说,记住一点就够了:llmwiki 把"安全"从提示词约定变成了运行时执行——这也是它敢说"编译一次,复用很久"的底气。想动手试试,可以从 docs/quickstart.mdx 跑一个最小项目开始。
【免费下载链接】llm-wiki-compilerThe knowledge compiler. Raw sources in, interlinked wiki out. Inspired by Karpathy's LLM Wiki pattern.项目地址: https://gitcode.com/gh_mirrors/ll/llm-wiki-compiler
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考