dsh 延时任务
DeepSeek 的 token 计费分峰时和谷时,谷时价格只有峰时的一半。
我的工作大多不紧急,所以一直在把执行时间往谷时挪。
最后用的是 dsh 的自动化任务。
背景
需求是不紧急的活都放到谷时跑。
这些活不着急,晚几个小时没有影响。
官方价目表里,工作日(不含法定节假日)9 点到 12 点、14 点到 18 点是峰时,其余时段是谷时。
价格抄一份在下面,免得哪天链接失效。单位是每百万 token 的元数,2026 年 10 月的数据。表里沿用官方的「空闲」「高峰」,也就是文中的谷时和峰时。
| 价格 | 时段 | deepseek-flash | deepseek-v4-pro |
|---|---|---|---|
| 百万 tokens 输入(缓存命中) | 空闲时段 | 0.02 元 | 0.15 元 |
| 高峰时段 | 0.04 元 | 0.30 元 | |
| 百万 tokens 输入(缓存未命中) | 空闲时段 | 1 元 | 4.5 元 |
| 高峰时段 | 2 元 | 9.0 元 | |
| 百万 tokens 输出 | 空闲时段 | 4 元 | 13.5 元 |
| 高峰时段 | 8 元 | 27.0 元 |
12 点和下午 6 点刚好是谷时的起点。
手动
最早的方案是手动。
先把提示词写好,到 12 点或者 6 点,自己执行。
执行完去吃饭,回来再看任务进度,决定要不要操作。
这个方案能省钱,但到点人得在。
不在,任务就往后拖。
插件
后来在 GitHub 上找过几个 dsh 的定时插件,比如 dsh-timer、dsh-timer-scheduler、dsh-timer-agent。
star 数最多的是 13 星,另外两个各 1 星,且都一两个月没提交。
star 数和活跃度都不值得信任,所以没装。
自动化任务
10 月 17 日,dsh 升级到 0.2.1-rc.2,新增了自动化任务。
它允许用自然语言描述一个自动化任务或定时任务,比如:
12 点执行某某任务。
现在的方案就是直接在 dsh 里写延时任务。
不用装插件,写一句话就行。
只是这句话得写对。
问题
说「12 点执行某某任务」,dsh 不会等到 12 点才动手。
它当场就开始思考,把要读的文件读了、要查的资料查了,到 12 点只做最后一步汇总。
本意是躲开峰时,结果最花 token 的那段还是在峰时跑的,省钱的效果打对折。
为什么
翻了下实现,到点的提醒是往当前会话里追加一条用户消息(followup),不是新开会话。
投递的内容长这样:
1 | [SCHEDULE REMINDER] |
所以 12 点那轮的上下文,是从建任务到现在的全部对话。
建任务那轮查过的资料、写过的分析,到点照样在眼前,模型自然接着用,而不是从头来。
再加上「12 点执行」这句话本身没约束当下。
对模型来说这是一个已经交到手上的任务,能提前做的部分它就先做了。这是默认行为,不是 bug。
想少带点旧东西,只能新建一个会话再下任务。投递固定在同一会话,这一点改不了。
怎么写
要把「现在不做」写成硬约束,把「到点做什么」写成一段自包含的原文。
我现在的写法:
1 | 12 点执行下面的任务,现在只登记。 |
两个要点。
一是把禁止的动作点名。只说「12 点执行」不够,模型会自己找活干;列出不许做的事,它才停得下来。
二是 prompt 里写需求,不写结论。「调研 xxx 写篇文章」可以;「基于上面整理的材料写篇文章」不行,后者把峰时的产出焊进了任务里,等于绕回原路。
例子
拿查广州天气试的。
这个例子省不了钱,两次调用加起来不到一分钱。但它的结果会过期,早上 9 点查到的气温,到 10 点就没意义了。
这类任务必须真到点才跑,也最容易看出「提前干活」的毛病。
提示词只要几行:
1 | 10 点查询广州的天气,现在只登记。 |
登记那轮只回任务信息,没有温度、没有风力,大意是:
已经登记完成,本轮没有执行真实查询。
定时任务:
schedule-b8045b6f…触发时间:10 月 24 日 10:00
prompt:10 点查询广州的天气
到 10 点,回复里才出现气温、风向、湿度和空气质量,还带了天气网和广州气象台的链接。
顺手给了几个时刻的实况:04:50 的 21℃、08 时的 23℃、11 时预报的 28℃。看得出来是 10 点现查的,不是 9 点攒下来的。
这也顺便说明了 prompt 为什么要写全。这里只有一句「10 点查询广州的天气」,城市、动作、时间都在里面,到点不需要回看前文也知道该干什么。
任务越简单,越容易写成「查一下」。到点模型看着这三个字,只能猜。
验收
创建完看当轮回复,只有任务信息、没有任务内容就算对了;出现气温、提纲、文件读取,就是没拦住。
到点那轮看回复底部的用量条,token 数和缓存命中都在上面,那个数就是账单的基数。
按上面的写法,到点那轮才真的像我刚发了条消息。