# 我给 AI 装了一个「潜意识」 > **一句话**:一个 DSH 插件,在模型动笔回答之前,先让它听见几件它自己不会注意到的事—— > **「你本来在干什么」、「这个之前好像发生过」、「这不对吧」。** > > 零第三方依赖 · 2 个工具 · 核心部分**不调用任何 LLM**。 --- ## 起因:三个真实发生过的事 这个项目不是从"我想做个插件"开始的。它是被三件事逼出来的。 ### ① 一个能跑的工具,等于不存在 作者先做了一个"疑惑哨兵":读模型的思考,检测"不对劲",给导航。**能跑,有效。** 然后它没有进任何一份流程文档。新窗口进来,读到的是必读卡和交接文档——**两份里都没有它的名字。** > **工具做出来了没用;得让它【在需要的时候自己出现】。** ### ② 靠"想起来去跑"的监控,等于没有监控 第一反应是"写进必读卡,让人记得跑"。 **这个反应是错的**: > **靠接手者"想起来去跑"警觉,等于让被监控者自己决定要不要被监控。** > **而一旦它开始漏事——那正是该报警的时候——它会同样漏掉这个报警。** 学术上这叫**元认知监控**,结论正好是:**监控者与被监控者若出自同一个模型,会共享同一个失败模式。** ⇒ 所以警觉必须是**外部的、自动的**,不是"被想起来的"。 ### ③ 它差点把我推进一个出不来循环 v1 的做法是"每轮把检测结果注入 system prompt"。看起来最直接,实际上埋了雷—— - 它**读了模型的思考通道**,而那个通道是**强制回传**的; - 于是模型**看见自己上一轮的痕迹,把它当成紧邻前缀,接着写**——自我强化。 - **实测:一段很长的会话里,推理通道真的出现了循环问题**(后经全库扫描确认:**只此一处,且只在单个会话里**)。 > ⚠️ 这里只说"发生过",**不写具体形态与占比** —— 那是刻意的,原因见文末「描述即传播」。 **最贴切的类比是"假醒"**:人在假醒循环里出不来,是因为"我要醒来"这个念头**本身也是梦的一部分**。 模型侧的对应是:**"我要谨慎一点"也是同一层生成的文本。** **⇒ 靠"再想一次"自救是没用的。要调一个【外部的、有反馈的】动作。** --- ## 它现在做什么 装完之后,模型在正式回答前会先问自己一次。它可能听到三种声音: ### 🔹「你本来在干什么」—— 锚点 ``` ⚓ 目标:给 dsh-alert-inject 写使用文档|子目标:补环境要求这一节 ⚠️ 目标被改过 2 次 —— 改目标需要理由(原目标不可行/有更优);理由是否成立由你判断 ``` **要解决的问题**:模型读了很长的文本之后,会**忘记自己在干什么**——不是目标消失了,是它**被挤到上下文边缘**了(这就是 [Lost in the Middle](https://arxiv.org/abs/2307.03172) 讲的注意力 U 型曲线)。 **做法**:把日志里已经存在的目标(`goal` 事件)、子目标(`todo` 事件)、长期约束(system prompt 里的规则块)**重新摆回眼前**。 **它不判断"你是否偏离了"** —— 只把锚点摆回来。因为"偏离"是语义判断,而这个项目**已经两次实测证明做不了**(NLI 三版全败;向量比对差异 −2.8pp 且方向相反)。 ### 🔹「这个之前好像发生过」—— 检索 ``` 📍 pos=876 · 思考 · 相似度 69% · 相关 ``` **关键设计:只给指针,不给原文。** 这不是妥协,是**机制**——对应的是 déjà vu 的 **`decoupled familiarity`**: 颞叶只发"这事发生过"这个信号给额叶决策区,**不把内容一起送上来**。要内容,主模型得按指针自己去取(`peek(pos)`)。 **为什么必须这样**:报一次 = 把内容写进上下文 = 下一轮又被匹配到 = **自我喂食**。这正是 v1 那个循环的成因。 ### 🔹「这不对吧」—— 检测器组 | 声音 | 怎么做的 | 成本 | 实测 | |---|---|---|---| | **我正在重复自己** | n-gram 统计 + 滑窗 | **0**(2.6ms/段) | **误报 0%**(271 段真实文本) | | **引用的东西不存在** | 查文件系统 | **0** | 误报 5.1%,**6 个命中人工核实全为真阳性** | | **当前语境内有可疑痕迹** | 判据表 + 与门 | **0** | 实测 | | **我好像知道这个** | 复用检索结果 | **0** | 分类 **10/10** | | **这是新东西** | 复用检索 + 术语覆盖 | **0** | 三档全对 | **⇒ 六个检测器里五个是纯程序,零成本。** --- ## 三个我认为值得单独讲的优化 ### ① 「当前语境 0 处」—— 误报的真正来源 **这是整个项目里最有价值的一次测量。** 原先的报警是这样的: ``` 我的老毛病 · 检出 12 处 · 最早第 272 处、最近第 1080 处 疑惑 · 检出 33 处 · 最早第 295 处、最近第 1055 处 ``` 看起来挺像回事。但作者要求"**基于上下文分块**"之后,我们量了一下: ``` 「我的老毛病」12 处命中 → 分布在 7 个不同语境块 「疑惑」 33 处命中 → 分布在 10 个不同语境块 ★ 当前块内命中:0 处 ``` **⇒ 全库报 45 处,当前语境 0 处 —— 100% 是跨语境的误报。** **这不是判据不准,是判据在错误的语境外报了。** 改法很便宜:按**用户每次发言**切块(用户说话 = 新指令 = 新语境),然后**只报当前块内的**。其余降级成一行计数。 **⇒ 45 处噪声 → 0 处。** > 顺便,这个分块同时解决了另一件事:**目标是会在局部改变的**。 > "模块 57 在谈教训记录"和"模块 52 在谈 token 显示"是不同的事,不该共用一套判据尺度。 ### ② 「608 字 → 60 字」—— 把报告改回成一个声音 锚点和语境加上之后,输出变成了这样: ``` 608 字 / 17 行 / 13 个列表项 / 列表项占 76% ``` **⇒ 这不是"一个声音",这是一份结构化报告。** 但第一次修复**修过头了**——砍到 207 字,却变成另一种失败: ``` 【自查结果】以下是【当前语境】内的痕迹(已扫 990 条 / 分 54 块) (另有 26 处命中在【其他语境】里 —— 与当前话题可能无关,故未展开) 按需核对即可;不必为它中止回答或重写整篇。 ``` **⇒ 这是"礼貌的空话"——说了 207 字,一条具体所指都没有。** **⇒ 现在 60 字,一句话,指出一个模式:** ``` 🧩 已换过 59 段话题 —— 主线目标值得回头确认一次(当前在谈:…) ``` **两条硬规矩**(借了 [dsh-plugin-save-token](https://github.com/vibe-any/dsh-plugin-save-token) 的 **never-worse 门控**思路): 1. **没值得说的就不出声** —— **"我查了,没找到"不构成信息。** 2. **一旦出声,必须有所指** —— 要么指向具体位置,要么指出某个模式。 ### ③ 「规则 93% vs 模型 50%」—— 但规则是死的 我们做过一次对照:让程序判断"这条结论是可复用知识还是操作决策"。 | 方案 | 准确率 | 耗时 | **能长吗** | |---|---|---|---| | 规则 | **93%** | 0 | ❌ **永远是 93%** | | qwen2.5:3b | 50% | 2.7s | ❌ | | **Laya(特化决策引擎)** | 50%(零样本)→ **76.6%(校准后)** | **130ms** | ✅ **能** | **第一轮我们差点得出"规则完胜"的结论——那漏掉了一个维度:规则不会长。** ⇒ 于是有了**样本层**:每次判断都记一条,等攒够了训练特化模型。 ⇒ 而这个项目的结论是:**能用的那两样(查表、向量检索)恰好都不需要模型**——所以大部分检测器就该是纯程序。 --- ## 一个必须说清的边界 **它不做语义判断。** "这两句是否矛盾"这类问题,这个项目**实测失败过两次**: - **NLI 三版全败**(整段/拆句/断言化)——**排序错,不是阈值错** - **向量相似度**:含错误的样本 59.3% vs 无错误的 56.5%——**差异 −2.8pp,方向还反了** **⇒ 根因:向量度量的是「话题像不像」,不是「预期是否实现」。** 所以它的定位很清楚:**做能做的(事实核对、统计、检索、图遍历),把判断留给人和模型。** --- ## 装上之后 **环境**:需要 **DeepSeek Harness(DSH)**。⚠️ **不是通用插件**——它依赖 DSH 的工具 API 和会话日志格式。 **必需依赖:无。** 可选装 Ollama + bge-m3(1.1 GB)解锁语义检索那三项,**不装则其余全部照常**。 **性能实测**:一次自查 **0.6~0.9 秒**;首次建索引 120 条约 15 秒(全量约 8 分钟)。 --- ## 我想要什么反馈 **这个项目最需要的不是点赞,是三件具体的事:** ### ★★★ 它在你这儿「报了什么没用的话」 请贴出**实际输出** + **你当时在做什么** + **那句话对你有用吗**。 **为什么这是第一位**:本项目的核心矛盾是**误报**。我们测出的"当前语境 0 处"结论**来自单一项目**——**你的项目里是不是这样,我不知道。** ### ★★ 你在什么场景下想到它 **它现在的用法是"回答前自查"。但最初的设想是「一个声音在你思考时提醒你」。** ⇒ **你会在什么时候希望它响?** 这个答案决定下一步往哪走。 ### ★ 明确的失败 崩溃、报错、卡住、装不上 —— 请带上**完整报错**与**环境**。 > **尤其是这一类**:我们踩过一个「**离线测了 27 项全绿,一挂上就报错**」的问题 > (工具返回了 `undefined`,DSH 拒收整个返回值)。 > **那类问题只有真实运行才会暴露——你的环境很可能还有别的。** --- ## 一个刻意的留白:为什么不写症状细节 这篇文里,凡涉及那次循环问题的地方,**我都只写"发生过",不写具体形态、不写占比数字**。 **这不是偷懒,是有意的。** > **描述它的文本本身,可能成为传播介质。** 机制很朴素: 1. 检测靠**词表/模式匹配**工作; 2. 而描述症状,**必然要引用那些词**; 3. ⇒ **描述一次 = 往上下文里植入一轮样本**; 4. 若那段描述进入模型的思考通道,**下一轮它必然再看见一次**。 **⇒ 所以本项目把内容分了三层**:对话只讲机制、报告留完整病程、源码只留结构说明。 **⇒ 引用时请引用路径,不要引用症状文本。** —— 包括"为了举例说明"。 --- ## 最后 **这个项目真正的赌注不在"零件多",而在"能不能长起来"**: ``` 规则冷启动(今天就能用) → 攒样本(机制已就绪:605 条判断 + 184 条纠正自带标签) → 训练特化模型(已实测过这条路:36% → 76.6%) ``` **⇒ 而当前唯一缺的动作是「标注」。** **⇒ 也就是说:你现在就能帮到它——当你纠正它的时候,那就是一条训练样本。** --- *本文由项目作者与 AI 协作完成。文中所有数字均为本机实测,非估算。 设计文档见 `PLUGIN.md`,故障记录见 `REPORT.md`。*