This commit is contained in:
SengokuCola
2025-04-30 17:19:25 +08:00
4 changed files with 94 additions and 13 deletions

View File

@@ -21,6 +21,7 @@ PROMPT_INITIAL_REPLY = """{persona_text}。现在你在参与一场QQ私聊
【当前对话目标】 【当前对话目标】
{goals_str} {goals_str}
{knowledge_info_str}
【最近行动历史概要】 【最近行动历史概要】
{action_history_summary} {action_history_summary}
@@ -33,7 +34,7 @@ PROMPT_INITIAL_REPLY = """{persona_text}。现在你在参与一场QQ私聊
------ ------
可选行动类型以及解释: 可选行动类型以及解释:
fetch_knowledge: 需要调取知识,当需要专业知识或特定信息时选择,对方若提到你不太认识的人名或实体也可以尝试选择 fetch_knowledge: 需要调取知识或记忆,当需要专业知识或特定信息时选择,对方若提到你不太认识的人名或实体也可以尝试选择
listening: 倾听对方发言,当你认为对方话才说到一半,发言明显未结束时选择 listening: 倾听对方发言,当你认为对方话才说到一半,发言明显未结束时选择
direct_reply: 直接回复对方 direct_reply: 直接回复对方
rethink_goal: 思考一个对话目标,当你觉得目前对话需要目标,或当前目标不再适用,或话题卡住时选择。注意私聊的环境是灵活的,有可能需要经常选择 rethink_goal: 思考一个对话目标,当你觉得目前对话需要目标,或当前目标不再适用,或话题卡住时选择。注意私聊的环境是灵活的,有可能需要经常选择
@@ -53,6 +54,7 @@ PROMPT_FOLLOW_UP = """{persona_text}。现在你在参与一场QQ私聊刚刚
【当前对话目标】 【当前对话目标】
{goals_str} {goals_str}
{knowledge_info_str}
【最近行动历史概要】 【最近行动历史概要】
{action_history_summary} {action_history_summary}
@@ -224,6 +226,41 @@ class ActionPlanner:
logger.error(f"[私聊][{self.private_name}]构建对话目标字符串时出错: {e}") logger.error(f"[私聊][{self.private_name}]构建对话目标字符串时出错: {e}")
goals_str = "- 构建对话目标时出错。\n" goals_str = "- 构建对话目标时出错。\n"
# --- 知识信息字符串构建开始 ---
knowledge_info_str = "【已获取的相关知识和记忆】\n"
try:
# 检查 conversation_info 是否有 knowledge_list 并且不为空
if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list:
# 最多只显示最近的 5 条知识,防止 Prompt 过长
recent_knowledge = conversation_info.knowledge_list[-5:]
for i, knowledge_item in enumerate(recent_knowledge):
if isinstance(knowledge_item, dict):
query = knowledge_item.get("query", "未知查询")
knowledge = knowledge_item.get("knowledge", "无知识内容")
source = knowledge_item.get("source", "未知来源")
# 只取知识内容的前 2000 个字,避免太长
knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 2000 else knowledge
knowledge_info_str += (
f"{i + 1}. 关于 '{query}' 的知识 (来源: {source}):\n {knowledge_snippet}\n"
)
else:
# 处理列表里不是字典的异常情况
knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n"
if not recent_knowledge: # 如果 knowledge_list 存在但为空
knowledge_info_str += "- 暂无相关知识和记忆。\n"
else:
# 如果 conversation_info 没有 knowledge_list 属性,或者列表为空
knowledge_info_str += "- 暂无相关知识记忆。\n"
except AttributeError:
logger.warning(f"[私聊][{self.private_name}]ConversationInfo 对象可能缺少 knowledge_list 属性。")
knowledge_info_str += "- 获取知识列表时出错。\n"
except Exception as e:
logger.error(f"[私聊][{self.private_name}]构建知识信息字符串时出错: {e}")
knowledge_info_str += "- 处理知识列表时出错。\n"
# --- 知识信息字符串构建结束 ---
# 获取聊天历史记录 (chat_history_text) # 获取聊天历史记录 (chat_history_text)
chat_history_text = "" chat_history_text = ""
try: try:
@@ -349,6 +386,7 @@ class ActionPlanner:
time_since_last_bot_message_info=time_since_last_bot_message_info, time_since_last_bot_message_info=time_since_last_bot_message_info,
timeout_context=timeout_context, timeout_context=timeout_context,
chat_history_text=chat_history_text if chat_history_text.strip() else "还没有聊天记录。", chat_history_text=chat_history_text if chat_history_text.strip() else "还没有聊天记录。",
knowledge_info_str=knowledge_info_str,
) )
logger.debug(f"[私聊][{self.private_name}]发送到LLM的最终提示词:\n------\n{prompt}\n------") logger.debug(f"[私聊][{self.private_name}]发送到LLM的最终提示词:\n------\n{prompt}\n------")

View File

@@ -525,9 +525,9 @@ class Conversation:
) )
action_successful = True action_successful = True
except Exception as fetch_err: except Exception as fetch_err:
logger.error(f"[私聊][{self.private_name}]获取知识时出错: {fetch_err}") logger.error(f"[私聊][{self.private_name}]获取知识时出错: {str(fetch_err)}")
conversation_info.done_action[action_index].update( conversation_info.done_action[action_index].update(
{"status": "recall", "final_reason": f"获取知识失败: {fetch_err}"} {"status": "recall", "final_reason": f"获取知识失败: {str(fetch_err)}"}
) )
self.conversation_info.last_successful_reply_action = None # 重置状态 self.conversation_info.last_successful_reply_action = None # 重置状态

View File

@@ -68,16 +68,18 @@ class KnowledgeFetcher:
max_depth=3, max_depth=3,
fast_retrieval=False, fast_retrieval=False,
) )
knowledge = "" knowledge_text = ""
sources_text = "无记忆匹配" # 默认值
if related_memory: if related_memory:
sources = [] sources = []
for memory in related_memory: for memory in related_memory:
knowledge += memory[1] + "\n" knowledge_text += memory[1] + "\n"
sources.append(f"记忆片段{memory[0]}") sources.append(f"记忆片段{memory[0]}")
knowledge = knowledge.strip(), "".join(sources) knowledge_text = knowledge_text.strip()
sources_text = "".join(sources)
knowledge += "现在有以下**知识**可供参考:\n " knowledge_text += "\n现在有以下**知识**可供参考:\n "
knowledge += self._lpmm_get_knowledge(query) knowledge_text += self._lpmm_get_knowledge(query)
knowledge += "请记住这些**知识**,并根据**知识**回答问题。\n" knowledge_text += "\n请记住这些**知识**,并根据**知识**回答问题。\n"
return "未找到相关知识", "无记忆匹配" return knowledge_text or "未找到相关知识", sources_text or "无记忆匹配"

View File

@@ -17,6 +17,9 @@ logger = get_module_logger("reply_generator")
PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊请根据以下信息生成一条回复 PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊请根据以下信息生成一条回复
当前对话目标:{goals_str} 当前对话目标:{goals_str}
{knowledge_info_str}
最近的聊天记录: 最近的聊天记录:
{chat_history_text} {chat_history_text}
@@ -25,7 +28,7 @@ PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊
1. 符合对话目标,以""的角度发言(不要自己与自己对话!) 1. 符合对话目标,以""的角度发言(不要自己与自己对话!)
2. 符合你的性格特征和身份细节 2. 符合你的性格特征和身份细节
3. 通俗易懂自然流畅像正常聊天一样简短通常20字以内除非特殊情况 3. 通俗易懂自然流畅像正常聊天一样简短通常20字以内除非特殊情况
4. 适当利用相关知识,但不要生硬引用 4. 可以适当利用相关知识,但不要生硬引用
5. 自然、得体,结合聊天记录逻辑合理,且没有重复表达同质内容 5. 自然、得体,结合聊天记录逻辑合理,且没有重复表达同质内容
请注意把握聊天内容,不要回复的太有条理,可以有个性。请分清""和对方说的话,不要把""说的话当做对方说的话,这是你自己说的话。 请注意把握聊天内容,不要回复的太有条理,可以有个性。请分清""和对方说的话,不要把""说的话当做对方说的话,这是你自己说的话。
@@ -39,6 +42,9 @@ PROMPT_DIRECT_REPLY = """{persona_text}。现在你在参与一场QQ私聊
PROMPT_SEND_NEW_MESSAGE = """{persona_text}。现在你在参与一场QQ私聊**刚刚你已经发送了一条或多条消息**,现在请根据以下信息再发一条新消息: PROMPT_SEND_NEW_MESSAGE = """{persona_text}。现在你在参与一场QQ私聊**刚刚你已经发送了一条或多条消息**,现在请根据以下信息再发一条新消息:
当前对话目标:{goals_str} 当前对话目标:{goals_str}
{knowledge_info_str}
最近的聊天记录: 最近的聊天记录:
{chat_history_text} {chat_history_text}
@@ -47,7 +53,7 @@ PROMPT_SEND_NEW_MESSAGE = """{persona_text}。现在你在参与一场QQ私聊
1. 符合对话目标,以""的角度发言(不要自己与自己对话!) 1. 符合对话目标,以""的角度发言(不要自己与自己对话!)
2. 符合你的性格特征和身份细节 2. 符合你的性格特征和身份细节
3. 通俗易懂自然流畅像正常聊天一样简短通常20字以内除非特殊情况 3. 通俗易懂自然流畅像正常聊天一样简短通常20字以内除非特殊情况
4. 适当利用相关知识,但不要生硬引用 4. 可以适当利用相关知识,但不要生硬引用
5. 跟之前你发的消息自然的衔接,逻辑合理,且没有重复表达同质内容或部分重叠内容 5. 跟之前你发的消息自然的衔接,逻辑合理,且没有重复表达同质内容或部分重叠内容
请注意把握聊天内容,不用太有条理,可以有个性。请分清""和对方说的话,不要把""说的话当做对方说的话,这是你自己说的话。 请注意把握聊天内容,不用太有条理,可以有个性。请分清""和对方说的话,不要把""说的话当做对方说的话,这是你自己说的话。
@@ -131,6 +137,38 @@ class ReplyGenerator:
else: else:
goals_str = "- 目前没有明确对话目标\n" # 简化无目标情况 goals_str = "- 目前没有明确对话目标\n" # 简化无目标情况
# --- 新增:构建知识信息字符串 ---
knowledge_info_str = "【供参考的相关知识和记忆】\n" # 稍微改下标题,表明是供参考
try:
# 检查 conversation_info 是否有 knowledge_list 并且不为空
if hasattr(conversation_info, "knowledge_list") and conversation_info.knowledge_list:
# 最多只显示最近的 5 条知识
recent_knowledge = conversation_info.knowledge_list[-5:]
for i, knowledge_item in enumerate(recent_knowledge):
if isinstance(knowledge_item, dict):
query = knowledge_item.get("query", "未知查询")
knowledge = knowledge_item.get("knowledge", "无知识内容")
source = knowledge_item.get("source", "未知来源")
# 只取知识内容的前 2000 个字
knowledge_snippet = knowledge[:2000] + "..." if len(knowledge) > 2000 else knowledge
knowledge_info_str += (
f"{i + 1}. 关于 '{query}' (来源: {source}): {knowledge_snippet}\n" # 格式微调,更简洁
)
else:
knowledge_info_str += f"{i + 1}. 发现一条格式不正确的知识记录。\n"
if not recent_knowledge:
knowledge_info_str += "- 暂无。\n" # 更简洁的提示
else:
knowledge_info_str += "- 暂无。\n"
except AttributeError:
logger.warning(f"[私聊][{self.private_name}]ConversationInfo 对象可能缺少 knowledge_list 属性。")
knowledge_info_str += "- 获取知识列表时出错。\n"
except Exception as e:
logger.error(f"[私聊][{self.private_name}]构建知识信息字符串时出错: {e}")
knowledge_info_str += "- 处理知识列表时出错。\n"
# 获取聊天历史记录 (chat_history_text) # 获取聊天历史记录 (chat_history_text)
chat_history_text = observation_info.chat_history_str chat_history_text = observation_info.chat_history_str
if observation_info.new_messages_count > 0 and observation_info.unprocessed_messages: if observation_info.new_messages_count > 0 and observation_info.unprocessed_messages:
@@ -162,7 +200,10 @@ class ReplyGenerator:
# --- 格式化最终的 Prompt --- # --- 格式化最终的 Prompt ---
prompt = prompt_template.format( prompt = prompt_template.format(
persona_text=persona_text, goals_str=goals_str, chat_history_text=chat_history_text persona_text=persona_text,
goals_str=goals_str,
chat_history_text=chat_history_text,
knowledge_info_str=knowledge_info_str,
) )
# --- 调用 LLM 生成 --- # --- 调用 LLM 生成 ---