feat: 环境感知 tier-1/tier-2(issue #39) #48

Merged
Yushu merged 1 commit from feature/39-environmental-awareness into main 2026-07-23 08:03:20 +00:00
Member

Closes #39

Summary

ADR-0014 落地——机器人开始对"同群其它插件/命令的产出"有感:群里有人查了成绩、抽了张稀有卡,机器人偶尔会自然地搭一句话;绝大多数时候只是安静地"感受气氛"。分层消费,在既有机制上做加法,不新造并行子系统。

  • EnvironmentSignalenvironmental_awareness.py):前处理 port 与 ConversationInput 并列的独立类型,永不当作 <message> 渲染。
  • tier-1 氛围恒感(常开,不受渐进解锁影响):所有信号仅以速率/热闹度(无内容)喂 per-chat 情感态传染——复用 issue #34 已有的 is_stimulus_repeat/dampen_repeated_stimulus 抗刷折扣(同一 (plugin, action) 短时间内重复触发打折),不新增独立的速率追踪/ring buffer。顺带发现:update_fast_state/update_slow_group_state 自 issue #34 建成后从未被真正调用过——本 ticket 是第一个真实生产入口,config.py 相应补上了速率配置。
  • tier-2 显著反应(晚解锁,需要关系网数据判熟人):级一本地启发式打分(零 LLM,tier2_significance_score——outcome 存在与否 + subject 熟悉度加权),喂给 issue #37/#38 已建但从未真正用到覆盖能力的 evaluate_gate(level1_score=...) 参数,不新造第二套裁决代码。
  • RuntimeLoop.run_environment_signal():全量对话上下文(复用 run() 的画像/召回/关系网组装),但拼进 context 的是独立 system 指令而不是 <message> 标签——顺带把 _recall_events/_triggered_injection 从接收 messages 改成接收 query_text,两条路径共用同一套检索/打分逻辑。不写 Delta/familiarity/距上次交互——旁观信号不构成真实互动。
  • IngressPort.to_environment_signal:host 未实现真实判定时恒返回 None,整个特性静默降级,其它功能不受影响。
  • __init__.py 新增 @event_postprocessor 入口,编排 tier-1(无条件)+ tier-2(关系网解锁后)。

Test plan

  • environmental_awareness.py 纯函数单测(抗刷折扣、显著性打分、指令渲染)
  • RuntimeLoop.run_environment_signal() 单测(零发送/正常发送/不写 Delta/不重置距上次交互/沉默窗口打断/永不出现 message 角色)
  • e2e(test_environmental_awareness_e2e.py):tier-1 在关系网未解锁时依然让 energy 变化;tier-2 在未解锁时保持沉默(零 LLM 调用);tier-2 在解锁后对显著信号真的可能搭话;对平淡信号即便解锁也保持沉默;同一 (plugin, action) 短时间重复触发被抗刷折扣
  • 完整测试套件 600/600 通过,ty check 干净(4 条无关预存警告),ruff check/format 干净
