初始化提交

This commit is contained in:
chenxin committed 2026-08-21 16:00:13 +08:00
commit 887c1f449e
963 files changed
+166869

No files matched your search

+91
View File
@@ -0,0 +1,91 @@
"""记忆上下文组装与检索结果数据结构(纯领域,无 IO)。
``MemoryRetrievalResult`` 持有已加载的 Memory ORM 实例(由 services/memory 检索后传入),
``build_memory_context`` 把它组装成注入上下文的文本。本模块只接收已加载数据、输出结构化对象。
"""
from __future__ import annotations
from datetime import UTC, datetime
from pydantic import BaseModel, ConfigDict
from app.core.time import utc_now
from app.models.memory import Memory
class MemoryRetrievalResult(BaseModel):
"""记忆检索结果(持有已加载的 Memory ORM 实例列表)。"""
model_config = ConfigDict(arbitrary_types_allowed=True)
memories: list[Memory]
def _to_aware(dt: datetime | None) -> datetime | None:
"""确保 datetime 有时区信息,naive 视为 UTC。"""
if dt is None:
return None
if dt.tzinfo is None:
return dt.replace(tzinfo=UTC)
return dt
def build_memory_context(result: MemoryRetrievalResult, *, max_length: int = 3000) -> str | None:
"""把检索到的记忆组装成注入上下文的文本;无记忆时返回 None。
按**重要性降序**排列,每条附带重要性标签和相对时间。
超过 ``max_length`` 字符时截断,避免上下文窗口膨胀。
"""
if not result.memories:
return None
now = utc_now()
def _mem_sort_key(m: Memory) -> float:
"""排序键:重要性(越高越优先),同时辅助时间衰减。"""
ca = _to_aware(m.created_at)
hours_ago = (now - ca).total_seconds() / 3600 if ca else 0
decay = max(0.5, 1.0 - hours_ago / 720) # 30 天内缓慢衰减
return (m.importance or 0.5) * decay
sorted_mems = sorted(result.memories, key=_mem_sort_key, reverse=True)
lines: list[str] = []
total_chars = 0
for idx, item in enumerate(sorted_mems):
importance_label = _importance_label(item.importance)
ca = _to_aware(item.created_at)
hours_ago = (now - ca).total_seconds() / 3600 if ca else 0
time_label = _time_ago_str(hours_ago)
line = f"- 「{item.title}」{time_label} [{importance_label}]\n {item.content}"
line_len = len(line) + 1 # +1 for newline
if total_chars + line_len > max_length:
remaining = len(sorted_mems) - idx
if remaining > 0:
lines.append(f"…以及 {remaining} 条其他记忆(已截断)")
break
lines.append(line)
total_chars += line_len
return "相关记忆:\n" + "\n".join(lines)
def _importance_label(importance: float) -> str:
if importance >= 0.8:
return "★重要"
if importance >= 0.5:
return "●一般"
return "○参考"
def _time_ago_str(hours_ago: float) -> str:
if hours_ago < 1:
return "刚刚"
if hours_ago < 24:
return f"{int(hours_ago)}小时前"
days = int(hours_ago / 24)
if days < 30:
return f"{days}天前"
months = int(days / 30)
return f"{months}个月前"