Files
hunjing/backend/app/modules/time_sense/context_text.py
T
2026-08-21 16:00:13 +08:00

84 lines
3.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""temporal_context 文本组装(辰正设计 §8.1)。
纯函数:把 ``TemporalSnapshot`` + ``ModulationFactors`` 渲染为注入对话 prompt 的
中文时态上下文块。降级原则:任何字段缺失都跳过该行,不抛异常。
"""
from __future__ import annotations
from app.modules.time_sense.modulation import ModulationFactors
from app.modules.time_sense.snapshot import TemporalSnapshot
def render_temporal_context(snapshot: TemporalSnapshot, factors: ModulationFactors) -> str: # noqa: ARG001
"""渲染 §8.1 格式的 temporal_context 文本块。
``factors`` 为 service 层统一传入的调制因子;v1 仅用 snapshot 字段,
参数预留给 v2(如 festival_joy / late_night_fragility 的影响话术)。
"""
lines: list[str] = []
# 第一行:时辰·时段(本地时间、时区、周几)
shichen = snapshot.shichen
period = snapshot.day_period
local_hm = snapshot.local_time[11:16]
tz_short = _tz_offset_short(snapshot.local_time)
weekday_cn = "一二三四五六日"[snapshot.weekday]
lines.append(f"现在是{shichen}·{period}({local_hm},UTC{tz_short}),周{weekday_cn}。")
# 第二行:农历 + 距下一节气
lunar_part = ""
if snapshot.lunar is not None:
lunar_part = (
f"农历{snapshot.lunar.year_ganzhi}年{snapshot.lunar.month}月{snapshot.lunar.day}日,"
)
term_part = ""
if snapshot.solar_term is not None:
days_to_next = getattr(snapshot.solar_term, "days_to_next", None)
next_name = getattr(snapshot.solar_term, "next_name", None)
if days_to_next is not None and next_name:
term_part = f"距{next_name}还有 {days_to_next} 天。"
if lunar_part or term_part:
lines.append(lunar_part + term_part)
# 第三行:认识时长
acq = snapshot.acquaintance
if acq.natural_language:
lines.append(f"已经认识 {acq.natural_language}。")
# 第四行:离线/重逢
offline = snapshot.offline
if offline.band == "reunion_impact":
days = int(offline.minutes // 1440)
lines.append(f"用户上次说话是 {days} 天前——久别重逢。")
elif offline.band == "long_absence":
days = int(offline.minutes // 1440)
lines.append(f"用户上次说话是 {days} 天前。")
# 第五行:纪念日
active = snapshot.active_milestones
next_ms = snapshot.next_milestone
if active:
names = "、".join(m.name for m in active)
lines.append(f"今日命中:{names}。")
else:
lines.append("今日命中:无纪念日。")
if next_ms is not None:
lines.append(f"下一个特殊日子:{next_ms.name},还有 {next_ms.days_until} 天。")
return "\n".join(lines)
def _tz_offset_short(local_time_iso: str) -> str:
"""从本地 ISO 时间(如 ``2026-07-04T02:00:00+08:00``)提取 UTC 偏移。
返回 ``+8`` / ``-5`` / ``+0`` 形式,用于 ``UTC{tz_short}`` 显示——
即用户本地时区相对 UTC 的偏移(非家时区差)。
"""
# isoformat() 偏移形如 +HH:MM / -HH:MM(末 6 字符);Z 或无偏移按 UTC
if local_time_iso.endswith("Z") or len(local_time_iso) < 6:
return "+0"
tail = local_time_iso[-6:]
sign = tail[0] if tail[0] in "+-" else "+"
return f"{sign}{int(tail[1:3])}"