mirror of https://github.com/Mai-with-u/MaiBot.git
PromptManager再修改,测试更新;将主程序的prompt独立到文件(部分)
parent
c15b77907e
commit
761e4c8940
|
|
@ -0,0 +1,5 @@
|
|||
{action_name}
|
||||
动作描述:{action_description}
|
||||
使用条件{parallel_text}:
|
||||
{action_require}
|
||||
{{"action":"{action_name}",{action_parameters}, "target_message_id":"消息id(m+数字)"}}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
上下文聊天内容:
|
||||
{chat_context}
|
||||
|
||||
在上下文中提取到的黑话及其含义:
|
||||
{jargon_explanations}
|
||||
|
||||
请根据上述信息,对黑话解释进行概括和整理。
|
||||
- 如果上下文中有黑话出现,请简要说明这些黑话在上下文中的使用情况
|
||||
- 将所有黑话解释整理成简洁、易读的一段话
|
||||
- 输出格式要自然,适合作为回复参考信息
|
||||
请输出概括后的黑话解释(直接输出一段平文本,不要标题,无特殊格式或markdown格式,不要使用JSON格式):
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
{time_block}
|
||||
{name_block}
|
||||
{chat_context_description},以下是具体的聊天内容
|
||||
**聊天内容**
|
||||
{chat_content_block}
|
||||
|
||||
**可选的action**
|
||||
reply
|
||||
动作描述:
|
||||
1.你可以选择呼叫了你的名字,但是你没有做出回应的消息进行回复
|
||||
2.你可以自然的顺着正在进行的聊天内容进行回复或自然的提出一个问题
|
||||
3.最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。
|
||||
4.不要选择回复你自己发送的消息
|
||||
5.不要单独对表情包进行回复
|
||||
6.将上下文中所有含义不明的,疑似黑话的,缩写词均写入unknown_words中
|
||||
{reply_action_example}
|
||||
|
||||
no_reply
|
||||
动作描述:
|
||||
保持沉默,不回复直到有新消息
|
||||
控制聊天频率,不要太过频繁的发言
|
||||
{{"action":"no_reply"}}
|
||||
|
||||
{action_options_text}
|
||||
|
||||
**你之前的action执行和思考记录**
|
||||
{actions_before_now_block}
|
||||
|
||||
请选择**可选的**且符合使用条件的action,并说明触发action的消息id(消息id格式:m+数字)
|
||||
先输出你的简短的选择思考理由,再输出你选择的action,理由不要分点,精简。
|
||||
**动作选择要求**
|
||||
请你根据聊天内容,用户的最新消息和以下标准选择合适的动作:
|
||||
{plan_style}
|
||||
{moderation_prompt}
|
||||
|
||||
target_message_id为必填,表示触发消息的id
|
||||
请选择所有符合使用要求的action,每个动作最多选择一次,但是可以选择多个动作;
|
||||
动作用json格式输出,用```json包裹,如果输出多个json,每个json都要单独一行放在同一个```json代码块内:
|
||||
**示例**
|
||||
// 理由文本(简短)
|
||||
```json
|
||||
{{"action":"动作名", "target_message_id":"m123", .....}}
|
||||
{{"action":"动作名", "target_message_id":"m456", .....}}
|
||||
```
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{knowledge_prompt}{tool_info_block}{extra_info_block}
|
||||
{expression_habits_block}{memory_retrieval}{jargon_explanation}
|
||||
|
||||
你正在qq群里聊天,下面是群里正在聊的内容,其中包含聊天记录和聊天中的图片
|
||||
其中标注 {bot_name}(你) 的发言是你自己的发言,请注意区分:
|
||||
{time_block}
|
||||
{dialogue_prompt}
|
||||
|
||||
{reply_target_block}。
|
||||
{planner_reasoning}
|
||||
{identity}
|
||||
{chat_prompt}你正在群里聊天,现在请你读读之前的聊天记录,把握当前的话题,然后给出日常且简短的回复。
|
||||
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。
|
||||
{keywords_reaction_prompt}
|
||||
请注意把握聊天内容。
|
||||
{reply_style}
|
||||
请注意不要输出多余内容(包括不必要的前后缀,冒号,括号,at或 @等 ),只输出发言内容就好。
|
||||
现在,你说:
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{knowledge_prompt}{tool_info_block}{extra_info_block}
|
||||
{expression_habits_block}{memory_retrieval}{jargon_explanation}
|
||||
|
||||
你正在qq群里聊天,下面是群里正在聊的内容,其中包含聊天记录和聊天中的图片
|
||||
其中标注 {bot_name}(你) 的发言是你自己的发言,请注意区分:
|
||||
{time_block}
|
||||
{dialogue_prompt}
|
||||
|
||||
{reply_target_block}。
|
||||
{planner_reasoning}
|
||||
{identity}
|
||||
{chat_prompt}你正在群里聊天,现在请你读读之前的聊天记录,然后给出日常且口语化的回复,
|
||||
尽量简短一些。{keywords_reaction_prompt}
|
||||
请注意把握聊天内容,不要回复的太有条理。
|
||||
{reply_style}
|
||||
请注意不要输出多余内容(包括不必要的前后缀,冒号,括号,表情包,at或 @等 ),只输出发言内容就好。
|
||||
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。
|
||||
现在,你说:
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -6,7 +6,7 @@ from src.common.logger import get_logger
|
|||
from src.common.database.database_model import Jargon
|
||||
from src.llm_models.utils_model import LLMRequest
|
||||
from src.config.config import model_config, global_config
|
||||
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||
from src.prompt.prompt_manager import prompt_manager
|
||||
from src.bw_learner.jargon_miner import search_jargon
|
||||
from src.bw_learner.learner_utils import (
|
||||
is_bot_message,
|
||||
|
|
@ -17,28 +17,6 @@ from src.bw_learner.learner_utils import (
|
|||
|
||||
logger = get_logger("jargon")
|
||||
|
||||
|
||||
def _init_explainer_prompts() -> None:
|
||||
"""初始化黑话解释器相关的prompt"""
|
||||
# Prompt:概括黑话解释结果
|
||||
summarize_prompt_str = """上下文聊天内容:
|
||||
{chat_context}
|
||||
|
||||
在上下文中提取到的黑话及其含义:
|
||||
{jargon_explanations}
|
||||
|
||||
请根据上述信息,对黑话解释进行概括和整理。
|
||||
- 如果上下文中有黑话出现,请简要说明这些黑话在上下文中的使用情况
|
||||
- 将所有黑话解释整理成简洁、易读的一段话
|
||||
- 输出格式要自然,适合作为回复参考信息
|
||||
请输出概括后的黑话解释(直接输出一段平文本,不要标题,无特殊格式或markdown格式,不要使用JSON格式):
|
||||
"""
|
||||
Prompt(summarize_prompt_str, "jargon_explainer_summarize_prompt")
|
||||
|
||||
|
||||
_init_explainer_prompts()
|
||||
|
||||
|
||||
class JargonExplainer:
|
||||
"""黑话解释器,用于在回复前识别和解释上下文中的黑话"""
|
||||
|
||||
|
|
@ -222,11 +200,15 @@ class JargonExplainer:
|
|||
explanations_text = "\n".join(jargon_explanations)
|
||||
|
||||
# 使用LLM概括黑话解释
|
||||
summarize_prompt = await global_prompt_manager.format_prompt(
|
||||
"jargon_explainer_summarize_prompt",
|
||||
chat_context=chat_context,
|
||||
jargon_explanations=explanations_text,
|
||||
)
|
||||
# summarize_prompt = await global_prompt_manager.format_prompt(
|
||||
# "jargon_explainer_summarize_prompt",
|
||||
# chat_context=chat_context,
|
||||
# jargon_explanations=explanations_text,
|
||||
# )
|
||||
prompt_of_summarize = prompt_manager.get_prompt("jargon_explainer_summarize_prompt")
|
||||
prompt_of_summarize.add_context("chat_context", lambda _: chat_context)
|
||||
prompt_of_summarize.add_context("jargon_explanations", lambda _: explanations_text)
|
||||
summarize_prompt = await prompt_manager.render_prompt(prompt_of_summarize)
|
||||
|
||||
summary, _ = await self.llm.generate_response_async(summarize_prompt, temperature=0.3)
|
||||
if not summary:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ from src.config.config import global_config, model_config
|
|||
from src.common.logger import get_logger
|
||||
from src.chat.logger.plan_reply_logger import PlanReplyLogger
|
||||
from src.common.data_models.info_data_model import ActionPlannerInfo
|
||||
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||
# from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
|
||||
from src.prompt.prompt_manager import prompt_manager
|
||||
from src.chat.utils.chat_message_builder import (
|
||||
build_readable_messages_with_id,
|
||||
get_raw_msg_before_timestamp_with_chat,
|
||||
|
|
@ -35,69 +36,6 @@ logger = get_logger("planner")
|
|||
|
||||
install(extra_lines=3)
|
||||
|
||||
|
||||
def init_prompt():
|
||||
Prompt(
|
||||
"""
|
||||
{time_block}
|
||||
{name_block}
|
||||
{chat_context_description},以下是具体的聊天内容
|
||||
**聊天内容**
|
||||
{chat_content_block}
|
||||
|
||||
**可选的action**
|
||||
reply
|
||||
动作描述:
|
||||
1.你可以选择呼叫了你的名字,但是你没有做出回应的消息进行回复
|
||||
2.你可以自然的顺着正在进行的聊天内容进行回复或自然的提出一个问题
|
||||
3.最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。
|
||||
4.不要选择回复你自己发送的消息
|
||||
5.不要单独对表情包进行回复
|
||||
6.将上下文中所有含义不明的,疑似黑话的,缩写词均写入unknown_words中
|
||||
{reply_action_example}
|
||||
|
||||
no_reply
|
||||
动作描述:
|
||||
保持沉默,不回复直到有新消息
|
||||
控制聊天频率,不要太过频繁的发言
|
||||
{{"action":"no_reply"}}
|
||||
|
||||
{action_options_text}
|
||||
|
||||
**你之前的action执行和思考记录**
|
||||
{actions_before_now_block}
|
||||
|
||||
请选择**可选的**且符合使用条件的action,并说明触发action的消息id(消息id格式:m+数字)
|
||||
先输出你的简短的选择思考理由,再输出你选择的action,理由不要分点,精简。
|
||||
**动作选择要求**
|
||||
请你根据聊天内容,用户的最新消息和以下标准选择合适的动作:
|
||||
{plan_style}
|
||||
{moderation_prompt}
|
||||
|
||||
target_message_id为必填,表示触发消息的id
|
||||
请选择所有符合使用要求的action,每个动作最多选择一次,但是可以选择多个动作;
|
||||
动作用json格式输出,用```json包裹,如果输出多个json,每个json都要单独一行放在同一个```json代码块内:
|
||||
**示例**
|
||||
// 理由文本(简短)
|
||||
```json
|
||||
{{"action":"动作名", "target_message_id":"m123", .....}}
|
||||
{{"action":"动作名", "target_message_id":"m456", .....}}
|
||||
```""",
|
||||
"planner_prompt",
|
||||
)
|
||||
|
||||
Prompt(
|
||||
"""
|
||||
{action_name}
|
||||
动作描述:{action_description}
|
||||
使用条件{parallel_text}:
|
||||
{action_require}
|
||||
{{"action":"{action_name}",{action_parameters}, "target_message_id":"消息id(m+数字)"}}
|
||||
""",
|
||||
"action_prompt",
|
||||
)
|
||||
|
||||
|
||||
class ActionPlanner:
|
||||
def __init__(self, chat_id: str, action_manager: ActionManager):
|
||||
self.chat_id = chat_id
|
||||
|
|
@ -663,19 +601,31 @@ class ActionPlanner:
|
|||
reply_action_example += ', "quote":"如果需要引用该message,设置为true"'
|
||||
reply_action_example += "}"
|
||||
|
||||
planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
|
||||
prompt = planner_prompt_template.format(
|
||||
time_block=time_block,
|
||||
chat_context_description=chat_context_description,
|
||||
chat_content_block=chat_content_block,
|
||||
actions_before_now_block=actions_before_now_block,
|
||||
action_options_text=action_options_block,
|
||||
moderation_prompt=moderation_prompt_block,
|
||||
name_block=name_block,
|
||||
interest=interest,
|
||||
plan_style=global_config.personality.plan_style,
|
||||
reply_action_example=reply_action_example,
|
||||
)
|
||||
# planner_prompt_template = await global_prompt_manager.get_prompt_async("planner_prompt")
|
||||
# prompt = planner_prompt_template.format(
|
||||
# time_block=time_block,
|
||||
# chat_context_description=chat_context_description,
|
||||
# chat_content_block=chat_content_block,
|
||||
# actions_before_now_block=actions_before_now_block,
|
||||
# action_options_text=action_options_block,
|
||||
# moderation_prompt=moderation_prompt_block,
|
||||
# name_block=name_block,
|
||||
# interest=interest,
|
||||
# plan_style=global_config.personality.plan_style,
|
||||
# reply_action_example=reply_action_example,
|
||||
# )
|
||||
planner_prompt_template = prompt_manager.get_prompt("planner_prompt")
|
||||
planner_prompt_template.add_context("time_block", time_block)
|
||||
planner_prompt_template.add_context("chat_context_description", chat_context_description)
|
||||
planner_prompt_template.add_context("chat_content_block", chat_content_block)
|
||||
planner_prompt_template.add_context("actions_before_now_block", actions_before_now_block)
|
||||
planner_prompt_template.add_context("action_options_text", action_options_block)
|
||||
planner_prompt_template.add_context("moderation_prompt", moderation_prompt_block)
|
||||
planner_prompt_template.add_context("name_block", name_block)
|
||||
planner_prompt_template.add_context("interest", interest)
|
||||
planner_prompt_template.add_context("plan_style", global_config.personality.plan_style)
|
||||
planner_prompt_template.add_context("reply_action_example", reply_action_example)
|
||||
prompt = await prompt_manager.render_prompt(planner_prompt_template)
|
||||
|
||||
return prompt, message_id_list
|
||||
except Exception as e:
|
||||
|
|
@ -759,16 +709,23 @@ class ActionPlanner:
|
|||
parallel_text = ""
|
||||
|
||||
# 获取动作提示模板并填充
|
||||
using_action_prompt = await global_prompt_manager.get_prompt_async("action_prompt")
|
||||
using_action_prompt = using_action_prompt.format(
|
||||
action_name=action_name,
|
||||
action_description=action_info.description,
|
||||
action_parameters=param_text,
|
||||
action_require=require_text,
|
||||
parallel_text=parallel_text,
|
||||
)
|
||||
# using_action_prompt = await global_prompt_manager.get_prompt_async("action_prompt")
|
||||
# using_action_prompt = using_action_prompt.format(
|
||||
# action_name=action_name,
|
||||
# action_description=action_info.description,
|
||||
# action_parameters=param_text,
|
||||
# action_require=require_text,
|
||||
# parallel_text=parallel_text,
|
||||
# )
|
||||
using_action_prompt = prompt_manager.get_prompt("action_prompt")
|
||||
using_action_prompt.add_context("action_name", action_name)
|
||||
using_action_prompt.add_context("action_description", action_info.description)
|
||||
using_action_prompt.add_context("action_parameters", param_text)
|
||||
using_action_prompt.add_context("action_require", require_text)
|
||||
using_action_prompt.add_context("parallel_text", parallel_text)
|
||||
using_action_rendered_prompt = await prompt_manager.render_prompt(using_action_prompt)
|
||||
|
||||
action_options_block += using_action_prompt
|
||||
action_options_block += using_action_rendered_prompt
|
||||
|
||||
return action_options_block
|
||||
|
||||
|
|
@ -994,6 +951,3 @@ class ActionPlanner:
|
|||
logger.debug(f"处理不完整的JSON代码块时出错: {e}")
|
||||
|
||||
return json_objects, reasoning_content
|
||||
|
||||
|
||||
init_prompt()
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from src.chat.message_receive.chat_stream import ChatStream
|
|||
from src.chat.message_receive.uni_message_sender import UniversalMessageSender
|
||||
from src.chat.utils.timer_calculator import Timer # <--- Import Timer
|
||||
from src.chat.utils.utils import get_chat_type_and_target_info, is_bot_self
|
||||
from src.prompt.prompt_manager import prompt_manager
|
||||
from src.chat.utils.prompt_builder import global_prompt_manager
|
||||
from src.chat.utils.chat_message_builder import (
|
||||
build_readable_messages,
|
||||
|
|
@ -33,14 +34,12 @@ from src.plugin_system.apis import llm_api
|
|||
|
||||
from src.chat.logger.plan_reply_logger import PlanReplyLogger
|
||||
from src.chat.replyer.prompt.lpmm_prompt import init_lpmm_prompt
|
||||
from src.chat.replyer.prompt.replyer_prompt import init_replyer_prompt
|
||||
from src.chat.replyer.prompt.rewrite_prompt import init_rewrite_prompt
|
||||
from src.memory_system.memory_retrieval import init_memory_retrieval_prompt, build_memory_retrieval_prompt
|
||||
from src.bw_learner.jargon_explainer import explain_jargon_in_context, retrieve_concepts_with_jargon
|
||||
from src.chat.utils.common_utils import TempMethodsExpression
|
||||
|
||||
init_lpmm_prompt()
|
||||
init_replyer_prompt()
|
||||
init_rewrite_prompt()
|
||||
init_memory_retrieval_prompt()
|
||||
|
||||
|
|
@ -947,6 +946,7 @@ class DefaultReplyer:
|
|||
else:
|
||||
reply_target_block = ""
|
||||
|
||||
dialogue_prompt: str = ""
|
||||
if message_list_before_now_long:
|
||||
latest_msgs = message_list_before_now_long[-int(global_config.chat.max_context_size) :]
|
||||
dialogue_prompt = build_readable_messages(
|
||||
|
|
@ -980,33 +980,55 @@ class DefaultReplyer:
|
|||
# 兜底:即使 multiple_reply_style 配置异常也不影响正常回复
|
||||
reply_style = global_config.personality.reply_style
|
||||
|
||||
return (
|
||||
await global_prompt_manager.format_prompt(
|
||||
prompt_name,
|
||||
expression_habits_block=expression_habits_block,
|
||||
tool_info_block=tool_info,
|
||||
bot_name=global_config.bot.nickname,
|
||||
knowledge_prompt=prompt_info,
|
||||
# relation_info_block=relation_info,
|
||||
extra_info_block=extra_info_block,
|
||||
jargon_explanation=jargon_explanation,
|
||||
identity=personality_prompt,
|
||||
action_descriptions=actions_info,
|
||||
sender_name=sender,
|
||||
dialogue_prompt=dialogue_prompt,
|
||||
time_block=time_block,
|
||||
reply_target_block=reply_target_block,
|
||||
reply_style=reply_style,
|
||||
keywords_reaction_prompt=keywords_reaction_prompt,
|
||||
moderation_prompt=moderation_prompt_block,
|
||||
memory_retrieval=memory_retrieval,
|
||||
chat_prompt=chat_prompt_block,
|
||||
planner_reasoning=planner_reasoning,
|
||||
),
|
||||
selected_expressions,
|
||||
timing_logs,
|
||||
almost_zero_str,
|
||||
)
|
||||
# return (
|
||||
# await global_prompt_manager.format_prompt(
|
||||
# prompt_name,
|
||||
# expression_habits_block=expression_habits_block,
|
||||
# tool_info_block=tool_info,
|
||||
# bot_name=global_config.bot.nickname,
|
||||
# knowledge_prompt=prompt_info,
|
||||
# # relation_info_block=relation_info,
|
||||
# extra_info_block=extra_info_block,
|
||||
# jargon_explanation=jargon_explanation,
|
||||
# identity=personality_prompt,
|
||||
# action_descriptions=actions_info,
|
||||
# sender_name=sender,
|
||||
# dialogue_prompt=dialogue_prompt,
|
||||
# time_block=time_block,
|
||||
# reply_target_block=reply_target_block,
|
||||
# reply_style=reply_style,
|
||||
# keywords_reaction_prompt=keywords_reaction_prompt,
|
||||
# moderation_prompt=moderation_prompt_block,
|
||||
# memory_retrieval=memory_retrieval,
|
||||
# chat_prompt=chat_prompt_block,
|
||||
# planner_reasoning=planner_reasoning,
|
||||
# ),
|
||||
# selected_expressions,
|
||||
# timing_logs,
|
||||
# almost_zero_str,
|
||||
# )
|
||||
prompt = prompt_manager.get_prompt(prompt_name)
|
||||
prompt.add_context("expression_habits_block", expression_habits_block)
|
||||
prompt.add_context("tool_info_block", tool_info)
|
||||
prompt.add_context("bot_name", global_config.bot.nickname)
|
||||
prompt.add_context("knowledge_prompt", prompt_info)
|
||||
# prompt.add_context("relation_info_block", relation_info)
|
||||
prompt.add_context("extra_info_block", extra_info_block)
|
||||
prompt.add_context("jargon_explanation", jargon_explanation)
|
||||
prompt.add_context("identity", personality_prompt)
|
||||
prompt.add_context("action_descriptions", actions_info)
|
||||
prompt.add_context("sender_name", sender)
|
||||
prompt.add_context("dialogue_prompt", dialogue_prompt)
|
||||
prompt.add_context("time_block", time_block)
|
||||
prompt.add_context("reply_target_block", reply_target_block)
|
||||
prompt.add_context("reply_style", reply_style)
|
||||
prompt.add_context("keywords_reaction_prompt", keywords_reaction_prompt)
|
||||
prompt.add_context("moderation_prompt", moderation_prompt_block)
|
||||
prompt.add_context("memory_retrieval", memory_retrieval)
|
||||
prompt.add_context("chat_prompt", chat_prompt_block)
|
||||
prompt.add_context("planner_reasoning", planner_reasoning)
|
||||
formatted_prompt = await prompt_manager.render_prompt(prompt)
|
||||
return (formatted_prompt, selected_expressions, timing_logs, almost_zero_str)
|
||||
|
||||
async def build_prompt_rewrite_context(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -1,48 +0,0 @@
|
|||
from src.chat.utils.prompt_builder import Prompt
|
||||
# from src.chat.memory_system.memory_activator import MemoryActivator
|
||||
|
||||
|
||||
def init_replyer_prompt():
|
||||
Prompt(
|
||||
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
|
||||
{expression_habits_block}{memory_retrieval}{jargon_explanation}
|
||||
|
||||
你正在qq群里聊天,下面是群里正在聊的内容,其中包含聊天记录和聊天中的图片
|
||||
其中标注 {bot_name}(你) 的发言是你自己的发言,请注意区分:
|
||||
{time_block}
|
||||
{dialogue_prompt}
|
||||
|
||||
{reply_target_block}。
|
||||
{planner_reasoning}
|
||||
{identity}
|
||||
{chat_prompt}你正在群里聊天,现在请你读读之前的聊天记录,然后给出日常且口语化的回复,
|
||||
尽量简短一些。{keywords_reaction_prompt}
|
||||
请注意把握聊天内容,不要回复的太有条理。
|
||||
{reply_style}
|
||||
请注意不要输出多余内容(包括不必要的前后缀,冒号,括号,表情包,at或 @等 ),只输出发言内容就好。
|
||||
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。
|
||||
现在,你说:""",
|
||||
"replyer_prompt_0",
|
||||
)
|
||||
|
||||
Prompt(
|
||||
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
|
||||
{expression_habits_block}{memory_retrieval}{jargon_explanation}
|
||||
|
||||
你正在qq群里聊天,下面是群里正在聊的内容,其中包含聊天记录和聊天中的图片
|
||||
其中标注 {bot_name}(你) 的发言是你自己的发言,请注意区分:
|
||||
{time_block}
|
||||
{dialogue_prompt}
|
||||
|
||||
{reply_target_block}。
|
||||
{planner_reasoning}
|
||||
{identity}
|
||||
{chat_prompt}你正在群里聊天,现在请你读读之前的聊天记录,把握当前的话题,然后给出日常且简短的回复。
|
||||
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。
|
||||
{keywords_reaction_prompt}
|
||||
请注意把握聊天内容。
|
||||
{reply_style}
|
||||
请注意不要输出多余内容(包括不必要的前后缀,冒号,括号,at或 @等 ),只输出发言内容就好。
|
||||
现在,你说:""",
|
||||
"replyer_prompt",
|
||||
)
|
||||
|
|
@ -26,6 +26,8 @@ from src.common.message import get_global_api
|
|||
from src.dream.dream_agent import start_dream_scheduler
|
||||
from src.bw_learner.expression_auto_check_task import ExpressionAutoCheckTask
|
||||
|
||||
from src.prompt.prompt_manager import prompt_manager
|
||||
|
||||
# 插件系统现在使用统一的插件加载器
|
||||
|
||||
install(extra_lines=3)
|
||||
|
|
@ -119,6 +121,8 @@ class MainSystem:
|
|||
# 将bot.py中的chat_bot.message_process消息处理函数注册到api.py的消息处理基类中
|
||||
self.app.register_message_handler(chat_bot.message_process)
|
||||
self.app.register_custom_message_handler("message_id_echo", chat_bot.echo_message_process)
|
||||
|
||||
prompt_manager.load_prompts()
|
||||
|
||||
# 触发 ON_START 事件
|
||||
from src.plugin_system.core.events_manager import events_manager
|
||||
|
|
|
|||
|
|
@ -19,19 +19,28 @@ SUFFIX_PROMPT = ".prompt"
|
|||
|
||||
|
||||
class Prompt:
|
||||
prompt_name: str
|
||||
template: str
|
||||
prompt_render_context: dict[str, Callable[[str], str | Coroutine[Any, Any, str]]] = {}
|
||||
|
||||
def __init__(self, prompt_name: str, template: str) -> None:
|
||||
self.prompt_name = prompt_name
|
||||
self.template = template
|
||||
self.prompt_render_context: dict[str, Callable[[str], str | Coroutine[Any, Any, str]]] = {}
|
||||
self._is_cloned = False
|
||||
self.__post_init__()
|
||||
|
||||
def add_context(self, name: str, func: Callable[[str], str | Coroutine[Any, Any, str]]) -> None:
|
||||
def add_context(self, name: str, func_or_str: Callable[[str], str | Coroutine[Any, Any, str]] | str) -> None:
|
||||
if name in self.prompt_render_context:
|
||||
raise KeyError(f"Context function name '{name}' 已存在于 Prompt '{self.prompt_name}' 中")
|
||||
self.prompt_render_context[name] = func
|
||||
if isinstance(func_or_str, str):
|
||||
|
||||
def tmp_func(_: str) -> str:
|
||||
return func_or_str
|
||||
|
||||
render_function = tmp_func
|
||||
else:
|
||||
render_function = func_or_str
|
||||
self.prompt_render_context[name] = render_function
|
||||
|
||||
def clone(self) -> "Prompt":
|
||||
return Prompt(self.prompt_name, self.template)
|
||||
|
||||
def __post_init__(self):
|
||||
if not self.prompt_name:
|
||||
|
|
@ -47,7 +56,7 @@ class PromptManager:
|
|||
def __init__(self) -> None:
|
||||
PROMPTS_DIR.mkdir(parents=True, exist_ok=True) # 确保提示词目录存在
|
||||
self.prompts: dict[str, Prompt] = {}
|
||||
"""存储 Prompt 实例"""
|
||||
"""存储 Prompt 实例,禁止直接从外部访问,否则将引起不可知后果"""
|
||||
self._context_construct_functions: dict[str, tuple[Callable[[str], str | Coroutine[Any, Any, str]], str]] = {}
|
||||
"""存储上下文构造函数及其所属模块"""
|
||||
self._formatter = Formatter() # 仅用来解析模板
|
||||
|
|
@ -57,6 +66,7 @@ class PromptManager:
|
|||
|
||||
def add_prompt(self, prompt: Prompt, need_save: bool = False) -> None:
|
||||
if prompt.prompt_name in self.prompts or prompt.prompt_name in self._context_construct_functions:
|
||||
# 确保名称无冲突
|
||||
raise KeyError(f"Prompt name '{prompt.prompt_name}' 已存在")
|
||||
self.prompts[prompt.prompt_name] = prompt
|
||||
if need_save:
|
||||
|
|
@ -81,14 +91,26 @@ class PromptManager:
|
|||
self._context_construct_functions[name] = func, caller_module
|
||||
|
||||
def get_prompt(self, prompt_name: str) -> Prompt:
|
||||
"""获取指定名称的 Prompt 实例的克隆"""
|
||||
if prompt_name not in self.prompts:
|
||||
raise KeyError(f"Prompt name '{prompt_name}' 不存在")
|
||||
return self.prompts[prompt_name]
|
||||
prompt = self.prompts[prompt_name].clone()
|
||||
prompt._is_cloned = True
|
||||
return prompt
|
||||
|
||||
async def render_prompt(self, prompt: Prompt) -> str:
|
||||
if not prompt._is_cloned:
|
||||
raise ValueError(
|
||||
"只能渲染通过 PromptManager.get_prompt 方法获取的 Prompt 实例,你可能对原始实例进行了修改和渲染操作"
|
||||
)
|
||||
return await self._render(prompt)
|
||||
|
||||
async def _render(self, prompt: Prompt, recursive_level: int = 0) -> str:
|
||||
async def _render(
|
||||
self,
|
||||
prompt: Prompt,
|
||||
recursive_level: int = 0,
|
||||
additional_construction_function_dict: dict[str, Callable[[str], str | Coroutine[Any, Any, str]]] = {}, # noqa: B006
|
||||
) -> str:
|
||||
prompt.template = prompt.template.replace("{{", _LEFT_BRACE).replace("}}", _RIGHT_BRACE)
|
||||
if recursive_level > 10:
|
||||
raise RecursionError("递归层级过深,可能存在循环引用")
|
||||
|
|
@ -96,16 +118,40 @@ class PromptManager:
|
|||
rendered_fields: dict[str, str] = {}
|
||||
for field_name in field_block:
|
||||
if field_name in self.prompts:
|
||||
rendered_fields[field_name] = await self._render(self.prompts[field_name], recursive_level + 1)
|
||||
nested_prompt = self.get_prompt(field_name)
|
||||
additional_construction_function_dict |= prompt.prompt_render_context
|
||||
rendered_fields[field_name] = await self._render(
|
||||
nested_prompt,
|
||||
recursive_level + 1,
|
||||
additional_construction_function_dict,
|
||||
)
|
||||
elif field_name in prompt.prompt_render_context:
|
||||
# 优先使用内部构造函数
|
||||
func = prompt.prompt_render_context[field_name]
|
||||
rendered_fields[field_name] = await self._get_function_result(
|
||||
func, prompt.prompt_name, field_name, is_prompt_context=True
|
||||
func,
|
||||
prompt.prompt_name,
|
||||
field_name,
|
||||
is_prompt_context=True,
|
||||
)
|
||||
elif field_name in self._context_construct_functions:
|
||||
# 随后查找全局构造函数
|
||||
func, module = self._context_construct_functions[field_name]
|
||||
rendered_fields[field_name] = await self._get_function_result(
|
||||
func, prompt.prompt_name, field_name, is_prompt_context=False, module=module
|
||||
func,
|
||||
prompt.prompt_name,
|
||||
field_name,
|
||||
is_prompt_context=False,
|
||||
module=module,
|
||||
)
|
||||
elif field_name in additional_construction_function_dict:
|
||||
# 最后查找额外传入的构造函数
|
||||
func = additional_construction_function_dict[field_name]
|
||||
rendered_fields[field_name] = await self._get_function_result(
|
||||
func,
|
||||
prompt.prompt_name,
|
||||
field_name,
|
||||
is_prompt_context=True,
|
||||
)
|
||||
else:
|
||||
raise KeyError(f"Prompt '{prompt.prompt_name}' 中缺少必要的内容块或构建函数: '{field_name}'")
|
||||
|
|
|
|||
Loading…
Reference in New Issue