72 lines
2.8 KiB
Python
72 lines
2.8 KiB
Python
"""角色卡导出映射:魂镜 Character + 世谱 → ST V3 卡静态快照。
|
|
|
|
反向于 import mapping。导出为静态快照——丢弃演化维度(人格版本 / 记忆 / 情绪),
|
|
仅保留当前设定 + 世谱。``mission`` / ``safety_guidelines`` 道体无 ST 对应字段,不导出。
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
|
|
from app.models.character import Character
|
|
from app.models.lorebook import Lorebook, LorebookEntry
|
|
|
|
|
|
def character_to_card(
|
|
character: Character,
|
|
lorebook: Lorebook | None = None,
|
|
entries: list[LorebookEntry] | None = None,
|
|
) -> dict:
|
|
"""Character + 世谱 → ST V3 卡 dict。"""
|
|
profile = json.loads(character.profile_json or "{}")
|
|
source_meta = profile.get("source_meta") or {}
|
|
data: dict = {
|
|
"name": character.name,
|
|
"description": profile.get("background", ""),
|
|
"personality": character.personality_summary or "",
|
|
"scenario": profile.get("scenario", ""),
|
|
"first_mes": profile.get("first_mes", ""),
|
|
"mes_example": profile.get("mes_example", ""),
|
|
"alternate_greetings": profile.get("alternate_greetings", []),
|
|
"tags": profile.get("tags", []),
|
|
"creator": source_meta.get("creator", ""),
|
|
"character_version": source_meta.get("character_version", ""),
|
|
"creator_notes": source_meta.get("creator_notes", ""),
|
|
"system_prompt": profile.get("system_prompt", ""),
|
|
"post_history_instructions": profile.get("post_history_instructions", ""),
|
|
"extensions": profile.get("st_extensions", {}),
|
|
}
|
|
if character.display_name and character.display_name != character.name:
|
|
data["nickname"] = character.display_name
|
|
if lorebook is not None:
|
|
data["character_book"] = lorebook_to_st_book(lorebook, entries or [])
|
|
return {"spec": "chara_card_v3", "spec_version": "3.0", "data": data}
|
|
|
|
|
|
def lorebook_to_st_book(lorebook: Lorebook, entries: list[LorebookEntry]) -> dict:
|
|
return {
|
|
"name": lorebook.name,
|
|
"description": lorebook.description,
|
|
"scan_depth": lorebook.scan_depth,
|
|
"token_budget": lorebook.token_budget,
|
|
"recursive_scanning": lorebook.recursive_scanning,
|
|
"entries": [entry_to_st(e) for e in entries],
|
|
}
|
|
|
|
|
|
def entry_to_st(entry: LorebookEntry) -> dict:
|
|
return {
|
|
"keys": json.loads(entry.keys_json or "[]"),
|
|
"content": entry.content,
|
|
"secondary_keys": json.loads(entry.secondary_keys_json or "[]"),
|
|
"constant": entry.constant,
|
|
"selective": entry.selective,
|
|
"enabled": entry.enabled,
|
|
"case_sensitive": entry.case_sensitive,
|
|
"use_regex": entry.use_regex,
|
|
"position": entry.position,
|
|
"insertion_order": entry.insertion_order,
|
|
"priority": entry.priority,
|
|
"comment": entry.comment,
|
|
}
|