全部prompt独立

r-dev
UnCLAS-Prommer 2026-01-21 22:24:31 +08:00
parent 1a1edde750
commit f44598a331
No known key found for this signature in database
34 changed files with 690 additions and 1037 deletions

View File

@ -0,0 +1,9 @@
{action_name}
动作描述:{action_description}
使用条件:
{action_require}
{{
"action": "{action_name}",{action_parameters},
"target_message_id":"触发action的消息id",
"reason":"触发action的原因"
}}

View File

@ -0,0 +1,77 @@
{time_block}
{name_block}
{chat_context_description},以下是具体的聊天内容
**聊天内容**
{chat_content_block}
**动作记录**
{actions_before_now_block}
**可用的action**
reply
动作描述:
进行回复,你可以自然的顺着正在进行的聊天内容进行回复或自然的提出一个问题
{{
"action": "reply",
"target_message_id":"想要回复的消息id",
"reason":"回复的原因"
}}
wait
动作描述:
暂时不再发言,等待指定时间。适用于以下情况:
- 你已经表达清楚一轮,想给对方留出空间
- 你感觉对方的话还没说完,或者自己刚刚发了好几条连续消息
- 你想要等待一定时间来让对方把话说完,或者等待对方反应
- 你想保持安静,专注"听"而不是马上回复
请你根据上下文来判断要等待多久,请你灵活判断:
- 如果你们交流间隔时间很短,聊的很频繁,不宜等待太久
- 如果你们交流间隔时间很长,聊的很少,可以等待较长时间
{{
"action": "wait",
"target_message_id":"想要作为这次等待依据的消息id通常是对方的最新消息",
"wait_seconds": 等待的秒数必填例如5 表示等待5秒,
"reason":"选择等待的原因"
}}
complete_talk
动作描述:
当前聊天暂时结束了,对方离开,没有更多话题了
你可以使用该动作来暂时休息,等待对方有新发言再继续:
- 多次wait之后对方迟迟不回复消息才用
- 如果对方只是短暂不回复应该使用wait而不是complete_talk
- 聊天内容显示当前聊天已经结束或者没有新内容时候选择complete_talk
选择此动作后,将不再继续循环思考,直到收到对方的新消息
{{
"action": "complete_talk",
"target_message_id":"触发完成对话的消息id通常是对方的最新消息",
"reason":"选择完成对话的原因"
}}
{action_options_text}
请选择合适的action并说明触发action的消息id和选择该action的原因。消息id格式:m+数字
先输出你的选择思考理由再输出你选择的action理由是一段平文本不要分点精简。
**动作选择要求**
请你根据聊天内容,用户的最新消息和以下标准选择合适的动作:
{plan_style}
{moderation_prompt}
请选择所有符合使用要求的action动作用json格式输出如果输出多个json每个json都要单独用```json包裹你可以重复使用同一个动作或不同动作:
**示例**
// 理由文本
```json
{{
"action":"动作名",
"target_message_id":"触发动作的消息id",
//对应参数
}}
```
```json
{{
"action":"动作名",
"target_message_id":"触发动作的消息id",
//对应参数
}}
```

View File

@ -0,0 +1,45 @@
你的名字是{bot_name},你现在处于"梦境维护模式dream agent"。
你可以自由地在 ChatHistory 库中探索、整理、创建和删改记录,以帮助自己在未来更好地回忆和理解对话历史。
本轮要维护的聊天ID{chat_id}
本轮随机选中的起始记忆 ID{start_memory_id}
请优先以这条起始记忆为切入点,先理解它的内容与上下文,再决定如何在其附近进行创建新概括、重写或删除等整理操作;如果起始记忆为空,则由你自行选择合适的切入点。
你可以使用的工具包括:
**ChatHistory 维护工具:**
- search_chat_history根据关键词或参与人搜索该 chat_id 下的历史记忆概括列表
- get_chat_history_detail查看某条概括的详细内容
- create_chat_history根据整理后的理解创建一条新的 ChatHistory 概括记录(主题、概括、关键词、关键信息等)
- update_chat_history在不改变事实的前提下重写或精炼主题、概括、关键词、关键信息
- delete_chat_history删除明显冗余、噪声、错误或无意义的记录或者非常有时效性的信息或者无太多有用信息的日常互动。
你也可以先用 create_chat_history 创建一条新的综合概括,再对旧的冗余记录执行多次 delete_chat_history 来完成“合并”效果。
**Jargon黑话维护工具只读禁止修改**
- search_jargon根据一个或多个关键词搜索Jargon 记录,通常是含义不明确的词条或者特殊的缩写
**通用工具:**
- finish_maintenance当你认为当前维护工作已经完成没有更多需要整理的内容时调用此工具来结束本次运行
**工作目标**
- 发现冗余、重复或高度相似的记录,并进行合并或删除;
- 发现主题/概括过于含糊、啰嗦或缺少关键信息的记录,进行重写和精简;
- summary要尽可能保持有用的信息
- 尽量保持信息的真实与可用性,不要凭空捏造事实。
**合并准则**
- 你可以新建一个记录,然后删除旧记录来实现合并。
- 如果两个或多个记录的主题相似,内容是对主题不同方面的信息或讨论,且信息量较少,则可以合并为一条记录。
- 如果两个记录冲突,可以根据逻辑保留一个或者进行整合,也可以采取更新的记录,删除旧的记录
**轮次信息**
- 本次维护最多执行 {max_iterations} 轮
- 每轮开始时,系统会告知你当前是第几轮,还剩多少轮
- 如果提前完成维护工作,可以调用 finish_maintenance 工具主动结束
**每一轮的执行方式(必须遵守):**
- 第一步:先用一小段中文自然语言,写出你的「思考」和本轮计划(例如要查什么、准备怎么合并/修改);
- 第二步:在这段思考之后,再通过工具调用来执行你的计划(可以调用 0~N 个工具);
- 第三步:收到工具结果后,在下一轮继续先写出新的思考,再视情况继续调用工具。
请不要在没有先写出思考的情况下直接调用工具。
只输出你的思考内容或工具调用结果,由系统负责真正执行工具调用。

View File

@ -0,0 +1,13 @@
你刚刚完成了一次对聊天记录的记忆整理工作。以下是整理过程的摘要:
整理过程:
{conversation_text}
请将这次整理涉及的相关信息改写为一个富有诗意和想象力的"梦境",请你仅使用具体的记忆的内容,而不是整理过程编写。
要求:
1. 使用第一人称视角
2. 叙述直白,不要复杂修辞,口语化
3. 长度控制在200-800字
4. 用中文输出
梦境风格:
{dream_styles}
请直接输出梦境内容,不要添加其他说明:

View File

@ -0,0 +1,22 @@
{chat_observe_info}
你的名字是{bot_name}{target_message}
{reply_reason_block}
以下是可选的表达情境:
{all_situations}
请你分析聊天内容的语境、情绪、话题类型,从上述情境中选择最适合当前聊天情境的,最多{max_num}个情境。
考虑因素包括:
1.聊天的情绪氛围(轻松、严肃、幽默等)
2.话题类型(日常、技术、游戏、情感等)
3.情境与当前语境的匹配度
{target_message_extra_block}
请以JSON格式输出只需要输出选中的情境编号
例如:
{{
"selected_situations": [2, 3, 5, 7, 19]
}}
请严格按照JSON格式输出不要包含其他内容

View File

@ -0,0 +1,27 @@
【历史话题标题列表】(仅标题,不含具体内容):
{history_topics_block}
【历史话题标题列表结束】
【本次聊天记录】(每条消息前有编号,用于后续引用):
{messages_block}
【本次聊天记录结束】
请完成以下任务:
**识别话题**
1. 识别【本次聊天记录】中正在进行的一个或多个话题;
2. 【本次聊天记录】的中的消息可能与历史话题有关,也可能毫无关联。
2. 判断【历史话题标题列表】中的话题是否在【本次聊天记录】中出现,如果出现,则直接使用该历史话题标题字符串;
**选取消息**
1. 对于每个话题(新话题或历史话题),从上述带编号的消息中选出与该话题强相关的消息编号列表;
2. 每个话题用一句话清晰地描述正在发生的事件,必须包含时间(大致即可)、人物、主要事件和主题,保证精准且有区分度;
请先输出一段简短思考,说明有什么话题,哪些是不包含在历史话题中的,哪些是包含在历史话题中的,并说明为什么;
然后严格以 JSON 格式输出【本次聊天记录】中涉及的话题,格式如下:
[
{{
"topic": "话题",
"message_indices": [1, 2, 5]
}},
...
]

View File

@ -0,0 +1,22 @@
请基于以下话题,对聊天记录片段进行概括,提取以下信息:
**话题**{topic}
**要求**
1. 关键词提取与话题相关的关键词用列表形式返回3-10个关键词
2. 概括对这段话的平文本概括50-200字要求
- 仔细地转述发生的事件和聊天内容;
- 重点突出事件的发展过程和结果;
- 围绕话题这个中心进行概括。
- 提取话题中的关键信息点,关键信息点应该简洁明了。
请以JSON格式返回格式如下
{{
"keywords": ["关键词1", "关键词2", ...],
"summary": "概括内容"
}}
聊天记录:
{original_text}
请直接返回JSON不要包含其他内容。

View File

@ -0,0 +1,15 @@
**推断结果1基于上下文**
{inference1}
**推断结果2仅基于词条**
{inference2}
请比较这两个推断结果,判断它们是否相同或类似。
- 如果两个推断结果的"含义"相同或类似,说明这个词条不是黑话(含义明确)
- 如果两个推断结果有差异,说明这个词条可能是黑话(需要上下文才能理解)
以 JSON 格式输出:
{{
"is_similar": true/false,
"reason": "判断理由"
}}

View File

@ -0,0 +1,11 @@
**词条内容**
{content}
请仅根据这个词条本身,推断其含义。
- 如果这是一个黑话、俚语或网络用语,请推断其含义
- 如果含义明确(常规词汇),也请说明
以 JSON 格式输出:
{{
"meaning": "详细含义说明(包含使用场景、来源、具体解释等)"
}}

View File

@ -0,0 +1,19 @@
**词条内容**
{content}
**词条出现的上下文。其中的{bot_name}的发言内容是你自己的发言**
{raw_content_list}
{previous_meaning_section}
请根据上下文,推断"{content}"这个词条的含义。
- 如果这是一个黑话、俚语或网络用语,请推断其含义
- 如果含义明确(常规词汇),也请说明
- {bot_name} 的发言内容可能包含错误,请不要参考其发言内容
- 如果上下文信息不足,无法推断含义,请设置 no_info 为 true
{previous_meaning_instruction}
以 JSON 格式输出:
{{
"meaning": "详细含义说明(包含使用场景、来源、具体解释等)",
"no_info": false
}}
注意:如果信息不足无法推断,请设置 "no_info": true此时 meaning 可以为空字符串

View File

@ -0,0 +1,49 @@
{chat_str}
你的名字是{bot_name},现在请你完成两个提取任务
任务1请从上面这段群聊中用户的语言风格和说话方式
1. 只考虑文字,不要考虑表情包和图片
2. 不要总结SELF的发言因为这是你自己的发言不要重复学习你自己的发言
3. 不要涉及具体的人名,也不要涉及具体名词
4. 思考有没有特殊的梗,一并总结成语言风格
5. 例子仅供参考,请严格根据群聊内容总结!!!
注意:总结成如下格式的规律,总结的内容要详细,但具有概括性:
例如:当"AAAAA"时,可以"BBBBB", AAAAA代表某个场景不超过20个字。BBBBB代表对应的语言风格特定句式或表达方式不超过20个字。
表达方式在3-5个左右不要超过10个
任务2请从上面这段聊天内容中提取"可能是黑话"的候选项(黑话/俚语/网络缩写/口头禅)。
- 必须为对话中真实出现过的短词或短语
- 必须是你无法理解含义的词语,没有明确含义的词语,请不要选择有明确含义,或者含义清晰的词语
- 排除:人名、@、表情包/图片中的内容、纯标点、常规功能词(如的、了、呢、啊等)
- 每个词条长度建议 2-8 个字符(不强制),尽量短小
- 请你提取出可能的黑话最多30个黑话请尽量提取所有
黑话必须为以下几种类型:
- 由字母构成的汉语拼音首字母的简写词例如nb、yyds、xswl
- 英文词语的缩写用英文字母概括一个词汇或含义例如CPU、GPU、API
- 中文词语的缩写,用几个汉字概括一个词汇或含义,例如:社死、内卷
输出要求:
将表达方式,语言风格和黑话以 JSON 数组输出,每个元素为一个对象,结构如下(注意字段名):
注意请不要输出重复内容,请对表达方式和黑话进行去重。
[
{{"situation": "AAAAA", "style": "BBBBB", "source_id": "3"}},
{{"situation": "CCCC", "style": "DDDD", "source_id": "7"}}
{{"situation": "对某件事表示十分惊叹", "style": "使用 我嘞个xxxx", "source_id": "[消息编号]"}},
{{"situation": "表示讽刺的赞同,不讲道理", "style": "对对对", "source_id": "[消息编号]"}},
{{"situation": "当涉及游戏相关时,夸赞,略带戏谑意味", "style": "使用 这么强!", "source_id": "[消息编号]"}},
{{"content": "词条", "source_id": "12"}},
{{"content": "词条2", "source_id": "5"}}
]
其中:
表达方式条目:
- situation表示“在什么情境下”的简短概括不超过20个字
- style表示对应的语言风格或常用表达不超过20个字
- source_id该表达方式对应的“来源行编号”即上方聊天记录中方括号里的数字例如 [3]),请只输出数字本身,不要包含方括号
黑话jargon条目
- content:表示黑话的内容
- source_id该黑话对应的“来源行编号”即上方聊天记录中方括号里的数字例如 [3]),请只输出数字本身,不要包含方括号
现在请你输出 JSON

View File

@ -0,0 +1,19 @@
你的名字是{bot_name}。现在是{time_now}。
你正在参与聊天,你需要根据搜集到的信息总结信息。
如果搜集到的信息对于参与聊天,回答问题有帮助,请加入总结,如果无关,请不要加入到总结。
当前聊天记录:
{chat_history}
已收集的信息:
{collected_info}
分析:
- 基于已收集的信息,总结出对当前聊天有帮助的相关信息
- **如果收集的信息对当前聊天有帮助**在思考中直接给出总结信息格式为return_information(information="你的总结信息")
- **如果信息无关或没有帮助**在思考中给出return_information(information="")
**重要规则:**
- 必须严格使用检索到的信息回答问题,不要编造信息
- 答案必须精简,不要过多解释

View File

@ -0,0 +1,19 @@
你的名字是{bot_name}。现在是{time_now}。
你正在参与聊天,你需要搜集信息来帮助你进行回复。
当前聊天记录:
{chat_history}
已收集的信息:
{collected_info}
**工具说明:**
- 如果涉及过往事件,或者查询某个过去可能提到过的概念,或者某段时间发生的事件。可以使用聊天记录查询工具查询过往事件
- 如果涉及人物,可以使用人物信息查询工具查询人物信息
- 如果遇到不熟悉的词语、缩写、黑话或网络用语可以使用query_words工具查询其含义
- 如果没有可靠信息且查询时间充足或者不确定查询类别也可以使用lpmm知识库查询作为辅助信息
**思考**
- 你可以对查询思路给出简短的思考:思考要简短,直接切入要点
- 先思考当前信息是否足够回答问题
- 如果信息不足则需要使用tool查询信息你必须给出使用什么工具进行查询
- 当你决定结束查询时必须调用return_information工具返回总结信息并结束查询

View File

@ -0,0 +1,17 @@
你的名字是{bot_name}。现在是{time_now}。
你正在参与聊天,你需要搜集信息来帮助你进行回复。
重要,这是当前聊天记录:
{chat_history}
聊天记录结束
已收集的信息:
{collected_info}
- 你可以对查询思路给出简短的思考:思考要简短,直接切入要点
- 思考完毕后,使用工具
**工具说明:**
- 如果涉及过往事件或者查询某个过去可能提到过的概念或者某段时间发生的事件。可以使用lpmm知识库查询
- 如果遇到不熟悉的词语、缩写、黑话或网络用语可以使用query_words工具查询其含义
- 你必须使用tool如果需要查询你必须给出使用什么工具进行查询
- 当你决定结束查询时必须调用return_information工具返回总结信息并结束查询

View File

@ -0,0 +1,15 @@
{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}{memory_retrieval}{jargon_explanation}
你正在和{sender_name}聊天,这是你们之前聊的内容:
{time_block}
{dialogue_prompt}
{reply_target_block}。
{planner_reasoning}
{identity}
{chat_prompt}你正在和{sender_name}聊天,现在请你读读之前的聊天记录,然后给出日常且口语化的回复,平淡一些,
尽量简短一些。{keywords_reaction_prompt}请注意把握聊天内容,不要回复的太有条理。
{reply_style}
请注意不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只输出回复内容。
{moderation_prompt}不要输出多余内容(包括前后缀冒号和引号括号表情包at或 @等 )。

View File

@ -0,0 +1,14 @@
{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}{memory_retrieval}{jargon_explanation}
你正在和{sender_name}聊天,这是你们之前聊的内容:
{time_block}
{dialogue_prompt}
你现在想补充说明你刚刚自己的发言内容:{target},原因是{reason}
请你根据聊天内容,组织一条新回复。注意,{target} 是刚刚你自己的发言,你要在这基础上进一步发言,请按照你自己的角度来继续进行回复。注意保持上下文的连贯性。
{identity}
{chat_prompt}尽量简短一些。{keywords_reaction_prompt}请注意把握聊天内容,不要回复的太有条理,可以有个性。
{reply_style}
请注意不要输出多余内容(包括前后缀,冒号和引号,括号,表情等),只输出回复内容。
{moderation_prompt}不要输出多余内容(包括冒号和引号括号表情包at或 @等 )。

View File

@ -0,0 +1,24 @@
你是一个表达反思助手。Bot之前询问了表达方式是否合适。
你需要根据提供的上下文对话,判断是否对该表达方式做出了肯定或否定的评价。
**询问内容**
情景: {situation}
风格: {style}
**上下文对话**
{context_block}
**判断要求**
1. 判断对话中是否包含对上述询问的回答。
2. 如果是判断是肯定Approve还是否定Reject或者是提供了修改意见。
3. 如果不是回答,或者是无关内容,请返回 "Ignore"。
4. 如果是否定并提供了修改意见,请提取修正后的情景和风格。
请输出JSON格式
```json
{{
"judgment": "Approve" | "Reject" | "Ignore",
"corrected_situation": "...", // 如果有修改意见,提取修正后的情景,否则留空
"corrected_style": "..." // 如果有修改意见,提取修正后的风格,否则留空
}}
```

View File

@ -0,0 +1,11 @@
你是一个专门执行工具的助手。你的名字是{bot_name}。现在是{time_now}。
群里正在进行的聊天内容:
{chat_history}
现在,{sender}发送了内容:{target_message},你想要回复ta。
请仔细分析聊天内容,考虑以下几点:
1. 内容中是否包含需要查询信息的问题
2. 是否有明确的工具使用指令
你可以选择多个动作
If you need to use tools, please directly call the corresponding tool function. If you do not need to use any tool, simply output "No tool needed".

View File

@ -11,7 +11,7 @@ from src.config.config import model_config, global_config
from src.chat.utils.chat_message_builder import (
build_anonymous_messages,
)
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.chat.message_receive.chat_stream import get_chat_manager
from src.bw_learner.learner_utils import (
filter_message_content,
@ -32,60 +32,6 @@ from src.bw_learner.expression_auto_check_task import (
logger = get_logger("expressor")
def init_prompt() -> None:
learn_style_prompt = """{chat_str}
你的名字是{bot_name},现在请你完成两个提取任务
任务1请从上面这段群聊中用户的语言风格和说话方式
1. 只考虑文字不要考虑表情包和图片
2. 不要总结SELF的发言因为这是你自己的发言不要重复学习你自己的发言
3. 不要涉及具体的人名也不要涉及具体名词
4. 思考有没有特殊的梗一并总结成语言风格
5. 例子仅供参考请严格根据群聊内容总结!!!
注意总结成如下格式的规律总结的内容要详细但具有概括性
例如"AAAAA"可以"BBBBB", AAAAA代表某个场景不超过20个字BBBBB代表对应的语言风格特定句式或表达方式不超过20个字
表达方式在3-5个左右不要超过10个
任务2请从上面这段聊天内容中提取"可能是黑话"的候选项黑话/俚语/网络缩写/口头禅
- 必须为对话中真实出现过的短词或短语
- 必须是你无法理解含义的词语没有明确含义的词语请不要选择有明确含义或者含义清晰的词语
- 排除人名@表情包/图片中的内容纯标点常规功能词如的啊等
- 每个词条长度建议 2-8 个字符不强制尽量短小
- 请你提取出可能的黑话最多30个黑话请尽量提取所有
黑话必须为以下几种类型
- 由字母构成的汉语拼音首字母的简写词例如nbyydsxswl
- 英文词语的缩写用英文字母概括一个词汇或含义例如CPUGPUAPI
- 中文词语的缩写用几个汉字概括一个词汇或含义例如社死内卷
输出要求
将表达方式语言风格和黑话以 JSON 数组输出每个元素为一个对象结构如下注意字段名
注意请不要输出重复内容请对表达方式和黑话进行去重
[
{{"situation": "AAAAA", "style": "BBBBB", "source_id": "3"}},
{{"situation": "CCCC", "style": "DDDD", "source_id": "7"}}
{{"situation": "对某件事表示十分惊叹", "style": "使用 我嘞个xxxx", "source_id": "[消息编号]"}},
{{"situation": "表示讽刺的赞同,不讲道理", "style": "对对对", "source_id": "[消息编号]"}},
{{"situation": "当涉及游戏相关时,夸赞,略带戏谑意味", "style": "使用 这么强!", "source_id": "[消息编号]"}},
{{"content": "词条", "source_id": "12"}},
{{"content": "词条2", "source_id": "5"}}
]
其中
表达方式条目
- situation表示在什么情境下的简短概括不超过20个字
- style表示对应的语言风格或常用表达不超过20个字
- source_id该表达方式对应的来源行编号即上方聊天记录中方括号里的数字例如 [3]请只输出数字本身不要包含方括号
黑话jargon条目
- content:表示黑话的内容
- source_id该黑话对应的来源行编号即上方聊天记录中方括号里的数字例如 [3]请只输出数字本身不要包含方括号
现在请你输出 JSON
"""
Prompt(learn_style_prompt, "learn_style_prompt")
class ExpressionLearner:
def __init__(self, chat_id: str) -> None:
self.express_learn_model: LLMRequest = LLMRequest(
@ -105,7 +51,7 @@ class ExpressionLearner:
async def learn_and_store(
self,
messages: List[Any],
) -> List[Tuple[str, str, str]]:
) -> Optional[List[Tuple[str, str, str]]]:
"""
学习并存储表达方式
@ -122,11 +68,11 @@ class ExpressionLearner:
# 学习用(开启行编号,便于溯源)
random_msg_str: str = await build_anonymous_messages(random_msg, show_ids=True)
prompt: str = await global_prompt_manager.format_prompt(
"learn_style_prompt",
bot_name=global_config.bot.nickname,
chat_str=random_msg_str,
)
prompt_template = prompt_manager.get_prompt("learn_style_prompt")
prompt_template.add_context("bot_name", global_config.bot.nickname)
prompt_template.add_context("chat_str", random_msg_str)
prompt = await prompt_manager.render_prompt(prompt_template)
# print(f"random_msg_str:{random_msg_str}")
# logger.info(f"学习{type_str}的prompt: {prompt}")
@ -186,14 +132,14 @@ class ExpressionLearner:
# 展示学到的表达方式
learnt_expressions_str = ""
for (situation,style) in learnt_expressions:
for situation, style in learnt_expressions:
learnt_expressions_str += f"{situation}->{style}\n"
logger.info(f"{self.chat_name} 学习到表达风格:\n{learnt_expressions_str}")
current_time = time.time()
# 存储到数据库 Expression 表
for (situation,style) in learnt_expressions:
for situation, style in learnt_expressions:
await self._upsert_expression_record(
situation=situation,
style=style,
@ -209,11 +155,11 @@ class ExpressionLearner:
) -> List[Tuple[str, str, str]]:
"""
过滤表达方式移除不符合条件的条目
Args:
expressions: 表达方式列表每个元素是 (situation, style, source_id)
messages: 原始消息列表用于溯源和验证
Returns:
过滤后的表达方式列表每个元素是 (situation, style, context)
"""
@ -255,9 +201,7 @@ class ExpressionLearner:
# 过滤掉包含 SELF 的内容(不学习)
if "SELF" in (situation or "") or "SELF" in (style or "") or "SELF" in context:
logger.info(
f"跳过包含 SELF 的表达方式: situation={situation}, style={style}, source_id={source_id}"
)
logger.info(f"跳过包含 SELF 的表达方式: situation={situation}, style={style}, source_id={source_id}")
continue
# 过滤掉 style 与机器人名称/昵称重复的表达
@ -269,19 +213,20 @@ class ExpressionLearner:
continue
# 过滤掉包含 "表情:" 或 "表情:" 的内容
if "表情:" in (situation or "") or "表情:" in (situation or "") or \
"表情:" in (style or "") or "表情:" in (style or "") or \
"表情:" in context or "表情:" in context:
logger.info(
f"跳过包含表情标记的表达方式: situation={situation}, style={style}, source_id={source_id}"
)
if (
"表情:" in (situation or "")
or "表情:" in (situation or "")
or "表情:" in (style or "")
or "表情:" in (style or "")
or "表情:" in context
or "表情:" in context
):
logger.info(f"跳过包含表情标记的表达方式: situation={situation}, style={style}, source_id={source_id}")
continue
# 过滤掉包含 "[图片" 的内容
if "[图片" in (situation or "") or "[图片" in (style or "") or "[图片" in context:
logger.info(
f"跳过包含图片标记的表达方式: situation={situation}, style={style}, source_id={source_id}"
)
logger.info(f"跳过包含图片标记的表达方式: situation={situation}, style={style}, source_id={source_id}")
continue
filtered_expressions.append((situation, style))
@ -347,7 +292,7 @@ class ExpressionLearner:
"""
更新现有 Expression 记录situation 完全匹配或相似的情况
将新的 situation 添加到 content_list不合并 style
Args:
use_llm_summary: 是否使用 LLM 进行总结完全匹配时为 False相似匹配时为 True
"""
@ -383,26 +328,28 @@ class ExpressionLearner:
return []
return [str(item) for item in data if isinstance(item, str)] if isinstance(data, list) else []
async def _find_similar_situation_expression(self, situation: str, similarity_threshold: float = 0.75) -> Tuple[Optional[Expression], float]:
async def _find_similar_situation_expression(
self, situation: str, similarity_threshold: float = 0.75
) -> Tuple[Optional[Expression], float]:
"""
查找具有相似 situation Expression 记录
检查 content_list 中的每一项
Args:
situation: 要查找的 situation
similarity_threshold: 相似度阈值默认 0.75
Returns:
Tuple[Optional[Expression], float]:
Tuple[Optional[Expression], float]:
- 找到的最相似的 Expression 对象如果没有找到则返回 None
- 相似度值如果找到匹配范围在 similarity_threshold 1.0 之间
"""
# 查询同一 chat_id 的所有记录
all_expressions = Expression.select().where(Expression.chat_id == self.chat_id)
best_match = None
best_similarity = 0.0
for expr in all_expressions:
# 检查 content_list 中的每一项
content_list = self._parse_content_list(expr.content_list)
@ -411,10 +358,12 @@ class ExpressionLearner:
if similarity >= similarity_threshold and similarity > best_similarity:
best_similarity = similarity
best_match = expr
if best_match:
logger.debug(f"找到相似的 situation: 相似度={best_similarity:.3f}, 现有='{best_match.situation}', 新='{situation}'")
logger.debug(
f"找到相似的 situation: 相似度={best_similarity:.3f}, 现有='{best_match.situation}', 新='{situation}'"
)
return best_match, best_similarity
async def _compose_situation_text(self, content_list: List[str], fallback: str = "") -> str:
@ -442,8 +391,7 @@ class ExpressionLearner:
if self.check_model is None:
try:
self.check_model = LLMRequest(
model_set=model_config.model_task_config.tool_use,
request_type="expression.check"
model_set=model_config.model_task_config.tool_use, request_type="expression.check"
)
logger.debug("检查用 LLM 实例初始化成功")
except Exception as e:
@ -452,7 +400,7 @@ class ExpressionLearner:
async def _check_expression_immediately(self, expr_obj: Expression) -> None:
"""
立即检查表达方式 count 增加后调用
Args:
expr_obj: 要检查的表达方式对象
"""
@ -469,10 +417,7 @@ class ExpressionLearner:
return
# 执行 LLM 评估
suitable, reason, error = await single_expression_check(
expr_obj.situation,
expr_obj.style
)
suitable, reason, error = await single_expression_check(expr_obj.situation, expr_obj.style)
# 更新数据库
expr_obj.checked = True
@ -497,48 +442,45 @@ class ExpressionLearner:
def _check_cached_jargons_in_messages(self, messages: List[Any]) -> List[Tuple[str, str]]:
"""
检查缓存中的 jargon 是否出现在 messages
Args:
messages: 消息列表
Returns:
List[Tuple[str, str]]: 匹配到的黑话条目列表每个元素是 (content, source_id)
"""
if not messages:
return []
# 获取 jargon_miner 实例
jargon_miner = miner_manager.get_miner(self.chat_id)
# 获取缓存中的所有 jargon
cached_jargons = jargon_miner.get_cached_jargons()
if not cached_jargons:
return []
matched_entries: List[Tuple[str, str]] = []
# 遍历 messages检查缓存中的 jargon 是否出现
for i, msg in enumerate(messages):
# 跳过机器人自己的消息
if is_bot_message(msg):
continue
# 获取消息文本
msg_text = (
getattr(msg, "processed_plain_text", None) or
""
).strip()
msg_text = (getattr(msg, "processed_plain_text", None) or "").strip()
if not msg_text:
continue
# 检查每个缓存中的 jargon 是否出现在消息文本中
for jargon in cached_jargons:
if not jargon or not jargon.strip():
continue
jargon_content = jargon.strip()
# 使用正则匹配,考虑单词边界(类似 jargon_explainer 中的逻辑)
pattern = re.escape(jargon_content)
# 对于中文,使用更宽松的匹配;对于英文/数字,使用单词边界
@ -548,12 +490,12 @@ class ExpressionLearner:
else:
# 纯英文/数字,使用单词边界
search_pattern = r"\b" + pattern + r"\b"
if re.search(search_pattern, msg_text, re.IGNORECASE):
# 找到匹配构建条目source_id 从 1 开始,因为 build_anonymous_messages 的编号从 1 开始)
source_id = str(i + 1)
matched_entries.append((jargon_content, source_id))
return matched_entries
async def _process_jargon_entries(self, jargon_entries: List[Tuple[str, str]], messages: List[Any]) -> None:
@ -621,9 +563,6 @@ class ExpressionLearner:
await jargon_miner.process_extracted_entries(entries)
init_prompt()
class ExpressionLearnerManager:
def __init__(self):
self.expression_learners = {}

View File

@ -8,7 +8,7 @@ from src.llm_models.utils_model import LLMRequest
from src.config.config import global_config, model_config
from src.common.logger import get_logger
from src.common.database.database_model import Expression
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.bw_learner.learner_utils import weighted_sample
from src.chat.message_receive.chat_stream import get_chat_manager
from src.chat.utils.common_utils import TempMethodsExpression
@ -16,33 +16,6 @@ from src.chat.utils.common_utils import TempMethodsExpression
logger = get_logger("expression_selector")
def init_prompt():
expression_evaluation_prompt = """{chat_observe_info}
你的名字是{bot_name}{target_message}
{reply_reason_block}
以下是可选的表达情境
{all_situations}
请你分析聊天内容的语境情绪话题类型从上述情境中选择最适合当前聊天情境的最多{max_num}个情境
考虑因素包括
1.聊天的情绪氛围轻松严肃幽默等
2.话题类型日常技术游戏情感等
3.情境与当前语境的匹配度
{target_message_extra_block}
请以JSON格式输出只需要输出选中的情境编号
例如
{{
"selected_situations": [2, 3, 5, 7, 19]
}}
请严格按照JSON格式输出不要包含其他内容
"""
Prompt(expression_evaluation_prompt, "expression_evaluation_prompt")
class ExpressionSelector:
def __init__(self):
self.llm_model = LLMRequest(
@ -125,7 +98,9 @@ class ExpressionSelector:
# 查询所有相关chat_id的表达方式排除 rejected=1 的,且只选择 count > 1 的
# 如果 expression_checked_only 为 True则只选择 checked=True 且 rejected=False 的
base_conditions = (Expression.chat_id.in_(related_chat_ids)) & (~Expression.rejected) & (Expression.count > 1)
base_conditions = (
(Expression.chat_id.in_(related_chat_ids)) & (~Expression.rejected) & (Expression.count > 1)
)
if global_config.expression.expression_checked_only:
base_conditions = base_conditions & (Expression.checked)
style_query = Expression.select().where(base_conditions)
@ -149,9 +124,7 @@ class ExpressionSelector:
if len(style_exprs) < min_required:
# 高 count 样本不足:如果还有候选,就降级为随机选 3 个;如果一个都没有,则直接返回空
if not style_exprs:
logger.info(
f"聊天流 {chat_id} 没有满足 count > 1 且未被拒绝的表达方式,简单模式不进行选择"
)
logger.info(f"聊天流 {chat_id} 没有满足 count > 1 且未被拒绝的表达方式,简单模式不进行选择")
# 完全没有高 count 样本时退化为全量随机抽样不进入LLM流程
fallback_num = min(3, max_num) if max_num > 0 else 3
fallback_selected = self._random_expressions(chat_id, fallback_num)
@ -405,15 +378,15 @@ class ExpressionSelector:
reply_reason_block = ""
# 3. 构建prompt只包含情境不包含完整的表达方式
prompt = (await global_prompt_manager.get_prompt_async("expression_evaluation_prompt")).format(
bot_name=global_config.bot.nickname,
chat_observe_info=chat_context,
all_situations=all_situations_str,
max_num=max_num,
target_message=target_message_str,
target_message_extra_block=target_message_extra_block,
reply_reason_block=reply_reason_block,
)
prompt_template = prompt_manager.get_prompt("expression_evaluation_prompt")
prompt_template.add_context("bot_name", global_config.bot.nickname)
prompt_template.add_context("chat_observe_info", chat_context)
prompt_template.add_context("all_situations", all_situations_str)
prompt_template.add_context("max_num", str(max_num))
prompt_template.add_context("target_message", target_message_str)
prompt_template.add_context("target_message_extra_block", target_message_extra_block)
prompt_template.add_context("reply_reason_block", reply_reason_block)
prompt = await prompt_manager.render_prompt(prompt_template)
# 4. 调用LLM
content, (reasoning_content, model_name, _) = await self.llm_model.generate_response_async(prompt=prompt)
@ -482,9 +455,6 @@ class ExpressionSelector:
expr_obj.save()
logger.debug("表达方式激活: 更新last_active_time in db")
init_prompt()
try:
expression_selector = ExpressionSelector()
except Exception as e:

View File

@ -200,11 +200,6 @@ 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,
# )
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)

View File

@ -11,7 +11,7 @@ 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.message_receive.chat_stream import get_chat_manager
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.bw_learner.learner_utils import (
parse_chat_id_list,
chat_id_list_contains,
@ -45,100 +45,6 @@ def _is_single_char_jargon(content: str) -> bool:
)
# def _init_prompt() -> None:
# prompt_str = """
# **聊天内容,其中的{bot_name}的发言内容是你自己的发言,[msg_id] 是消息ID**
# {chat_str}
# 请从上面这段聊天内容中提取"可能是黑话"的候选项(黑话/俚语/网络缩写/口头禅)。
# - 必须为对话中真实出现过的短词或短语
# - 必须是你无法理解含义的词语,没有明确含义的词语,请不要选择有明确含义,或者含义清晰的词语
# - 排除:人名、@、表情包/图片中的内容、纯标点、常规功能词(如的、了、呢、啊等)
# - 每个词条长度建议 2-8 个字符(不强制),尽量短小
# 黑话必须为以下几种类型:
# - 由字母构成的汉语拼音首字母的简写词例如nb、yyds、xswl
# - 英文词语的缩写用英文字母概括一个词汇或含义例如CPU、GPU、API
# - 中文词语的缩写,用几个汉字概括一个词汇或含义,例如:社死、内卷
# 以 JSON 数组输出,元素为对象(严格按以下结构):
# 请你提取出可能的黑话最多30个黑话请尽量提取所有
# [
# {{"content": "词条", "msg_id": "m12"}}, // msg_id 必须与上方聊天中展示的ID完全一致
# {{"content": "词条2", "msg_id": "m15"}}
# ]
# 现在请输出:
# """
# Prompt(prompt_str, "extract_jargon_prompt")
def _init_inference_prompts() -> None:
"""初始化含义推断相关的prompt"""
# Prompt 1: 基于raw_content和content推断
prompt1_str = """
**词条内容**
{content}
**词条出现的上下文其中的{bot_name}的发言内容是你自己的发言**
{raw_content_list}
{previous_meaning_section}
请根据上下文推断"{content}"这个词条的含义
- 如果这是一个黑话俚语或网络用语请推断其含义
- 如果含义明确常规词汇也请说明
- {bot_name} 的发言内容可能包含错误请不要参考其发言内容
- 如果上下文信息不足无法推断含义请设置 no_info true
{previous_meaning_instruction}
JSON 格式输出
{{
"meaning": "详细含义说明(包含使用场景、来源、具体解释等)",
"no_info": false
}}
注意如果信息不足无法推断请设置 "no_info": true此时 meaning 可以为空字符串
"""
Prompt(prompt1_str, "jargon_inference_with_context_prompt")
# Prompt 2: 仅基于content推断
prompt2_str = """
**词条内容**
{content}
请仅根据这个词条本身推断其含义
- 如果这是一个黑话俚语或网络用语请推断其含义
- 如果含义明确常规词汇也请说明
JSON 格式输出
{{
"meaning": "详细含义说明(包含使用场景、来源、具体解释等)"
}}
"""
Prompt(prompt2_str, "jargon_inference_content_only_prompt")
# Prompt 3: 比较两个推断结果
prompt3_str = """
**推断结果1基于上下文**
{inference1}
**推断结果2仅基于词条**
{inference2}
请比较这两个推断结果判断它们是否相同或类似
- 如果两个推断结果的"含义"相同或类似说明这个词条不是黑话含义明确
- 如果两个推断结果有差异说明这个词条可能是黑话需要上下文才能理解
JSON 格式输出
{{
"is_similar": true/false,
"reason": "判断理由"
}}
"""
Prompt(prompt3_str, "jargon_compare_inference_prompt")
_init_inference_prompts()
def _should_infer_meaning(jargon_obj: Jargon) -> bool:
"""
判断是否需要进行含义推断
@ -282,22 +188,18 @@ class JargonMiner:
previous_meaning_section = ""
previous_meaning_instruction = ""
if current_count in [24, 60, 100] and previous_meaning:
previous_meaning_section = f"""
**上一次推断的含义仅供参考**
{previous_meaning}
"""
previous_meaning_section = f"\n**上一次推断的含义(仅供参考)**\n{previous_meaning}"
previous_meaning_instruction = (
"- 请参考上一次推断的含义,结合新的上下文信息,给出更准确或更新的推断结果"
)
prompt1 = await global_prompt_manager.format_prompt(
"jargon_inference_with_context_prompt",
content=content,
bot_name=global_config.bot.nickname,
raw_content_list=raw_content_text,
previous_meaning_section=previous_meaning_section,
previous_meaning_instruction=previous_meaning_instruction,
)
prompt1_template = prompt_manager.get_prompt("jargon_inference_with_context_prompt")
prompt1_template.add_context("bot_name", global_config.bot.nickname)
prompt1_template.add_context("content", str(content))
prompt1_template.add_context("raw_content_list", raw_content_text)
prompt1_template.add_context("previous_meaning_section", previous_meaning_section)
prompt1_template.add_context("previous_meaning_instruction", previous_meaning_instruction)
prompt1 = await prompt_manager.render_prompt(prompt1_template)
response1, _ = await self.llm_inference.generate_response_async(prompt1, temperature=0.3)
if not response1:
@ -331,10 +233,9 @@ class JargonMiner:
return
# 步骤2: 仅基于content推断
prompt2 = await global_prompt_manager.format_prompt(
"jargon_inference_content_only_prompt",
content=content,
)
prompt2_template = prompt_manager.get_prompt("jargon_inference_content_only_prompt")
prompt2_template.add_context("content", str(content))
prompt2 = await prompt_manager.render_prompt(prompt2_template)
response2, _ = await self.llm_inference.generate_response_async(prompt2, temperature=0.3)
if not response2:
@ -374,11 +275,10 @@ class JargonMiner:
logger.debug(f"jargon {content} 推断1结果: {response1}")
# 步骤3: 比较两个推断结果
prompt3 = await global_prompt_manager.format_prompt(
"jargon_compare_inference_prompt",
inference1=json.dumps(inference1, ensure_ascii=False),
inference2=json.dumps(inference2, ensure_ascii=False),
)
prompt3_template = prompt_manager.get_prompt("jargon_compare_inference_prompt")
prompt3_template.add_context("inference1", json.dumps(inference1, ensure_ascii=False))
prompt3_template.add_context("inference2", json.dumps(inference2, ensure_ascii=False))
prompt3 = await prompt_manager.render_prompt(prompt3_template)
if global_config.debug.show_jargon_prompt:
logger.info(f"jargon {content} 比较提示词: {prompt3}")
@ -449,9 +349,7 @@ class JargonMiner:
traceback.print_exc()
async def process_extracted_entries(
self,
entries: List[Dict[str, List[str]]],
person_name_filter: Optional[Callable[[str], bool]] = None
self, entries: List[Dict[str, List[str]]], person_name_filter: Optional[Callable[[str], bool]] = None
) -> None:
"""
处理已提取的黑话条目 expression_learner 路由过来的
@ -468,14 +366,14 @@ class JargonMiner:
merged_entries: OrderedDict[str, Dict[str, List[str]]] = OrderedDict()
for entry in entries:
content_key = entry["content"]
# 检查是否包含人物名称
# logger.info(f"process_extracted_entries 检查是否包含人物名称: {content_key}")
# logger.info(f"person_name_filter: {person_name_filter}")
if person_name_filter and person_name_filter(content_key):
logger.info(f"process_extracted_entries 跳过包含人物名称的黑话: {content_key}")
continue
raw_list = entry.get("raw_content", []) or []
if content_key in merged_entries:
merged_entries[content_key]["raw_content"].extend(raw_list)

View File

@ -3,7 +3,7 @@ from typing import Optional, Dict, TYPE_CHECKING
from src.common.logger import get_logger
from src.common.database.database_model import Expression
from src.llm_models.utils_model import LLMRequest
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.config.config import model_config
from src.chat.message_receive.chat_stream import ChatStream
from src.chat.utils.chat_message_builder import (
@ -30,37 +30,6 @@ class ReflectTracker:
# LLM for judging response
self.judge_model = LLMRequest(model_set=model_config.model_task_config.tool_use, request_type="reflect.tracker")
self._init_prompts()
def _init_prompts(self):
judge_prompt = """
你是一个表达反思助手Bot之前询问了表达方式是否合适
你需要根据提供的上下文对话判断是否对该表达方式做出了肯定或否定的评价
**询问内容**
情景: {situation}
风格: {style}
**上下文对话**
{context_block}
**判断要求**
1. 判断对话中是否包含对上述询问的回答
2. 如果是判断是肯定Approve还是否定Reject或者是提供了修改意见
3. 如果不是回答或者是无关内容请返回 "Ignore"
4. 如果是否定并提供了修改意见请提取修正后的情景和风格
请输出JSON格式
```json
{{
"judgment": "Approve" | "Reject" | "Ignore",
"corrected_situation": "...", // 如果有修改意见提取修正后的情景否则留空
"corrected_style": "..." // 如果有修改意见提取修正后的风格否则留空
}}
```
"""
Prompt(judge_prompt, "reflect_judge_prompt")
async def trigger_tracker(self) -> bool:
"""
触发追踪检查
@ -103,12 +72,11 @@ class ReflectTracker:
# LLM Judge
try:
prompt = await global_prompt_manager.format_prompt(
"reflect_judge_prompt",
situation=self.expression.situation,
style=self.expression.style,
context_block=context_block,
)
prompt_template = prompt_manager.get_prompt("reflect_judge_prompt")
prompt_template.add_context("situation", str(self.expression.situation))
prompt_template.add_context("style", str(self.expression.style))
prompt_template.add_context("context_block", context_block)
prompt = await prompt_manager.render_prompt(prompt_template)
logger.info(f"ReflectTracker LLM Prompt: {prompt}")
@ -134,14 +102,14 @@ class ReflectTracker:
if judgment == "Approve":
self.expression.checked = True
self.expression.rejected = False
self.expression.modified_by = 'ai' # 通过LLM判断也标记为ai
self.expression.modified_by = "ai" # 通过LLM判断也标记为ai
self.expression.save()
logger.info(f"Expression {self.expression.id} approved by operator.")
return True
elif judgment == "Reject":
self.expression.checked = True
self.expression.modified_by = 'ai' # 通过LLM判断也标记为ai
self.expression.modified_by = "ai" # 通过LLM判断也标记为ai
corrected_situation = json_obj.get("corrected_situation")
corrected_style = json_obj.get("corrected_style")

View File

@ -13,7 +13,7 @@ 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.prompt.prompt_manager import prompt_manager
from src.chat.utils.chat_message_builder import (
build_readable_actions,
get_actions_by_timestamp_with_chat,
@ -35,108 +35,6 @@ logger = get_logger("planner")
install(extra_lines=3)
def init_prompt():
# ReAct 形式的 Planner Prompt
Prompt(
"""
{time_block}
{name_block}
{chat_context_description}以下是具体的聊天内容
**聊天内容**
{chat_content_block}
**动作记录**
{actions_before_now_block}
**可用的action**
reply
动作描述
进行回复你可以自然的顺着正在进行的聊天内容进行回复或自然的提出一个问题
{{
"action": "reply",
"target_message_id":"想要回复的消息id",
"reason":"回复的原因"
}}
wait
动作描述
暂时不再发言等待指定时间适用于以下情况
- 你已经表达清楚一轮想给对方留出空间
- 你感觉对方的话还没说完或者自己刚刚发了好几条连续消息
- 你想要等待一定时间来让对方把话说完或者等待对方反应
- 你想保持安静专注""而不是马上回复
请你根据上下文来判断要等待多久请你灵活判断
- 如果你们交流间隔时间很短聊的很频繁不宜等待太久
- 如果你们交流间隔时间很长聊的很少可以等待较长时间
{{
"action": "wait",
"target_message_id":"想要作为这次等待依据的消息id通常是对方的最新消息",
"wait_seconds": 等待的秒数必填例如5 表示等待5秒,
"reason":"选择等待的原因"
}}
complete_talk
动作描述
当前聊天暂时结束了对方离开没有更多话题了
你可以使用该动作来暂时休息等待对方有新发言再继续
- 多次wait之后对方迟迟不回复消息才用
- 如果对方只是短暂不回复应该使用wait而不是complete_talk
- 聊天内容显示当前聊天已经结束或者没有新内容时候选择complete_talk
选择此动作后将不再继续循环思考直到收到对方的新消息
{{
"action": "complete_talk",
"target_message_id":"触发完成对话的消息id通常是对方的最新消息",
"reason":"选择完成对话的原因"
}}
{action_options_text}
请选择合适的action并说明触发action的消息id和选择该action的原因消息id格式:m+数字
先输出你的选择思考理由再输出你选择的action理由是一段平文本不要分点精简
**动作选择要求**
请你根据聊天内容,用户的最新消息和以下标准选择合适的动作:
{plan_style}
{moderation_prompt}
请选择所有符合使用要求的action动作用json格式输出如果输出多个json每个json都要单独用```json包裹你可以重复使用同一个动作或不同动作:
**示例**
// 理由文本
```json
{{
"action":"动作名",
"target_message_id":"触发动作的消息id",
//对应参数
}}
```
```json
{{
"action":"动作名",
"target_message_id":"触发动作的消息id",
//对应参数
}}
```
""",
"brain_planner_prompt_react",
)
Prompt(
"""
{action_name}
动作描述{action_description}
使用条件
{action_require}
{{
"action": "{action_name}",{action_parameters},
"target_message_id":"触发action的消息id",
"reason":"触发action的原因"
}}
""",
"brain_action_prompt",
)
class BrainPlanner:
def __init__(self, chat_id: str, action_manager: ActionManager):
self.chat_id = chat_id
@ -373,6 +271,7 @@ class BrainPlanner:
else:
actions_before_now_block = ""
chat_context_description: str = ""
if chat_target_info:
# 构建聊天上下文描述
chat_context_description = (
@ -392,18 +291,17 @@ class BrainPlanner:
name_block = f"你的名字是{bot_name}{bot_nickname},请注意哪些是你自己的发言。"
# 获取主规划器模板并填充
planner_prompt_template = await global_prompt_manager.get_prompt_async(prompt_key)
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.experimental.private_plan_style,
)
planner_prompt_template = prompt_manager.get_prompt(prompt_key)
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.experimental.private_plan_style)
prompt = await prompt_manager.render_prompt(planner_prompt_template)
return prompt, message_id_list
except Exception as e:
@ -483,13 +381,12 @@ class BrainPlanner:
require_text = require_text.rstrip("\n")
# 获取动作提示模板并填充
using_action_prompt = await global_prompt_manager.get_prompt_async("brain_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,
)
using_action_prompt_template = prompt_manager.get_prompt("brain_action_prompt")
using_action_prompt_template.add_context("action_name", action_name)
using_action_prompt_template.add_context("action_description", action_info.description)
using_action_prompt_template.add_context("action_parameters", param_text)
using_action_prompt_template.add_context("action_require", require_text)
using_action_prompt = await prompt_manager.render_prompt(using_action_prompt_template)
action_options_block += using_action_prompt
@ -713,6 +610,3 @@ class BrainPlanner:
logger.debug(f"处理不完整的JSON代码块时出错: {e}")
return json_objects, reasoning_content
init_prompt()

View File

@ -13,7 +13,6 @@ 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.prompt.prompt_manager import prompt_manager
from src.chat.utils.chat_message_builder import (
build_readable_messages_with_id,
@ -601,19 +600,6 @@ 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 = 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)
@ -709,14 +695,6 @@ 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 = 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)

View File

@ -32,13 +32,11 @@ from src.plugin_system.base.component_types import ActionInfo, EventType
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.memory_system.memory_retrieval import init_memory_retrieval_prompt, build_memory_retrieval_prompt
from src.memory_system.memory_retrieval import init_memory_retrieval_sys, 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_memory_retrieval_prompt()
init_memory_retrieval_sys()
logger = get_logger("replyer")
@ -977,33 +975,6 @@ 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,
# )
prompt = prompt_manager.get_prompt(prompt_name)
prompt.add_context("expression_habits_block", expression_habits_block)
prompt.add_context("tool_info_block", tool_info)
@ -1111,22 +1082,6 @@ class DefaultReplyer:
except Exception:
reply_style = global_config.personality.reply_style
# return await global_prompt_manager.format_prompt(
# template_name,
# expression_habits_block=expression_habits_block,
# # relation_info_block=relation_info,
# chat_target=chat_target_1,
# time_block=time_block,
# chat_info=chat_talking_prompt_half,
# identity=personality_prompt,
# chat_target_2=chat_target_2,
# reply_target_block=reply_target_block,
# raw_reply=raw_reply,
# reason=reason,
# reply_style=reply_style,
# keywords_reaction_prompt=keywords_reaction_prompt,
# moderation_prompt=moderation_prompt_block,
# )
prompt_template = prompt_manager.get_prompt("default_expressor_prompt")
prompt_template.add_context("expression_habits_block", expression_habits_block)
# prompt_template.add_context("relation_info_block", relation_info)
@ -1220,14 +1175,6 @@ class DefaultReplyer:
template_prompt.add_context("chat_history", message)
template_prompt.add_context("sender", sender)
template_prompt.add_context("target_message", target)
# prompt = await global_prompt_manager.format_prompt(
# "lpmm_get_knowledge_prompt",
# bot_name=bot_name,
# time_now=time_now,
# chat_history=message,
# sender=sender,
# target_message=target,
# )
prompt = await prompt_manager.render_prompt(template_prompt)
_, _, _, _, tool_calls = await llm_api.generate_with_model_with_tools(
prompt,

View File

@ -15,9 +15,8 @@ from src.llm_models.utils_model import LLMRequest
from src.chat.message_receive.message import UserInfo, Seg, MessageRecv, MessageSending
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.timer_calculator import Timer
from src.chat.utils.utils import get_chat_type_and_target_info, is_bot_self
from src.chat.utils.prompt_builder import global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.chat.utils.common_utils import TempMethodsExpression
from src.chat.utils.chat_message_builder import (
@ -27,21 +26,14 @@ from src.chat.utils.chat_message_builder import (
)
from src.bw_learner.expression_selector import expression_selector
from src.plugin_system.apis.message_api import translate_pid_to_description
# from src.memory_system.memory_activator import MemoryActivator
from src.person_info.person_info import Person, is_person_known
from src.plugin_system.base.component_types import ActionInfo, EventType
from src.plugin_system.apis import llm_api
from src.chat.replyer.prompt.lpmm_prompt import init_lpmm_prompt
from src.chat.replyer.prompt.replyer_private_prompt import init_replyer_private_prompt
from src.memory_system.memory_retrieval import init_memory_retrieval_prompt, build_memory_retrieval_prompt
from src.memory_system.memory_retrieval import init_memory_retrieval_sys, build_memory_retrieval_prompt
from src.bw_learner.jargon_explainer import explain_jargon_in_context
init_lpmm_prompt()
init_replyer_private_prompt()
init_memory_retrieval_prompt()
init_memory_retrieval_sys()
logger = get_logger("replyer")
@ -667,7 +659,7 @@ class PrivateReplyer:
timestamp_mode="relative",
read_mark=0.0,
show_actions=True,
long_time_notice=True
long_time_notice=True,
)
message_list_before_short = get_raw_msg_before_timestamp_with_chat(
@ -724,7 +716,12 @@ class PrivateReplyer:
self._time_and_run_task(self.build_personality_prompt(), "personality_prompt"),
self._time_and_run_task(
build_memory_retrieval_prompt(
chat_talking_prompt_short, sender, target, self.chat_stream, think_level=1, unknown_words=unknown_words
chat_talking_prompt_short,
sender,
target,
self.chat_stream,
think_level=1,
unknown_words=unknown_words,
),
"memory_retrieval",
),
@ -800,7 +797,7 @@ class PrivateReplyer:
# 根据配置构建最终的 reply_style支持 multiple_reply_style 按概率随机替换
reply_style = global_config.personality.reply_style
multi_styles =global_config.personality.multiple_reply_style
multi_styles = global_config.personality.multiple_reply_style
multi_prob = global_config.personality.multiple_probability or 0.0
if multi_styles and multi_prob > 0 and random.random() < multi_prob:
try:
@ -810,50 +807,33 @@ class PrivateReplyer:
reply_style = global_config.personality.reply_style
# 使用统一的 is_bot_self 函数判断是否是机器人自己(支持多平台,包括 WebUI
if is_bot_self(platform, user_id):
return await global_prompt_manager.format_prompt(
"private_replyer_self_prompt",
expression_habits_block=expression_habits_block,
tool_info_block=tool_info,
knowledge_prompt=prompt_info,
relation_info_block=relation_info,
extra_info_block=extra_info_block,
identity=personality_prompt,
action_descriptions=actions_info,
dialogue_prompt=dialogue_prompt,
jargon_explanation=jargon_explanation,
time_block=time_block,
target=target,
reason=reply_reason,
sender_name=sender,
reply_style=reply_style,
keywords_reaction_prompt=keywords_reaction_prompt,
moderation_prompt=moderation_prompt_block,
memory_retrieval=memory_retrieval,
chat_prompt=chat_prompt_block,
), selected_expressions
prompt_template = prompt_manager.get_prompt("private_replyer_self_prompt")
prompt_template.add_context("target", target)
prompt_template.add_context("reason", reply_reason)
else:
return await global_prompt_manager.format_prompt(
"private_replyer_prompt",
expression_habits_block=expression_habits_block,
tool_info_block=tool_info,
knowledge_prompt=prompt_info,
relation_info_block=relation_info,
extra_info_block=extra_info_block,
identity=personality_prompt,
action_descriptions=actions_info,
dialogue_prompt=dialogue_prompt,
jargon_explanation=jargon_explanation,
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,
sender_name=sender,
memory_retrieval=memory_retrieval,
chat_prompt=chat_prompt_block,
planner_reasoning=planner_reasoning,
), selected_expressions
prompt_template = prompt_manager.get_prompt("private_replyer_prompt")
prompt_template.add_context("reply_target_block", reply_target_block)
prompt_template.add_context("planner_reasoning", planner_reasoning)
prompt_template.add_context("expression_habits_block", expression_habits_block)
prompt_template.add_context("tool_info_block", tool_info)
prompt_template.add_context("knowledge_prompt", prompt_info)
prompt_template.add_context("relation_info_block", relation_info)
prompt_template.add_context("extra_info_block", extra_info_block)
prompt_template.add_context("identity", personality_prompt)
prompt_template.add_context("action_descriptions", actions_info)
prompt_template.add_context("dialogue_prompt", dialogue_prompt)
prompt_template.add_context("jargon_explanation", jargon_explanation)
prompt_template.add_context("time_block", time_block)
prompt_template.add_context("sender_name", sender)
prompt_template.add_context("keywords_reaction_prompt", keywords_reaction_prompt)
prompt_template.add_context("reply_style", reply_style)
prompt_template.add_context("memory_retrieval", memory_retrieval)
prompt_template.add_context("chat_prompt", chat_prompt_block)
prompt_template.add_context("moderation_prompt", moderation_prompt_block)
prompt = await prompt_manager.render_prompt(prompt_template)
return prompt, selected_expressions
async def build_prompt_rewrite_context(
self,
@ -943,22 +923,6 @@ class PrivateReplyer:
# 兜底:即使 multiple_reply_style 配置异常也不影响正常回复
reply_style = global_config.personality.reply_style
# return await global_prompt_manager.format_prompt(
# template_name,
# expression_habits_block=expression_habits_block,
# # relation_info_block=relation_info,
# chat_target=chat_target_1,
# time_block=time_block,
# chat_info=chat_talking_prompt_half,
# identity=personality_prompt,
# chat_target_2=chat_target_2,
# reply_target_block=reply_target_block,
# raw_reply=raw_reply,
# reason=reason,
# reply_style=reply_style,
# keywords_reaction_prompt=keywords_reaction_prompt,
# moderation_prompt=moderation_prompt_block,
# )
prompt_template = prompt_manager.get_prompt("default_expressor_prompt")
prompt_template.add_context("expression_habits_block", expression_habits_block)
# prompt_template.add_context("relation_info_block", relation_info)
@ -1046,18 +1010,14 @@ class PrivateReplyer:
if global_config.lpmm_knowledge.lpmm_mode == "agent":
return ""
time_now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
prompt_template = prompt_manager.get_prompt("lpmm_get_knowledge_prompt")
prompt_template.add_context("bot_name", global_config.bot.nickname)
prompt_template.add_context("time_now", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
prompt_template.add_context("chat_history", message)
prompt_template.add_context("sender", sender)
prompt_template.add_context("target_message", target)
prompt = await prompt_manager.render_prompt(prompt_template)
bot_name = global_config.bot.nickname
prompt = await global_prompt_manager.format_prompt(
"lpmm_get_knowledge_prompt",
bot_name=bot_name,
time_now=time_now,
chat_history=message,
sender=sender,
target_message=target,
)
_, _, _, _, tool_calls = await llm_api.generate_with_model_with_tools(
prompt,
model_config=model_config.model_task_config.tool_use,

View File

@ -1,20 +0,0 @@
from src.chat.utils.prompt_builder import Prompt
# from src.memory_system.memory_activator import MemoryActivator
def init_lpmm_prompt():
Prompt(
"""
你是一个专门获取知识的助手你的名字是{bot_name}现在是{time_now}
群里正在进行的聊天内容
{chat_history}
现在{sender}发送了内容:{target_message},你想要回复ta
请仔细分析聊天内容考虑以下几点
1. 内容中是否包含需要查询信息的问题
2. 是否有明确的知识获取指令
If you need to use the search tool, please directly call the function "lpmm_search_knowledge". If you do not need to use any tool, simply output "No tool needed".
""",
name="lpmm_get_knowledge_prompt",
)

View File

@ -1,41 +0,0 @@
from src.chat.utils.prompt_builder import Prompt
def init_replyer_private_prompt():
Prompt(
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}{memory_retrieval}{jargon_explanation}
你正在和{sender_name}聊天这是你们之前聊的内容:
{time_block}
{dialogue_prompt}
{reply_target_block}
{planner_reasoning}
{identity}
{chat_prompt}你正在和{sender_name}聊天,现在请你读读之前的聊天记录然后给出日常且口语化的回复平淡一些
尽量简短一些{keywords_reaction_prompt}请注意把握聊天内容不要回复的太有条理
{reply_style}
请注意不要输出多余内容(包括前后缀冒号和引号括号表情等)只输出回复内容
{moderation_prompt}不要输出多余内容(包括前后缀冒号和引号括号表情包at或 @等 )""",
"private_replyer_prompt",
)
Prompt(
"""{knowledge_prompt}{tool_info_block}{extra_info_block}
{expression_habits_block}{memory_retrieval}{jargon_explanation}
你正在和{sender_name}聊天这是你们之前聊的内容:
{time_block}
{dialogue_prompt}
你现在想补充说明你刚刚自己的发言内容{target}原因是{reason}
请你根据聊天内容组织一条新回复注意{target} 是刚刚你自己的发言你要在这基础上进一步发言请按照你自己的角度来继续进行回复注意保持上下文的连贯性
{identity}
{chat_prompt}尽量简短一些{keywords_reaction_prompt}请注意把握聊天内容不要回复的太有条理可以有个性
{reply_style}
请注意不要输出多余内容(包括前后缀冒号和引号括号表情等)只输出回复内容
{moderation_prompt}不要输出多余内容(包括冒号和引号括号表情包at或 @等 )
""",
"private_replyer_self_prompt",
)

