初始化提交

This commit is contained in:
chenxin committed 2026-08-21 16:00:13 +08:00
commit 887c1f449e
963 files changed
+166869

No files matched your search

@@ -0,0 +1,135 @@
"""人物模板配置加载与 Config→DB 同步测试。"""
from __future__ import annotations
import pytest
from app.core.config import settings
from app.db.session import AsyncSessionLocal
from app.repositories import characters as character_repo
from app.repositories.json_utils import loads_dict
from app.services.character_templates import get_default_template, load_character_templates
def test_load_templates_from_example():
""".example.yaml 加载成功且含 default 模板。"""
templates = load_character_templates()
assert "default" in templates
cfg = templates["default"]
assert cfg.key == "default"
assert cfg.name == "魂镜"
assert cfg.display_name == "魂镜"
assert cfg.language == "zh-CN"
assert cfg.privacy_level == "normal"
assert cfg.profile["background"] == "默认人物"
assert cfg.profile["speaking_style"] == "温和、清晰、简洁"
assert cfg.profile["temperament"] == "沉静而温暖"
assert isinstance(cfg.profile["hobbies"], list)
assert "哲学" in cfg.profile["hobbies"]
assert isinstance(cfg.profile["values"], list)
assert "真诚" in cfg.profile["values"]
assert cfg.model_policy["memory_extraction_model_hint"] == "memory-extraction"
assert cfg.model_policy["personality_analysis_model_hint"] == "personality-analysis"
assert cfg.model_policy["embedding_model_hint"] == "embedding"
def test_get_default_template():
"""取 default 模板配置成功。"""
cfg = get_default_template()
assert cfg.key == "default"
assert cfg.name == "魂镜"
@pytest.mark.asyncio
async def test_ensure_default_system_template_creates_from_config():
"""第一次调用 → 按 config 创建系统模板并写入 DB。"""
from app.services.characters import ensure_default_system_template
async with AsyncSessionLocal() as session:
existing = await character_repo.get_system_template_by_key(session, "default")
if existing:
await session.delete(existing)
await session.flush()
template = await ensure_default_system_template(session)
assert template is not None
assert template.name == "魂镜"
assert template.display_name == "魂镜"
assert template.language == "zh-CN"
assert template.privacy_level == "normal"
assert template.template_key == "default"
assert template.is_system_template is True
assert template.owner_scope == "system"
assert template.status == "active"
profile = loads_dict(template.profile_json)
assert profile.get("background") == "默认人物"
assert profile.get("temperament") == "沉静而温暖"
assert isinstance(profile.get("hobbies"), list)
assert isinstance(profile.get("values"), list)
assert isinstance(profile.get("birthday"), str) # _ensure_default_birthday 兜底
policy = loads_dict(template.model_policy_json)
assert policy.get("default_chat_model_hint") == settings.default_model_hint
assert policy.get("memory_extraction_model_hint") == "memory-extraction"
assert policy.get("personality_analysis_model_hint") == "personality-analysis"
assert policy.get("embedding_model_hint") == "embedding"
await session.rollback()
@pytest.mark.asyncio
async def test_ensure_default_system_template_updates_changed_fields():
"""已有模板时 config 字段变化 → 覆盖更新。"""
from app.services.characters import ensure_default_system_template
async with AsyncSessionLocal() as session:
template = await ensure_default_system_template(session)
await session.flush()
template_id = template.id
template.name = "旧名覆盖测试"
await session.flush()
template2 = await ensure_default_system_template(session)
assert template2.name == "魂镜" # 被 config 覆盖回来
assert template2.id == template_id # 同一条记录
await session.rollback()
@pytest.mark.asyncio
async def test_template_resync_no_spurious_updates():
"""config 与 DB 一致时同步不应触发无意义更新。"""
from app.services.characters import ensure_default_system_template
async with AsyncSessionLocal() as session:
template = await ensure_default_system_template(session)
await session.flush()
template2 = await ensure_default_system_template(session)
assert template2.id == template.id
await session.rollback()
@pytest.mark.asyncio
async def test_create_character_uses_new_defaults():
"""create_character 使用 ``_MODEL_POLICY_CREATE_DEFAULTS``。"""
from app.schemas.character import CreateCharacterRequest
from app.services.characters import create_character
async with AsyncSessionLocal() as session:
character = await create_character(
session,
CreateCharacterRequest(name="测试人物"),
)
assert character is not None
assert character.name == "测试人物"
assert character.status == "wuji"
# create_character 返回 CharacterResponse,model_policy 是 dict
assert "default_chat_model_hint" in character.model_policy
assert "memory_extraction_model_hint" in character.model_policy
await session.rollback()