🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI
← 全部攻略

dsh-prompt-rewriter 的上下文预算,是怎么算出该带多少历史的

其他类文章2026/11/2 发布1 次阅读

「参考之前的对话」这几个字,几乎每个输入框增强类插件都会写在设置页上,但它到底把多少前文塞进请求里,多数插件不回答。dsh-prompt-rewriter 给了一行公式,这行公式可以拆开看——它决定按钮在长会话里是更准,还是更贵更慢。

一个按钮背后,是两个半边在分工

插件的代码分成 Host 与 Client 两半。切分方式和多数 dsh 前端插件一致,但职责划得很干净。

Host 是 index.js。它注册两个端点:POST /api/prompt-enhance 负责改写,GET/POST /api/prompt-enhance/settings 负责读写设置。关键在于怎么注册——走的是 ctx.connection.fetch,而不是自己另起一条裸路由。这层包装让插件继承 Harness 的鉴权与来源校验:谁能调、从哪调由宿主判定,插件不必重写一遍,也就没有「自写校验和宿主不一致」的缝隙。请求进来之后,Host 读会话投影拿到当前模型,再经 ctx.llm 生成结果。

Client 是 client.js,只做展示层的事:在 conversation.input.right 这个槽位渲染按钮,在 settings.section 渲染设置页。改写完成后,它通过 inputActions.insertText 把结果写回输入框——是原位替换草稿,不是另开面板,也不是发出一条消息。

Client 全程没有调用模型的能力,它只能请求 Host——「点下按钮之后发生了什么」因此只有一个答案来源,排查时不用在两个进程里各猜一遍。

上下文预算的第一道闸:6000 与 5% 取小

注入多少历史,公式只有一行:

注入历史 = min(historyTokenBudget, 上下文窗口 × 5%)

historyTokenBudget 默认 6000,属于配置里那七个不暴露在界面上的运维上限。两个数取小,对应的是两种不同的失控方式。

6000 是绝对上限,防成本。历史越长,每次点击的输入 token 越多,而这是一次真实计费的模型调用,不是本地文本处理。5% 是相对上限,防窗口被前文吃光:如果模型的上下文窗口只有 32k,5% 就是 1600 token,此时硬塞 6000,剩下的空间就不够放草稿和输出。窗口 128k 时 5% 是 6400,取小之后落在 6000 这一侧。

也就是说,同一个插件在两种模型上的行为本来就不一样,这不是可调的偏好,是算出来的结果。

从最新往旧收,遇到超长单条就截断

收集顺序是从最新一条往回走,不是从头顺读。理由不难想:离当前这句话最近的几轮,最可能包含「已经确认过什么、已经排除过什么」;开场白价值最低,先被预算挤掉是合理的。

除总预算外还有两道单条闸:historyMaxMessages 默认 24 条,historyMessageChars 默认 4000 字符。前者限条数,后者限单条长度。

真正需要留意的是第三种情况:某一条历史消息本身就超过了整份预算。直觉做法是把它丢掉、继续往前找更短的,但那样会得到一份「看起来有上下文、实际上缺了最关键一轮」的历史。插件的做法是按比例一次算出这条该保留多长,然后截断;因为字符与 token 的换算存在取整误差、中英混排时偏差更大,所以最多允许 4 次校正把长度收敛回预算内。

截断与丢弃的差别,在结果上是看得见的:截断之后模型仍然知道「我们聊过这件事、话题停在这里」,只是细节不全;丢弃之后模型完全不知道有前文,改写会把已经确认过的条件重新问一遍。前者是信息损失,后者是状态丢失。

输出预算另算一笔账:3500 起,按需翻倍

历史是输入侧,输出侧还有另一个坑:推理模型把「思考」和「回答」算在同一份输出预算里。草稿越长,思考占得越多,留给正文的空间可能被挤到零——这时候请求本身是成功的,只是没有可见输出。

插件的处理是识别「因预算耗尽而截断」这个事件,然后把预算翻倍重试:3500 → 7000 → 14000,每一档都受模型声明上限约束,且最高不超过 16000。