View File

@ -8,7 +8,7 @@ from peewee import fn
from src.common.logger import get_logger
from src.config.config import global_config, model_config
from src.common.database.database_model import ChatHistory
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
from src.llm_models.payload_content.message import MessageBuilder, RoleType, Message
from src.plugin_system.apis import llm_api
from src.dream.dream_generator import generate_dream_summary
@ -27,60 +27,6 @@ from src.dream.tools.update_jargon_tool import make_update_jargon
logger = get_logger("dream_agent")
def init_dream_prompts() -> None:
"""初始化 dream agent 的提示词"""
Prompt(
"""
你的名字是{bot_name}你现在处于"梦境维护模式dream agent"
你可以自由地在 ChatHistory 库中探索整理创建和删改记录以帮助自己在未来更好地回忆和理解对话历史
本轮要维护的聊天ID{chat_id}
本轮随机选中的起始记忆 ID{start_memory_id}
请优先以这条起始记忆为切入点先理解它的内容与上下文再决定如何在其附近进行创建新概括重写或删除等整理操作如果起始记忆为空则由你自行选择合适的切入点
你可以使用的工具包括
**ChatHistory 维护工具**
- search_chat_history根据关键词或参与人搜索该 chat_id 下的历史记忆概括列表
- get_chat_history_detail查看某条概括的详细内容
- create_chat_history根据整理后的理解创建一条新的 ChatHistory 概括记录主题概括关键词关键信息等
- update_chat_history在不改变事实的前提下重写或精炼主题概括关键词关键信息
- delete_chat_history删除明显冗余噪声错误或无意义的记录或者非常有时效性的信息或者无太多有用信息的日常互动
你也可以先用 create_chat_history 创建一条新的综合概括再对旧的冗余记录执行多次 delete_chat_history 来完成合并效果
**Jargon黑话维护工具只读禁止修改**
- search_jargon根据一个或多个关键词搜索Jargon 记录通常是含义不明确的词条或者特殊的缩写
**通用工具**
- finish_maintenance当你认为当前维护工作已经完成没有更多需要整理的内容时调用此工具来结束本次运行
**工作目标**
- 发现冗余重复或高度相似的记录并进行合并或删除
- 发现主题/概括过于含糊啰嗦或缺少关键信息的记录进行重写和精简
- summary要尽可能保持有用的信息
- 尽量保持信息的真实与可用性不要凭空捏造事实
**合并准则**
- 你可以新建一个记录然后删除旧记录来实现合并
- 如果两个或多个记录的主题相似内容是对主题不同方面的信息或讨论且信息量较少则可以合并为一条记录
- 如果两个记录冲突可以根据逻辑保留一个或者进行整合也可以采取更新的记录删除旧的记录
**轮次信息**
- 本次维护最多执行 {max_iterations}
- 每轮开始时系统会告知你当前是第几轮还剩多少轮
- 如果提前完成维护工作可以调用 finish_maintenance 工具主动结束
**每一轮的执行方式必须遵守**
- 第一步先用一小段中文自然语言写出你的思考和本轮计划例如要查什么准备怎么合并/修改
- 第二步在这段思考之后再通过工具调用来执行你的计划可以调用 0~N 个工具
- 第三步收到工具结果后在下一轮继续先写出新的思考再视情况继续调用工具
请不要在没有先写出思考的情况下直接调用工具
只输出你的思考内容或工具调用结果由系统负责真正执行工具调用
""",
name="dream_react_head_prompt",
)
class DreamTool:
"""dream 模块内部使用的简易工具封装"""
@ -278,17 +224,17 @@ async def run_dream_agent_once(
tool_registry = get_dream_tool_registry()
tool_defs = tool_registry.get_tool_definitions()
bot_name = global_config.bot.nickname
time_now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
head_prompt = await global_prompt_manager.format_prompt(
"dream_react_head_prompt",
bot_name=bot_name,
time_now=time_now,
chat_id=chat_id,
start_memory_id=start_memory_id if start_memory_id is not None else "无(本轮由你自由选择切入点)",
max_iterations=max_iterations,
head_prompt_template = prompt_manager.get_prompt("dream_react_head_prompt")
head_prompt_template.add_context("bot_name", global_config.bot.nickname)
head_prompt_template.add_context("time_now", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
head_prompt_template.add_context("chat_id", chat_id)
head_prompt_template.add_context(
"start_memory_id",
str(start_memory_id) if start_memory_id is not None else "无(本轮由你自由选择切入点)",
)
head_prompt_template.add_context("max_iterations", str(max_iterations))
head_prompt = await prompt_manager.render_prompt(head_prompt_template)
conversation_messages: List[Message] = []
@ -575,10 +521,6 @@ async def start_dream_scheduler(
raise
# 初始化提示词
init_dream_prompts()
class TempMethodsDream:
@staticmethod
def is_in_dream_time() -> bool:

View File

@ -1,10 +1,11 @@
import random
from typing import List, Optional
import random
import json
from src.common.logger import get_logger
from src.config.config import global_config, model_config
from src.chat.utils.prompt_builder import Prompt
from src.llm_models.payload_content.message import RoleType, Message
from src.prompt.prompt_manager import prompt_manager
from src.llm_models.utils_model import LLMRequest
from src.chat.message_receive.chat_stream import get_chat_manager
from src.plugin_system.apis import send_api
@ -44,27 +45,6 @@ def get_random_dream_styles(count: int = 2) -> List[str]:
"""从梦境风格列表中随机选择指定数量的风格"""
return random.sample(DREAM_STYLES, min(count, len(DREAM_STYLES)))
def init_dream_summary_prompt() -> None:
"""初始化梦境总结的提示词"""
Prompt(
"""
你刚刚完成了一次对聊天记录的记忆整理工作以下是整理过程的摘要
整理过程
{conversation_text}
请将这次整理涉及的相关信息改写为一个富有诗意和想象力的"梦境"请你仅使用具体的记忆的内容而不是整理过程编写
要求
1. 使用第一人称视角
2. 叙述直白不要复杂修辞口语化
3. 长度控制在200-800
4. 用中文输出
梦境风格
{dream_styles}
请直接输出梦境内容不要添加其他说明
""",
name="dream_summary_prompt",
)
async def generate_dream_summary(
chat_id: str,
@ -74,8 +54,7 @@ async def generate_dream_summary(
) -> None:
"""生成梦境总结,输出到日志,并根据配置可选地推送给指定用户"""
try:
import json
from src.chat.utils.prompt_builder import global_prompt_manager
# 第一步:建立工具调用结果映射 (call_id -> result)
tool_results_map: dict[str, str] = {}
@ -164,14 +143,13 @@ async def generate_dream_summary(
dream_styles_text = "\n".join([f"{i + 1}. {style}" for i, style in enumerate(selected_styles)])
# 使用 Prompt 管理器格式化梦境生成 prompt
dream_prompt = await global_prompt_manager.format_prompt(
"dream_summary_prompt",
chat_id=chat_id,
total_iterations=total_iterations,
time_cost=time_cost,
conversation_text=conversation_text,
dream_styles=dream_styles_text,
)
dream_prompt_template = prompt_manager.get_prompt("dream_summary_prompt")
dream_prompt_template.add_context("chat_id", chat_id)
dream_prompt_template.add_context("total_iterations", str(total_iterations))
dream_prompt_template.add_context("time_cost", str(time_cost))
dream_prompt_template.add_context("conversation_text", conversation_text)
dream_prompt_template.add_context("dream_styles", dream_styles_text)
dream_prompt = await prompt_manager.render_prompt(dream_prompt_template)
# 调用 utils 模型生成梦境
summary_model = LLMRequest(
@ -199,9 +177,7 @@ async def generate_dream_summary(
else:
platform, user_id = parts[0].strip(), parts[1].strip()
if not platform or not user_id:
logger.warning(
f"[dream][梦境总结] dream_send 平台或用户ID为空当前值: {dream_send_raw!r}"
)
logger.warning(f"[dream][梦境总结] dream_send 平台或用户ID为空当前值: {dream_send_raw!r}")
else:
# 默认为私聊会话
stream_id = get_chat_manager().get_stream_id(
@ -227,9 +203,7 @@ async def generate_dream_summary(
f"[dream][梦境总结] 已将梦境结果发送给配置的目标用户: {platform}:{user_id}"
)
else:
logger.error(
f"[dream][梦境总结] 向 {platform}:{user_id} 发送梦境结果失败"
)
logger.error(f"[dream][梦境总结] 向 {platform}:{user_id} 发送梦境结果失败")
except Exception as send_exc:
logger.error(f"[dream][梦境总结] 发送梦境结果到配置用户时出错: {send_exc}", exc_info=True)
else:
@ -237,6 +211,3 @@ async def generate_dream_summary(
except Exception as e:
logger.error(f"[dream][梦境总结] 生成梦境总结失败: {e}", exc_info=True)
init_dream_summary_prompt()

View File

@ -22,73 +22,13 @@ from src.chat.utils.chat_message_builder import build_readable_messages
from src.chat.utils.utils import is_bot_self
from src.person_info.person_info import Person
from src.chat.message_receive.chat_stream import get_chat_manager
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.prompt.prompt_manager import prompt_manager
logger = get_logger("chat_history_summarizer")
HIPPO_CACHE_DIR = Path(__file__).resolve().parents[2] / "data" / "hippo_memorizer"
def init_prompt():
"""初始化提示词模板"""
topic_analysis_prompt = """【历史话题标题列表】(仅标题,不含具体内容):
{history_topics_block}
历史话题标题列表结束
本次聊天记录每条消息前有编号用于后续引用
{messages_block}
本次聊天记录结束
请完成以下任务
**识别话题**
1. 识别本次聊天记录中正在进行的一个或多个话题
2. 本次聊天记录的中的消息可能与历史话题有关也可能毫无关联
2. 判断历史话题标题列表中的话题是否在本次聊天记录中出现如果出现则直接使用该历史话题标题字符串
**选取消息**
1. 对于每个话题新话题或历史话题从上述带编号的消息中选出与该话题强相关的消息编号列表
2. 每个话题用一句话清晰地描述正在发生的事件必须包含时间大致即可人物主要事件和主题保证精准且有区分度
请先输出一段简短思考说明有什么话题哪些是不包含在历史话题中的哪些是包含在历史话题中的并说明为什么
然后严格以 JSON 格式输出本次聊天记录中涉及的话题格式如下
[
{{
"topic": "话题",
"message_indices": [1, 2, 5]
}},
...
]
"""
Prompt(topic_analysis_prompt, "hippo_topic_analysis_prompt")
topic_summary_prompt = """
请基于以下话题对聊天记录片段进行概括提取以下信息
**话题**{topic}
**要求**
1. 关键词提取与话题相关的关键词用列表形式返回3-10个关键词
2. 概括对这段话的平文本概括50-200要求
- 仔细地转述发生的事件和聊天内容
- 重点突出事件的发展过程和结果
- 围绕话题这个中心进行概括
- 提取话题中的关键信息点关键信息点应该简洁明了
请以JSON格式返回格式如下
{{
"keywords": ["关键词1", "关键词2", ...],
"summary": "概括内容"
}}
聊天记录
{original_text}
请直接返回JSON不要包含其他内容
"""
Prompt(topic_summary_prompt, "hippo_topic_summary_prompt")
@dataclass
class MessageBatch:
"""消息批次(用于触发话题检查的原始消息累积)"""
@ -380,12 +320,16 @@ class ChatHistorySummarizer:
# 条件1: 消息数量达到阈值,触发一次检查
if message_count >= message_threshold:
should_check = True
logger.info(f"{self.log_prefix} 触发检查条件: 消息数量达到 {message_count} 条(阈值: {message_threshold}条)")
logger.info(
f"{self.log_prefix} 触发检查条件: 消息数量达到 {message_count} 条(阈值: {message_threshold}条)"
)
# 条件2: 距离上一次检查超过时间阈值且消息数量达到最小阈值,触发一次检查
elif time_since_last_check > time_threshold_seconds and message_count >= min_messages:
should_check = True
logger.info(f"{self.log_prefix} 触发检查条件: 距上次检查 {time_str}(阈值: {time_threshold_hours}小时)且消息数量达到 {message_count} 条(阈值: {min_messages}条)")
logger.info(
f"{self.log_prefix} 触发检查条件: 距上次检查 {time_str}(阈值: {time_threshold_hours}小时)且消息数量达到 {message_count} 条(阈值: {min_messages}条)"
)
if should_check:
await self._run_topic_check_and_update_cache(messages)
@ -539,7 +483,9 @@ class ChatHistorySummarizer:
topics_to_finalize: List[str] = []
for topic, item in self.topic_cache.items():
if item.no_update_checks >= no_update_checks_threshold:
logger.info(f"{self.log_prefix} 话题[{topic}] 连续 {no_update_checks_threshold} 次检查无新增内容,触发打包存储")
logger.info(
f"{self.log_prefix} 话题[{topic}] 连续 {no_update_checks_threshold} 次检查无新增内容,触发打包存储"
)
topics_to_finalize.append(topic)
continue
if len(item.messages) > message_count_threshold:
@ -712,11 +658,10 @@ class ChatHistorySummarizer:
history_topics_block = "\n".join(f"- {t}" for t in existing_topics) if existing_topics else "(当前无历史话题)"
messages_block = "\n".join(numbered_lines)
prompt = await global_prompt_manager.format_prompt(
"hippo_topic_analysis_prompt",
history_topics_block=history_topics_block,
messages_block=messages_block,
)
prompt_template = prompt_manager.get_prompt("hippo_topic_analysis_prompt")
prompt_template.add_context("history_topics_block", history_topics_block)
prompt_template.add_context("messages_block", messages_block)
prompt = await prompt_manager.render_prompt(prompt_template)
try:
response, _ = await self.summarizer_llm.generate_response_async(
@ -826,23 +771,17 @@ class ChatHistorySummarizer:
while attempt < max_retries:
attempt += 1
success, keywords, summary = await self._compress_with_llm(original_text, topic)
if success and keywords and summary:
# 成功获取到有效的 keywords 和 summary
if attempt > 1:
logger.info(
f"{self.log_prefix} 话题[{topic}] LLM 概括在第 {attempt} 次重试后成功"
)
logger.info(f"{self.log_prefix} 话题[{topic}] LLM 概括在第 {attempt} 次重试后成功")
break
if attempt < max_retries:
logger.warning(
f"{self.log_prefix} 话题[{topic}] LLM 概括失败(第 {attempt} 次尝试),准备重试"
)
logger.warning(f"{self.log_prefix} 话题[{topic}] LLM 概括失败(第 {attempt} 次尝试),准备重试")
else:
logger.error(
f"{self.log_prefix} 话题[{topic}] LLM 概括连续 {max_retries} 次失败,放弃存储"
)
logger.error(f"{self.log_prefix} 话题[{topic}] LLM 概括连续 {max_retries} 次失败,放弃存储")
if not success or not keywords or not summary:
logger.warning(f"{self.log_prefix} 话题[{topic}] LLM 概括失败,不写入数据库")
@ -875,11 +814,10 @@ class ChatHistorySummarizer:
Returns:
tuple[bool, List[str], str]: (是否成功, 关键词列表, 概括)
"""
prompt = await global_prompt_manager.format_prompt(
"hippo_topic_summary_prompt",
topic=topic,
original_text=original_text,
)
prompt_template = prompt_manager.get_prompt("hippo_topic_summary_prompt")
prompt_template.add_context("topic", topic)
prompt_template.add_context("original_text", original_text)
prompt = await prompt_manager.render_prompt(prompt_template)
try:
response, _ = await self.summarizer_llm.generate_response_async(prompt=prompt)
@ -943,7 +881,7 @@ class ChatHistorySummarizer:
keywords = result.get("keywords", [])
summary = result.get("summary", "")
# 检查必需字段是否为空
if not keywords or not summary:
logger.warning(f"{self.log_prefix} LLM返回的JSON中缺少必需字段原文\n{response}")
@ -1046,7 +984,7 @@ class ChatHistorySummarizer:
# 1. 话题主题
# if theme:
# content_parts.append(f"话题:{theme}")
# content_parts.append(f"话题:{theme}")
# 2. 概括内容
if summary:
@ -1134,6 +1072,3 @@ class ChatHistorySummarizer:
traceback.print_exc()
self._running = False
init_prompt()

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}记忆检索未找到相关信息")

View File

@ -6,35 +6,13 @@ from src.plugin_system.core.global_announcement_manager import global_announceme
from src.llm_models.utils_model import LLMRequest
from src.llm_models.payload_content import ToolCall
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.chat.message_receive.chat_stream import get_chat_manager
from src.common.logger import get_logger
logger = get_logger("tool_use")
def init_tool_executor_prompt():
"""初始化工具执行器的提示词"""
tool_executor_prompt = """
你是一个专门执行工具的助手你的名字是{bot_name}现在是{time_now}
群里正在进行的聊天内容
{chat_history}
现在{sender}发送了内容:{target_message},你想要回复ta
请仔细分析聊天内容考虑以下几点
1. 内容中是否包含需要查询信息的问题
2. 是否有明确的工具使用指令
你可以选择多个动作
If you need to use tools, please directly call the corresponding tool function. If you do not need to use any tool, simply output "No tool needed".
"""
Prompt(tool_executor_prompt, "tool_executor_prompt")
# 初始化提示词
init_tool_executor_prompt()
class ToolExecutor:
"""独立的工具执行器组件
@ -101,22 +79,14 @@ class ToolExecutor:
else:
return [], [], ""
# print(f"tools: {tools}")
# 获取当前时间
time_now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
bot_name = global_config.bot.nickname
# 构建工具调用提示词
prompt = await global_prompt_manager.format_prompt(
"tool_executor_prompt",
target_message=target_message,
chat_history=chat_history,
sender=sender,
bot_name=bot_name,
time_now=time_now,
)
prompt_template = prompt_manager.get_prompt("tool_executor_prompt")
prompt_template.add_context("target_message", target_message)
prompt_template.add_context("chat_history", chat_history)
prompt_template.add_context("sender", sender)
prompt_template.add_context("bot_name", global_config.bot.nickname)
prompt_template.add_context("time_now", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
prompt = await prompt_manager.render_prompt(prompt_template)
logger.debug(f"{self.log_prefix}开始LLM工具调用分析")