全部prompt独立

This commit is contained in:
UnCLAS-Prommer
2026-01-21 22:24:31 +08:00
parent 1a1edde750
commit f44598a331
34 changed files with 690 additions and 1037 deletions

View File

@@ -4,7 +4,7 @@ import asyncio
from typing import List, Dict, Any, Optional, Tuple
from src.common.logger import get_logger
from src.config.config import global_config, model_config
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.plugin_system.apis import llm_api
from src.common.database.database_model import ThinkingBack
from src.memory_system.retrieval_tools import get_tool_registry, init_all_tools
@@ -41,84 +41,11 @@ def _cleanup_stale_not_found_thinking_back() -> None:
logger.error(f"清理未找到答案的thinking_back记录失败: {e}")
def init_memory_retrieval_prompt():
"""初始化记忆检索相关的 prompt 模板和工具"""
# 首先注册所有工具
def init_memory_retrieval_sys():
"""初始化记忆检索相关工具"""
# 注册所有工具
init_all_tools()
# 第二步ReAct Agent prompt使用function calling要求先思考再行动
Prompt(
"""你的名字是{bot_name}。现在是{time_now}
你正在参与聊天,你需要搜集信息来帮助你进行回复。
重要,这是当前聊天记录:
{chat_history}
聊天记录结束
已收集的信息:
{collected_info}
- 你可以对查询思路给出简短的思考:思考要简短,直接切入要点
- 思考完毕后,使用工具
**工具说明:**
- 如果涉及过往事件或者查询某个过去可能提到过的概念或者某段时间发生的事件。可以使用lpmm知识库查询
- 如果遇到不熟悉的词语、缩写、黑话或网络用语可以使用query_words工具查询其含义
- 你必须使用tool如果需要查询你必须给出使用什么工具进行查询
- 当你决定结束查询时必须调用return_information工具返回总结信息并结束查询
""",
name="memory_retrieval_react_prompt_head_lpmm",
)
# 第二步ReAct Agent prompt使用function calling要求先思考再行动
Prompt(
"""你的名字是{bot_name}。现在是{time_now}
你正在参与聊天,你需要搜集信息来帮助你进行回复。
当前聊天记录:
{chat_history}
已收集的信息:
{collected_info}
**工具说明:**
- 如果涉及过往事件,或者查询某个过去可能提到过的概念,或者某段时间发生的事件。可以使用聊天记录查询工具查询过往事件
- 如果涉及人物,可以使用人物信息查询工具查询人物信息
- 如果遇到不熟悉的词语、缩写、黑话或网络用语可以使用query_words工具查询其含义
- 如果没有可靠信息且查询时间充足或者不确定查询类别也可以使用lpmm知识库查询作为辅助信息
**思考**
- 你可以对查询思路给出简短的思考:思考要简短,直接切入要点
- 先思考当前信息是否足够回答问题
- 如果信息不足则需要使用tool查询信息你必须给出使用什么工具进行查询
- 当你决定结束查询时必须调用return_information工具返回总结信息并结束查询
""",
name="memory_retrieval_react_prompt_head",
)
# 额外如果最后一轮迭代ReAct Agent prompt使用function calling要求先思考再行动
Prompt(
"""你的名字是{bot_name}。现在是{time_now}
你正在参与聊天,你需要根据搜集到的信息总结信息。
如果搜集到的信息对于参与聊天,回答问题有帮助,请加入总结,如果无关,请不要加入到总结。
当前聊天记录:
{chat_history}
已收集的信息:
{collected_info}
分析:
- 基于已收集的信息,总结出对当前聊天有帮助的相关信息
- **如果收集的信息对当前聊天有帮助**在思考中直接给出总结信息格式为return_information(information="你的总结信息")
- **如果信息无关或没有帮助**在思考中给出return_information(information="")
**重要规则:**
- 必须严格使用检索到的信息回答问题,不要编造信息
- 答案必须精简,不要过多解释
""",
name="memory_retrieval_react_final_prompt",
)
def _log_conversation_messages(
conversation_messages: List[Message],
@@ -304,17 +231,20 @@ async def _react_agent_solve_question(
# 第一次构建使用初始的collected_info即initial_info
initial_collected_info = initial_info if initial_info else ""
# 根据配置选择使用哪个 prompt
prompt_name = "memory_retrieval_react_prompt_head_lpmm" if global_config.experimental.lpmm_memory else "memory_retrieval_react_prompt_head"
first_head_prompt = await global_prompt_manager.format_prompt(
prompt_name,
bot_name=bot_name,
time_now=time_now,
chat_history=chat_history,
collected_info=initial_collected_info,
current_iteration=current_iteration,
remaining_iterations=remaining_iterations,
max_iterations=max_iterations,
prompt_name = (
"memory_retrieval_react_prompt_head_lpmm"
if global_config.experimental.lpmm_memory
else "memory_retrieval_react_prompt_head"
)
first_head_prompt_template = prompt_manager.get_prompt(prompt_name)
first_head_prompt_template.add_context("bot_name", bot_name)
first_head_prompt_template.add_context("time_now", time_now)
first_head_prompt_template.add_context("chat_history", chat_history)
first_head_prompt_template.add_context("collected_info", initial_collected_info)
first_head_prompt_template.add_context("current_iteration", str(current_iteration))
first_head_prompt_template.add_context("remaining_iterations", str(remaining_iterations))
first_head_prompt_template.add_context("max_iterations", str(max_iterations))
first_head_prompt = await prompt_manager.render_prompt(first_head_prompt_template)
# 后续迭代都复用第一次构建的head_prompt
head_prompt = first_head_prompt
@@ -394,11 +324,11 @@ async def _react_agent_solve_question(
"""从文本中解析JSON格式的return_information返回information字符串如果未找到则返回None"""
if not text:
return None, None
try:
# 尝试提取JSON对象可能包含在代码块中或直接是JSON
json_text = text.strip()
# 如果包含代码块标记提取JSON部分
if "```json" in json_text:
start = json_text.find("```json") + 7
@@ -410,10 +340,10 @@ async def _react_agent_solve_question(
end = json_text.find("```", start)
if end != -1:
json_text = json_text[start:end].strip()
# 尝试解析JSON
data = json.loads(json_text)
# 检查是否包含return_information字段
if isinstance(data, dict) and "return_information" in data:
information = data.get("information", "")
@@ -422,20 +352,20 @@ async def _react_agent_solve_question(
# 如果JSON解析失败尝试在文本中查找JSON对象
try:
# 查找第一个 { 和最后一个 } 之间的内容更健壮的JSON提取
first_brace = text.find('{')
first_brace = text.find("{")
if first_brace != -1:
# 从第一个 { 开始,找到匹配的 }
brace_count = 0
json_end = -1
for i in range(first_brace, len(text)):
if text[i] == '{':
if text[i] == "{":
brace_count += 1
elif text[i] == '}':
elif text[i] == "}":
brace_count -= 1
if brace_count == 0:
json_end = i + 1
break
if json_end != -1:
json_text = text[first_brace:json_end]
data = json.loads(json_text)
@@ -444,9 +374,9 @@ async def _react_agent_solve_question(
return information
except (json.JSONDecodeError, ValueError, TypeError):
pass
return None
# 尝试从文本中解析return_information函数调用
def parse_return_information_from_text(text: str):
"""从文本中解析return_information函数调用返回information字符串如果未找到则返回None"""
@@ -462,14 +392,14 @@ async def _react_agent_solve_question(
# 解析information参数字符串使用extract_quoted_content
information = extract_quoted_content(text, "return_information", "information")
# 如果information存在即使是空字符串也返回它
return information
# 首先尝试解析JSON格式
parsed_information_json = parse_json_return_information(response)
is_json_format = parsed_information_json is not None
# 如果JSON解析成功使用JSON结果
if is_json_format:
parsed_information = parsed_information_json
@@ -519,9 +449,7 @@ async def _react_agent_solve_question(
# 如果没有检测到return_information格式记录思考过程继续下一轮迭代
step["observations"] = [f"思考完成,但未调用工具。响应: {response}"]
logger.info(
f"{react_log_prefix}{iteration + 1} 次迭代 思考完成但未调用工具: {response}"
)
logger.info(f"{react_log_prefix}{iteration + 1} 次迭代 思考完成但未调用工具: {response}")
collected_info += f"思考: {response}"
else:
logger.warning(f"{react_log_prefix}{iteration + 1} 次迭代 无工具调用且无响应")
@@ -566,9 +494,7 @@ async def _react_agent_solve_question(
# 信息为空,直接退出查询
step["observations"] = ["检测到return_information工具调用信息为空"]
thinking_steps.append(step)
logger.info(
f"{react_log_prefix}{iteration + 1} 次迭代 通过return_information工具判断信息为空"
)
logger.info(f"{react_log_prefix}{iteration + 1} 次迭代 通过return_information工具判断信息为空")
_log_conversation_messages(
conversation_messages,
@@ -614,9 +540,7 @@ async def _react_agent_solve_question(
return f"查询{tool_name_str}({param_str})的结果:{observation}"
except Exception as e:
error_msg = f"工具执行失败: {str(e)}"
logger.error(
f"{react_log_prefix}{iter_num + 1} 次迭代 工具 {tool_name_str} {error_msg}"
)
logger.error(f"{react_log_prefix}{iter_num + 1} 次迭代 工具 {tool_name_str} {error_msg}")
return f"查询{tool_name_str}失败: {error_msg}"
tool_tasks.append(execute_single_tool(tool, tool_params, tool_name, iteration))
@@ -636,9 +560,7 @@ async def _react_agent_solve_question(
for i, (tool_call_item, observation) in enumerate(zip(tool_calls, observations, strict=False)):
if isinstance(observation, Exception):
observation = f"工具执行异常: {str(observation)}"
logger.error(
f"{react_log_prefix}{iteration + 1} 次迭代 工具 {i + 1} 执行异常: {observation}"
)
logger.error(f"{react_log_prefix}{iteration + 1} 次迭代 工具 {i + 1} 执行异常: {observation}")
observation_text = observation if isinstance(observation, str) else str(observation)
stripped_observation = observation_text.strip()
@@ -740,16 +662,15 @@ async def _react_agent_solve_question(
return None
# 执行最终评估
evaluation_prompt = await global_prompt_manager.format_prompt(
"memory_retrieval_react_final_prompt",
bot_name=bot_name,
time_now=time_now,
chat_history=chat_history,
collected_info=collected_info if collected_info else "暂无信息",
current_iteration=current_iteration,
remaining_iterations=remaining_iterations,
max_iterations=max_iterations,
)
evaluation_prompt_template = prompt_manager.get_prompt("memory_retrieval_react_final_prompt")
evaluation_prompt_template.add_context("bot_name", bot_name)
evaluation_prompt_template.add_context("time_now", time_now)
evaluation_prompt_template.add_context("chat_history", chat_history)
evaluation_prompt_template.add_context("collected_info", collected_info if collected_info else "暂无信息")
evaluation_prompt_template.add_context("current_iteration", str(current_iteration))
evaluation_prompt_template.add_context("remaining_iterations", str(remaining_iterations))
evaluation_prompt_template.add_context("max_iterations", str(max_iterations))
evaluation_prompt = await prompt_manager.render_prompt(evaluation_prompt_template)
(
eval_success,
@@ -788,7 +709,9 @@ async def _react_agent_solve_question(
eval_step = {
"iteration": current_iteration,
"thought": f"[最终评估] {eval_response}",
"actions": [{"action_type": "return_information", "action_params": {"information": return_information_content}}],
"actions": [
{"action_type": "return_information", "action_params": {"information": return_information_content}}
],
"observations": ["最终评估阶段检测到return_information"],
}
thinking_steps.append(eval_step)
@@ -813,9 +736,7 @@ async def _react_agent_solve_question(
eval_step = {
"iteration": current_iteration,
"thought": f"[最终评估] {eval_response}",
"actions": [
{"action_type": "return_information", "action_params": {"information": ""}}
],
"actions": [{"action_type": "return_information", "action_params": {"information": ""}}],
"observations": ["已到达最大迭代次数,信息为空"],
}
thinking_steps.append(eval_step)
@@ -1124,9 +1045,7 @@ async def build_memory_retrieval_prompt(
end_time = time.time()
if result:
logger.info(
f"{log_prefix}记忆检索成功,耗时: {(end_time - start_time):.3f}"
)
logger.info(f"{log_prefix}记忆检索成功,耗时: {(end_time - start_time):.3f}")
return f"你回忆起了以下信息:\n{result}\n如果与回复内容相关,可以参考这些回忆的信息。\n"
else:
logger.debug(f"{log_prefix}记忆检索未找到相关信息")