refactor nickname
This commit is contained in:
@@ -45,6 +45,7 @@ from src.classes.appearance import Appearance, get_random_appearance
|
||||
from src.classes.battle import get_base_strength
|
||||
from src.classes.spirit_animal import SpiritAnimal
|
||||
from src.classes.long_term_objective import LongTermObjective
|
||||
from src.classes.nickname_data import Nickname
|
||||
|
||||
persona_num = CONFIG.avatar.persona_num
|
||||
|
||||
@@ -110,7 +111,7 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
# 灵兽:最多一个;若再次捕捉则覆盖
|
||||
spirit_animal: Optional[SpiritAnimal] = None
|
||||
# 绰号:江湖中对该角色的称谓,满足条件后生成,永久不变
|
||||
nickname: Optional[str] = None
|
||||
nickname: Optional[Nickname] = None
|
||||
# 自定义头像ID:如果设置,优先使用此ID显示头像
|
||||
custom_pic_id: Optional[int] = None
|
||||
# 当月/当步新设动作标记:在 commit_next_plan 设为 True,首次 tick_action 后清为 False
|
||||
@@ -264,7 +265,7 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
}
|
||||
# 绰号:仅在存在时显示
|
||||
if self.nickname is not None:
|
||||
info_dict["绰号"] = self.nickname
|
||||
info_dict["绰号"] = self.nickname.value
|
||||
# 灵兽:仅在存在时显示
|
||||
if self.spirit_animal is not None:
|
||||
info_dict["灵兽"] = spirit_animal_info
|
||||
@@ -295,7 +296,8 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
"thinking": self.thinking,
|
||||
"short_term_objective": self.short_term_objective,
|
||||
"long_term_objective": self.long_term_objective.content if self.long_term_objective else "",
|
||||
"nickname": self.nickname,
|
||||
"nickname": self.nickname.value if self.nickname else None,
|
||||
"nickname_reason": self.nickname.reason if self.nickname else None,
|
||||
}
|
||||
|
||||
# 复杂对象结构化
|
||||
@@ -687,7 +689,7 @@ class Avatar(AvatarSaveMixin, AvatarLoadMixin):
|
||||
lines: list[str] = []
|
||||
# 基础信息
|
||||
if self.nickname:
|
||||
add_kv(lines, "绰号", f"「{self.nickname}」")
|
||||
add_kv(lines, "绰号", f"「{self.nickname.value}」")
|
||||
|
||||
add_kv(lines, "性别", self.gender)
|
||||
add_kv(lines, "年龄", self.age)
|
||||
|
||||
@@ -13,6 +13,8 @@ from src.utils.config import CONFIG
|
||||
from src.utils.llm import call_llm_with_template, LLMMode
|
||||
from src.run.log import get_logger
|
||||
|
||||
from src.classes.nickname_data import Nickname
|
||||
|
||||
logger = get_logger().logger
|
||||
|
||||
|
||||
@@ -50,7 +52,7 @@ def can_get_nickname(avatar: "Avatar") -> bool:
|
||||
return major_count >= major_threshold and minor_count >= minor_threshold
|
||||
|
||||
|
||||
async def generate_nickname(avatar: "Avatar") -> Optional[str]:
|
||||
async def generate_nickname(avatar: "Avatar") -> Optional[dict]:
|
||||
"""
|
||||
为角色生成绰号
|
||||
|
||||
@@ -60,7 +62,7 @@ async def generate_nickname(avatar: "Avatar") -> Optional[str]:
|
||||
avatar: 要生成绰号的角色
|
||||
|
||||
Returns:
|
||||
生成的绰号,失败则返回None
|
||||
包含 nickname 和 reason 的字典,失败则返回None
|
||||
"""
|
||||
try:
|
||||
# 获取 expanded_info(包含详细信息和事件历史)
|
||||
@@ -77,15 +79,19 @@ async def generate_nickname(avatar: "Avatar") -> Optional[str]:
|
||||
|
||||
nickname = response_data.get("nickname", "").strip()
|
||||
thinking = response_data.get("thinking", "")
|
||||
reason = response_data.get("reason", "").strip()
|
||||
|
||||
if not nickname:
|
||||
logger.warning(f"为角色 {avatar.name} 生成绰号失败:返回空绰号")
|
||||
return None
|
||||
|
||||
logger.info(f"为角色 {avatar.name} 生成绰号:{nickname}")
|
||||
logger.info(f"为角色 {avatar.name} 生成绰号:{nickname} (原因:{reason})")
|
||||
logger.debug(f"绰号生成思考过程:{thinking}")
|
||||
|
||||
return nickname
|
||||
return {
|
||||
"nickname": nickname,
|
||||
"reason": reason
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"生成绰号时出错:{e}")
|
||||
@@ -107,15 +113,19 @@ async def process_avatar_nickname(avatar: "Avatar") -> Optional[Event]:
|
||||
if not can_get_nickname(avatar):
|
||||
return None
|
||||
|
||||
nickname = await generate_nickname(avatar)
|
||||
if not nickname:
|
||||
result = await generate_nickname(avatar)
|
||||
if not result:
|
||||
return None
|
||||
|
||||
avatar.nickname = nickname
|
||||
nickname_str = result["nickname"]
|
||||
reason = result["reason"]
|
||||
|
||||
avatar.nickname = Nickname(value=nickname_str, reason=reason)
|
||||
|
||||
# 生成事件:角色获得绰号
|
||||
event = Event(
|
||||
avatar.world.month_stamp,
|
||||
f"{avatar.name}在修仙界中闯出名号,被人称为「{nickname}」。",
|
||||
f"{avatar.name}在修仙界中闯出名号,被人称为「{nickname_str}」。",
|
||||
related_avatars=[avatar.id],
|
||||
is_major=True
|
||||
)
|
||||
|
||||
30
src/classes/nickname_data.py
Normal file
30
src/classes/nickname_data.py
Normal file
@@ -0,0 +1,30 @@
|
||||
"""
|
||||
Nickname 数据类
|
||||
"""
|
||||
from dataclasses import dataclass, asdict
|
||||
from typing import Optional
|
||||
|
||||
@dataclass
|
||||
class Nickname:
|
||||
"""
|
||||
绰号数据类
|
||||
包含绰号本身及其来源原因
|
||||
"""
|
||||
value: str
|
||||
reason: str
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
return asdict(self)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict) -> "Nickname":
|
||||
if not data:
|
||||
return None
|
||||
return cls(
|
||||
value=data["value"],
|
||||
reason=data["reason"]
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.value
|
||||
|
||||
@@ -144,10 +144,14 @@ class AvatarLoadMixin:
|
||||
|
||||
# 设置外貌(通过level获取完整的Appearance对象)
|
||||
avatar.appearance = get_appearance_by_level(data.get("appearance", 5))
|
||||
|
||||
# 恢复绰号
|
||||
from src.classes.nickname_data import Nickname
|
||||
avatar.nickname = Nickname.from_dict(data.get("nickname"))
|
||||
|
||||
# 设置行动与AI
|
||||
avatar.thinking = data.get("thinking", "")
|
||||
avatar.short_term_objective = data.get("short_term_objective", data.get("objective", "")) # 兼容旧存档
|
||||
avatar.short_term_objective = data.get("short_term_objective", "")
|
||||
avatar._action_cd_last_months = data.get("_action_cd_last_months", {})
|
||||
|
||||
# 加载长期目标
|
||||
|
||||
@@ -89,6 +89,7 @@ class AvatarSaveMixin:
|
||||
"alignment": self.alignment.name if self.alignment else None,
|
||||
"persona_ids": [p.id for p in self.personas] if self.personas else [],
|
||||
"appearance": self.appearance.level,
|
||||
"nickname": self.nickname.to_dict() if self.nickname else None,
|
||||
|
||||
# 行动与AI
|
||||
"current_action": current_action_dict,
|
||||
|
||||
Reference in New Issue
Block a user