全部prompt独立
This commit is contained in:
@@ -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}记忆检索未找到相关信息")
|
||||
|
||||
Reference in New Issue
Block a user