Files
matrix-show/backend/app/services/character_generator.py
T
2026-06-04 17:59:53 +08:00

103 lines
3.8 KiB
Python

import logging
import random
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.orm import Character
from app.models.schemas import CharacterRole
from app.services.hermes_client import hermes_client
from app.services.soul_generator import soul_generator
logger = logging.getLogger(__name__)
class CharacterGenerator:
async def generate_characters(
self,
session: AsyncSession,
script_id: str,
characters_data: list[dict],
is_json: bool = False,
) -> list[Character]:
characters = []
killer_index = random.randint(0, len(characters_data) - 1) if len(characters_data) > 1 else 0
for i, char_data in enumerate(characters_data):
role = CharacterRole.KILLER if i == killer_index else CharacterRole.SUSPECT
if is_json and "role" in char_data:
role = CharacterRole(char_data["role"]) if char_data["role"] in [r.value for r in CharacterRole] else role
name = char_data.get("name", f"角色{i + 1}")
profile_name = name.lower().replace(" ", "_").replace("·", "_")
character = Character(
script_id=script_id,
name=name,
role=role,
personality=char_data.get("personality", ""),
speaking_style=char_data.get("speaking_style", ""),
background=char_data.get("background", ""),
secret=char_data.get("secret", ""),
motive=char_data.get("motive", ""),
hermes_profile=profile_name,
is_revealed_killer=False,
)
session.add(character)
characters.append(character)
await session.commit()
for character in characters:
await session.refresh(character)
return characters
async def create_profile(self, character: Character) -> bool:
soul_content = soul_generator.generate(
name=character.name,
personality=character.personality,
speaking_style=character.speaking_style,
background=character.background,
secret=character.secret,
motive=character.motive,
knowledge_base=character.knowledge_base,
)
success = await hermes_client.create_profile(character.hermes_profile, soul_content)
if success:
character.soul_md = soul_content
return success
async def create_all_profiles(self, session: AsyncSession, script_id: str) -> int:
result = await session.execute(
select(Character).where(Character.script_id == script_id)
)
characters = list(result.scalars().all())
created = 0
for character in characters:
try:
if await self.create_profile(character):
created += 1
character.soul_md = soul_generator.generate(
name=character.name,
personality=character.personality,
speaking_style=character.speaking_style,
background=character.background,
secret=character.secret,
motive=character.motive,
knowledge_base=character.knowledge_base,
)
except Exception as e:
logger.error(f"Failed to create profile for {character.name}: {e}")
await session.commit()
logger.info(f"Created {created}/{len(characters)} profiles for script {script_id}")
return created
async def delete_profile(self, character: Character) -> bool:
return await hermes_client.delete_profile(character.hermes_profile)
character_generator = CharacterGenerator()