113 lines
3.8 KiB
Python
113 lines
3.8 KiB
Python
"""世谱注入编排测试(DB 集成)。"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from app.db.session import AsyncSessionLocal
|
|
from app.models.character import Character
|
|
from app.models.lorebook import Lorebook, LorebookEntry
|
|
from app.services.lorebook import build_lorebook_injection
|
|
|
|
|
|
async def _make_character(session, owner_scope: str = "local-user") -> Character:
|
|
char = Character(name="tester", language="zh-CN", owner_scope=owner_scope)
|
|
session.add(char)
|
|
await session.flush()
|
|
return char
|
|
|
|
|
|
async def _add_entry(session, lorebook_id: str, keys: list[str], content: str, **kw) -> None:
|
|
session.add(
|
|
LorebookEntry(
|
|
lorebook_id=lorebook_id,
|
|
keys_json=json.dumps(keys),
|
|
content=content,
|
|
**kw,
|
|
)
|
|
)
|
|
await session.commit()
|
|
|
|
|
|
async def test_no_books_returns_none() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
before, after = await build_lorebook_injection(
|
|
session, "character_missing", "local-user", "任意文本"
|
|
)
|
|
assert before is None and after is None
|
|
|
|
|
|
async def test_keyword_match_injects_after_char() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
char = await _make_character(session)
|
|
book = Lorebook(character_id=char.id, owner_scope="local-user", scope="character")
|
|
session.add(book)
|
|
await session.flush()
|
|
await _add_entry(session, book.id, ["猫"], "她喜欢猫。", position="after_char")
|
|
|
|
before, after = await build_lorebook_injection(
|
|
session, char.id, "local-user", "今天看到一只猫"
|
|
)
|
|
assert before is None
|
|
assert after == "她喜欢猫。"
|
|
|
|
|
|
async def test_no_match_returns_none() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
char = await _make_character(session)
|
|
book = Lorebook(character_id=char.id, owner_scope="local-user")
|
|
session.add(book)
|
|
await session.flush()
|
|
await _add_entry(session, book.id, ["猫"], "她喜欢猫。")
|
|
|
|
before, after = await build_lorebook_injection(
|
|
session, char.id, "local-user", "无关文本"
|
|
)
|
|
assert before is None and after is None
|
|
|
|
|
|
async def test_before_position() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
char = await _make_character(session)
|
|
book = Lorebook(character_id=char.id, owner_scope="local-user")
|
|
session.add(book)
|
|
await session.flush()
|
|
await _add_entry(
|
|
session, book.id, ["魔法"], "世界观:存在魔法。", position="before_char"
|
|
)
|
|
|
|
before, after = await build_lorebook_injection(
|
|
session, char.id, "local-user", "使用魔法"
|
|
)
|
|
assert before == "世界观:存在魔法。"
|
|
assert after is None
|
|
|
|
|
|
async def test_global_scope_book_matched_for_any_character() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
char = await _make_character(session)
|
|
# global 书:character_id=None,所有人物共享
|
|
book = Lorebook(character_id=None, owner_scope="local-user", scope="global")
|
|
session.add(book)
|
|
await session.flush()
|
|
await _add_entry(session, book.id, ["龙"], "龙是传说生物。")
|
|
|
|
before, after = await build_lorebook_injection(
|
|
session, char.id, "local-user", "提到龙"
|
|
)
|
|
assert after == "龙是传说生物。"
|
|
|
|
|
|
async def test_disabled_entry_not_matched() -> None:
|
|
async with AsyncSessionLocal() as session:
|
|
char = await _make_character(session)
|
|
book = Lorebook(character_id=char.id, owner_scope="local-user")
|
|
session.add(book)
|
|
await session.flush()
|
|
await _add_entry(session, book.id, ["猫"], "x", enabled=False)
|
|
|
|
before, after = await build_lorebook_injection(
|
|
session, char.id, "local-user", "一只猫"
|
|
)
|
|
assert before is None and after is None
|