前言¶
在 QQ 群里挂 AI,常见痛点不是模型不会答,而是每句都接:随口吐槽被分析、@ 别人时它插嘴、深夜它比谁都精神。DSH(DeepSeek Harness)侧已有对话与工具链,但「要不要开口」往往仍由 AstrBot 原逻辑或全量转发决定,token 和群氛围都扛不住。
dsh-air-sense 是维护者 yingchaoyi 发布的 DSH 工作流类插件:在 AstrBot 群消息进入正常回复流程之前,先问 DSH 一次——这条消息现在值不值得接;不值得则客户端侧直接停事件,群里看不到任何回复,也不消耗回复 token。判断失败或插件不可用时会退回 AstrBot 原逻辑,避免把群聊憋死。
这是什么¶
- 名称:dsh-air-sense(读空气)
- 分类:工作流(社区目录 SkillHub 插件页)
- 源码:github.com/yingchaoyi/dsh-air-sense(MIT,package 版本 0.1.16,需 Node.js >= 22)
- 定位:DSH 插件 + AstrBot
astrbot_plugin_dsh配合使用;群消息流先POST到 DSH 的/api/air-sense/decide,通过才走原回复流程,并在正文前按配置插入时间戳。
社区插件目录为独立站点,与 DeepSeek / 幻方无官方从属关系;安装前请自行审阅源码与许可证。插件在 当前 DSH 进程权限 下运行,数据与 token 落在本机 ~/.dsh/air-sense/。
核心功能¶
消息漏斗:接不接,再接回什么¶
判断目标不是「回什么」,而是要不要开口。README 描述的闸门顺序大致为:
总开关 → 群黑/白名单 → 发送者黑名单 → 闭麦 → 指令前缀 → 戳一戳 → 关键词 → 静默时段 → @ 机器人(硬过)→ @ 别人(硬拦)→ 刷屏氛围 → 活跃度 → 每日/每小时额度 → 同人冷却 → 概率(基础 × 回复加成 × 注意力 × 戳戳增值 × 表情衰减 × 密度衰减 × 自适应分数)→ 掷骰子 → 可选:判断模型只答 yes/no。
任一步不过即「不接」。面板里关闭「AI 判断 → 启用 AI 判断」后,不再调判断模型;掷骰子或关键词过了可直接开口,日志记为 judgeOff。
与 AstrBot 的协作方式¶
QQ ── AstrBot(dsh 插件 + 补丁) ──POST /api/air-sense/decide──> DSH(dsh-air-sense)
│
不接 ────────┴──────── 接:走原来的回复流程,正文前插时间戳
│
└─ stop_event(),群里什么都看不到
AstrBot 侧需在 astrbot_plugin_dsh/main.py 中拼请求体(含 groupId、senderId、text、atBot、recent 等)、读 ~/.dsh/air-sense/token、默认请求 http://127.0.0.1:3080(超时 20 秒)。非 200、异常或 ok=false 时 _air_decide 返回 None,自动退回原逻辑。
出口清理与发图等补丁单独维护在 dsh-astrbot-patches;patch_astrbot_export.py 已包含 DSML 清理,打补丁后需重载 AstrBot 插件。
Web 面板与数据¶
设置 → 读空气,四个 tab:概览(统计、每群分数与闭麦、总开关)、规则(九组折叠共 49 项说明)、日志(未接理由可搜)、设置(时间戳格式、并发、数据目录等)。右上角总开关关闭后插件完全不插手。
数据目录 ~/.dsh/air-sense/:store.json(设置与日志等)、token(0600)、air-sense.log(超 512KB 自动截断)。整目录拷贝即可备份或迁移。
图片参与判断¶
AstrBot 可将消息内图片本地路径(images,最多两张)一并传入;DSH 对图片内容 sha256 缓存,未命中时用模型生成一句描述写入判断提示词,同图不再重复调用;模型不支持时记 unsupported,不反复试(描述超时 8 秒,失败当无图)。
设计上的硬规矩¶
插件不注册任何工具(避免 schema 投影导致会话 400);apply 内异常只写日志不抛出;判定失败按「不接」处理,而非默认接所有人。
安装与启用¶
这是 DSH profile 内安装的 bundle,不是凭仓库名拼接的 dsh plugin add。官方 README 步骤如下。
先把插件目录拷进 profile(在仓库根目录执行):
# 1) 拷进 profile
cp -R . ~/.dsh/profiles/web/node_modules/dsh-air-sense
# 2) 让 profile 认识它(bundles 管加载,dependencies 管插件页显示)
python3 - <<'PY'
import json, os
p = os.path.expanduser('~/.dsh/profiles/web/package.json')
d = json.load(open(p))
d.setdefault('dependencies', {})['dsh-air-sense'] = 'file:' + os.getcwd()
b = d.setdefault('dsh', {}).setdefault('profile', {}).setdefault('bundles', [])
if 'dsh-air-sense' not in b:
b.append('dsh-air-sense')
json.dump(d, open(p, 'w'), ensure_ascii=False, indent=2)
PY
# 3) 重启 dsh web(新 bundle 不会热加载)
AstrBot 侧按 README 修改 astrbot_plugin_dsh/main.py 四处(_air_body / _air_base / _air_token、_air_decide、on_message 开头、_forward 时间戳),并视需要运行 patches 仓库中的脚本,例如:
git clone https://github.com/yingchaoyi/dsh-astrbot-patches
python3 dsh-astrbot-patches/patch_astrbot_export.py ~/data/plugins/astrbot_plugin_dsh/main.py
改完重载 AstrBot 插件;DSH web 重启后才能在面板看到「读空气」。
典型用法与参数直觉¶
日常主要在 DSH Web 读空气面板调规则:例如初始读空气概率默认 0.02(约 50 条普通消息看 1 条)、回复后概率 0.2 且提升持续 120s、每日/每小时上限 80/10、自适应分数与饥饿加成等。静默时段默认 23:30–07:30 但默认关闭;判定超时 15s,超时按不接处理。
开发者在插件仓库可跑自测:
node test/smoke.mjs # 40 项:假 ctx 假 req/res,跑完整漏斗与 HTTP
node test/client-smoke.mjs # 14 项:假 React 把四个 tab 真渲染一遍
npm test # 两个一起跑
适用场景与注意¶
适合:已在 QQ 群通过 AstrBot + DSH 跑 AI,希望用可开关、可日志追溯的规则控制接话频率,并可选地用轻量 yes/no 模型做最后一道闸。
注意:
- 必须同时维护 DSH 插件与 AstrBot 侧改动(及可选 patches);只装一半不会形成完整链路。
- 群昵称由 AstrBot 拼进时间戳发送者格式,DSH 侧拿不到原始群名片。
- 已知限制见 README:单条最多两张图描述、描述计入判断耗时等。
- 安装与运行前请检查源码;插件不以沙箱隔离,token 与
store.json含群聊相关数据,权限与备份需自行规划。
结尾¶
dsh-air-sense 把「读空气」做成 DSH 内可配置的工作流:先决定接不接,再接才走原有对话;故障时退回 AstrBot,避免 silent failure 变成「全接」或「全死」。目录与文档: