feat:移除watching,增加回复生成缓冲,添加头部动作

This commit is contained in:
SengokuCola
2025-07-17 22:25:33 +08:00
parent 8768b5d31b
commit 9be97acb00
14 changed files with 497 additions and 512 deletions

View File

@@ -1,6 +1,6 @@
import json
import time
import random
from src.chat.message_receive.message import MessageRecv
from src.llm_models.utils_model import LLMRequest
from src.common.logger import get_logger
@@ -8,10 +8,35 @@ from src.chat.utils.chat_message_builder import build_readable_messages, get_raw
from src.config.config import global_config
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.manager.async_task_manager import AsyncTask, async_task_manager
from src.plugin_system.apis import send_api
from json_repair import repair_json
from src.mais4u.s4u_config import s4u_config
logger = get_logger("action")
HEAD_CODE = {
"看向上方": "(0,0.5,0)",
"看向下方": "(0,-0.5,0)",
"看向左边": "(-1,0,0)",
"看向右边": "(1,0,0)",
"随意朝向": "random",
"看向摄像机": "camera",
"注视对方": "(0,0,0)",
"看向正前方": "(0,0,0)",
}
BODY_CODE = {
"双手背后向前弯腰": "010_0070",
"歪头双手合十": "010_0100",
"标准文静站立": "010_0101",
"双手交叠腹部站立": "010_0150",
"帅气的姿势": "010_0190",
"另一个帅气的姿势": "010_0191",
"手掌朝前可爱": "010_0210",
"平静,双手后放":"平静,双手后放",
"思考": "思考"
}
def init_prompt():
Prompt(
@@ -21,16 +46,15 @@ def init_prompt():
{indentify_block}
你现在的动作状态是:
- 手部:{hand_action}
- 上半身:{upper_body_action}
- 头部:{head_action}
- 身体动作:{body_action}
现在,因为你发送了消息,或者群里其他人发送了消息,引起了你的注意,你对其进行了阅读和思考,请你更新你的动作状态。
请只按照以下json格式输出描述你新的动作状态每个动作一到三个中文词确保每个字段都存在
身体动作可选
{all_actions}
请只按照以下json格式输出描述你新的动作状态确保每个字段都存在
{{
"hand_action": "...",
"upper_body_action": "...",
"head_action": "..."
"body_action": "..."
}}
""",
"change_action_prompt",
@@ -41,17 +65,16 @@ def init_prompt():
以上是群里最近的聊天记录
{indentify_block}
你之前的动作状态是
- 手部:{hand_action}
- 上半身:{upper_body_action}
- 头部:{head_action}
你之前的动作状态是
- 身体动作:{body_action}
身体动作可选:
{all_actions}
距离你上次关注群里消息已经过去了一段时间,你冷静了下来,你的动作会趋于平缓或静止,请你输出你现在新的动作状态,用中文。
请只按照以下json格式输出描述你新的动作状态每个动作一到三个词,确保每个字段都存在:
请只按照以下json格式输出描述你新的动作状态确保每个字段都存在
{{
"hand_action": "...",
"upper_body_action": "...",
"head_action": "..."
"body_action": "..."
}}
""",
"regress_action_prompt",
@@ -62,19 +85,38 @@ class ChatAction:
def __init__(self, chat_id: str):
self.chat_id: str = chat_id
self.hand_action: str = "双手放在桌面"
self.upper_body_action: str = "坐着"
self.body_action: str = "坐着"
self.head_action: str = "注视摄像机"
self.regression_count: int = 0
# 新增body_action冷却池key为动作名value为剩余冷却次数
self.body_action_cooldown: dict[str, int] = {}
print(s4u_config.models.motion)
print(global_config.model.emotion)
self.action_model = LLMRequest(
model=global_config.model.emotion,
temperature=0.7,
request_type="action",
request_type="motion",
)
self.last_change_time = 0
async def send_action_update(self):
"""发送动作更新到前端"""
body_code = BODY_CODE.get(self.body_action, "")
await send_api.custom_to_stream(
message_type="body_action",
content=body_code,
stream_id=self.chat_id,
storage_message=False,
show_log=True,
)
async def update_action_by_message(self, message: MessageRecv):
self.regression_count = 0
@@ -104,29 +146,43 @@ class ChatAction:
prompt_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
try:
# 冷却池处理:过滤掉冷却中的动作
self._update_body_action_cooldown()
available_actions = [k for k in BODY_CODE.keys() if k not in self.body_action_cooldown]
all_actions = "\n".join(available_actions)
prompt = await global_prompt_manager.format_prompt(
"change_action_prompt",
chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block,
body_action=self.body_action,
all_actions=all_actions,
)
prompt = await global_prompt_manager.format_prompt(
"change_action_prompt",
chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block,
hand_action=self.hand_action,
upper_body_action=self.upper_body_action,
head_action=self.head_action,
)
logger.info(f"prompt: {prompt}")
response, (reasoning_content, model_name) = await self.action_model.generate_response_async(prompt=prompt)
logger.info(f"response: {response}")
logger.info(f"reasoning_content: {reasoning_content}")
logger.info(f"prompt: {prompt}")
response, (reasoning_content, model_name) = await self.action_model.generate_response_async(prompt=prompt)
logger.info(f"response: {response}")
logger.info(f"reasoning_content: {reasoning_content}")
action_data = json.loads(repair_json(response))
action_data = json.loads(repair_json(response))
if action_data:
# 记录原动作,切换后进入冷却
prev_body_action = self.body_action
new_body_action = action_data.get("body_action", self.body_action)
if new_body_action != prev_body_action:
if prev_body_action:
self.body_action_cooldown[prev_body_action] = 3
self.body_action = new_body_action
self.head_action = action_data.get("head_action", self.head_action)
# 发送动作更新
await self.send_action_update()
if action_data:
self.hand_action = action_data.get("hand_action", self.hand_action)
self.upper_body_action = action_data.get("upper_body_action", self.upper_body_action)
self.head_action = action_data.get("head_action", self.head_action)
self.last_change_time = message_time
self.last_change_time = message_time
except Exception as e:
logger.error(f"update_action_by_message error: {e}")
async def regress_action(self):
message_time = time.time()
@@ -134,7 +190,7 @@ class ChatAction:
chat_id=self.chat_id,
timestamp_start=self.last_change_time,
timestamp_end=message_time,
limit=15,
limit=10,
limit_mode="last",
)
chat_talking_prompt = build_readable_messages(
@@ -155,33 +211,56 @@ class ChatAction:
prompt_personality = global_config.personality.personality_core
indentify_block = f"你的名字是{bot_name}{bot_nickname},你{prompt_personality}"
try:
prompt = await global_prompt_manager.format_prompt(
"regress_action_prompt",
chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block,
hand_action=self.hand_action,
upper_body_action=self.upper_body_action,
head_action=self.head_action,
)
# 冷却池处理:过滤掉冷却中的动作
self._update_body_action_cooldown()
available_actions = [k for k in BODY_CODE.keys() if k not in self.body_action_cooldown]
all_actions = "\n".join(available_actions)
logger.info(f"prompt: {prompt}")
response, (reasoning_content, model_name) = await self.action_model.generate_response_async(prompt=prompt)
logger.info(f"response: {response}")
logger.info(f"reasoning_content: {reasoning_content}")
prompt = await global_prompt_manager.format_prompt(
"regress_action_prompt",
chat_talking_prompt=chat_talking_prompt,
indentify_block=indentify_block,
body_action=self.body_action,
all_actions=all_actions,
)
action_data = json.loads(repair_json(response))
if action_data:
self.hand_action = action_data.get("hand_action", self.hand_action)
self.upper_body_action = action_data.get("upper_body_action", self.upper_body_action)
self.head_action = action_data.get("head_action", self.head_action)
logger.info(f"prompt: {prompt}")
response, (reasoning_content, model_name) = await self.action_model.generate_response_async(prompt=prompt)
logger.info(f"response: {response}")
logger.info(f"reasoning_content: {reasoning_content}")
self.regression_count += 1
action_data = json.loads(repair_json(response))
if action_data:
prev_body_action = self.body_action
new_body_action = action_data.get("body_action", self.body_action)
if new_body_action != prev_body_action:
if prev_body_action:
self.body_action_cooldown[prev_body_action] = 6
self.body_action = new_body_action
# 发送动作更新
await self.send_action_update()
self.regression_count += 1
self.last_change_time = message_time
except Exception as e:
logger.error(f"regress_action error: {e}")
# 新增:冷却池维护方法
def _update_body_action_cooldown(self):
remove_keys = []
for k in self.body_action_cooldown:
self.body_action_cooldown[k] -= 1
if self.body_action_cooldown[k] <= 0:
remove_keys.append(k)
for k in remove_keys:
del self.body_action_cooldown[k]
class ActionRegressionTask(AsyncTask):
def __init__(self, action_manager: "ActionManager"):
super().__init__(task_name="ActionRegressionTask", run_interval=30)
super().__init__(task_name="ActionRegressionTask", run_interval=3)
self.action_manager = action_manager
async def run(self):
@@ -191,7 +270,7 @@ class ActionRegressionTask(AsyncTask):
if action_state.last_change_time == 0:
continue
if now - action_state.last_change_time > 180:
if now - action_state.last_change_time > 10:
if action_state.regression_count >= 3:
continue
@@ -225,15 +304,8 @@ class ActionManager:
self.action_state_list.append(new_action_state)
return new_action_state
def reset_action_state_by_chat_id(self, chat_id: str):
for action_state in self.action_state_list:
if action_state.chat_id == chat_id:
action_state.hand_action = "双手放在桌面"
action_state.upper_body_action = "坐着"
action_state.head_action = "注视摄像机"
action_state.regression_count = 0
return
self.action_state_list.append(ChatAction(chat_id))
init_prompt()