- 新增 utterance_substance:短时/应答/元话语可跳过记忆检索、阶段 LLM 与资料抽取 LLM;可配置 - 输入归一化:LLM 模式默认仅语音/ASR;配置项写入 .env.example - Memoir Phase1:可选 batch LLM 一次性抽取+分类(失败回退逐段);Extraction 空槽位时阶段与 current_stage 对齐,prompt 约束收紧 - 叙事与忠实度:narrative_safety、证据重叠/场合锚点、标题 slots 与履历短语 grounded;fidelity 解析失败 fail-open 可配置 - 章节管线:锁 TTL 上调、锁竞争 Celery 重试、Phase2 immediate singleflight 等;story_pipeline_sync / chapter_compose / memoir_tasks 联动 - Memory:compaction / repo / summarizer / evidence 小修;事实 FTS 未命中是否回退最近事实可配置 - 新增 memoir_pipeline_trace;补充 memoir_reliability 文档与多项回归/门控测试
68 lines
2.0 KiB
Python
68 lines
2.0 KiB
Python
"""Memory 检索:事实 fallback 开关;compaction 后事实 stale。"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from unittest.mock import MagicMock
|
||
|
||
import pytest
|
||
|
||
from app.core.config import settings
|
||
from app.features.memory import repo as memory_repo
|
||
|
||
|
||
def test_search_facts_sync_skips_recent_fallback_when_disabled(
|
||
monkeypatch: pytest.MonkeyPatch,
|
||
) -> None:
|
||
monkeypatch.setattr(
|
||
settings, "memory_fact_search_use_recent_fallback", False, raising=False
|
||
)
|
||
calls: list[bool] = []
|
||
|
||
def boom(*_a, **_k):
|
||
calls.append(True)
|
||
raise AssertionError("get_facts_for_user_sync should not run")
|
||
|
||
monkeypatch.setattr(memory_repo, "get_facts_for_user_sync", boom)
|
||
|
||
mock_session = MagicMock()
|
||
mock_session.execute.return_value.unique.return_value.scalars.return_value.all.return_value = []
|
||
|
||
out = memory_repo.search_facts_for_user_sync(
|
||
mock_session, "user-1", "no_such_subject_xyz", 5
|
||
)
|
||
assert out == []
|
||
assert calls == []
|
||
|
||
|
||
def test_search_facts_sync_uses_recent_fallback_when_enabled(
|
||
monkeypatch: pytest.MonkeyPatch,
|
||
) -> None:
|
||
monkeypatch.setattr(
|
||
settings, "memory_fact_search_use_recent_fallback", True, raising=False
|
||
)
|
||
stub_fact = object()
|
||
|
||
def fake_get_facts(sess, uid, lim):
|
||
assert sess is mock_session
|
||
assert uid == "user-1"
|
||
return [stub_fact] # type: ignore[list-item]
|
||
|
||
monkeypatch.setattr(memory_repo, "get_facts_for_user_sync", fake_get_facts)
|
||
|
||
mock_session = MagicMock()
|
||
mock_session.execute.return_value.unique.return_value.scalars.return_value.all.return_value = []
|
||
|
||
out = memory_repo.search_facts_for_user_sync(
|
||
mock_session, "user-1", "no_match_query", 5
|
||
)
|
||
assert out == [stub_fact]
|
||
|
||
|
||
def test_mark_facts_stale_for_excluded_chunk_returns_rowcount() -> None:
|
||
session = MagicMock()
|
||
session.execute.return_value.rowcount = 3
|
||
n = memory_repo.mark_facts_stale_for_excluded_chunk_sync(
|
||
session, user_id="u1", chunk_id="chunk-9"
|
||
)
|
||
assert n == 3
|