Files
cultivation-world-simulator/src/classes/nickname.py
2025-11-19 01:06:42 +08:00

124 lines
3.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
绰号生成模块
为满足条件的角色生成修仙界绰号
"""
from typing import Optional, List, TYPE_CHECKING
if TYPE_CHECKING:
from src.classes.avatar import Avatar
from src.classes.world import World
from src.classes.event import Event
from src.utils.config import CONFIG
from src.utils.llm import get_prompt_and_call_llm_async
from src.run.log import get_logger
logger = get_logger().logger
def can_get_nickname(avatar: "Avatar") -> bool:
"""
检查角色是否满足获得绰号的条件
条件:
1. 尚未拥有绰号nickname为None
2. 长期事件数量 >= major_event_threshold
3. 短期事件数量 >= minor_event_threshold
Args:
avatar: 要检查的角色
Returns:
是否满足条件
"""
# 已有绰号,不再生成
if avatar.nickname is not None:
return False
# 检查事件数量
em = avatar.world.event_manager
major_threshold = CONFIG.nickname.major_event_threshold
minor_threshold = CONFIG.nickname.minor_event_threshold
major_events = em.get_major_events_by_avatar(avatar.id)
minor_events = em.get_minor_events_by_avatar(avatar.id)
major_count = len(major_events)
minor_count = len(minor_events)
# AND逻辑两个条件都要满足
return major_count >= major_threshold and minor_count >= minor_threshold
async def generate_nickname(avatar: "Avatar") -> Optional[str]:
"""
为角色生成绰号
调用LLM基于角色信息和事件历史生成合适的绰号
Args:
avatar: 要生成绰号的角色
Returns:
生成的绰号失败则返回None
"""
try:
# 获取 expanded_info包含详细信息和事件历史
expanded_info = avatar.get_expanded_info(detailed=True)
# 准备模板参数
template_path = CONFIG.paths.templates / "nickname.txt"
infos = {
"avatar_info": expanded_info,
}
# 调用LLM并自动解析JSON
response_data = await get_prompt_and_call_llm_async(template_path, infos, mode="fast")
nickname = response_data.get("nickname", "").strip()
thinking = response_data.get("thinking", "")
if not nickname:
logger.warning(f"为角色 {avatar.name} 生成绰号失败:返回空绰号")
return None
logger.info(f"为角色 {avatar.name} 生成绰号:{nickname}")
logger.debug(f"绰号生成思考过程:{thinking}")
return nickname
except Exception as e:
logger.error(f"生成绰号时出错:{e}")
return None
async def process_avatar_nickname(avatar: "Avatar") -> Optional[Event]:
"""
处理单个角色的绰号生成
检查角色是否满足条件,满足则生成绰号并返回对应事件
Args:
avatar: 要处理的角色
Returns:
生成的事件如果不满足条件或生成失败则返回None
"""
if not can_get_nickname(avatar):
return None
nickname = await generate_nickname(avatar)
if not nickname:
return None
avatar.nickname = nickname
# 生成事件:角色获得绰号
event = Event(
avatar.world.month_stamp,
f"{avatar.name}在修仙界中闯出名号,被人称为'{nickname}'",
related_avatars=[avatar.id],
is_major=True
)
return event