115 lines
4.0 KiB
Python
115 lines
4.0 KiB
Python
"""记忆上下文组装测试。"""
|
|
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
from app.models.memory import Memory
|
|
from app.modules.memory.context import (
|
|
MemoryRetrievalResult,
|
|
build_memory_context,
|
|
)
|
|
|
|
|
|
def _make_memory(
|
|
*,
|
|
importance: float = 0.5,
|
|
hours_ago: float = 1.0,
|
|
title: str = "测试记忆",
|
|
content: str = "这是一条测试记忆内容。",
|
|
) -> Memory:
|
|
return Memory(
|
|
id=f"mem_{title}",
|
|
character_id="char_1",
|
|
type="observation",
|
|
title=title,
|
|
content=content,
|
|
importance=importance,
|
|
created_at=datetime.now(UTC) - timedelta(hours=hours_ago),
|
|
source="test",
|
|
confidence=1.0,
|
|
sensitivity="low",
|
|
evidence_ids_json="[]",
|
|
status="active",
|
|
)
|
|
|
|
|
|
def test_empty_memories_returns_none() -> None:
|
|
result = MemoryRetrievalResult(memories=[])
|
|
assert build_memory_context(result) is None
|
|
|
|
|
|
def test_single_memory_returns_text() -> None:
|
|
mem = _make_memory()
|
|
result = MemoryRetrievalResult(memories=[mem])
|
|
text = build_memory_context(result)
|
|
assert text is not None
|
|
assert "相关记忆:" in text
|
|
assert "测试记忆" in text
|
|
|
|
|
|
def test_high_importance_memory_comes_first() -> None:
|
|
low = _make_memory(importance=0.3, title="不重要的")
|
|
high = _make_memory(importance=0.9, title="重要的")
|
|
result = MemoryRetrievalResult(memories=[low, high])
|
|
text = build_memory_context(result)
|
|
assert text is not None
|
|
important_pos = text.index("重要的")
|
|
trivial_pos = text.index("不重要的")
|
|
assert important_pos < trivial_pos, "重要性高的应该排前面"
|
|
|
|
|
|
def test_memories_are_sorted_by_importance_descending() -> None:
|
|
"""传入任意顺序,输出始终重要性降序。"""
|
|
a = _make_memory(importance=0.5, title="中")
|
|
b = _make_memory(importance=0.1, title="低")
|
|
c = _make_memory(importance=0.9, title="高")
|
|
result = MemoryRetrievalResult(memories=[a, b, c])
|
|
text = build_memory_context(result)
|
|
assert text is not None
|
|
positions = {title: text.index(title) for title in ["高", "中", "低"]}
|
|
assert positions["高"] < positions["中"]
|
|
assert positions["中"] < positions["低"]
|
|
|
|
|
|
def test_importance_label_appears() -> None:
|
|
high = _make_memory(importance=0.9, title="重要记忆", content="重要内容")
|
|
medium = _make_memory(importance=0.5, title="普通记忆", content="普通内容")
|
|
low = _make_memory(importance=0.2, title="低优先级", content="低优先级内容")
|
|
|
|
result = MemoryRetrievalResult(memories=[high, medium, low])
|
|
text = build_memory_context(result)
|
|
assert text is not None
|
|
assert "★重要" in text
|
|
assert "●一般" in text
|
|
assert "○参考" in text
|
|
|
|
|
|
def test_time_labels() -> None:
|
|
just_now = _make_memory(title="刚刚发生", hours_ago=0.1)
|
|
hours_ago = _make_memory(title="几小时前", hours_ago=5)
|
|
days_ago = _make_memory(title="几天前", hours_ago=72)
|
|
result = MemoryRetrievalResult(memories=[just_now, hours_ago, days_ago])
|
|
text = build_memory_context(result)
|
|
assert text is not None
|
|
assert "刚刚" in text
|
|
assert "5小时前" in text or "几小时前" in text
|
|
assert "3天前" in text
|
|
|
|
|
|
def test_truncation_respects_max_length() -> None:
|
|
content = "A" * 500
|
|
mem = _make_memory(content=content, title="一长内容")
|
|
result = MemoryRetrievalResult(memories=[mem] * 20)
|
|
text = build_memory_context(result, max_length=500)
|
|
assert text is not None
|
|
assert len(text) <= 550 # max_length + header + padding
|
|
assert "已截断" in text
|
|
|
|
|
|
def test_large_content_not_exceeding_max_length() -> None:
|
|
"""大量记忆时,内容不应超过 max_length 太多。"""
|
|
mems = [_make_memory(content="B" * 200, title=f"记忆{i}", importance=0.5) for i in range(50)]
|
|
result = MemoryRetrievalResult(memories=mems)
|
|
text = build_memory_context(result, max_length=1000)
|
|
assert text is not None
|
|
assert len(text) <= 1200 # 1000 + header + some padding
|