121 lines
4.3 KiB
Python
121 lines
4.3 KiB
Python
"""演化候选派生 applier 测试。"""
|
|
|
|
import pytest
|
|
|
|
from app.db.session import AsyncSessionLocal
|
|
from app.models.big_cycle import BigCycle
|
|
from app.models.evolution import EvolutionCandidate
|
|
from app.models.memory import Memory
|
|
from app.repositories import evolution as evolution_repo
|
|
from app.repositories import personality as personality_repo
|
|
from app.repositories.json_utils import dumps
|
|
from app.services import evolution as evolution_service
|
|
from app.services.characters import get_active_character_model
|
|
from app.services.personality import create_default_personality
|
|
|
|
|
|
async def _setup(session) -> tuple:
|
|
character = await get_active_character_model(session)
|
|
if await personality_repo.get_latest_personality(session, character.id) is None:
|
|
await create_default_personality(session, character.id)
|
|
await session.flush()
|
|
cycle = BigCycle(
|
|
character_id=character.id,
|
|
trigger="test",
|
|
status="completed",
|
|
memory_count_at_trigger=20,
|
|
)
|
|
session.add(cycle)
|
|
await session.flush()
|
|
return character, cycle
|
|
|
|
|
|
def _candidate(character_id: str, cycle_id: str, **overrides) -> EvolutionCandidate:
|
|
base = {
|
|
"character_id": character_id,
|
|
"cycle_id": cycle_id,
|
|
"type": "personality",
|
|
"source": "big_cycle",
|
|
"level": "L4",
|
|
"scope": "character_scope",
|
|
"title": "t",
|
|
"proposal": "p",
|
|
"delta_json": "{}",
|
|
"evidence_ids_json": "[]",
|
|
"confidence": 0.5,
|
|
"benefit_score": 0.5,
|
|
"risk_score": 0.5,
|
|
"drift_score": 0.0,
|
|
"auto_apply_allowed": False,
|
|
"status": "pending",
|
|
}
|
|
base.update(overrides)
|
|
return EvolutionCandidate(**base)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_apply_personality_candidate_derives_version() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
character, cycle = await _setup(session)
|
|
base_version = await personality_repo.get_latest_personality(session, character.id)
|
|
candidate = _candidate(
|
|
character.id,
|
|
cycle.id,
|
|
type="personality",
|
|
delta_json=dumps({"expression_style": "更简洁、更主动"}),
|
|
title="表达风格演化",
|
|
)
|
|
await evolution_repo.add_candidates(session, [candidate])
|
|
await session.flush()
|
|
|
|
target_id = await evolution_service.apply_evolution_candidate(session, candidate)
|
|
await session.commit()
|
|
|
|
assert target_id is not None
|
|
async with AsyncSessionLocal() as session:
|
|
new_version = await personality_repo.get_personality(session, target_id)
|
|
character2 = await get_active_character_model(session)
|
|
assert new_version is not None
|
|
assert new_version.version == base_version.version + 1
|
|
assert new_version.created_by == "big_cycle"
|
|
assert "更简洁" in new_version.expression_style
|
|
assert character2.current_personality_version_id == target_id
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_apply_procedural_candidate_creates_memory() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
character, cycle = await _setup(session)
|
|
candidate = _candidate(
|
|
character.id,
|
|
cycle.id,
|
|
type="procedural",
|
|
level="L2",
|
|
delta_json=dumps({"title": "先确认关键假设", "content": "技术问题先确认前提再作答"}),
|
|
)
|
|
await evolution_repo.add_candidates(session, [candidate])
|
|
await session.flush()
|
|
|
|
target_id = await evolution_service.apply_evolution_candidate(session, candidate)
|
|
await session.commit()
|
|
|
|
assert target_id is not None
|
|
async with AsyncSessionLocal() as session:
|
|
mem = await session.get(Memory, target_id)
|
|
assert mem is not None
|
|
assert mem.type == "procedural"
|
|
assert mem.title == "先确认关键假设"
|
|
assert mem.source == "big_cycle"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_apply_unimplemented_type_returns_none() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
character, cycle = await _setup(session)
|
|
candidate = _candidate(character.id, cycle.id, type="tool_strategy", level="L2")
|
|
await evolution_repo.add_candidates(session, [candidate])
|
|
await session.flush()
|
|
|
|
result = await evolution_service.apply_evolution_candidate(session, candidate)
|
|
assert result is None
|