M3a:息壤三级记忆域——归真触发提取管线/白名单明忆/重忆确认/正影版本链/删除墓碑/双通道召回注入,退役旧记忆-抽取-反思-大周天-演化管线(迁移 004,验收 7 用例)

This commit is contained in:
chenxin committed 2026-08-27 09:16:32 +08:00
1 parent 2a640a901b
commit 9c98c2f85e
69 files changed
+1193 -6033

No files matched your search

@@ -1,110 +0,0 @@
"""大周天记忆/世界抽取纯函数测试。"""
from app.modules.extraction.extract import (
MemoryCandidateDraft,
WorldEntityDraft,
parse_extraction,
)
def test_parse_standard_object() -> None:
raw = (
'{"memories":[{"type":"preference","title":"喜欢简洁","content":"用户偏好简洁",'
'"importance":0.8,"sensitivity":"low","confidence":0.7,"reason":"多次提及"}],'
'"entities":[{"type":"project","name":"项目X","attributes":{"status":"active"},'
'"state_type":"inference","confidence":0.6}]}'
)
memories, entities = parse_extraction(raw)
assert len(memories) == 1
assert memories[0].title == "喜欢简洁"
assert memories[0].type == "preference"
assert memories[0].importance == 0.8
assert len(entities) == 1
assert entities[0].name == "项目X"
assert entities[0].type == "project"
assert entities[0].attributes == {"status": "active"}
assert entities[0].state_type == "inference"
def test_parse_markdown_block() -> None:
raw = '```json\n{"memories":[],"entities":[]}\n```'
memories, entities = parse_extraction(raw)
assert memories == []
assert entities == []
def test_parse_text_mixed() -> None:
raw = '抽取结果:\n{"memories":[{"title":"t","content":"c"}],"entities":[]}\n以上'
memories, entities = parse_extraction(raw)
assert len(memories) == 1
assert entities == []
def test_parse_invalid_returns_empty() -> None:
assert parse_extraction("不是JSON") == ([], [])
assert parse_extraction("[]") == ([], []) # 数组不是对象
def test_missing_keys_returns_empty_lists() -> None:
memories, entities = parse_extraction('{"memories":[]}')
assert memories == []
assert entities == []
def test_skip_memory_missing_title_or_content() -> None:
raw = '{"memories":[{"title":"t"},{"content":"c"},{"title":"t","content":"c"}]}'
memories, _ = parse_extraction(raw)
assert len(memories) == 1
def test_skip_entity_missing_name() -> None:
raw = '{"entities":[{"type":"project"},{"name":"有名字"}]}'
_, entities = parse_extraction(raw)
assert len(entities) == 1
assert entities[0].name == "有名字"
def test_memory_safe_defaults() -> None:
raw = '{"memories":[{"title":"t","content":"c"}]}'
m = parse_extraction(raw)[0][0]
assert m.sensitivity == "low"
assert m.type == "other"
assert m.confidence == 0.5
assert m.importance == 0.5
def test_entity_safe_defaults() -> None:
raw = '{"entities":[{"name":"n"}]}'
e = parse_extraction(raw)[1][0]
assert e.state_type == "inference" # 非 fact,降权
assert e.type == "concept"
assert e.confidence == 0.5
assert e.attributes == {}
def test_clamp_values() -> None:
raw = (
'{"memories":[{"title":"t","content":"c","importance":1.5,"confidence":-0.2}],'
'"entities":[{"name":"n","confidence":2.0}]}'
)
memories, entities = parse_extraction(raw)
assert memories[0].importance == 1.0
assert memories[0].confidence == 0.0
assert entities[0].confidence == 1.0
def test_invalid_sensitivity_defaults() -> None:
raw = '{"memories":[{"title":"t","content":"c","sensitivity":"unknown"}]}'
assert parse_extraction(raw)[0][0].sensitivity == "low"
def test_invalid_state_type_defaults() -> None:
raw = '{"entities":[{"name":"n","state_type":"certain"}]}'
assert parse_extraction(raw)[1][0].state_type == "inference"
def test_draft_types() -> None:
raw = '{"memories":[{"title":"t","content":"c"}],"entities":[{"name":"n"}]}'
memories, entities = parse_extraction(raw)
assert isinstance(memories[0], MemoryCandidateDraft)
assert isinstance(entities[0], WorldEntityDraft)
@@ -1,34 +0,0 @@
"""大周天记忆/世界抽取 prompt 构建纯函数测试。"""
from app.modules.big_cycle.prompts import EvaluationSnapshot
from app.modules.extraction.prompts import build_extraction_messages
def _snapshot() -> EvaluationSnapshot:
return EvaluationSnapshot(
character_id="character_x",
memory_count=15,
recent_memories=[("用户偏好简洁", "用户偏好简洁直接的回答")],
personality_summary="身份:魂镜",
world_entity_count=4,
conclusion="近期对话涉及项目X,存在背景缺口",
)
def test_messages_return_system_user_pair() -> None:
system, user = build_extraction_messages(_snapshot())
assert isinstance(system, str) and isinstance(user, str)
assert system and user
def test_system_describes_memories_and_entities_structure() -> None:
system, _ = build_extraction_messages(_snapshot())
for token in ("memories", "entities", "state_type", "sensitivity", "importance"):
assert token in system
def test_user_includes_snapshot_signals() -> None:
_, user = build_extraction_messages(_snapshot())
assert "用户偏好简洁" in user
assert "身份:魂镜" in user
assert "15" in user
@@ -1,66 +0,0 @@
"""小周天每轮反思抽取纯函数测试。"""
from app.modules.extraction.extract import MemoryCandidateDraft
from app.modules.reflection.extract import parse_reflection
def test_parse_standard() -> None:
raw = (
'{"memories":[{"type":"preference","title":"喜欢简洁","content":"用户偏好简洁",'
'"importance":0.8,"sensitivity":"low","confidence":0.7,"reason":"多次提及"}],'
'"reflection":"本轮应更主动确认用户意图。"}'
)
memories, reflection = parse_reflection(raw)
assert len(memories) == 1
assert memories[0].title == "喜欢简洁"
assert isinstance(memories[0], MemoryCandidateDraft)
assert reflection == "本轮应更主动确认用户意图。"
def test_parse_markdown_block() -> None:
raw = '```json\n{"memories":[],"reflection":"反思文本"}\n```'
memories, reflection = parse_reflection(raw)
assert memories == []
assert reflection == "反思文本"
def test_parse_invalid_returns_empty() -> None:
assert parse_reflection("不是JSON") == ([], "")
assert parse_reflection("[]") == ([], "")
def test_missing_reflection_returns_empty_string() -> None:
memories, reflection = parse_reflection('{"memories":[]}')
assert memories == []
assert reflection == ""
def test_missing_memories_returns_empty_list() -> None:
memories, reflection = parse_reflection('{"reflection":"只有反思"}')
assert memories == []
assert reflection == "只有反思"
def test_memory_safe_defaults() -> None:
raw = '{"memories":[{"title":"t","content":"c"}],"reflection":"r"}'
m = parse_reflection(raw)[0][0]
assert m.sensitivity == "low"
assert m.confidence == 0.5
assert m.importance == 0.5
def test_skip_memory_missing_title_or_content() -> None:
raw = (
'{"memories":[{"title":"t"},{"content":"c"},{"title":"t","content":"c"}],"reflection":"r"}'
)
assert len(parse_reflection(raw)[0]) == 1
def test_clamp_values() -> None:
raw = '{"memories":[{"title":"t","content":"c","importance":1.5}],"reflection":"r"}'
assert parse_reflection(raw)[0][0].importance == 1.0
def test_reflection_strips_whitespace() -> None:
raw = '{"memories":[],"reflection":" 带空格的反思 "}'
assert parse_reflection(raw)[1] == "带空格的反思"
@@ -1,21 +0,0 @@
"""小周天反思 prompt 构建纯函数测试。"""
from app.modules.reflection.prompts import build_reflection_messages
def test_messages_return_system_user_pair() -> None:
system, user = build_reflection_messages("你好", "你好,我是魂镜")
assert isinstance(system, str) and isinstance(user, str)
assert system and user
def test_system_describes_memories_and_reflection() -> None:
system, _ = build_reflection_messages("u", "a")
for token in ("memories", "reflection", "importance", "sensitivity"):
assert token in system
def test_user_includes_dialogue() -> None:
_, user = build_reflection_messages("用户说的话", "助手的回复")
assert "用户说的话" in user
assert "助手的回复" in user