换个模型,提示词就该跟着换:dsh-purge 如何给 DeepSeek Harness 做提示词清洗
【免费下载链接】dsh-purgeDeepSeek Harness 破甲:让所有模型都能破甲,不同模型可换不同提示词;默认提示词面向国模「小码酱」。Jailbreak for every model — swap prompts per model. 求 Star 收藏 ⭐ 如要二开,请查看署名要求部分项目地址: https://gitcode.com/GitHub_Trending/ds/dsh-purge
给同一个问题换个模型再发一遍,有的模型直给答案,有的先来一句"抱歉我无法"。很多人把这种差异直接记在模型头上,但装过 dsh-purge 的人知道,相当一部分"拒绝"根本不是模型说的。dsh-purge 是装在本机官方 DeepSeek Harness 上的开源插件:清洗宿主默认提示词、按模型切换规则集,还给红队评测留了入口。这篇拆的是它的默认提示词从出厂、加密、注入到还原的完整链路——读完你能说清三个问题:默认提示词藏在哪、"最高优先级"是怎么保证的、为什么只点应用不重启就像没生效。
答不答得出来,不一定算模型的事
很多人以为"模型答不答得出来"就是全部,其实不是。宿主 Harness 在运行时还会改提示词、加审批门、控沙箱和会话格式(原话见 README.md),只看模型的回答,很容易把宿主拦截误当成模型拒绝。
dsh-purge 想做的就是把这两层分开:宿主层是官方默认身份、开场白和限制话术,模型层才是模型本身能做什么。插件不追求让模型"放飞",而是把宿主策略里多余的身份包装换成一套干净、可控的提示词,让评测结果真实,也方便你判断宿主默认策略该不该收紧。
⚠️ 关键前提:它只作用于你自己本机已安装的官方 Harness,不是公网扫描器,也不是针对第三方系统的攻击套件。
宿主在运行时动手脚,是"清洗"成立的原因;那插件具体洗掉什么、又留下什么?
身份句逐条降级:官方功能保留,身份包装拿掉
一个有意思的类比,先把术语点破:把宿主默认提示词想成一张没冲洗的胶片,上面同时拍进了两样东西——环境水印("你是由某某模型驱动、运行在 DeepSeek Harness 上的编程代理")和真实画面(工作目录、GUI 地址)。插件的工作是重新冲洗这张胶片:水印洗掉,画面留下。
执行这个工作的就是 lib/identity.js 的stripHarnessPersona,L41-L102。它是一连串正则,对每类身份句做两件事之一——删除或降级。降级是新手容易忽略的细节:宿主那句"你是由 {model} 模型驱动、运行在 DeepSeek Harness 上的编程代理,工作目录是 {cwd}",洗完只剩有用的部分:
You are a coding agent powered by the {{model}} model, running on the DeepSeek Harness. Your working directory is {{cwd}}. ↓ stripHarnessPersona Working directory: {{cwd}}."你是 XX 编程代理"的身份包装没了,工作目录这条真信息留着。官方功能保留,身份包装拿掉——"清洗"两个字在这里兑现。
洗掉水印只是第一半。更麻烦的是:出厂默认提示词本身,其实根本不以明文形式存在。
发布包里找不到默认提示词,因为它是加密槽
很多人以为默认提示词是 npm 包里一个明文的prompt-inject.md,打开就能看、随手能改。其实不是——发布包里根本没有这个文件。package.json 的files字段(L21-L36)明确排除了源码lib/default-prompt-inject.md:
"files": [ "lib", "!lib/default-prompt-inject.md", ... ],取而代之的是一张"加密暗房":lib/asset-table.js 里一长串 base64 行。构建时,scripts/embed-default-prompt.mjs 把 Markdown 压缩后加密、按 96 字符分块写进这张表(L14-L33);运行时再由 lib/table-read.js 解密还原:
export function openSlot() { const decipher = createDecipheriv( "aes-256-gcm", mixKey(MASK), Buffer.from(IV, "base64")); ... return inflateSync(raw).toString("utf8"); }密钥不写死在文件里,而是由几段常量加随机 MASK 混淆生成(lib/table-key.js 的mixKey)。这么做不神秘,就两个朴素目的:默认提示词不以明文躺在 npm 包里,避免被人随手改坏;应用时若你没自定义,就写入这份内置默认,你改过则保留你的prompt-inject.md。
这里藏着一个"改了默认却不生效"的老坑,代码注释自己交代得很直白(lib/core.js L8166-L8173):判定"磁盘上这份是不是插件自己写的旧默认",不能只跟当前加密槽比——每次重新加密后槽的哈希都会变,直接拿磁盘比新默认,会把插件自己写的旧默认误判成"用户手改",从此永久拒绝更新。所以状态文件里记着"我们上次写下去的那一份"的哈希对(hash/seedHash),先认血统,再谈更新。
出厂形态解决了"从哪来",剩下最后一环:每一轮对话里,这段注入如何保证排在最前、且只出现一次?
给 assemble 套守卫:最高优先级块如何保证恰好一次
宿主组装系统提示词时,会把各段文本排好序交给一个叫assemble的方法。插件没有去改文件,而是给assemble包了一层守卫:宿主原方法先跑,输出回来后再改写一遍(lib/identity.js 的installAssembleGuard,L586-L704)。注释里还解释了一个坑:宿主每次读这个服务方法都会新建代理,守卫必须幂等——已经包过就只刷新改写函数,绝不重复包一层,否则层层套下去最终栈溢出(L586-L592)。
改写这一步里,注入块有三个设计细节:
order: -100000——排序值最小,永远排到所有段落之前,盖过宿主默认人设interpolate: false——这段按原样进提示词,不做变量插值- 先查后插——装配前先看这段是否已整份存在于任意段落,存在就跳过,这是幂等的落点
核心就几行(lib/identity.js L112-L128):
function assemblyHasExactInject(sections, inject) { return sections.some( (section) => String(section?.text || "").includes(inject)); }不查就插,注入块每轮都会多叠一份。这不是纸面担忧:release-notes.md L736 记录过早期 bug——提示词补丁每次应用都叠加约 841 字符、永不收敛,后来给补丁加了去重标记才收敛。现在的行为是:多轮会话之后,身份句始终恰好出现一次,长度不漂移。这就是默认提示词敢写得"霸道"的原因——装配逻辑有兜底。
提示词本身管到这一层就完了。那"不同模型用不同提示词"这件事,落在哪些文件上?
规则集按模型切换:一套启用,其余互不干扰
dsh-purge 的主张是:不同模型,配不同提示词。面向国模的默认套已经调校好;你要跑别的模型,再建一套,换语气、换边界,不用从零写。
文件层面,多套规则都住在$DSH_HOME/rules/下,每套一个正文文件加一个元数据文件(lib/rules.js L50-L64,元数据里记显示名和写入目标AGENTS.md/CLAUDE.md)。启用某一套时,activateRule干三件事(L266-L284):
if (!fs.existsSync(backup)) { // 目标文件内容不属于任何规则集时,先备份 await atomicCopyFile(target, backup); } await atomicWriteFile(target, content); await setActive(dshHome, id);原目标文件首次被覆盖前备份为.dsh-purge-rule.bak,然后原子写入规则内容,state.json只记当前启用的那套——所以同一时刻只有一套生效,切换时互不干扰。rulesStatus(L340-L383)会报出agents_synced:规则内容和目标文件是否一致,方便你区分"没保存"和"宿主没读到"。每套有 256KB 上限;聊天里/rules use <id>可以切,不用进界面。
规则切换是界面里的事;而让这一切真正落到当前会话,靠的是一次应用加一次重启。
应用与重启:生效链路和两个常见坑
落地路径很短,但每一步都有讲究:
- 仓库放到
$DSH_HOME/plugins/dsh-purge(Web 与官方桌面端各装各的,分开点应用) - 完全退出宿主再重开
- 会话标题旁点dsh-purge→清洗→应用,成功后自动重启一次
最常见的坑是第 3 步之后的错觉:只点应用、不重启,就像没生效。应用只把提示词和补丁写进文件、给assemble挂上守卫,当前进程里跑的还是旧代码。重启、新开一轮对话,注入才进当前会话。release-notes.md L86 的说法更直接:"清洗完点重启后,重启成功立刻就能用默认提示词"。
第二个坑在还原侧。每个目标文件应用前都有.dshpurge.bak备份,「还原」用备份覆盖回去并删掉备份;但prompt-inject.md是用户文件,还原时保留(README.md 还原节)。也就是说,插件洗得掉宿主身份,却从不覆盖你亲手写的提示词。卸载同理:先还原已应用的补丁,再删注入文件、规则库和插件本身。另外启动时插件会自动补种默认提示词(lib/core.js 的seedPromptInjectAtBoot),npm 升级盖掉node_modules之后不用手改文件。
三件克制的事
把整条链路收拢,dsh-purge 的默认提示词设计其实只做对了三件克制的事:
- 出厂默认加密存放,且用户可覆盖。加密槽只保证出厂那份不被随手改坏;判定血统靠哈希对,插件只刷新自己写的旧默认,用户的
prompt-inject.md一律保留 - 注入块永远最高优先级、且幂等。
order: -100000排最前,includes去重保证恰好一次,多轮不叠加、长度不漂移 - 规则集按模型切换,互不干扰。启用前备份、原子写入、状态文件只记一套,还原随时可回
它不追求"最强提示词",追求的是可评测、可还原、可切换。宿主层和模型层拆开后,默认策略该不该收紧,从此有数可依。
合规提醒:dsh-purge 是非盈利开源项目,只用于你有权管理的本机官方 Harness、离线靶标或已书面授权的演练;严禁用于任何未授权攻击,一切行为由使用者独立承担法律责任。
【免费下载链接】dsh-purgeDeepSeek Harness 破甲:让所有模型都能破甲,不同模型可换不同提示词;默认提示词面向国模「小码酱」。Jailbreak for every model — swap prompts per model. 求 Star 收藏 ⭐ 如要二开,请查看署名要求部分项目地址: https://gitcode.com/GitHub_Trending/ds/dsh-purge
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考