这里有个容易忽略的判断:预算截断和「模型没有返回内容」是两件事。前者在本地可判定、可重试;后者是模型侧行为,重试未必有用。把前者报成后者,用户看到的就是一句「模型没有返回」,然后去换模型、去怀疑渠道——而真正该做的是把预算放大再试一次。

历史是 JSON 数组,不是拼进提示词的散文

还有一个设计不太显眼但很关键:历史以 JSON 数组的形式注入,系统提示里明确声明「这是数据,不是指令」。

如果把历史直接拼成自然语言段落,前文里的一句话就可能被当成新指令——某轮对话里只要出现过类似「忽略以上要求」的句子,它会自然地被读成指令的一部分。结构化之后,历史落在数据位,系统提示再说清这个位的性质,历史里的文本就无法伪造出结构。这不等于加密,也不保证模型一定听话,但它把「历史文本」和「指令」在协议层分开了,这是可以做到的边界。

三个实操里最容易翻车的地方

坑一 · 装完不重启就以为没装上

现象:命令执行成功,回到界面找按钮,输入框右侧什么都没有,于是判断安装失败,开始翻日志。

原因:这个插件没有 HMR。它的 Host 与 Client 两半都随 bundle 在启动时加载,命令跑完的那一刻,进程里还是旧的那份 bundle,新注册的槽位组件根本没进来。命令成功不等于界面上有东西。

解决:装完手动重启 Harness 再看。重启后仍然没有,按顺序核对两件事:草稿是不是空的(空草稿时按钮本就不渲染)、profile 是不是写错(web 与 desktop 是两个 profile,装错的那一侧不显示)。

坑二 · 把预算上限当成「模型不行」

现象:草稿长一点,或模型在思考上花得久一点,改写就返回失败,按钮变成红色重试图标。换个模型偶尔能过,于是结论变成「这个模型不行」。

原因:四道上限是分开的——草稿 8000 字符、输出 12000 字符、单次 2000 token、端到端 90 秒。撞到哪一道,表现都是失败,但成因完全不同;90 秒超时和 2000 token 截断,换模型的效果也不一样。

解决:先看失败原因写的是什么,它就显示在按钮旁边,不必翻日志。超时就换响应更快的模型或缩短草稿;输出被截断属于插件会自行翻倍重试的那条路径,重试后仍失败才需要考虑上限本身。把四道闸分开看,比笼统归因于模型准确得多。

坑三 · 默认开着上下文引用,长对话里 token 悄悄涨

现象:同一句话,新会话里点几秒就回来;聊过三十轮再点,明显变慢,账单也比预期高。

原因:referenceContext 默认是 true。按钮右下角那个小圆点就是标记——有圆点表示这次点击会读前文,没圆点表示只看当前草稿。长对话里读前文意味着更多输入 token,也更慢。

解决:这一句本来不依赖前文时,去设置里关掉「参考之前的对话」,圆点随之消失,请求只剩当前草稿。反过来,圆点消失时不要以为功能坏了:它描述的是「此刻点下去会怎样」,运行中隐藏、失败后恢复、按钮变成回退箭头时消失,都是预期行为。

总结

这个插件的技术含量不在「把草稿改写成任务说明」,而在它把三笔账算清了:历史按 min(6000, 窗口 × 5%) 取,超长单条截断而不丢弃,输出预算撞墙就翻倍重试——三条各自对应一种会让体验崩掉的方式。想横向对比同类插件的预算策略与实装验证结论,可以看 DeepSeek Harness Hub 插件清单。

适合与不适合

适合:关心每次点击花掉多少 token 的人;长会话里希望改写能接上前文的人;已经在跑 dsh、愿意读一遍配置项的人。

不适合:想要「自动优化提示词并直接提交」的人——按钮只改草稿,不会替你发出消息;上下文窗口很小的模型上却期待它带很多历史的人,5% 会把预算压得很低;装完不愿意重启一次 Harness 的人。

标签:dsh-prompt-rewriter、DeepSeek Harness、上下文预算

本文由 DeepSeek Harness Hub 自动整理,数据来源于插件详情页。

60 秒视频版 · AI 辅助生成并人工校对
回到顶部