feat:重构的关系构建,关系处理器,更加精准

This commit is contained in:
SengokuCola
2025-06-08 00:00:54 +08:00
parent c6ffad2a84
commit 4d20ee0c72
10 changed files with 767 additions and 199 deletions

View File

@@ -29,13 +29,13 @@ def init_prompt() -> None:
4. 思考有没有特殊的梗,一并总结成语言风格
5. 例子仅供参考,请严格根据群聊内容总结!!!
注意:总结成如下格式的规律,总结的内容要详细,但具有概括性:
"xxx"时,可以"xxx", xxx不超过10个字
"xxxxxx"时,可以"xxxxxx", xxxxxx不超过20个字
例如:
"表示十分惊叹,有些意外"时,使用"我嘞个xxxx"
"对某件事表示十分惊叹,有些意外"时,使用"我嘞个xxxx"
"表示讽刺的赞同,不想讲道理"时,使用"对对对"
"想说明某个观点,但懒得明说,或者不便明说",使用"懂的都懂"
"表示意外的夸赞,略带戏谑意味"时,使用"这么强!"
"想说明某个具体的事实观点,但懒得明说,或者不便明说,或表达一种默契",使用"懂的都懂"
"当涉及游戏相关时,表示意外的夸赞,略带戏谑意味"时,使用"这么强!"
注意不要总结你自己SELF的发言
现在请你概括

View File

@@ -13,27 +13,39 @@ from typing import List, Optional
from typing import Dict
from src.chat.focus_chat.info.info_base import InfoBase
from src.chat.focus_chat.info.relation_info import RelationInfo
from json_repair import repair_json
from src.person_info.person_info import person_info_manager
import json
logger = get_logger("processor")
def init_prompt():
relationship_prompt = """
{name_block}
你和别人的关系信息是,请从这些信息中提取出你和别人的关系的原文:
{relation_prompt}
请只从上面这些信息中提取出内容。
<聊天记录>
{chat_observe_info}
</聊天记录>
现在请你根据现有的信息,总结你和群里的人的关系
1. 根据聊天记录的需要,精简你和其他人的关系并输出
2. 根据聊天记录,如果需要提及你和某个人的关系,请输出你和这个人之间的关系
3. 如果没有特别需要提及的关系,就不用输出这个人的关系
<人物信息>
{relation_prompt}
</人物信息>
输出内容平淡一些,说中文
请注意不要输出多余内容(包括前后缀,括号()表情包at或 @等 )。只输出关系内容,记得明确说明这是你的关系。
请区分聊天记录的内容和你之前对人的了解,聊天记录是现在发生的事情,人物信息是之前对某个人的持久的了解
{name_block}
现在请你总结提取某人的信息,提取成一串文本
1. 根据聊天记录的需求,如果需要你和某个人的信息,请输出你和这个人之间精简的信息
2. 如果没有特别需要提及的信息,就不用输出这个人的信息
3. 如果有人问你对他的看法或者关系,请输出你和这个人之间的信息
请从这些信息中提取出你对某人的了解信息,信息提取成一串文本:
请严格按照以下输出格式不要输出多余内容person_name可以有多个
{{
"person_name": "信息",
"person_name2": "信息",
"person_name3": "信息",
}}
"""
Prompt(relationship_prompt, "relationship_prompt")
@@ -122,8 +134,10 @@ class RelationshipProcessor(BaseProcessor):
relation_prompt_init = "你对对方的印象是:\n"
relation_prompt = ""
person_name_list = []
for person in person_list:
relation_prompt += f"{await relationship_manager.build_relationship_info(person, is_id=True)}\n"
relation_prompt += f"{await relationship_manager.build_relationship_info(person, is_id=True)}\n\n"
person_name_list.append(await person_info_manager.get_value(person, "person_name"))
if relation_prompt:
relation_prompt = relation_prompt_init + relation_prompt
@@ -141,22 +155,41 @@ class RelationshipProcessor(BaseProcessor):
content = ""
try:
logger.info(f"{self.log_prefix} 关系识别prompt: \n{prompt}\n")
content, _ = await self.llm_model.generate_response_async(prompt=prompt)
if not content:
logger.warning(f"{self.log_prefix} LLM返回空结果关系识别失败。")
print(f"content: {content}")
content = repair_json(content)
content = json.loads(content)
person_info_str = ""
for person_name, person_info in content.items():
# print(f"person_name: {person_name}, person_info: {person_info}")
# print(f"person_list: {person_name_list}")
if person_name not in person_name_list:
continue
person_str = f"你对 {person_name} 的了解:{person_info}\n"
person_info_str += person_str
except Exception as e:
# 处理总体异常
logger.error(f"{self.log_prefix} 执行LLM请求或处理响应时出错: {e}")
logger.error(traceback.format_exc())
content = "关系识别过程中出现错误"
person_info_str = "关系识别过程中出现错误"
if content == "None":
content = ""
if person_info_str == "None":
person_info_str = ""
# 记录初步思考结果
logger.info(f"{self.log_prefix} 关系识别prompt: \n{prompt}\n")
logger.info(f"{self.log_prefix} 关系识别: {content}")
logger.info(f"{self.log_prefix} 关系识别: {person_info_str}")
return content
return person_info_str
init_prompt()

