add group-aware persona bias for xiaoniu bot
This commit is contained in:
@@ -16,6 +16,8 @@ from wechat_ipad.models.message import MessageType
|
||||
|
||||
from .context_builder import ContextBuilder
|
||||
from .flow_manager import FlowManager
|
||||
from .group_memory import GroupMemoryService
|
||||
from .group_profile import GroupProfileResolver
|
||||
from .llm_client import LLMClient
|
||||
from .memory_store import MemoryStore
|
||||
from .persona_engine import PersonaEngine
|
||||
@@ -72,6 +74,8 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
self.db_manager = context.get("db_manager")
|
||||
self.enable = bool(self._config.get("enable", True))
|
||||
self.persona_engine = PersonaEngine(self.get_plugin_path(), self._config.get("persona", {}))
|
||||
self.group_memory_service = GroupMemoryService(self.db_manager, self._config.get("group_profiles", {}) or {})
|
||||
self.group_profile_resolver = GroupProfileResolver(self._config.get("group_profiles", {}) or {})
|
||||
self.flow_manager = FlowManager({
|
||||
**(self._config.get("flow", {}) or {}),
|
||||
"night_silent_hours": (self._config.get("cooldown", {}) or {}).get("night_silent_hours", []),
|
||||
@@ -134,11 +138,19 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
bot: WechatAPIClient = message.get("bot")
|
||||
content = self._normalize_content(message)
|
||||
sender_name = self._get_sender_name(room_id, sender)
|
||||
group_name = self._get_group_name(room_id, message)
|
||||
group_memory_profile = self.group_memory_service.build_group_memory_profile(room_id, group_name)
|
||||
group_profile = self.group_profile_resolver.resolve(room_id, group_name, group_memory_profile)
|
||||
self._log_event(
|
||||
"recv",
|
||||
room_id=room_id,
|
||||
sender=sender,
|
||||
sender_name=sender_name,
|
||||
group_mode=group_profile.get("mode", ""),
|
||||
knowledge_domain=group_profile.get("knowledge_domain", ""),
|
||||
memory_domain=group_profile.get("group_memory_domain", ""),
|
||||
humor_style=group_profile.get("humor_style", ""),
|
||||
sharpness_style=group_profile.get("sharpness_style", ""),
|
||||
is_at=message.get("is_at", False),
|
||||
content_preview=self._preview(content),
|
||||
msg_type=str(message.get("type")),
|
||||
@@ -218,6 +230,8 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
"context",
|
||||
room_id=room_id,
|
||||
sender=sender,
|
||||
group_mode=group_profile.get("mode", ""),
|
||||
knowledge_domain=group_profile.get("knowledge_domain", ""),
|
||||
reply_mode=reply_mode,
|
||||
recent_message_count=len(recent_messages),
|
||||
vector_hit_count=len(vector_memories),
|
||||
@@ -225,6 +239,7 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
|
||||
context = self.context_builder.build(
|
||||
room_id=room_id,
|
||||
group_profile=group_profile,
|
||||
sender=sender,
|
||||
sender_name=sender_name,
|
||||
content=content,
|
||||
@@ -236,7 +251,7 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
vector_memories=vector_memories,
|
||||
)
|
||||
|
||||
system_prompt = self.persona_engine.build_system_prompt()
|
||||
system_prompt = self.persona_engine.build_system_prompt(group_profile)
|
||||
user_prompt = self._build_user_prompt(context, memory_hints)
|
||||
response = self._sanitize_response(self.llm_client.chat(system_prompt, user_prompt, user_id=f"{room_id}:{sender}"))
|
||||
if not response:
|
||||
@@ -314,6 +329,11 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
except Exception:
|
||||
return sender
|
||||
|
||||
@staticmethod
|
||||
def _get_group_name(room_id: str, message: Dict[str, Any]) -> str:
|
||||
all_contacts = message.get("all_contacts", {}) or {}
|
||||
return str(all_contacts.get(room_id, room_id))
|
||||
|
||||
def _pass_cooldown(self, room_id: str, trigger: Dict) -> bool:
|
||||
current_ts = time.time()
|
||||
room_cd = int(self.cooldown_config.get("group_reply_cooldown_sec", 45))
|
||||
@@ -333,6 +353,7 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
f"触发类型:{context.get('trigger_type', 'none')}\n"
|
||||
f"回复模式:{context.get('reply_mode', 'social_short')}\n"
|
||||
f"当前心流状态:{context.get('flow_state', 'idle')}\n"
|
||||
f"当前群画像:\n{context.get('group_profile_prompt', '暂无')}\n\n"
|
||||
f"成员稳定记忆:\n{context.get('memory_prompt', '暂无')}\n\n"
|
||||
f"向量召回记忆:\n{context.get('vector_memory_prompt', '') or '暂无'}\n\n"
|
||||
f"补充信息:回归状态={memory_hints.get('returning_member_state', '') or 'none'}\n"
|
||||
@@ -348,6 +369,7 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
f"9. 如果你不确定自己是否理解对了,就宁可不展开,只回很短。\n"
|
||||
f"10. 把这次回复当作真人聊天里的第一反应,先只给第一层结论,不要主动补第二层解释。\n"
|
||||
f"11. 如果一句话已经够了,就立刻停,不要为了完整而补充。\n"
|
||||
f"12. 回答时优先服从当前群画像里的知识域和回答风格,不要跨领域乱发挥。\n"
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@@ -478,7 +500,9 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
if event == "recv":
|
||||
return (
|
||||
f"[XIAONIU] RECV room={room} user={sender_name}/{sender} "
|
||||
f"at={self._yn(data.get('is_at'))} msg={data.get('content_preview', '')}"
|
||||
f"at={self._yn(data.get('is_at'))} "
|
||||
f"style={self._style_mark(data.get('humor_style', ''), data.get('sharpness_style', ''))} "
|
||||
f"msg={data.get('content_preview', '')}"
|
||||
).strip()
|
||||
|
||||
if event == "memory":
|
||||
@@ -552,3 +576,9 @@ class AIAutoResponsePlugin(MessagePluginInterface):
|
||||
if len(value) <= 10:
|
||||
return value
|
||||
return value[:4] + "..." + value[-4:]
|
||||
|
||||
@staticmethod
|
||||
def _style_mark(humor_style: str, sharpness_style: str) -> str:
|
||||
humor = "humor" if "中等" in str(humor_style) or "偏上" in str(humor_style) else "plain"
|
||||
sharp = "sharp" if "毒舌" in str(sharpness_style) or "嘴欠" in str(sharpness_style) else "soft"
|
||||
return f"{humor}/{sharp}"
|
||||
|
||||
Reference in New Issue
Block a user