Files
life-echo/api/tests/test_reply_planner.py

113 lines
3.7 KiB
Python
Raw Permalink Normal View History

"""reply_plannerJSON 合并与安全边界。"""
import json
from app.agents.chat.interview_turn_plan import InterviewTurnPlan
from app.agents.chat.reply_planner import merge_reply_planner_json_into_turn_plan
def _base_plan(**kwargs) -> InterviewTurnPlan:
defaults = dict(
mode="memoir_push",
anchor_slot_key="place",
anchor_slot_readable="成长的地方",
anchor_snippet="河边",
memory_usage="allowed_with_attribution",
reply_shape="flexible",
memory_reference_style="你之前提过",
)
defaults.update(kwargs)
return InterviewTurnPlan(**defaults)
def test_merge_does_not_upgrade_memory_from_none_to_allowed():
plan = _base_plan(memory_usage="none")
raw = json.dumps(
{
"memory_usage": "allowed_with_attribution",
"reply_shape": "ack_then_question",
"memory_reference_style": "你说过",
"forbid_first_person_experience": True,
}
)
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.memory_usage == "none"
assert merged.reply_shape == "ack_then_question"
assert merged.memory_reference_style == "你说过"
def test_merge_allows_downgrade_memory_usage_to_none():
plan = _base_plan(memory_usage="allowed_with_attribution")
raw = json.dumps({"memory_usage": "none"})
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.memory_usage == "none"
def test_merge_invalid_json_returns_original():
plan = _base_plan()
merged = merge_reply_planner_json_into_turn_plan(plan, "not json")
assert merged == plan
def test_merge_ignores_non_dict_json():
plan = _base_plan()
merged = merge_reply_planner_json_into_turn_plan(plan, "[1,2]")
assert merged == plan
def test_merge_trims_memory_reference_style():
plan = _base_plan()
raw = json.dumps({"memory_reference_style": " 你刚讲到 "})
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.memory_reference_style == "你刚讲到"
def test_merge_sets_focus_and_summary():
plan = _base_plan()
raw = json.dumps(
{
"primary_focus": "relationship",
"focus_summary": "先接住用户提到的在场关系与面子压力",
"forbid_first_person_experience": True,
}
)
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.primary_focus == "relationship"
assert "关系" in merged.focus_summary
assert merged.focus_source == "llm"
def test_merge_mode_override_memoir_to_emotion_when_focus_supports():
plan = _base_plan(mode="memoir_push")
raw = json.dumps(
{
"mode_override": "emotion_first",
"primary_focus": "identity",
"forbid_first_person_experience": True,
}
)
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.mode == "emotion_first"
assert merged.focus_source == "llm"
def test_merge_rejects_unsafe_mode_override_emotion_to_memoir():
plan = _base_plan(mode="emotion_first")
raw = json.dumps(
{
"mode_override": "memoir_push",
"primary_focus": "memoir_gap",
"forbid_first_person_experience": True,
}
)
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.mode == "emotion_first"
def test_merge_omitted_secondary_focus_unchanged():
plan = _base_plan()
raw = json.dumps({"reply_shape": "ack_only", "forbid_first_person_experience": True})
merged = merge_reply_planner_json_into_turn_plan(plan, raw)
assert merged.reply_shape == "ack_only"
assert merged.focus_source == "rule"