View File

@@ -31,8 +31,6 @@ def init_prompt():
{self_info_block}
请记住你的性格,身份和特点。
{relation_info_block}
{extra_info_block}
{memory_str}
@@ -42,6 +40,8 @@ def init_prompt():
{chat_content_block}
{relation_info_block}
{cycle_info_block}
{moderation_prompt}
@@ -181,7 +181,7 @@ class ActionPlanner(BasePlanner):
prompt = f"{prompt}"
llm_content, (reasoning_content, _) = await self.planner_llm.generate_response_async(prompt=prompt)
logger.info(f"{self.log_prefix}规划器原始提示词: {prompt}")
logger.debug(f"{self.log_prefix}规划器原始提示词: {prompt}")
logger.info(f"{self.log_prefix}规划器原始响应: {llm_content}")
logger.info(f"{self.log_prefix}规划器推理: {reasoning_content}")
@@ -225,7 +225,10 @@ class ActionPlanner(BasePlanner):
extra_info_block = ""
action_data["extra_info_block"] = extra_info_block
if relation_info:
action_data["relation_info_block"] = relation_info
# 对于reply动作不需要额外处理因为相关字段已经在上面的循环中添加到action_data
if extracted_action not in current_available_actions:

View File

@@ -41,6 +41,8 @@ def init_prompt():
你现在正在群里聊天,以下是群里正在进行的聊天内容:
{chat_info}
{relation_info_block}
以上是聊天内容,你需要了解聊天记录中的内容
{chat_target}
@@ -262,6 +264,7 @@ class DefaultReplyer:
target_message = action_data.get("target", "")
identity = action_data.get("identity", "")
extra_info_block = action_data.get("extra_info_block", "")
relation_info_block = action_data.get("relation_info_block", "")
# 3. 构建 Prompt
with Timer("构建Prompt", {}): # 内部计时器,可选保留
@@ -270,6 +273,7 @@ class DefaultReplyer:
# in_mind_reply=in_mind_reply,
identity=identity,
extra_info_block=extra_info_block,
relation_info_block=relation_info_block,
reason=reason,
sender_name=sender_name_for_prompt, # Pass determined name
target_message=target_message,
@@ -286,8 +290,7 @@ class DefaultReplyer:
try:
with Timer("LLM生成", {}): # 内部计时器,可选保留
# TODO: API-Adapter修改标记
# logger.info(f"{self.log_prefix}[Replier-{thinking_id}]\nPrompt:\n{prompt}\n")
logger.info(f"{self.log_prefix}Prompt:\n{prompt}\n")
content, (reasoning_content, model_name) = await self.express_model.generate_response_async(prompt)
# logger.info(f"prompt: {prompt}")
@@ -331,6 +334,7 @@ class DefaultReplyer:
sender_name,
# in_mind_reply,
extra_info_block,
relation_info_block,
identity,
target_message,
config_expression_style,
@@ -428,6 +432,7 @@ class DefaultReplyer:
chat_target=chat_target_1,
chat_info=chat_talking_prompt,
extra_info_block=extra_info_block,
relation_info_block=relation_info_block,
time_block=time_block,
# bot_name=global_config.bot.nickname,
# prompt_personality="",
@@ -448,6 +453,7 @@ class DefaultReplyer:
chat_target=chat_target_1,
chat_info=chat_talking_prompt,
extra_info_block=extra_info_block,
relation_info_block=relation_info_block,
time_block=time_block,
# bot_name=global_config.bot.nickname,
# prompt_personality="",

View File

@@ -0,0 +1,70 @@
import os
import sys
# 添加项目根目录到Python路径
current_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(os.path.dirname(current_dir))
sys.path.append(project_root)
from loguru import logger
import json
from src.common.database.database_model import PersonInfo
def fix_points_format():
"""修复数据库中的points和forgotten_points格式"""
fixed_count = 0
error_count = 0
try:
# 获取所有用户
all_persons = PersonInfo.select()
for person in all_persons:
try:
# 修复points
if person.points:
try:
# 尝试解析JSON
points_data = json.loads(person.points)
except json.JSONDecodeError:
logger.error(f"无法解析points数据: {person.points}")
points_data = []
# 确保数据是列表格式
if not isinstance(points_data, list):
points_data = []
# 直接更新数据库
person.points = json.dumps(points_data, ensure_ascii=False)
person.save()
fixed_count += 1
# 修复forgotten_points
if person.forgotten_points:
try:
# 尝试解析JSON
forgotten_data = json.loads(person.forgotten_points)
except json.JSONDecodeError:
logger.error(f"无法解析forgotten_points数据: {person.forgotten_points}")
forgotten_data = []
# 确保数据是列表格式
if not isinstance(forgotten_data, list):
forgotten_data = []
# 直接更新数据库
person.forgotten_points = json.dumps(forgotten_data, ensure_ascii=False)
person.save()
fixed_count += 1
except Exception as e:
logger.error(f"处理用户 {person.person_id} 时出错: {str(e)}")
error_count += 1
continue
logger.info(f"修复完成!成功修复 {fixed_count} 条记录,失败 {error_count} 条记录")
except Exception as e:
logger.error(f"数据库操作出错: {str(e)}")
if __name__ == "__main__":
fix_points_format()

