feat: 现在使用工具调用来更新关系和心情而不是固定更新

This commit is contained in:
SengokuCola
2025-04-14 00:36:33 +08:00
parent d1bbda9e60
commit 7eba42f84a
16 changed files with 551 additions and 87 deletions

View File

@@ -21,6 +21,7 @@ from ...person_info.relationship_manager import relationship_manager
from ...chat.message_buffer import message_buffer
from src.plugins.respon_info_catcher.info_catcher import info_catcher_manager
from ...utils.timer_calculater import Timer
from src.do_tool.tool_use import ToolUser
# 定义日志配置
chat_config = LogConfig(
@@ -37,6 +38,7 @@ class ThinkFlowChat:
self.gpt = ResponseGenerator()
self.mood_manager = MoodManager.get_instance()
self.mood_manager.start_mood_update()
self.tool_user = ToolUser()
async def _create_thinking_message(self, message, chat, userinfo, messageinfo):
"""创建思考消息"""
@@ -110,14 +112,10 @@ class ThinkFlowChat:
"""处理表情包"""
if random() < global_config.emoji_chance:
emoji_raw = await emoji_manager.get_emoji_for_text(response)
# print("11111111111111")
# logger.info(emoji_raw)
if emoji_raw:
emoji_path, description = emoji_raw
emoji_cq = image_path_to_base64(emoji_path)
# logger.info(emoji_cq)
thinking_time_point = round(message.message_info.time, 2)
message_segment = Seg(type="emoji", data=emoji_cq)
@@ -136,19 +134,9 @@ class ThinkFlowChat:
is_emoji=True,
)
# logger.info("22222222222222")
message_manager.add_message(bot_message)
async def _update_using_response(self, message, response_set):
"""更新心流状态"""
stream_id = message.chat_stream.stream_id
chat_talking_prompt = ""
if stream_id:
chat_talking_prompt = get_recent_group_detailed_plain_text(
stream_id, limit=global_config.MAX_CONTEXT_SIZE, combine=True
)
await heartflow.get_subheartflow(stream_id).do_thinking_after_reply(response_set, chat_talking_prompt)
async def _update_relationship(self, message: MessageRecv, response_set):
"""更新关系情绪"""
@@ -224,13 +212,6 @@ class ThinkFlowChat:
logger.info("触发缓冲,已炸飞消息列")
return
# 计算回复意愿
# current_willing_old = willing_manager.get_willing(chat_stream=chat)
# # current_willing_new = (heartflow.get_subheartflow(chat.stream_id).current_state.willing - 5) / 4
# # current_willing = (current_willing_old + current_willing_new) / 2
# # 有点bug
# current_willing = current_willing_old
# 获取回复概率
is_willing = False
if reply_probability != 1:
@@ -266,7 +247,7 @@ class ThinkFlowChat:
except Exception as e:
logger.error(f"心流创建思考消息失败: {e}")
logger.debug(f"创建捕捉器thinking_id:{thinking_id}")
logger.trace(f"创建捕捉器thinking_id:{thinking_id}")
info_catcher = info_catcher_manager.get_info_catcher(thinking_id)
info_catcher.catch_decide_to_response(message)
@@ -279,7 +260,72 @@ class ThinkFlowChat:
logger.error(f"心流观察失败: {e}")
info_catcher.catch_after_observe(timing_results["观察"])
# 思考前使用工具
update_relationship = ""
try:
with Timer("思考前使用工具", timing_results):
tool_result = await self.tool_user.use_tool(message.processed_plain_text, message.message_info.user_info.user_nickname, chat)
# 如果工具被使用且获得了结果,将收集到的信息合并到思考中
collected_info = ""
if tool_result.get("used_tools", False):
# 如果有收集到的结构化信息,将其格式化后添加到当前思考中
if "structured_info" in tool_result:
info = tool_result["structured_info"]
# 处理记忆信息
if info["memory"]:
collected_info += "\n记忆相关信息:\n"
for mem in info["memory"]:
collected_info += f"- {mem['name']}: {mem['content']}\n"
# 处理日程信息
if info["schedule"]:
collected_info += "\n日程相关信息:\n"
for sch in info["schedule"]:
collected_info += f"- {sch['name']}: {sch['content']}\n"
# 处理知识信息
if info["knowledge"]:
collected_info += "\n知识相关信息:\n"
for know in info["knowledge"]:
collected_info += f"- {know['name']}: {know['content']}\n"
# 处理关系信息
if info["change_relationship"]:
collected_info += "\n关系相关信息:\n"
for rel in info["change_relationship"]:
collected_info += f"- {rel['name']}: {rel['content']}\n"
# print("11111111111111111111111111111")
update_relationship += rel["content"]
# print(f"11111111111111111111111111111{update_relationship}")
# 处理心情信息
if info["change_mood"]:
collected_info += "\n心情相关信息:\n"
for mood in info["change_mood"]:
collected_info += f"- {mood['name']}: {mood['content']}\n"
# 处理其他信息
if info["other"]:
collected_info += "\n其他相关信息:\n"
for other in info["other"]:
collected_info += f"- {other['name']}: {other['content']}\n"
except Exception as e:
logger.error(f"思考前工具调用失败: {e}")
logger.error(traceback.format_exc())
if update_relationship:
# ori_response = ",".join(response_set)
# print("22222222222222222222222222222")
stance, emotion = await self.gpt._get_emotion_tags_with_reason("你还没有回复", message.processed_plain_text,update_relationship)
await relationship_manager.calculate_update_relationship_value(
chat_stream=message.chat_stream, label=emotion, stance=stance
)
print("33333333333333333333333333333")
# 思考前脑内状态
try:
with Timer("思考前脑内状态", timing_results):
@@ -289,6 +335,7 @@ class ThinkFlowChat:
message_txt=message.processed_plain_text,
sender_name=message.message_info.user_info.user_nickname,
chat_stream=chat,
extra_info=collected_info
)
except Exception as e:
logger.error(f"心流思考前脑内状态失败: {e}")
@@ -323,19 +370,80 @@ class ThinkFlowChat:
except Exception as e:
logger.error(f"心流处理表情包失败: {e}")
# 更新心流
try:
with Timer("更新心流", timing_results):
await self._update_using_response(message, response_set)
except Exception as e:
logger.error(f"心流更新失败: {e}")
# 更新关系情绪
# 思考后使用工具
try:
with Timer("更新关系情绪", timing_results):
await self._update_relationship(message, response_set)
with Timer("思考后使用工具", timing_results):
tool_result = await self.tool_user.use_tool(message.processed_plain_text, message.message_info.user_info.user_nickname, chat)
# 如果工具被使用且获得了结果,将收集到的信息合并到思考中
collected_info = ""
if tool_result.get("used_tools", False):
# 如果有收集到的结构化信息,将其格式化后添加到当前思考中
if "structured_info" in tool_result:
info = tool_result["structured_info"]
# 处理记忆信息
if info["memory"]:
collected_info += "\n记忆相关信息:\n"
for mem in info["memory"]:
collected_info += f"- {mem['name']}: {mem['content']}\n"
# 处理日程信息
if info["schedule"]:
collected_info += "\n日程相关信息:\n"
for sch in info["schedule"]:
collected_info += f"- {sch['name']}: {sch['content']}\n"
# 处理知识信息
if info["knowledge"]:
collected_info += "\n知识相关信息:\n"
for know in info["knowledge"]:
collected_info += f"- {know['name']}: {know['content']}\n"
# 处理关系信息
if info["change_relationship"]:
collected_info += "\n关系相关信息:\n"
for rel in info["change_relationship"]:
collected_info += f"- {rel['name']}: {rel['content']}\n"
# 处理心情信息
if info["change_mood"]:
collected_info += "\n心情相关信息:\n"
for mood in info["change_mood"]:
collected_info += f"- {mood['name']}: {mood['content']}\n"
# 处理其他信息
if info["other"]:
collected_info += "\n其他相关信息:\n"
for other in info["other"]:
collected_info += f"- {other['name']}: {other['content']}\n"
except Exception as e:
logger.error(f"心流更新关系情绪失败: {e}")
logger.error(f"思考后工具调用失败: {e}")
logger.error(traceback.format_exc())
# 更新关系
if info["change_relationship"]:
ori_response = ",".join(response_set)
stance, emotion = await self.gpt._get_emotion_tags(ori_response, message.processed_plain_text,info["change_relationship"]["content"])
await relationship_manager.calculate_update_relationship_value(
chat_stream=message.chat_stream, label=emotion, stance=stance
)
try:
with Timer("思考后脑内状态更新", timing_results):
stream_id = message.chat_stream.stream_id
chat_talking_prompt = ""
if stream_id:
chat_talking_prompt = get_recent_group_detailed_plain_text(
stream_id, limit=global_config.MAX_CONTEXT_SIZE, combine=True
)
await heartflow.get_subheartflow(stream_id).do_thinking_after_reply(response_set, chat_talking_prompt,collected_info)
except Exception as e:
logger.error(f"心流思考后脑内状态更新失败: {e}")
# 回复后处理
await willing_manager.after_generate_reply_handle(message.message_info.message_id)

