初始化提交
This commit is contained in:
commit
887c1f449e
963 files changed
+166869
No files matched your search
@@ -0,0 +1,175 @@
|
||||
"""调制因子派生:从时态快照 + 对话信号派生 [0,1] 因子与关怀类型。
|
||||
|
||||
消费 ``TemporalSnapshot``(Plan 1)与 ``ModulationInput``(service 层收集的对话信号),
|
||||
输出 ``ModulationFactors``(设计 §5.2)。全部纯函数,无副作用。
|
||||
|
||||
v1 用即时启发式(参数集中为模块常量,便于调参);节律曲线 / 窗口函数留 v2。
|
||||
care_kind 触发规则见设计 §7.3。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.modules.time_sense.snapshot import TemporalSnapshot
|
||||
|
||||
# ==================== v1 启发式参数(可调) ====================
|
||||
|
||||
# 节日喜悦度权重(设计 §5.2 festival_joy)
|
||||
_FESTIVAL_JOY_WEIGHTS: dict[str, float] = {
|
||||
"春节": 0.9,
|
||||
"中秋节": 0.9,
|
||||
"元宵节": 0.7,
|
||||
"端午节": 0.7,
|
||||
"七夕": 0.7,
|
||||
"重阳节": 0.7,
|
||||
"腊八节": 0.7,
|
||||
"元旦": 0.5,
|
||||
"劳动节": 0.5,
|
||||
"国庆节": 0.5,
|
||||
"圣诞节": 0.5,
|
||||
"情人节": 0.5,
|
||||
}
|
||||
_FESTIVAL_JOY_BASELINE = 0.1 # 无节日
|
||||
_FESTIVAL_JOY_DEFAULT = 0.5 # 未登记节日
|
||||
|
||||
# 季节共振(设计 §5.2 season_resonance;v2 用季节调制函数)
|
||||
_SEASON_RESONANCE: dict[str, float] = {"春": 0.5, "夏": 0.6, "秋": 0.7, "冬": 0.6}
|
||||
|
||||
# 时段共振(设计 §5.2 same_period_resonance;v2 用窗口函数)
|
||||
_DAY_PERIOD_RESONANCE: dict[str, float] = {
|
||||
"凌晨": 0.8,
|
||||
"深夜": 0.7,
|
||||
"清晨": 0.4,
|
||||
"夜晚": 0.4,
|
||||
"傍晚": 0.3,
|
||||
"上午": 0.2,
|
||||
"下午": 0.2,
|
||||
"中午": 0.2,
|
||||
}
|
||||
|
||||
# 深夜脆弱度(设计 §5.2 late_night_fragility)
|
||||
_FRAGILITY_DEEP_NIGHT_BASE = 0.7 # 凌晨基线
|
||||
_FRAGILITY_LATE_NIGHT_BASE = 0.5 # 深夜基线
|
||||
_FRAGILITY_DAYTIME = 0.1
|
||||
_FRAGILITY_PER_TURN_DEEP = 0.05 # 凌晨每轮增量
|
||||
_FRAGILITY_PER_TURN_LATE = 0.03 # 深夜每轮增量
|
||||
|
||||
# 周末放松度
|
||||
_RELAX_WEEKEND = 0.8
|
||||
_RELAX_WEEKEND_WITH_FESTIVAL = 0.9
|
||||
_RELAX_WORKDAY = 0.2
|
||||
|
||||
# 关怀
|
||||
_CARE_SUGGEST_HIT = 0.7 # care_kind 命中时
|
||||
_CARE_SUGGEST_MISS_FACTOR = 0.5 # 未命中时按脆弱度折半
|
||||
|
||||
# 时差关怀阈值(分钟,3 小时)
|
||||
_JETLAG_DIFF_MINUTES = 180
|
||||
# 深夜持续聊天阈值(轮数)
|
||||
_LATE_NIGHT_TURNS = 3
|
||||
|
||||
|
||||
class ModulationInput(BaseModel):
|
||||
"""compute_modulation 的对话信号输入。
|
||||
|
||||
信号由 Plan 3 service 层收集(轮数统计、内容分类等);本模块只做纯函数判定。
|
||||
关怀阈值(``jetlag_threshold_minutes`` / ``late_night_min_turns``)默认 None,
|
||||
由 service 层从 ``settings`` 注入(设计 §7.1/§7.3"阈值可调");None 时回退模块常量。
|
||||
"""
|
||||
|
||||
conversation_turns_today: int = 0
|
||||
is_first_message_today: bool = False
|
||||
content_work_related: bool = False
|
||||
content_lonely: bool = False
|
||||
user_birthday_today: bool = False
|
||||
# 关怀触发阈值(None → 回退模块常量;service 层从 settings 注入,设计 §7.3)
|
||||
jetlag_threshold_minutes: int | None = None
|
||||
late_night_min_turns: int | None = None
|
||||
|
||||
|
||||
class ModulationFactors(BaseModel):
|
||||
"""辰正输出的调制因子(设计 §5.2)。"""
|
||||
|
||||
festival_joy: float
|
||||
late_night_fragility: float
|
||||
reunion_intensity: float
|
||||
weekend_relax: float
|
||||
season_resonance: float
|
||||
same_period_resonance: float
|
||||
care_suggest: float
|
||||
care_kind: str | None = None
|
||||
|
||||
|
||||
def _festival_joy(snapshot: TemporalSnapshot) -> float:
|
||||
if not snapshot.festivals:
|
||||
return _FESTIVAL_JOY_BASELINE
|
||||
return max(_FESTIVAL_JOY_WEIGHTS.get(f.name, _FESTIVAL_JOY_DEFAULT) for f in snapshot.festivals)
|
||||
|
||||
|
||||
def _late_night_fragility(snapshot: TemporalSnapshot, turns: int) -> float:
|
||||
period = snapshot.day_period
|
||||
if period == "凌晨":
|
||||
return min(1.0, _FRAGILITY_DEEP_NIGHT_BASE + turns * _FRAGILITY_PER_TURN_DEEP)
|
||||
if period == "深夜":
|
||||
return min(1.0, _FRAGILITY_LATE_NIGHT_BASE + turns * _FRAGILITY_PER_TURN_LATE)
|
||||
return _FRAGILITY_DAYTIME
|
||||
|
||||
|
||||
def _weekend_relax(snapshot: TemporalSnapshot) -> float:
|
||||
if not snapshot.is_weekend:
|
||||
return _RELAX_WORKDAY
|
||||
if snapshot.festivals:
|
||||
return _RELAX_WEEKEND_WITH_FESTIVAL
|
||||
return _RELAX_WEEKEND
|
||||
|
||||
|
||||
def _care_kind(snapshot: TemporalSnapshot, signals: ModulationInput) -> str | None:
|
||||
"""设计 §7.3 关怀触发判定(按优先级)。
|
||||
|
||||
阈值读 ``signals``(None 回退模块常量),由 service 层从 settings 注入(§7.3 可调)。
|
||||
"""
|
||||
deep = snapshot.day_period in {"凌晨", "深夜"}
|
||||
jetlag_threshold = signals.jetlag_threshold_minutes or _JETLAG_DIFF_MINUTES
|
||||
late_night_turns = signals.late_night_min_turns or _LATE_NIGHT_TURNS
|
||||
# 1. 时差关怀:深夜/凌晨 + 家时差显著
|
||||
if deep and abs(snapshot.home_tz_diff_minutes) >= jetlag_threshold:
|
||||
return "jetlag"
|
||||
# 2. 用户生日
|
||||
if signals.user_birthday_today:
|
||||
return "birthday"
|
||||
# 3. 清晨异常:清晨时段 + 本地 4-6 点 + 今日首条
|
||||
if signals.is_first_message_today and snapshot.day_period == "清晨" and snapshot.local_hour < 6:
|
||||
return "early_morning"
|
||||
# 4. 深夜工作话题
|
||||
if deep and signals.content_work_related:
|
||||
return "overwork"
|
||||
# 5. 节日孤独
|
||||
if bool(snapshot.festivals) and signals.content_lonely:
|
||||
return "festival_lonely"
|
||||
# 6. 深夜持续聊天:深夜/凌晨 + 连续 ≥ N 轮
|
||||
if deep and signals.conversation_turns_today >= late_night_turns:
|
||||
return "late_night"
|
||||
return None
|
||||
|
||||
|
||||
def _care_suggest(fragility: float, care_kind_value: str | None) -> float:
|
||||
if care_kind_value is not None:
|
||||
return _CARE_SUGGEST_HIT
|
||||
return round(fragility * _CARE_SUGGEST_MISS_FACTOR, 3)
|
||||
|
||||
|
||||
def compute_modulation(snapshot: TemporalSnapshot, signals: ModulationInput) -> ModulationFactors:
|
||||
"""从时态快照 + 对话信号派生调制因子。纯函数。"""
|
||||
fragility = _late_night_fragility(snapshot, signals.conversation_turns_today)
|
||||
care_kind_value = _care_kind(snapshot, signals)
|
||||
return ModulationFactors(
|
||||
festival_joy=round(_festival_joy(snapshot), 3),
|
||||
late_night_fragility=round(fragility, 3),
|
||||
reunion_intensity=round(snapshot.offline.reunion_intensity, 3),
|
||||
weekend_relax=_weekend_relax(snapshot),
|
||||
season_resonance=_SEASON_RESONANCE.get(snapshot.season, 0.5),
|
||||
same_period_resonance=_DAY_PERIOD_RESONANCE.get(snapshot.day_period, 0.3),
|
||||
care_suggest=_care_suggest(fragility, care_kind_value),
|
||||
care_kind=care_kind_value,
|
||||
)
|
||||
Reference in new issue
Block a user