View File

@@ -8,7 +8,6 @@ import datetime
import asyncio
from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config
from src.individuality.individuality import individuality
import json # 新增导入
from json_repair import repair_json
@@ -29,7 +28,7 @@ PersonInfoManager 类方法功能摘要:
logger = get_logger("person_info")
JSON_SERIALIZED_FIELDS = ["hobby", "hates", "meme", "relationship_others", "interaction"]
JSON_SERIALIZED_FIELDS = ["points", "forgotten_points"]
person_info_default = {
"person_id": None,
@@ -169,9 +168,9 @@ class PersonInfoManager:
processed_value = value
if field_name in JSON_SERIALIZED_FIELDS:
if isinstance(value, (list, dict)):
processed_value = json.dumps(value, ensure_ascii=False)
processed_value = json.dumps(value, ensure_ascii=False, indent=None)
elif value is None: # Store None as "[]" for JSON list fields
processed_value = json.dumps([], ensure_ascii=False)
processed_value = json.dumps([], ensure_ascii=False, indent=None)
# If value is already a string, assume it's pre-serialized or a non-JSON string.
def _db_update_sync(p_id: str, f_name: str, val_to_set):
@@ -280,7 +279,7 @@ class PersonInfoManager:
while current_try < max_retries:
# prompt_personality = individuality.get_prompt(x_person=2, level=1)
bot_name = individuality.personality.bot_nickname
bot_name = global_config.bot.nickname
qv_name_prompt = f"你是{bot_name}一个伪装成人类的AI你不能让别人发现这一点"
qv_name_prompt += f"现在你想给一个用户取一个昵称用户的qq昵称是{user_nickname}"

View File

@@ -134,7 +134,7 @@ class RelationshipManager:
except (SyntaxError, ValueError):
points = []
random_points = random.sample(points, min(3, len(points))) if points else []
random_points = random.sample(points, min(5, len(points))) if points else []
nickname_str = await person_info_manager.get_value(person_id, "nickname")
platform = await person_info_manager.get_value(person_id, "platform")
@@ -312,13 +312,14 @@ class RelationshipManager:
current_points = await person_info_manager.get_value(person_id, "points") or []
if isinstance(current_points, str):
try:
current_points = ast.literal_eval(current_points)
except (SyntaxError, ValueError):
current_points = json.loads(current_points)
except json.JSONDecodeError:
logger.error(f"解析points JSON失败: {current_points}")
current_points = []
elif not isinstance(current_points, list):
current_points = []
current_points.extend(points_list)
await person_info_manager.update_one_field(person_id, "points", str(current_points).replace("(", "[").replace(")", "]"))
await person_info_manager.update_one_field(person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None))
# 将新记录添加到现有记录中
if isinstance(current_points, list):
@@ -365,8 +366,9 @@ class RelationshipManager:
forgotten_points = await person_info_manager.get_value(person_id, "forgotten_points") or []
if isinstance(forgotten_points, str):
try:
forgotten_points = ast.literal_eval(forgotten_points)
except (SyntaxError, ValueError):
forgotten_points = json.loads(forgotten_points)
except json.JSONDecodeError:
logger.error(f"解析forgotten_points JSON失败: {forgotten_points}")
forgotten_points = []
elif not isinstance(forgotten_points, list):
forgotten_points = []
@@ -487,10 +489,12 @@ class RelationshipManager:
return
# 更新数据库
await person_info_manager.update_one_field(person_id, "forgotten_points", str(forgotten_points).replace("(", "[").replace(")", "]"))
await person_info_manager.update_one_field(person_id, "forgotten_points", json.dumps(forgotten_points, ensure_ascii=False, indent=None))
# 更新数据库
await person_info_manager.update_one_field(person_id, "points", str(current_points).replace("(", "[").replace(")", "]"))
await person_info_manager.update_one_field(person_id, "points", json.dumps(current_points, ensure_ascii=False, indent=None))
know_times = await person_info_manager.get_value(person_id, "know_times") or 0
await person_info_manager.update_one_field(person_id, "know_times", know_times + 1)
await person_info_manager.update_one_field(person_id, "last_know", timestamp)