View File

@@ -225,6 +225,58 @@ class ResponseGenerator:
except Exception as e:
logger.debug(f"获取情感标签时出错: {e}")
return "中立", "平静" # 出错时返回默认值
async def _get_emotion_tags_with_reason(self, content: str, processed_plain_text: str, reason: str):
"""提取情感标签,结合立场和情绪"""
try:
# 构建提示词,结合回复内容、被回复的内容以及立场分析
prompt = f"""
请严格根据以下对话内容,完成以下任务:
1. 判断回复者对被回复者观点的直接立场:
- "支持":明确同意或强化被回复者观点
- "反对":明确反驳或否定被回复者观点
- "中立":不表达明确立场或无关回应
2. 从"开心,愤怒,悲伤,惊讶,平静,害羞,恐惧,厌恶,困惑"中选出最匹配的1个情感标签
3. 按照"立场-情绪"的格式直接输出结果,例如:"反对-愤怒"
4. 考虑回复者的人格设定为{global_config.personality_core}
对话示例:
被回复「A就是笨」
回复「A明明很聪明」 → 反对-愤怒
当前对话:
被回复:「{processed_plain_text}
回复:「{content}
原因:「{reason}
输出要求:
- 只需输出"立场-情绪"结果,不要解释
- 严格基于文字直接表达的对立关系判断
"""
# 调用模型生成结果
result, _, _ = await self.model_sum.generate_response(prompt)
result = result.strip()
# 解析模型输出的结果
if "-" in result:
stance, emotion = result.split("-", 1)
valid_stances = ["支持", "反对", "中立"]
valid_emotions = ["开心", "愤怒", "悲伤", "惊讶", "害羞", "平静", "恐惧", "厌恶", "困惑"]
if stance in valid_stances and emotion in valid_emotions:
return stance, emotion # 返回有效的立场-情绪组合
else:
logger.debug(f"无效立场-情感组合:{result}")
return "中立", "平静" # 默认返回中立-平静
else:
logger.debug(f"立场-情感格式错误:{result}")
return "中立", "平静" # 格式错误时返回默认值
except Exception as e:
logger.debug(f"获取情感标签时出错: {e}")
return "中立", "平静" # 出错时返回默认值
async def _process_response(self, content: str) -> List[str]:
"""处理响应内容,返回处理后的内容和情感标签"""

