feat: 现在使用工具调用来更新关系和心情而不是固定更新
This commit is contained in:
58
src/do_tool/tool_can_use/change_mood.py
Normal file
58
src/do_tool/tool_can_use/change_mood.py
Normal file
@@ -0,0 +1,58 @@
|
||||
from src.do_tool.tool_can_use.base_tool import BaseTool, register_tool
|
||||
from src.plugins.config.config import global_config
|
||||
from src.common.logger import get_module_logger
|
||||
from src.plugins.moods.moods import MoodManager
|
||||
from src.plugins.chat_module.think_flow_chat.think_flow_generator import ResponseGenerator
|
||||
|
||||
from typing import Dict, Any
|
||||
|
||||
logger = get_module_logger("change_mood_tool")
|
||||
|
||||
|
||||
class ChangeMoodTool(BaseTool):
|
||||
"""改变心情的工具"""
|
||||
|
||||
name = "change_mood"
|
||||
description = "根据收到的内容和自身回复的内容,改变心情,当你回复了别人的消息,你可以使用这个工具"
|
||||
parameters = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {"type": "string", "description": "引起你改变心情的文本"},
|
||||
"response_set": {"type": "list", "description": "你对文本的回复"}
|
||||
},
|
||||
"required": ["text", "response_set"],
|
||||
}
|
||||
|
||||
|
||||
async def execute(self, function_args: Dict[str, Any],message_txt:str) -> Dict[str, Any]:
|
||||
"""执行心情改变
|
||||
|
||||
Args:
|
||||
function_args: 工具参数
|
||||
message_processed_plain_text: 原始消息文本
|
||||
response_set: 原始消息文本
|
||||
|
||||
Returns:
|
||||
Dict: 工具执行结果
|
||||
"""
|
||||
try:
|
||||
response_set = function_args.get("response_set")
|
||||
message_processed_plain_text = function_args.get("text")
|
||||
|
||||
mood_manager = MoodManager.get_instance()
|
||||
gpt = ResponseGenerator()
|
||||
|
||||
if response_set is None:
|
||||
response_set = ["你还没有回复"]
|
||||
|
||||
ori_response = ",".join(response_set)
|
||||
_stance, emotion = await gpt._get_emotion_tags(ori_response, message_processed_plain_text)
|
||||
mood_manager.update_mood_from_emotion(emotion, global_config.mood_intensity_factor)
|
||||
return {"name": "change_mood", "content": f"你的心情刚刚变化了,现在的心情是: {emotion}"}
|
||||
except Exception as e:
|
||||
logger.error(f"心情改变工具执行失败: {str(e)}")
|
||||
return {"name": "change_mood", "content": f"心情改变失败: {str(e)}"}
|
||||
|
||||
|
||||
# 注册工具
|
||||
# register_tool(ChangeMoodTool)
|
||||
53
src/do_tool/tool_can_use/change_relationship.py
Normal file
53
src/do_tool/tool_can_use/change_relationship.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from src.plugins.person_info.relationship_manager import relationship_manager
|
||||
from src.common.logger import get_module_logger
|
||||
from src.do_tool.tool_can_use.base_tool import BaseTool
|
||||
from src.plugins.chat_module.think_flow_chat.think_flow_generator import ResponseGenerator
|
||||
|
||||
|
||||
logger = get_module_logger("relationship_tool")
|
||||
|
||||
class RelationshipTool(BaseTool):
|
||||
name = "change_relationship"
|
||||
description = "根据收到的文本和回复内容,修改与特定用户的关系值,当你回复了别人的消息,你可以使用这个工具"
|
||||
parameters = {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"text": {
|
||||
"type": "string",
|
||||
"description": "收到的文本"
|
||||
},
|
||||
"changed_value": {
|
||||
"type": "number",
|
||||
"description": "变更值"
|
||||
},
|
||||
"reason": {
|
||||
"type": "string",
|
||||
"description": "变更原因"
|
||||
}
|
||||
},
|
||||
"required": ["text", "changed_value", "reason"]
|
||||
}
|
||||
|
||||
|
||||
async def execute(self, args: dict,message_txt:str) -> dict:
|
||||
"""执行工具功能
|
||||
|
||||
Args:
|
||||
args: 包含工具参数的字典
|
||||
text: 原始消息文本
|
||||
changed_value: 变更值
|
||||
reason: 变更原因
|
||||
|
||||
Returns:
|
||||
dict: 包含执行结果的字典
|
||||
"""
|
||||
try:
|
||||
text = args.get("text")
|
||||
changed_value = args.get("changed_value")
|
||||
reason = args.get("reason")
|
||||
|
||||
return {"content": f"因为你刚刚因为{reason},所以你和发[{text}]这条消息的人的关系值变化为{changed_value}"}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"修改关系值时发生错误: {str(e)}")
|
||||
return {"content": f"修改关系值失败: {str(e)}"}
|
||||
@@ -47,4 +47,4 @@ class CompareNumbersTool(BaseTool):
|
||||
|
||||
|
||||
# 注册工具
|
||||
register_tool(CompareNumbersTool)
|
||||
# register_tool(CompareNumbersTool)
|
||||
|
||||
@@ -51,4 +51,4 @@ class GetCurrentTaskTool(BaseTool):
|
||||
|
||||
|
||||
# 注册工具
|
||||
register_tool(GetCurrentTaskTool)
|
||||
# register_tool(GetCurrentTaskTool)
|
||||
|
||||
@@ -132,4 +132,4 @@ class SearchKnowledgeTool(BaseTool):
|
||||
|
||||
|
||||
# 注册工具
|
||||
register_tool(SearchKnowledgeTool)
|
||||
# register_tool(SearchKnowledgeTool)
|
||||
|
||||
@@ -56,4 +56,4 @@ class GetMemoryTool(BaseTool):
|
||||
|
||||
|
||||
# 注册工具
|
||||
register_tool(GetMemoryTool)
|
||||
# register_tool(GetMemoryTool)
|
||||
|
||||
@@ -21,7 +21,7 @@ class ToolUser:
|
||||
model=global_config.llm_heartflow, temperature=0.2, max_tokens=1000, request_type="tool_use"
|
||||
)
|
||||
|
||||
async def _build_tool_prompt(self, message_txt: str, sender_name: str, chat_stream: ChatStream):
|
||||
async def _build_tool_prompt(self, message_txt: str, sender_name: str, chat_stream: ChatStream, reply_message:str = ""):
|
||||
"""构建工具使用的提示词
|
||||
|
||||
Args:
|
||||
@@ -45,9 +45,11 @@ class ToolUser:
|
||||
prompt = ""
|
||||
prompt += "你正在思考如何回复群里的消息。\n"
|
||||
prompt += f"你注意到{sender_name}刚刚说:{message_txt}\n"
|
||||
if reply_message:
|
||||
prompt += f"你刚刚回复的内容是:{reply_message}\n"
|
||||
prompt += f"注意你就是{bot_name},{bot_name}指的就是你。"
|
||||
|
||||
prompt += "你现在需要对群里的聊天内容进行回复,现在请你思考,你是否需要额外的信息,或者一些工具来帮你回复,不要使用危险功能(比如文件操作或者系统操作爬虫),比如回忆或者搜寻已有的知识,或者了解你现在正在做什么,请输出你需要的工具,或者你需要的额外信息。"
|
||||
prompt += "你现在需要对群里的聊天内容进行回复,现在选择工具来对消息和你的回复进行处理,你是否需要额外的信息,或者进行一些动作,比如回忆或者搜寻已有的知识,改变关系和情感,或者了解你现在正在做什么,请输出你需要的工具,或者你需要的额外信息。"
|
||||
return prompt
|
||||
|
||||
def _define_tools(self):
|
||||
@@ -81,10 +83,26 @@ class ToolUser:
|
||||
# 执行工具
|
||||
result = await tool_instance.execute(function_args, message_txt)
|
||||
if result:
|
||||
# 根据工具名称确定类型标签
|
||||
tool_type = ""
|
||||
if "memory" in function_name.lower():
|
||||
tool_type = "memory"
|
||||
elif "schedule" in function_name.lower() or "task" in function_name.lower():
|
||||
tool_type = "schedule"
|
||||
elif "knowledge" in function_name.lower():
|
||||
tool_type = "knowledge"
|
||||
elif "change_relationship" in function_name.lower():
|
||||
tool_type = "change_relationship"
|
||||
elif "change_mood" in function_name.lower():
|
||||
tool_type = "change_mood"
|
||||
else:
|
||||
tool_type = "other"
|
||||
|
||||
return {
|
||||
"tool_call_id": tool_call["id"],
|
||||
"role": "tool",
|
||||
"name": function_name,
|
||||
"type": tool_type,
|
||||
"content": result["content"],
|
||||
}
|
||||
return None
|
||||
@@ -101,7 +119,7 @@ class ToolUser:
|
||||
chat_stream: 聊天流对象
|
||||
|
||||
Returns:
|
||||
dict: 工具使用结果
|
||||
dict: 工具使用结果,包含结构化的信息
|
||||
"""
|
||||
try:
|
||||
# 构建提示词
|
||||
@@ -109,6 +127,7 @@ class ToolUser:
|
||||
|
||||
# 定义可用工具
|
||||
tools = self._define_tools()
|
||||
logger.trace(f"工具定义: {tools}")
|
||||
|
||||
# 使用llm_model_tool发送带工具定义的请求
|
||||
payload = {
|
||||
@@ -119,7 +138,7 @@ class ToolUser:
|
||||
"temperature": 0.2,
|
||||
}
|
||||
|
||||
logger.debug(f"发送工具调用请求,模型: {self.llm_model_tool.model_name}")
|
||||
logger.trace(f"发送工具调用请求,模型: {self.llm_model_tool.model_name}")
|
||||
# 发送请求获取模型是否需要调用工具
|
||||
response = await self.llm_model_tool._execute_request(
|
||||
endpoint="/chat/completions", payload=payload, prompt=prompt
|
||||
@@ -128,36 +147,50 @@ class ToolUser:
|
||||
# 根据返回值数量判断是否有工具调用
|
||||
if len(response) == 3:
|
||||
content, reasoning_content, tool_calls = response
|
||||
logger.info(f"工具思考: {tool_calls}")
|
||||
# logger.info(f"工具思考: {tool_calls}")
|
||||
# logger.debug(f"工具思考: {content}")
|
||||
|
||||
# 检查响应中工具调用是否有效
|
||||
if not tool_calls:
|
||||
logger.info("模型返回了空的tool_calls列表")
|
||||
logger.debug("模型返回了空的tool_calls列表")
|
||||
return {"used_tools": False}
|
||||
|
||||
logger.info(f"模型请求调用{len(tool_calls)}个工具")
|
||||
tool_calls_str = ""
|
||||
for tool_call in tool_calls:
|
||||
tool_calls_str += f"{tool_call['function']['name']}\n"
|
||||
logger.info(f"模型请求调用{len(tool_calls)}个工具: {tool_calls_str}")
|
||||
tool_results = []
|
||||
collected_info = ""
|
||||
structured_info = {
|
||||
"memory": [],
|
||||
"schedule": [],
|
||||
"knowledge": [],
|
||||
"change_relationship": [],
|
||||
"change_mood": [],
|
||||
"other": []
|
||||
}
|
||||
|
||||
# 执行所有工具调用
|
||||
for tool_call in tool_calls:
|
||||
result = await self._execute_tool_call(tool_call, message_txt)
|
||||
if result:
|
||||
tool_results.append(result)
|
||||
# 将工具结果添加到收集的信息中
|
||||
collected_info += f"\n{result['name']}返回结果: {result['content']}\n"
|
||||
# 将工具结果添加到对应类型的列表中
|
||||
structured_info[result["type"]].append({
|
||||
"name": result["name"],
|
||||
"content": result["content"]
|
||||
})
|
||||
|
||||
# 如果有工具结果,直接返回收集的信息
|
||||
if collected_info:
|
||||
logger.info(f"工具调用收集到信息: {collected_info}")
|
||||
# 如果有工具结果,返回结构化的信息
|
||||
if any(structured_info.values()):
|
||||
logger.info(f"工具调用收集到结构化信息: {json.dumps(structured_info, ensure_ascii=False)}")
|
||||
return {
|
||||
"used_tools": True,
|
||||
"collected_info": collected_info,
|
||||
"structured_info": structured_info
|
||||
}
|
||||
else:
|
||||
# 没有工具调用
|
||||
content, reasoning_content = response
|
||||
logger.info("模型没有请求调用任何工具")
|
||||
logger.debug("模型没有请求调用任何工具")
|
||||
|
||||
# 如果没有工具调用或处理失败,直接返回原始思考
|
||||
return {
|
||||
|
||||
82
src/heart_flow/README.md
Normal file
82
src/heart_flow/README.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# 心流系统 (Heart Flow System)
|
||||
|
||||
心流系统是一个模拟AI机器人内心思考和情感流动的核心系统。它通过多层次的心流结构,使AI能够对外界信息进行观察、思考和情感反应,从而产生更自然的对话和行为。
|
||||
|
||||
## 系统架构
|
||||
|
||||
### 1. 主心流 (Heartflow)
|
||||
- 位于 `heartflow.py`
|
||||
- 作为整个系统的主控制器
|
||||
- 负责管理和协调多个子心流
|
||||
- 维护AI的整体思维状态
|
||||
- 定期进行全局思考更新
|
||||
|
||||
### 2. 子心流 (SubHeartflow)
|
||||
- 位于 `sub_heartflow.py`
|
||||
- 处理具体的对话场景(如群聊)
|
||||
- 维护特定场景下的思维状态
|
||||
- 通过观察者模式接收和处理信息
|
||||
- 能够进行独立的思考和回复判断
|
||||
|
||||
### 3. 观察系统 (Observation)
|
||||
- 位于 `observation.py`
|
||||
- 负责收集和处理外部信息
|
||||
- 支持多种观察类型(如聊天观察)
|
||||
- 对信息进行实时总结和更新
|
||||
|
||||
## 主要功能
|
||||
|
||||
### 思维系统
|
||||
- 定期进行思维更新
|
||||
- 维护短期记忆和思维连续性
|
||||
- 支持多层次的思维处理
|
||||
|
||||
### 情感系统
|
||||
- 情绪状态管理
|
||||
- 回复意愿判断
|
||||
- 情感因素影响决策
|
||||
|
||||
### 交互系统
|
||||
- 群聊消息处理
|
||||
- 多场景并行处理
|
||||
- 智能回复生成
|
||||
|
||||
## 工作流程
|
||||
|
||||
1. 主心流启动并创建必要的子心流
|
||||
2. 子心流通过观察者接收外部信息
|
||||
3. 系统进行信息处理和思维更新
|
||||
4. 根据情感状态和思维结果决定是否回复
|
||||
5. 生成合适的回复并更新思维状态
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 创建新的子心流
|
||||
```python
|
||||
heartflow = Heartflow()
|
||||
subheartflow = heartflow.create_subheartflow(chat_id)
|
||||
```
|
||||
|
||||
### 添加观察者
|
||||
```python
|
||||
observation = ChattingObservation(chat_id)
|
||||
subheartflow.add_observation(observation)
|
||||
```
|
||||
|
||||
### 启动心流系统
|
||||
```python
|
||||
await heartflow.heartflow_start_working()
|
||||
```
|
||||
|
||||
## 配置说明
|
||||
|
||||
系统的主要配置参数:
|
||||
- `sub_heart_flow_stop_time`: 子心流停止时间
|
||||
- `sub_heart_flow_freeze_time`: 子心流冻结时间
|
||||
- `heart_flow_update_interval`: 心流更新间隔
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 子心流会在长时间不活跃后自动清理
|
||||
2. 需要合理配置更新间隔以平衡性能和响应速度
|
||||
3. 观察系统会限制消息处理数量以避免过载
|
||||
@@ -18,7 +18,6 @@ import random
|
||||
from src.plugins.chat.chat_stream import ChatStream
|
||||
from src.plugins.person_info.relationship_manager import relationship_manager
|
||||
from src.plugins.chat.utils import get_recent_group_speaker
|
||||
from src.do_tool.tool_use import ToolUser
|
||||
from ..plugins.utils.prompt_builder import Prompt, global_prompt_manager
|
||||
|
||||
subheartflow_config = LogConfig(
|
||||
@@ -32,7 +31,7 @@ logger = get_module_logger("subheartflow", config=subheartflow_config)
|
||||
def init_prompt():
|
||||
prompt = ""
|
||||
# prompt += f"麦麦的总体想法是:{self.main_heartflow_info}\n\n"
|
||||
prompt += "{collected_info}\n"
|
||||
prompt += "{extra_info}\n"
|
||||
prompt += "{relation_prompt_all}\n"
|
||||
prompt += "{prompt_personality}\n"
|
||||
prompt += "刚刚你的想法是{current_thinking_info}。如果有新的内容,记得转换话题\n"
|
||||
@@ -47,6 +46,7 @@ def init_prompt():
|
||||
Prompt(prompt, "sub_heartflow_prompt_before")
|
||||
prompt = ""
|
||||
# prompt += f"你现在正在做的事情是:{schedule_info}\n"
|
||||
prompt += "{extra_info}\n"
|
||||
prompt += "{prompt_personality}\n"
|
||||
prompt += "现在你正在上网,和qq群里的网友们聊天,群里正在聊的话题是:{chat_observe_info}\n"
|
||||
prompt += "刚刚你的想法是{current_thinking_info}。"
|
||||
@@ -97,7 +97,7 @@ class SubHeartflow:
|
||||
|
||||
self.bot_name = global_config.BOT_NICKNAME
|
||||
|
||||
self.tool_user = ToolUser()
|
||||
|
||||
|
||||
def add_observation(self, observation: Observation):
|
||||
"""添加一个新的observation对象到列表中,如果已存在相同id的observation则不添加"""
|
||||
@@ -151,25 +151,14 @@ class SubHeartflow:
|
||||
observation = self.observations[0]
|
||||
await observation.observe()
|
||||
|
||||
async def do_thinking_before_reply(self, message_txt: str, sender_name: str, chat_stream: ChatStream):
|
||||
async def do_thinking_before_reply(self, message_txt: str, sender_name: str, chat_stream: ChatStream, extra_info: str):
|
||||
current_thinking_info = self.current_mind
|
||||
mood_info = self.current_state.mood
|
||||
# mood_info = "你很生气,很愤怒"
|
||||
observation = self.observations[0]
|
||||
chat_observe_info = observation.observe_info
|
||||
# print(f"chat_observe_info:{chat_observe_info}")
|
||||
|
||||
# 首先尝试使用工具获取更多信息
|
||||
tool_result = await self.tool_user.use_tool(message_txt, sender_name, chat_stream)
|
||||
|
||||
# 如果工具被使用且获得了结果,将收集到的信息合并到思考中
|
||||
collected_info = ""
|
||||
if tool_result.get("used_tools", False):
|
||||
logger.info("使用工具收集了信息")
|
||||
|
||||
# 如果有收集到的信息,将其添加到当前思考中
|
||||
if "collected_info" in tool_result:
|
||||
collected_info = tool_result["collected_info"]
|
||||
|
||||
# 开始构建prompt
|
||||
prompt_personality = f"你的名字是{self.bot_name},你"
|
||||
@@ -226,7 +215,7 @@ class SubHeartflow:
|
||||
# prompt += f"记得结合上述的消息,生成内心想法,文字不要浮夸,注意你就是{self.bot_name},{self.bot_name}指的就是你。"
|
||||
|
||||
prompt = (await global_prompt_manager.get_prompt_async("sub_heartflow_prompt_before")).format(
|
||||
collected_info,
|
||||
extra_info,
|
||||
relation_prompt_all,
|
||||
prompt_personality,
|
||||
current_thinking_info,
|
||||
@@ -250,7 +239,7 @@ class SubHeartflow:
|
||||
logger.info(f"麦麦的思考前脑内状态:{self.current_mind}")
|
||||
return self.current_mind, self.past_mind
|
||||
|
||||
async def do_thinking_after_reply(self, reply_content, chat_talking_prompt):
|
||||
async def do_thinking_after_reply(self, reply_content, chat_talking_prompt, extra_info):
|
||||
# print("麦麦回复之后脑袋转起来了")
|
||||
|
||||
# 开始构建prompt
|
||||
@@ -277,20 +266,15 @@ class SubHeartflow:
|
||||
|
||||
message_new_info = chat_talking_prompt
|
||||
reply_info = reply_content
|
||||
# schedule_info = bot_schedule.get_current_num_task(num=1, time_info=False)
|
||||
|
||||
# prompt = ""
|
||||
# # prompt += f"你现在正在做的事情是:{schedule_info}\n"
|
||||
# prompt += f"{prompt_personality}\n"
|
||||
# prompt += f"现在你正在上网,和qq群里的网友们聊天,群里正在聊的话题是:{chat_observe_info}\n"
|
||||
# prompt += f"刚刚你的想法是{current_thinking_info}。"
|
||||
# prompt += f"你现在看到了网友们发的新消息:{message_new_info}\n"
|
||||
# prompt += f"你刚刚回复了群友们:{reply_info}"
|
||||
# prompt += f"你现在{mood_info}"
|
||||
# prompt += "现在你接下去继续思考,产生新的想法,记得保留你刚刚的想法,不要分点输出,输出连贯的内心独白"
|
||||
# prompt += "不要太长,但是记得结合上述的消息,要记得你的人设,关注聊天和新内容,关注你回复的内容,不要思考太多:"
|
||||
prompt = (await global_prompt_manager.get_prompt_async("sub_heartflow_prompt_after")).format(
|
||||
prompt_personality, chat_observe_info, current_thinking_info, message_new_info, reply_info, mood_info
|
||||
extra_info,
|
||||
prompt_personality,
|
||||
chat_observe_info,
|
||||
current_thinking_info,
|
||||
message_new_info,
|
||||
reply_info,
|
||||
mood_info,
|
||||
)
|
||||
|
||||
try:
|
||||
|
||||
@@ -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)
|
||||
@@ -280,6 +261,71 @@ class ThinkFlowChat:
|
||||
|
||||
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)
|
||||
|
||||
@@ -226,6 +226,58 @@ class ResponseGenerator:
|
||||
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]:
|
||||
"""处理响应内容,返回处理后的内容和情感标签"""
|
||||
if not content:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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}, "
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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}, "
|
||||
@@ -155,6 +160,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])
|
||||
relationship_value = await person_info_manager.get_value(person_id, "relationship_value")
|
||||
|
||||
@@ -189,7 +189,7 @@ pri_out = 16 #模型的输出价格(非必填,可以记录消耗)
|
||||
|
||||
#非推理模型
|
||||
|
||||
[model.llm_normal] #V3 回复模型1 主要回复模型
|
||||
[model.llm_normal] #V3 回复模型1 主要回复模型,默认temp 0.2 如果你使用的是老V3或者其他模型,请自己修改代码中的temp参数
|
||||
name = "Pro/deepseek-ai/DeepSeek-V3"
|
||||
provider = "SILICONFLOW"
|
||||
pri_in = 2 #模型的输入价格(非必填,可以记录消耗)
|
||||
|
||||
Reference in New Issue
Block a user