Closes #39 ## Summary ADR-0014 落地——机器人开始对"同群其它插件/命令的产出"有感:群里有人查了成绩、抽了张稀有卡,机器人偶尔会自然地搭一句话;绝大多数时候只是安静地"感受气氛"。分层消费,在既有机制上做加法,不新造并行子系统。 - **EnvironmentSignal**(`environmental_awareness.py`):前处理 port 与 `ConversationInput` 并列的独立类型,永不当作 `<message>` 渲染。 - **tier-1 氛围恒感**(常开,不受渐进解锁影响):所有信号仅以速率/热闹度(无内容)喂 per-chat 情感态传染——复用 issue #34 已有的 `is_stimulus_repeat`/`dampen_repeated_stimulus` 抗刷折扣(同一 `(plugin, action)` 短时间内重复触发打折),不新增独立的速率追踪/ring buffer。顺带发现:`update_fast_state`/`update_slow_group_state` 自 issue #34 建成后从未被真正调用过——本 ticket 是第一个真实生产入口,`config.py` 相应补上了速率配置。 - **tier-2 显著反应**(晚解锁,需要关系网数据判熟人):级一本地启发式打分(零 LLM,`tier2_significance_score`——outcome 存在与否 + subject 熟悉度加权),喂给 issue #37/#38 已建但从未真正用到覆盖能力的 `evaluate_gate(level1_score=...)` 参数,不新造第二套裁决代码。 - **`RuntimeLoop.run_environment_signal()`**:全量对话上下文(复用 `run()` 的画像/召回/关系网组装),但拼进 context 的是独立 system 指令而不是 `<message>` 标签——顺带把 `_recall_events`/`_triggered_injection` 从接收 `messages` 改成接收 `query_text`,两条路径共用同一套检索/打分逻辑。不写 Delta/familiarity/距上次交互——旁观信号不构成真实互动。 - **`IngressPort.to_environment_signal`**:host 未实现真实判定时恒返回 `None`,整个特性静默降级,其它功能不受影响。 - `__init__.py` 新增 `@event_postprocessor` 入口,编排 tier-1(无条件)+ tier-2(关系网解锁后)。 ## Test plan - [x] `environmental_awareness.py` 纯函数单测(抗刷折扣、显著性打分、指令渲染) - [x] `RuntimeLoop.run_environment_signal()` 单测(零发送/正常发送/不写 Delta/不重置距上次交互/沉默窗口打断/永不出现 message 角色) - [x] e2e(`test_environmental_awareness_e2e.py`):tier-1 在关系网未解锁时依然让 energy 变化;tier-2 在未解锁时保持沉默(零 LLM 调用);tier-2 在解锁后对显著信号真的可能搭话;对平淡信号即便解锁也保持沉默;同一 `(plugin, action)` 短时间重复触发被抗刷折扣 - [x] 完整测试套件 600/600 通过,`ty check` 干净(4 条无关预存警告),`ruff check`/`format` 干净
feat: environmental awareness tier-1/tier-2 (issue #39)
Some checks failed
CI / Prek (pull_request) Has been cancelled
CI / typos (pull_request) Has been cancelled
CI / ty (pull_request) Has been cancelled
CI / Coverage (pull_request) Has been cancelled
CI / Coverage-1 (pull_request) Has been cancelled
CI / Coverage-2 (pull_request) Has been cancelled
CI / Coverage-3 (pull_request) Has been cancelled
Release Drafter / Update Release Draft (pull_request) Has been cancelled
df8bd90e4c
ADR-0014 落地——机器人开始对"同群其它插件/命令的产出"有感:EnvironmentSignal
作为前处理 port 与 ConversationInput 并列的独立类型,分层消费,在既有机制
上做加法,不新造并行子系统。

- environmental_awareness.py: EnvironmentSignal 类型 + tier-1 氛围恒感
  (ambient_energy_raw_delta,复用 issue #34 已有的 is_stimulus_repeat/
  dampen_repeated_stimulus 抗刷折扣,不新增独立速率追踪)+ tier-2 级一显著
  性打分(tier2_significance_score,outcome 存在与否 + subject 熟悉度
  加权,零 LLM)+ 信号描述指令渲染(永不当作 <message> 渲染)。
- ports.py: IngressPort 新增 to_environment_signal——host 未实现真实判定
  时恒返回 None,整个特性静默降级(同一 ingress port 内归一化,不新起第
  8 类 port)。
- affective_state.py 的 update_fast_state/update_slow_group_state 自
  issue #34 建成后从未被真正调用过——本 ticket 是第一个真实生产入口,
  config.py 相应新增快/慢情感态更新速率配置。
- RuntimeLoop:_recall_events/_triggered_injection 从接收 messages 改为
  接收 query_text(run() 传当轮消息文本,新增的 run_environment_signal()
  传信号合成描述文本),两者共用同一套检索/打分逻辑;新增
  run_environment_signal() 复用画像/召回/关系网组装,但拼进 context 的是
  独立 system 指令而不是 <message> 标签,不写 Delta/familiarity/距上次
  交互(旁观信号不构成真实互动)。
- gating.py(issue #37/#38 已建)的 evaluate_gate(level1_score=...) 覆盖
  参数在这里首次被用于真正的显著性区分(tier-2 用真实打分覆盖默认的"满分
  直通")。
- __init__.py: 新增 @event_postprocessor 入口 + tier-1/tier-2 编排;
  tier-2 需要关系网解锁(is_relationship_network_unlocked)才继续,晚
  解锁避免陌生群/冷启动对命令产出评头论足。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Yushu merged commit df6b99fdfd into main 2026-07-23 08:03:20 +00:00
Yushu deleted branch feature/39-environmental-awareness 2026-07-23 08:03:21 +00:00
Sign in to join this conversation.
No description provided.