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()