View File

@@ -436,7 +436,7 @@ class Hippocampus:
activation_values[neighbor] = new_activation
visited_nodes.add(neighbor)
nodes_to_process.append((neighbor, new_activation, current_depth + 1))
logger.debug(
logger.trace(
f"节点 '{neighbor}' 被激活,激活值: {new_activation:.2f} (通过 '{current_node}' 连接,强度: {strength}, 深度: {current_depth + 1})"
) # noqa: E501
@@ -1144,7 +1144,7 @@ class Hippocampus:
activation_values[neighbor] = new_activation
visited_nodes.add(neighbor)
nodes_to_process.append((neighbor, new_activation, current_depth + 1))
logger.debug(
logger.trace(
f"节点 '{neighbor}' 被激活,激活值: {new_activation:.2f} (通过 '{current_node}' 连接,强度: {strength}, 深度: {current_depth + 1})"
) # noqa: E501

View File

@@ -98,7 +98,7 @@ class LLM_request:
"timestamp": datetime.now(),
}
db.llm_usage.insert_one(usage_data)
logger.debug(
logger.trace(
f"Token使用情况 - 模型: {self.model_name}, "
f"用户: {user_id}, 类型: {request_type}, "
f"提示词: {prompt_tokens}, 完成: {completion_tokens}, "

View File

@@ -117,7 +117,7 @@ class PersonInfoManager:
return document[field_name]
else:
default_value = copy.deepcopy(person_info_default[field_name])
logger.debug(f"获取{person_id}{field_name}失败,已返回默认值{default_value}")
logger.trace(f"获取{person_id}{field_name}失败,已返回默认值{default_value}")
return default_value
async def get_values(self, person_id: str, field_names: list) -> dict:

View File

@@ -75,7 +75,7 @@ class RelationshipManager:
else:
return mood_value / coefficient
async def calculate_update_relationship_value(self, chat_stream: ChatStream, label: str, stance: str) -> None:
async def calculate_update_relationship_value(self, chat_stream: ChatStream, label: str, stance: str) -> tuple:
"""计算并变更关系值
新的关系值变更计算方式:
将关系值限定在-1000到1000
@@ -84,6 +84,10 @@ class RelationshipManager:
2.关系越差,改善越难,关系越好,恶化越容易
3.人维护关系的精力往往有限,所以当高关系值用户越多,对于中高关系值用户增长越慢
4.连续正面或负面情感会正反馈
返回:
用户昵称,变更值,变更后关系等级
"""
stancedict = {
"支持": 0,
@@ -147,6 +151,7 @@ class RelationshipManager:
level_num = self.calculate_level_num(old_value + value)
relationship_level = ["厌恶", "冷漠", "一般", "友好", "喜欢", "暧昧"]
logger.info(
f"用户: {chat_stream.user_info.user_nickname}"
f"当前关系: {relationship_level[level_num]}, "
f"关系值: {old_value:.2f}, "
f"当前立场情感: {stance}-{label}, "
@@ -154,6 +159,95 @@ class RelationshipManager:
)
await person_info_manager.update_one_field(person_id, "relationship_value", old_value + value, data)
return chat_stream.user_info.user_nickname,value,relationship_level[level_num]
async def calculate_update_relationship_value_with_reason(self, chat_stream: ChatStream, label: str, stance: str, reason: str) -> tuple:
"""计算并变更关系值
新的关系值变更计算方式:
将关系值限定在-1000到1000
对于关系值的变更,期望:
1.向两端逼近时会逐渐减缓
2.关系越差,改善越难,关系越好,恶化越容易
3.人维护关系的精力往往有限,所以当高关系值用户越多,对于中高关系值用户增长越慢
4.连续正面或负面情感会正反馈
返回:
用户昵称,变更值,变更后关系等级
"""
stancedict = {
"支持": 0,
"中立": 1,
"反对": 2,
}
valuedict = {
"开心": 1.5,
"愤怒": -2.0,
"悲伤": -0.5,
"惊讶": 0.6,
"害羞": 2.0,
"平静": 0.3,
"恐惧": -1.5,
"厌恶": -1.0,
"困惑": 0.5,
}
person_id = person_info_manager.get_person_id(chat_stream.user_info.platform, chat_stream.user_info.user_id)
data = {
"platform": chat_stream.user_info.platform,
"user_id": chat_stream.user_info.user_id,
"nickname": chat_stream.user_info.user_nickname,
"konw_time": int(time.time()),
}
old_value = await person_info_manager.get_value(person_id, "relationship_value")
old_value = self.ensure_float(old_value, person_id)
if old_value > 1000:
old_value = 1000
elif old_value < -1000:
old_value = -1000
value = valuedict[label]
if old_value >= 0:
if valuedict[label] >= 0 and stancedict[stance] != 2:
value = value * math.cos(math.pi * old_value / 2000)
if old_value > 500:
rdict = await person_info_manager.get_specific_value_list("relationship_value", lambda x: x > 700)
high_value_count = len(rdict)
if old_value > 700:
value *= 3 / (high_value_count + 2) # 排除自己
else:
value *= 3 / (high_value_count + 3)
elif valuedict[label] < 0 and stancedict[stance] != 0:
value = value * math.exp(old_value / 2000)
else:
value = 0
elif old_value < 0:
if valuedict[label] >= 0 and stancedict[stance] != 2:
value = value * math.exp(old_value / 2000)
elif valuedict[label] < 0 and stancedict[stance] != 0:
value = value * math.cos(math.pi * old_value / 2000)
else:
value = 0
self.positive_feedback_sys(label, stance)
value = self.mood_feedback(value)
level_num = self.calculate_level_num(old_value + value)
relationship_level = ["厌恶", "冷漠", "一般", "友好", "喜欢", "暧昧"]
logger.info(
f"用户: {chat_stream.user_info.user_nickname}"
f"当前关系: {relationship_level[level_num]}, "
f"关系值: {old_value:.2f}, "
f"当前立场情感: {stance}-{label}, "
f"变更: {value:+.5f}"
)
await person_info_manager.update_one_field(person_id, "relationship_value", old_value + value, data)
return chat_stream.user_info.user_nickname,value,relationship_level[level_num]
async def build_relationship_info(self, person) -> str:
person_id = person_info_manager.get_person_id(person[0], person[1])