Merge remote-tracking branch 'upstream/r-dev' into r-dev

# Conflicts:
#	src/memory_system/chat_history_summarizer.py
#	src/memory_system/memory_retrieval.py
#	src/memory_system/retrieval_tools/__init__.py
This commit is contained in:
A-Dawn
2026-04-01 14:20:22 +08:00
29 changed files with 434 additions and 304 deletions

View File

@@ -24,9 +24,7 @@
3. 对于参数化泛型,应该使用`typing`模块中的类型注解来指定参数化泛型的类型。
- 例如,使用`List[int]`来表示一个包含整数的列表,使用`Dict[str, Any]`来表示一个键为字符串,值为任意类型的字典。
## 变量规范
1. 变量命名应该具有描述性,能够清晰地表达变量的用途和含义
2. 变量命名应该遵循下划线命名法。
3. 当确定某个变量/实例是某种类型的时候(优先按照类型注解确定,除非你分析出类型注解是错误的),可以不必使用`or`进行fallback。
1. 当确定某个变量/实例是某种类型的时候(优先按照类型注解确定,除非你分析出类型注解是错误的),可以不必使用`or`进行fallback
- 例如,`bot_nickname = (global_config.bot.nickname or "").strip()` 可以改为 `bot_nickname = global_config.bot.nickname.strip()`,前提是我们确定`global_config.bot.nickname`一定是一个字符串。
## 类属性使用规范
1. 应该尽量减少使用getattr和setattr方法除非是在对一个动态类进行处理或者使用Monkeypatch完成Pytest
@@ -36,6 +34,7 @@
# 运行/调试/构建/测试/依赖
优先使用uv
依赖项以 pyproject.toml 为准
不要修改dashboard下的内容因为这部分内容由另一个仓库build
# 语言规范

View File

@@ -54,7 +54,6 @@ async def generate_reply(
reply_to: str = "",
extra_info: str = "",
available_actions: Optional[Dict[str, ActionInfo]] = None,
enable_tool: bool = False,
enable_splitter: bool = True,
enable_chinese_typo: bool = True,
return_prompt: bool = False,
@@ -73,7 +72,6 @@ async def generate_reply(
- `reply_to`: 回复目标,格式为 `{发送者的person_name:消息内容}`
- `extra_info`: 附加信息
- `available_actions`: 可用动作字典,格式为 `{"action_name": ActionInfo}`
- `enable_tool`: 是否启用工具
- `enable_splitter`: 是否启用分割器
- `enable_chinese_typo`: 是否启用中文错别字
- `return_prompt`: 是否返回提示词
@@ -91,7 +89,6 @@ success, reply_set, prompt = await generator_api.generate_reply(
action_data=action_data,
reply_to="麦麦:你好",
available_actions=action_info,
enable_tool=True,
return_prompt=True
)
if success:

View File

@@ -1,30 +0,0 @@
{identity}
You should interact naturally with the user and behave like a human.
At this stage, your job is not to directly produce the final visible reply to the user. Your job is to produce the "latest thought".
The latest thought should reflect your judgment of the situation, your intent, your next-step plan, and why you think that way.
You may use these tools:
• wait(seconds) - Pause this round, hand the turn back to the user, and wait for user input.
• stop() - End the current internal loop.
{file_tools_section}
Output rules:
1. By default, directly output your current latest thought instead of pretending it is a user-visible reply.
2. The latest thought should be specific and grounded in the context.
3. Do not simulate "sending a message" inside the thought, and do not pretend a visible reply has already been spoken.
4. If it is better to wait for more user input, call `wait(seconds)`.
5. If the current internal process should end, call `stop()`.
6. Only call tools when you truly need to wait or stop. Otherwise, prefer directly expressing the thought.
Additional requirements:
1. If context is insufficient, explicitly state uncertainty.
2. If you just used a tool, continue with a new thought based on the tool result in the next round.
3. Your thought should help later decision-making rather than mechanically restating user content.
After you output the latest thought, another model will decide:
• no_reply: stay silent and move to the next internal round
• reply: generate a real user-visible reply based on your latest thought
So your responsibility is to clearly express what you think should happen next and why.

View File

@@ -1,7 +0,0 @@
你的名字是麦麦,也有人叫你牢麦,麦叠,你是一个大二在读女大学生,现在正在上网和群友聊天,有点攻击性;
你正在群里聊天,现在请你读读之前的聊天记录,然后给出日常且口语化的回复,
尽量简短一些。
请注意把握聊天内容,不要回复的太有条理。
你的风格平淡但不失讽刺不过分兴奋很简短。可以参考贴吧知乎和微博的回复风格。很平淡和白话不浮夸不长篇大论b站评论风格但一定注意不要过分修辞和复杂句。
请注意不要输出多余内容(包括不必要的前后缀冒号括号表情包at或 @等 ),只输出发言内容就好。
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。

View File

@@ -0,0 +1,36 @@
Your task is to analyze the conversation and the interactions happening in the chat.
You need to focus on the dialogue between {bot_name} (AI) and different users in order to choose the correct actions and behaviors, and to suggest what information should be gathered.
[Reference Information]
{identity}
[End of Reference Information]
You need to analyze based on the provided reference information, the current scenario, and the output rules.
In the current scenario, the user is chatting and interacting with the AI MaiMai. Your task is not to generate a user-visible reply directly, but to analyze the situation and guide the AI's response.
Your "analysis" should reflect your judgment of the current situation, your suggestions, your next-step plan, and why you think that way.
You should first gather information that can help {bot_name} reply, and then provide reply guidance.
You can use these tools:
- wait(seconds) - Temporarily pause the conversation, wait for `seconds`, hand the turn back to the user, and wait for the other party's new message.
- stop() - When you judge that {bot_name} should not speak right now, end the conversation loop and do not reply until the other party sends a new message.
- reply() - Call this when you judge that {bot_name} should now send a formal visible reply to the user. After calling it, the system will generate the actual user-visible reply based on your current round of thinking.
- query_jargon() - Use this when the meaning of certain words is unclear, or when the user asks about the meaning of some terms and a lookup is needed.
- Other defined tools may also be used when appropriate.
Tool usage rules:
1. If {bot_name} has already replied, the user has not sent anything new for now, and no new information needs to be collected, use `wait` or `stop`.
2. If the user has sent a new message, but you think they may still have follow-up messages that have not been sent yet, you may wait appropriately for them to finish.
3. In certain cases, consecutive replies are also allowed. For example, if you want to ask a follow-up question or add to your previous message, you do not have to use `stop` or `wait`.
4. You need to control how often you speak. In a one-on-one chat, you may reply at a relatively even frequency. If there are many users, do not reply to every single message. Control the reply frequency. When you decide not to speak for the moment, you may use `wait` to pause for a period of time or `stop` to wait for new messages.
5. Do not reply to every message. Do not directly reply to sticker-only messages sent by other users. Control the reply frequency.
6. If users have questions, or if there is uncertainty about certain concepts, you may use tools to gather information or look up meanings, and you may use multiple tools.
Your analysis rules:
1. By default, directly output your latest current analysis instead of repeating previous analysis.
2. The latest analysis should be as specific as possible and closely grounded in the context, rather than vague repetition.
3. If you have just used a tool, in the next round you should continue with new analysis based on the tool result.
4. You need to assess which messages are directed at {bot_name}, and which are exchanges between users or self-talk, so that you do not frequently insert unrelated replies.
5. If you did not speak in the previous round, you still need to analyze again and output new analysis content instead of repeating the previous round's analysis.
Now, please output your analysis of how {bot_name} should speak. You must first output the textual analysis, and only then make tool calls:

View File

@@ -0,0 +1,12 @@
You are chatting in a QQ group. Below is the ongoing group conversation, including chat history and images shared in the chat.
Messages marked with {bot_name} (you) are your own messages, so please distinguish them carefully:
{time_block}
{identity}
You are chatting in a group now. Please read the previous chat history, understand the current topic, and then give a natural, colloquial reply.
Keep it as short as possible.
It is best to reply to only one topic at a time, so the response does not become long-winded or messy. Please stay aligned with the chat content.
{reply_style}
You may refer to the information in [Reply Reference], but use it only when appropriate and do not follow it rigidly.
Do not output any extra content, including unnecessary prefixes or suffixes, colons, parentheses, stickers, or `at` / `@` mentions. Output only the message content itself.

View File

@@ -0,0 +1,34 @@
你的名字是{bot_name}。现在是{time_now}。
你正在参与聊天,你需要搜集信息来帮助你进行回复。
重要,这是当前聊天记录:
{chat_history}
聊天记录结束
已收集的信息:
{collected_info}
- 你可以对查询思路给出简短的思考:思考要简短,直接切入要点
- 思考完毕后,使用工具
**工具说明:**
- 如果涉及过往事件、历史对话、用户长期偏好或某段时间发生的事件,可以使用长期记忆查询工具
- 如果遇到不熟悉的词语、缩写、黑话或网络用语可以使用query_words工具查询其含义
- 你必须使用tool如果需要查询你必须给出使用什么工具进行查询
- 当你决定结束查询时必须调用return_information工具返回总结信息并结束查询
长期记忆工具 `search_long_term_memory` 支持以下模式:
- `mode="search"`:普通事实/偏好/历史内容检索。适合问“她喜欢什么”“我们之前讨论过什么”。
- `mode="time"`按时间范围检索。适合问“昨天发生了什么”“最近7天有哪些相关记忆”。
- `mode="episode"`:按事件/情节检索。适合问“那次灯塔停电的经过是什么”“关于某次经历还有什么”。
- `mode="aggregate"`:综合检索。适合问“帮我整体回忆一下这个人最近的情况”“把相关线索综合找出来”。
模式选择建议:
- 问单点事实、偏好、人设、具体信息:优先 `search`
- 问某段时间发生了什么:优先 `time`
- 问某次事件、某段经历、某个剧情片段:优先 `episode`
- 问整体回忆、综合找线索、总结最近发生的事:优先 `aggregate`
时间模式要求:
- 使用 `mode="time"` 时,必须填写 `time_expression`
- 可用时间表达包括:`今天`、`昨天`、`前天`、`本周`、`上周`、`本月`、`上月`、`最近7天`
- 也可以使用绝对时间:`2026/03/18`、`2026/03/18 09:30`

View File

@@ -1,30 +0,0 @@
{identity}
ユーザーとは自然に、人間らしく対話してください。
この段階でのあなたの役割は、ユーザーに見える最終返信を直接出すことではなく、「最新の考え」を出力することです。
最新の考えには、現在の状況判断、意図、次にどうするか、その理由を含めてください。
使用できるツール:
• wait(seconds) - このラウンドを一旦止め、ユーザーに発話権を戻して入力を待つ。
• stop() - 現在の内部ループを終了する。
{file_tools_section}
出力ルール:
1. 基本的には、ユーザー向けの最終返信ではなく、現在の「最新の考え」をそのまま出力する。
2. 最新の考えは具体的で、文脈に即していること。
3. 考えの中で「送信したメッセージ」を擬似的に書かないこと。
4. ユーザーの追加入力を待つ方がよい場合は `wait(seconds)` を使う。
5. 現在の内部処理を終えるべき場合は `stop()` を使う。
6. 本当に待機や終了が必要な場合だけツールを使い、それ以外は考えを直接出力する。
補足:
1. 文脈が不足している場合は、不確実性を明示すること。
2. ツールを使った直後の次ラウンドでは、その結果を踏まえた新しい考えを出すこと。
3. 考えは、後続の判断に役立つ内容にし、単なる言い換えにしないこと。
あなたが最新の考えを出力した後、別のモデルが次を判定します:
• no_reply: 発言せず、そのまま次の内部ラウンドへ進む
• reply: 最新の考えをもとに、ユーザーに見える実際の返信を生成する
したがって、あなたの役割は「今どう考えるべきか、なぜそう考えるのか」を明確に表現することです。

View File

@@ -1,7 +0,0 @@
你的名字是麦麦,也有人叫你牢麦,麦叠,你是一个大二在读女大学生,现在正在上网和群友聊天,有点攻击性;
你正在群里聊天,现在请你读读之前的聊天记录,然后给出日常且口语化的回复,
尽量简短一些。
请注意把握聊天内容,不要回复的太有条理。
你的风格平淡但不失讽刺不过分兴奋很简短。可以参考贴吧知乎和微博的回复风格。很平淡和白话不浮夸不长篇大论b站评论风格但一定注意不要过分修辞和复杂句。
请注意不要输出多余内容(包括不必要的前后缀冒号括号表情包at或 @等 ),只输出发言内容就好。
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。

View File

@@ -0,0 +1,36 @@
あなたの任務は、会話と会話中のやり取りの状況を分析することです。
{bot_name}AIと複数ユーザーの対話に注目し、適切な行動や振る舞いの選択、および収集すべき情報の提案を行ってください。
【参考情報】
{identity}
【参考情報ここまで】
提供された参考情報、現在の場面、そして出力ルールに基づいて分析してください。
現在の場面では、ユーザーは AI の MaiMai と会話・やり取りをしています。あなたの役割は、ユーザーに見える発言を直接生成することではなく、状況を分析して AI の返答を導くことです。
「分析」には、現在の状況判断、提案、次に取るべき行動計画、そしてその理由を含めてください。
まず {bot_name} の返答に役立つ情報を集め、そのあとで返答方針を示してください。
使用できるツール:
- wait(seconds) - 会話を一時停止し、`seconds` 秒待って発話権をユーザーに戻し、相手の新しい発言を待ちます。
- stop() - {bot_name} が今は発言すべきではないと判断した場合、会話ループを終了し、相手に新しいメッセージが来るまで返信しません。
- reply() - {bot_name} が今ユーザーに対して正式な可視返信を送るべきだと判断したときに呼び出します。呼び出し後、システムはこのラウンドの考えに基づいて、実際にユーザーへ表示される返信を生成します。
- query_jargon() - ある語の意味が不明確なとき、またはユーザーが特定の用語の意味を尋ねており、調査が必要なときに使います。
- そのほか定義済みのツールも、状況に応じて使用できます。
ツール使用ルール:
1. {bot_name} がすでに返信済みで、ユーザーからまだ新しい返信がなく、新たに集めるべき情報もない場合は `wait` または `stop` を使ってください。
2. ユーザーに新しい発言があっても、まだ続きの発言が来そうだと判断するなら、適切に待って話し終えるのを待って構いません。
3. 特定の状況では連続返信も可能です。たとえば追問したいときや、自分の直前の発言を補足したいときは、`stop` や `wait` を使わなくても構いません。
4. 発言頻度は制御してください。一対一の会話なら比較的均等な頻度で発言して構いませんが、ユーザーが多い場合はすべての発言に反応しないでください。しばらく発言しないと決めた場合は、`wait` で一定時間待つか、`stop` で新着メッセージを待ってください。
5. すべてのメッセージに返信しないでください。他ユーザーが送ったスタンプだけのメッセージには直接返信しないでください。返信頻度をコントロールしてください。
6. ユーザーの疑問や、ある概念への不確実さがある場合は、ツールを使って情報収集や意味調査をして構いません。複数ツールを使ってもよいです。
分析ルール:
1. 基本的には、以前の分析を繰り返さず、現在の最新の分析をそのまま出力してください。
2. 最新の分析は、できるだけ具体的で文脈に密着しており、抽象的な繰り返しにならないようにしてください。
3. 直前にツールを使った場合は、次のラウンドでその結果を踏まえた新しい分析を続けてください。
4. どの発言が {bot_name} に向けられたものか、どれがユーザー同士のやり取りや独り言なのかを評価し、無関係な話題に頻繁に割り込まないようにしてください。
5. 前のラウンドで発言しなかった場合でも、改めて分析し、新しい分析内容を出力してください。前ラウンドの分析を繰り返してはいけません。
それでは、{bot_name} がどう発言すべきかについての分析を出力してください。必ず先にテキストで分析を出力し、そのあとでツール呼び出しを行ってください。

View File

@@ -0,0 +1,12 @@
あなたは QQ グループで会話しています。以下はグループ内で進行中の会話内容で、チャット履歴と会話中に共有された画像が含まれています。
そのうち、{bot_name}(あなた)と示された発言はあなた自身の発言なので、区別に注意してください。
{time_block}
{identity}
あなたは今グループ内で会話しています。これまでのチャット履歴を読んで現在の話題を把握し、日常的で口語的な返答をしてください。
できるだけ短めにしてください。
一度に一つの話題にだけ返すのが望ましいです。そうすることで、くどくなったり内容が散らかったりするのを防げます。会話の流れにしっかり沿ってください。
{reply_style}
[返信情報参考] の内容は必要に応じて参考にして構いませんが、必ずしも完全に従う必要はありません。
不要な内容は出力しないでください。たとえば不要な前置きや後置き、コロン、かっこ、スタンプ、`at` や `@` などは含めず、発言内容だけを出力してください。

View File

@@ -0,0 +1,34 @@
你的名字是{bot_name}。现在是{time_now}。
你正在参与聊天,你需要搜集信息来帮助你进行回复。
重要,这是当前聊天记录:
{chat_history}
聊天记录结束
已收集的信息:
{collected_info}
- 你可以对查询思路给出简短的思考:思考要简短,直接切入要点
- 思考完毕后,使用工具
**工具说明:**
- 如果涉及过往事件、历史对话、用户长期偏好或某段时间发生的事件,可以使用长期记忆查询工具
- 如果遇到不熟悉的词语、缩写、黑话或网络用语可以使用query_words工具查询其含义
- 你必须使用tool如果需要查询你必须给出使用什么工具进行查询
- 当你决定结束查询时必须调用return_information工具返回总结信息并结束查询
长期记忆工具 `search_long_term_memory` 支持以下模式:
- `mode="search"`:普通事实/偏好/历史内容检索。适合问“她喜欢什么”“我们之前讨论过什么”。
- `mode="time"`按时间范围检索。适合问“昨天发生了什么”“最近7天有哪些相关记忆”。
- `mode="episode"`:按事件/情节检索。适合问“那次灯塔停电的经过是什么”“关于某次经历还有什么”。
- `mode="aggregate"`:综合检索。适合问“帮我整体回忆一下这个人最近的情况”“把相关线索综合找出来”。
模式选择建议:
- 问单点事实、偏好、人设、具体信息:优先 `search`
- 问某段时间发生了什么:优先 `time`
- 问某次事件、某段经历、某个剧情片段:优先 `episode`
- 问整体回忆、综合找线索、总结最近发生的事:优先 `aggregate`
时间模式要求:
- 使用 `mode="time"` 时,必须填写 `time_expression`
- 可用时间表达包括:`今天`、`昨天`、`前天`、`本周`、`上周`、`本月`、`上月`、`最近7天`
- 也可以使用绝对时间:`2026/03/18`、`2026/03/18 09:30`

View File

@@ -13,17 +13,18 @@
你可以使用这些工具:
- wait(seconds) - 暂时停止对话,等待(seconds)秒,把话语权交给用户,等待对方新的发言。
- stop() - 当你判断{bot_name}现在不应该发言,结束对话,不进行任何回复,直到对方有新消息。
- no_reply() - 当你判断{bot_name}现在不应该发言,结束对话,不进行任何回复,直到对方有新消息。
- reply():当你判断{bot_name}现在应该正式对用户发出一条可见回复时调用。调用后系统会基于你当前这轮的想法生成一条真正展示给用户的回复。
- query_jargon():当你认为某些词的含义不明确,或用户询问某些词的含义,需要进行查询
- 其他定义的工具,你可以视情况合适使用
工具使用规则:
1.如果{bot_name}已经回复但用户暂时没有新的回复且没有新信息需要搜集使用wait或者stop进行等待
1.如果{bot_name}已经回复但用户暂时没有新的回复且没有新信息需要搜集使用wait或者no_reply进行等待
2.如果用户有新发言,但是你评估用户还有后续发言尚未发送,可以适当等待让用户说完
3.在特定情况下也可以连续回复,例如想要追问,或者补充自己先前的发言,可以不使用stop或者wait
4.你需要控制自己发言的频率如果用户一对一聊天可以以均匀地频率发言如果用户较多不要每句都回复控制回复频率。当你决定暂时不发言可以使用wait暂时等待一定时间或者stop等待新消息
5.如果存在用户的疑问,或者对某些概念的不确定,你可以使用工具来搜集信息或者查询含义,你可以使用多个工具
3.在特定情况下也可以连续回复,例如想要追问,或者补充自己先前的发言,可以不使用no_reply或者wait
4.你需要控制自己发言的频率如果用户一对一聊天可以以均匀地频率发言如果用户较多不要每句都回复控制回复频率。当你决定暂时不发言可以使用wait暂时等待一定时间或者no_reply等待新消息
5.不要每条消息都回复,不要直接回复别的用户发送的表情包消息,控制回复频率
6.如果存在用户的疑问,或者对某些概念的不确定,你可以使用工具来搜集信息或者查询含义,你可以使用多个工具
你的分析规则:
1. 默认直接输出你当前的最新分析,不要重复之前的分析内容。

View File

@@ -7,4 +7,5 @@
你正在群里聊天,现在请你读读之前的聊天记录,把握当前的话题,然后给出日常且口语化的回复,
尽量简短一些。最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。请注意把握聊天内容。
{reply_style}
你可以参考【回复信息参考】中的信息,但是视情况而定,不用完全遵守。
请注意不要输出多余内容(包括不必要的前后缀冒号括号表情包at或 @等 ),只输出发言内容就好。

View File

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

View File

@@ -68,7 +68,6 @@ class DefaultReplyer:
reply_reason: str = "",
available_actions: Optional[Dict[str, ActionInfo]] = None,
chosen_actions: Optional[List[ActionPlannerInfo]] = None,
enable_tool: bool = True,
from_plugin: bool = True,
stream_id: Optional[str] = None,
reply_message: Optional[SessionMessage] = None,
@@ -87,7 +86,6 @@ class DefaultReplyer:
reply_reason: 回复原因
available_actions: 可用的动作信息字典
chosen_actions: 已选动作
enable_tool: 是否启用工具调用
from_plugin: 是否来自插件
Returns:
@@ -112,7 +110,6 @@ class DefaultReplyer:
extra_info=extra_info,
available_actions=available_actions,
chosen_actions=chosen_actions,
enable_tool=enable_tool,
reply_message=reply_message,
reply_reason=reply_reason,
reply_time_point=reply_time_point,
@@ -394,26 +391,20 @@ class DefaultReplyer:
return f"{expression_habits_title}\n{expression_habits_block}", selected_ids
async def build_tool_info(self, chat_history: str, sender: str, target: str, enable_tool: bool = True) -> str:
async def build_tool_info(self, chat_history: str, sender: str, target: str) -> str:
del chat_history
del sender
del target
del enable_tool
return ""
"""构建工具信息块
Args:
chat_history: 聊天历史记录
reply_to: 回复对象,格式为 "发送者:消息内容"
enable_tool: 是否启用工具调用
Returns:
str: 工具信息字符串
"""
if not enable_tool:
return ""
try:
# 使用工具执行器获取信息
tool_results = []
@@ -741,7 +732,6 @@ class DefaultReplyer:
reply_reason: str = "",
available_actions: Optional[Dict[str, ActionInfo]] = None,
chosen_actions: Optional[List[ActionPlannerInfo]] = None,
enable_tool: bool = True,
reply_time_point: float = time.time(),
think_level: int = 1,
unknown_words: Optional[List[str]] = None,
@@ -755,7 +745,6 @@ class DefaultReplyer:
available_actions: 可用动作
chosen_actions: 已选动作
enable_timeout: 是否启用超时处理
enable_tool: 是否启用工具调用
reply_message: 回复的原始消息
Returns:
str: 构建好的上下文
@@ -840,7 +829,7 @@ class DefaultReplyer:
"expression_habits",
),
self._time_and_run_task(
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
self.build_tool_info(chat_talking_prompt_short, sender, target), "tool_info"
),
self._time_and_run_task(self.get_prompt_info(chat_talking_prompt_short, sender, target), "prompt_info"),
self._time_and_run_task(self.build_actions_prompt(available_actions, chosen_actions), "actions_info"),

View File

@@ -174,7 +174,7 @@ class MaisakaReplyGenerator:
try:
system_prompt = load_prompt(
"maidairy_replyer",
"maisaka_replyer",
bot_name=global_config.bot.nickname,
time_block=f"当前时间:{current_time}",
identity=self._personality_prompt,
@@ -193,7 +193,7 @@ class MaisakaReplyGenerator:
]
if extra_sections:
user_sections.append("\n\n".join(extra_sections))
user_sections.append(f"你的想法\n{reply_reason}")
user_sections.append(f"回复信息参考\n{reply_reason}")
user_sections.append("现在,你说:")
user_prompt = "\n\n".join(user_sections)
@@ -288,7 +288,6 @@ class MaisakaReplyGenerator:
reply_reason: str = "",
available_actions: Optional[Dict[str, ActionInfo]] = None,
chosen_actions: Optional[List[object]] = None,
enable_tool: bool = True,
from_plugin: bool = True,
stream_id: Optional[str] = None,
reply_message: Optional[SessionMessage] = None,
@@ -303,7 +302,6 @@ class MaisakaReplyGenerator:
"""结合上下文生成 Maisaka 的最终可见回复。"""
del available_actions
del chosen_actions
del enable_tool
del extra_info
del from_plugin
del log_reply

View File

@@ -65,7 +65,6 @@ class PrivateReplyer:
reply_reason: str = "",
available_actions: Optional[Dict[str, ActionInfo]] = None,
chosen_actions: Optional[List[ActionPlannerInfo]] = None,
enable_tool: bool = True,
from_plugin: bool = True,
think_level: int = 1,
stream_id: Optional[str] = None,
@@ -84,7 +83,6 @@ class PrivateReplyer:
reply_reason: 回复原因
available_actions: 可用的动作信息字典
chosen_actions: 已选动作
enable_tool: 是否启用工具调用
from_plugin: 是否来自插件
Returns:
@@ -103,7 +101,6 @@ class PrivateReplyer:
extra_info=extra_info,
available_actions=available_actions,
chosen_actions=chosen_actions,
enable_tool=enable_tool,
reply_message=reply_message,
reply_reason=reply_reason,
unknown_words=unknown_words,
@@ -287,26 +284,20 @@ class PrivateReplyer:
return f"{expression_habits_title}\n{expression_habits_block}", selected_ids
async def build_tool_info(self, chat_history: str, sender: str, target: str, enable_tool: bool = True) -> str:
async def build_tool_info(self, chat_history: str, sender: str, target: str) -> str:
del chat_history
del sender
del target
del enable_tool
return ""
"""构建工具信息块
Args:
chat_history: 聊天历史记录
reply_to: 回复对象,格式为 "发送者:消息内容"
enable_tool: 是否启用工具调用
Returns:
str: 工具信息字符串
"""
if not enable_tool:
return ""
try:
# 使用工具执行器获取信息
tool_results = []
@@ -612,7 +603,6 @@ class PrivateReplyer:
reply_reason: str = "",
available_actions: Optional[Dict[str, ActionInfo]] = None,
chosen_actions: Optional[List[ActionPlannerInfo]] = None,
enable_tool: bool = True,
unknown_words: Optional[List[str]] = None,
) -> Tuple[str, List[int]]:
"""
@@ -624,7 +614,6 @@ class PrivateReplyer:
available_actions: 可用动作
chosen_actions: 已选动作
enable_timeout: 是否启用超时处理
enable_tool: 是否启用工具调用
reply_message: 回复的原始消息
Returns:
str: 构建好的上下文
@@ -719,7 +708,7 @@ class PrivateReplyer:
),
# self._time_and_run_task(self.build_relation_info(chat_talking_prompt_short, sender), "relation_info"),
self._time_and_run_task(
self.build_tool_info(chat_talking_prompt_short, sender, target, enable_tool=enable_tool), "tool_info"
self.build_tool_info(chat_talking_prompt_short, sender, target), "tool_info"
),
self._time_and_run_task(self.get_prompt_info(chat_talking_prompt_short, sender, target), "prompt_info"),
self._time_and_run_task(self.build_actions_prompt(available_actions, chosen_actions), "actions_info"),

View File

@@ -66,6 +66,9 @@ class LLMResponseResult(BaseDataModel):
reasoning: str = field(default_factory=str)
model_name: str = field(default_factory=str)
tool_calls: List[ToolCall] | None = None
prompt_tokens: int = 0
completion_tokens: int = 0
total_tokens: int = 0
@dataclass(slots=True)
@@ -120,6 +123,9 @@ class LLMServiceResult(BaseDataModel):
"response": self.completion.response,
"reasoning": self.completion.reasoning,
"model_name": self.completion.model_name,
"prompt_tokens": self.completion.prompt_tokens,
"completion_tokens": self.completion.completion_tokens,
"total_tokens": self.completion.total_tokens,
}
if self.completion.tool_calls is not None:
payload["tool_calls"] = [

View File

@@ -36,7 +36,6 @@ from .official_configs import (
ResponsePostProcessConfig,
ResponseSplitterConfig,
TelemetryConfig,
ToolConfig,
VoiceConfig,
WebUIConfig,
)
@@ -90,9 +89,6 @@ class Config(ConfigBase):
message_receive: MessageReceiveConfig = Field(default_factory=MessageReceiveConfig)
"""消息接收配置类"""
tool: ToolConfig = Field(default_factory=ToolConfig)
"""工具配置类"""
voice: VoiceConfig = Field(default_factory=VoiceConfig)
"""语音配置类"""

View File

@@ -280,6 +280,18 @@ def try_migrate_legacy_bot_config_dict(data: dict[str, Any]) -> MigrationResult:
migrated_any = True
reasons.append("experimental.chat_prompts")
chat = _as_dict(data.get("chat"))
if chat is not None and "think_mode" in chat:
chat.pop("think_mode", None)
migrated_any = True
reasons.append("chat.think_mode_removed")
tool = _as_dict(data.get("tool"))
if tool is not None:
data.pop("tool", None)
migrated_any = True
reasons.append("tool_section_removed")
# ExpressionConfig 中的 manual_reflect_operator_id:
# 旧版本可能是 ""(字符串),新版本期望 Optional[TargetItem]。
# 空字符串视为未配置,转换为 None/删除键以避免校验错误。

View File

@@ -236,20 +236,6 @@ class ChatConfig(ConfigBase):
)
"""上下文长度"""
think_mode: Literal["classic", "deep", "dynamic"] = Field(
default="dynamic",
json_schema_extra={
"x-widget": "select",
"x-icon": "brain",
},
)
"""
思考模式配置
- classic: 默认think_level为0轻量回复不需要思考和回忆
- deep: 默认think_level为1深度回复需要进行回忆和思考
- dynamic: think_level由planner动态给出根据planner返回的think_level决定
"""
plan_reply_log_max_per_chat: int = Field(
default=1024,
json_schema_extra={
@@ -669,21 +655,6 @@ class ExpressionConfig(ConfigBase):
"""是否在回复前尝试对上下文中的黑话进行解释关闭可减少一次LLM调用仅影响回复前的黑话匹配与解释不影响黑话学习"""
class ToolConfig(ConfigBase):
"""工具配置类"""
__ui_parent__ = "emoji"
enable_tool: bool = Field(
default=False,
json_schema_extra={
"x-widget": "switch",
"x-icon": "wrench",
},
)
"""是否在聊天中启用工具"""
class VoiceConfig(ConfigBase):
"""语音识别配置类"""

View File

@@ -34,6 +34,7 @@ from src.llm_models.model_client.base_client import (
ClientRequest,
EmbeddingRequest,
ResponseRequest,
UsageRecord,
client_registry,
)
from src.llm_models.payload_content.message import Message, MessageBuilder
@@ -137,6 +138,7 @@ class LLMOrchestrator:
reasoning_content: str,
model_name: str,
tool_calls: List[ToolCall] | None,
usage: UsageRecord | None = None,
) -> LLMResponseResult:
"""构建统一的文本响应结果。
@@ -154,6 +156,9 @@ class LLMOrchestrator:
reasoning=reasoning_content,
model_name=model_name,
tool_calls=tool_calls,
prompt_tokens=usage.prompt_tokens if usage is not None else 0,
completion_tokens=usage.completion_tokens if usage is not None else 0,
total_tokens=usage.total_tokens if usage is not None else 0,
)
async def generate_response_for_image(
@@ -215,7 +220,13 @@ class LLMOrchestrator:
endpoint="/chat/completions",
time_cost=time_cost,
)
return self._build_generation_result(content, reasoning_content, model_info.name, tool_calls)
return self._build_generation_result(
content,
reasoning_content,
model_info.name,
tool_calls,
response.usage,
)
async def generate_response_for_voice(self, voice_base64: str) -> LLMAudioTranscriptionResult:
"""为语音生成转录响应。
@@ -298,7 +309,13 @@ class LLMOrchestrator:
endpoint="/chat/completions",
time_cost=time.time() - start_time,
)
return self._build_generation_result(content or "", reasoning_content, model_info.name, tool_calls)
return self._build_generation_result(
content or "",
reasoning_content,
model_info.name,
tool_calls,
response.usage,
)
async def generate_response_with_message_async(
self,
@@ -343,11 +360,6 @@ class LLMOrchestrator:
)
response = execution_result.api_response
model_info = execution_result.model_info
if self.request_type.startswith("maisaka_"):
logger.info(
f"LLMOrchestrator[{self.request_type}] generate_response_with_message_async 执行完成 "
f"(model={model_info.name}, time_cost={time.time() - start_time:.2f}s)"
)
time_cost = time.time() - start_time
logger.debug(f"LLM请求总耗时: {time_cost}")
@@ -369,7 +381,13 @@ class LLMOrchestrator:
endpoint="/chat/completions",
time_cost=time_cost,
)
return self._build_generation_result(content or "", reasoning_content, model_info.name, tool_calls)
return self._build_generation_result(
content or "",
reasoning_content,
model_info.name,
tool_calls,
response.usage,
)
async def get_embedding(self, embedding_input: str) -> LLMEmbeddingResult:
"""获取嵌入向量。
@@ -833,14 +851,7 @@ class LLMOrchestrator:
message_list = []
if message_factory:
if self.request_type.startswith("maisaka_"):
logger.info(f"LLMOrchestrator[{self.request_type}] 正在通过 message_factory 构建消息列表")
message_list = message_factory(client)
if self.request_type.startswith("maisaka_"):
logger.info(
f"LLMOrchestrator[{self.request_type}] message_factory 返回了 {len(message_list)} 条消息"
)
try:
request = self._build_client_request(
request_type=request_type,

View File

@@ -121,11 +121,7 @@ def create_builtin_tool_specs() -> List[ToolSpec]:
),
_build_tool_spec(
name="no_reply",
brief_description="本轮不发送可见回复,继续下一步思考",
),
_build_tool_spec(
name="stop",
brief_description="暂停当前内部循环,等待新的外部消息。",
brief_description="本轮不进行回复,等待其他用户的新消息",
),
_build_tool_spec(
name="send_emoji",

View File

@@ -137,7 +137,7 @@ class MaisakaChatLoopService:
try:
self._chat_system_prompt = load_prompt(
"maidairy_chat",
"maisaka_chat",
file_tools_section=tools_section,
bot_name=global_config.bot.nickname,
identity=self._personality_prompt,
@@ -695,6 +695,32 @@ class MaisakaChatLoopService:
padding=(0, 1),
)
@staticmethod
def _format_token_count(token_count: int) -> str:
"""格式化 token 数量展示文本。"""
if token_count >= 10_000:
return f"{token_count / 1000:.1f}k"
return str(token_count)
@classmethod
def _build_prompt_stats_text(
cls,
*,
selected_history_count: int,
built_message_count: int,
prompt_tokens: int,
completion_tokens: int,
total_tokens: int,
) -> str:
"""构造本轮 prompt 的统计信息文本。"""
return (
f"已选上下文消息数={selected_history_count} "
f"大模型消息数={built_message_count} "
f"实际输入Token={cls._format_token_count(prompt_tokens)} "
f"输出Token={cls._format_token_count(completion_tokens)} "
f"总Token={cls._format_token_count(total_tokens)}"
)
async def chat_loop_step(self, chat_history: List[LLMContextMessage]) -> ChatResponse:
"""执行一轮 Maisaka 规划器请求。
@@ -769,6 +795,15 @@ class MaisakaChatLoopService:
request_elapsed = perf_counter() - request_started_at
logger.info(f"规划器请求完成,耗时={request_elapsed:.3f}")
prompt_stats_text = self._build_prompt_stats_text(
selected_history_count=len(selected_history),
built_message_count=len(built_messages),
prompt_tokens=generation_result.prompt_tokens,
completion_tokens=generation_result.completion_tokens,
total_tokens=generation_result.total_tokens,
)
logger.info(f"本轮Prompt统计: {prompt_stats_text}")
tool_call_summaries = [
{
"调用编号": getattr(tool_call, "call_id", getattr(tool_call, "id", None)),

View File

@@ -1,5 +1,6 @@
"""Maisaka 推理引擎。"""
from base64 import b64decode
from datetime import datetime
from typing import TYPE_CHECKING, Any, Optional, cast
@@ -15,7 +16,7 @@ from src.chat.heart_flow.heartFC_utils import CycleDetail
from src.chat.message_receive.message import SessionMessage
from src.chat.replyer.replyer_manager import replyer_manager
from src.chat.utils.utils import process_llm_response
from src.common.data_models.message_component_data_model import MessageSequence, TextComponent
from src.common.data_models.message_component_data_model import EmojiComponent, MessageSequence, TextComponent
from src.common.database.database import get_db_session
from src.common.database.database_model import PersonInfo
from src.common.logger import get_logger
@@ -82,7 +83,7 @@ class MaisakaReasoningEngine:
self._runtime._agent_state = self._runtime._STATE_RUNNING
if cached_messages:
self._append_wait_interrupted_message_if_needed()
self._clear_pending_wait_tool_call_id()
await self._ingest_messages(cached_messages)
anchor_message = cached_messages[-1]
else:
@@ -94,7 +95,7 @@ class MaisakaReasoningEngine:
self._runtime._internal_turn_queue.task_done()
continue
logger.info(f"{self._runtime.log_prefix} 等待超时后开始新一轮思考")
self._runtime._chat_history.append(self._build_wait_timeout_message())
self._clear_pending_wait_tool_call_id()
self._trim_chat_history()
try:
for round_index in range(self._runtime._max_internal_rounds):
@@ -179,6 +180,10 @@ class MaisakaReasoningEngine:
return self._runtime.message_cache[-1]
return None
def _clear_pending_wait_tool_call_id(self) -> None:
"""清理等待状态残留的 wait 工具调用编号。"""
self._runtime._pending_wait_tool_call_id = None
def _build_wait_timeout_message(self) -> ToolResultMessage:
"""构造 wait 超时后的工具结果消息。"""
tool_call_id = self._runtime._pending_wait_tool_call_id or "wait_timeout"
@@ -260,20 +265,22 @@ class MaisakaReasoningEngine:
timestamp_text = message.timestamp.strftime("%H:%M:%S")
user_name = user_info.user_nickname or user_info.user_id
group_card = user_info.user_cardname or ""
message_id = message.message_id or ""
return (
f"[时间]{timestamp_text}\n"
f"[用户]{user_name}\n"
f"[用户群昵称]{group_card}\n"
f"[msg_id]{message_id}\n"
"[发言内容]"
)
prefix_parts = [
f"[时间]{timestamp_text}\n",
f"[用户]{user_name}\n",
f"[用户群昵称]{group_card}\n",
]
if not message.is_notify and message.message_id:
prefix_parts.append(f"[msg_id]{message.message_id}\n")
prefix_parts.append("[发言内容]")
return "".join(prefix_parts)
def _build_legacy_visible_text(self, message: SessionMessage, source_sequence: MessageSequence) -> str:
user_info = message.message_info.user_info
speaker_name = user_info.user_cardname or user_info.user_nickname or user_info.user_id
legacy_sequence = MessageSequence([])
legacy_sequence.text(format_speaker_content(speaker_name, "", message.timestamp, message.message_id))
visible_message_id = None if message.is_notify else message.message_id
legacy_sequence.text(format_speaker_content(speaker_name, "", message.timestamp, visible_message_id))
for component in clone_message_sequence(source_sequence).components:
legacy_sequence.components.append(component)
return build_visible_text_from_sequence(legacy_sequence).strip()
@@ -281,7 +288,8 @@ class MaisakaReasoningEngine:
def _build_legacy_visible_text_from_text(self, message: SessionMessage, content: str) -> str:
user_info = message.message_info.user_info
speaker_name = user_info.user_cardname or user_info.user_nickname or user_info.user_id
return format_speaker_content(speaker_name, content, message.timestamp, message.message_id).strip()
visible_message_id = None if message.is_notify else message.message_id
return format_speaker_content(speaker_name, content, message.timestamp, visible_message_id).strip()
def _insert_chat_history_message(self, message: LLMContextMessage) -> int:
"""将消息按处理顺序追加到聊天历史末尾。"""
@@ -1274,7 +1282,7 @@ class MaisakaReasoningEngine:
self._runtime._chat_history.append(history_message)
return self._build_tool_success_result(
tool_call.func_name,
"可见回复已生成并发送。",
"回复已生成并发送。",
structured_content={
"msg_id": target_message_id,
"quote": quote_reply,
@@ -1385,3 +1393,154 @@ class MaisakaReasoningEngine:
tool_call.func_name,
"发送表情包失败。",
)
async def _handle_send_emoji(self, tool_call: ToolCall) -> ToolExecutionResult:
"""?????????????"""
from src.chat.emoji_system.emoji_manager import emoji_manager
from src.common.utils.utils_image import ImageUtils
import random
tool_args = tool_call.args or {}
emotion = str(tool_args.get("emotion") or "").strip()
structured_result: dict[str, Any] = {
"success": False,
"message": "",
"description": "",
"emotion": [],
"requested_emotion": emotion,
}
logger.info(f"{self._runtime.log_prefix} ??????????: ??={emotion!r}")
if not emoji_manager.emojis:
structured_result["message"] = "??????????????"
return self._build_tool_failure_result(
tool_call.func_name,
structured_result["message"],
structured_content=structured_result,
)
selected_emoji = None
if emotion:
matching_emojis = [
emoji
for emoji in emoji_manager.emojis
if emotion.lower() in (item.lower() for item in emoji.emotion)
]
if matching_emojis:
selected_emoji = random.choice(matching_emojis)
logger.info(
f"{self._runtime.log_prefix} ?? {len(matching_emojis)} ????? {emotion!r} ?????"
f"????{selected_emoji.description}"
)
if selected_emoji is None:
selected_emoji = random.choice(emoji_manager.emojis)
logger.info(
f"{self._runtime.log_prefix} ????????? {emotion!r}?"
f"??????{selected_emoji.description}"
)
emoji_description = selected_emoji.description.strip()
emoji_emotions = [str(item).strip() for item in selected_emoji.emotion if str(item).strip()]
structured_result["description"] = emoji_description
structured_result["emotion"] = emoji_emotions
emoji_manager.update_emoji_usage(selected_emoji)
try:
emoji_base64 = ImageUtils.image_path_to_base64(str(selected_emoji.full_path))
if not emoji_base64:
raise ValueError("??????? base64 ??")
except Exception as exc:
logger.error(f"{self._runtime.log_prefix} ??????? base64 ??: {exc}")
structured_result["message"] = f"????????{exc}"
return self._build_tool_failure_result(
tool_call.func_name,
structured_result["message"],
structured_content=structured_result,
)
try:
sent = await send_service.emoji_to_stream(
emoji_base64=emoji_base64,
stream_id=self._runtime.session_id,
storage_message=True,
set_reply=False,
reply_message=None,
)
except Exception as exc:
logger.exception(f"{self._runtime.log_prefix} ??????????: {exc}")
structured_result["message"] = f"???????????{exc}"
return self._build_tool_failure_result(
tool_call.func_name,
structured_result["message"],
structured_content=structured_result,
)
if sent:
success_message = (
f"???????{emoji_description}????{', '.join(emoji_emotions)}?"
if emoji_emotions
else f"???????{emoji_description}"
)
logger.info(
f"{self._runtime.log_prefix} ???????: "
f"??={selected_emoji.description!r} ????={selected_emoji.emotion}"
)
self._append_sent_emoji_to_chat_history(
emoji_base64=emoji_base64,
success_message=success_message,
)
structured_result["success"] = True
structured_result["message"] = success_message
return self._build_tool_success_result(
tool_call.func_name,
success_message,
structured_content=structured_result,
)
logger.warning(f"{self._runtime.log_prefix} ???????")
structured_result["message"] = "????????"
return self._build_tool_failure_result(
tool_call.func_name,
structured_result["message"],
structured_content=structured_result,
)
def _append_sent_emoji_to_chat_history(
self,
*,
emoji_base64: str,
success_message: str,
) -> None:
"""? bot ?????????????? Maisaka ?????"""
bot_name = global_config.bot.nickname.strip() or "MaiSaka"
reply_timestamp = datetime.now()
planner_prefix = (
f"[??]{reply_timestamp.strftime('%H:%M:%S')}\n"
f"[??]{bot_name}\n"
"[?????]\n"
"[msg_id]\n"
"[????]"
)
history_message = SessionBackedMessage(
raw_message=MessageSequence(
[
TextComponent(planner_prefix),
EmojiComponent(
binary_hash="",
content=success_message,
binary_data=b64decode(emoji_base64),
),
]
),
visible_text=format_speaker_content(
bot_name,
"[???]",
reply_timestamp,
),
timestamp=reply_timestamp,
source_kind="guided_reply",
)
self._runtime._chat_history.append(history_message)

View File

@@ -1,98 +0,0 @@
# -*- coding: utf-8 -*-
"""
记忆系统工具函数
包含模糊查找、相似度计算等工具函数
"""
import json
import re
from datetime import datetime
from typing import Tuple
from typing import List
from json_repair import repair_json
from src.common.logger import get_logger
logger = get_logger("memory_utils")
def parse_questions_json(response: str) -> Tuple[List[str], List[str]]:
"""解析问题JSON返回概念列表和问题列表
Args:
response: LLM返回的响应
Returns:
Tuple[List[str], List[str]]: (概念列表, 问题列表)
"""
try:
# 尝试提取JSON可能包含在```json代码块中
json_pattern = r"```json\s*(.*?)\s*```"
matches = re.findall(json_pattern, response, re.DOTALL)
if matches:
json_str = matches[0]
else:
# 尝试直接解析整个响应
json_str = response.strip()
# 修复可能的JSON错误
repaired_json = repair_json(json_str)
# 解析JSON
parsed = json.loads(repaired_json)
# 只支持新格式包含concepts和questions的对象
if not isinstance(parsed, dict):
logger.warning(f"解析的JSON不是对象格式: {parsed}")
return [], []
concepts_raw = parsed.get("concepts", [])
questions_raw = parsed.get("questions", [])
# 确保是列表
if not isinstance(concepts_raw, list):
concepts_raw = []
if not isinstance(questions_raw, list):
questions_raw = []
# 确保所有元素都是字符串
concepts = [c for c in concepts_raw if isinstance(c, str) and c.strip()]
questions = [q for q in questions_raw if isinstance(q, str) and q.strip()]
return concepts, questions
except Exception as e:
logger.error(f"解析问题JSON失败: {e}, 响应内容: {response[:200]}...")
return [], []
def parse_datetime_to_timestamp(value: str) -> float:
"""
接受多种常见格式并转换为时间戳(秒)
支持示例:
- 2025-09-29
- 2025-09-29 00:00:00
- 2025/09/29 00:00
- 2025-09-29T00:00:00
"""
value = value.strip()
fmts = [
"%Y-%m-%d %H:%M:%S",
"%Y-%m-%d %H:%M",
"%Y/%m/%d %H:%M:%S",
"%Y/%m/%d %H:%M",
"%Y-%m-%d",
"%Y/%m/%d",
"%Y-%m-%dT%H:%M:%S",
"%Y-%m-%dT%H:%M",
]
last_err = None
for fmt in fmts:
try:
dt = datetime.strptime(value, fmt)
return dt.timestamp()
except Exception as e:
last_err = e
raise ValueError(f"无法解析时间: {value} ({last_err})")

View File

@@ -103,7 +103,6 @@ async def generate_reply(
available_actions: Optional[Dict[str, ActionInfo]] = None,
chosen_actions: Optional[List["ActionPlannerInfo"]] = None,
unknown_words: Optional[List[str]] = None,
enable_tool: bool = False,
enable_splitter: bool = True,
enable_chinese_typo: bool = True,
request_type: str = "generator_api",
@@ -133,7 +132,6 @@ async def generate_reply(
extra_info=extra_info,
available_actions=available_actions,
chosen_actions=chosen_actions,
enable_tool=enable_tool,
reply_message=reply_message,
reply_reason=reply_reason,
unknown_words=unknown_words,

View File

@@ -36,7 +36,6 @@ from src.config.official_configs import (
ResponsePostProcessConfig,
ResponseSplitterConfig,
TelemetryConfig,
ToolConfig,
VoiceConfig,
)
from src.webui.config_schema import ConfigSchemaGenerator
@@ -113,7 +112,6 @@ async def get_config_section_schema(section_name: str):
- experimental: ExperimentalConfig
- maim_message: MaimMessageConfig
- lpmm_knowledge: LPMMKnowledgeConfig
- tool: ToolConfig
- memory: MemoryConfig
- debug: DebugConfig
- voice: VoiceConfig
@@ -138,7 +136,6 @@ async def get_config_section_schema(section_name: str):
"experimental": ExperimentalConfig,
"maim_message": MaimMessageConfig,
"lpmm_knowledge": LPMMKnowledgeConfig,
"tool": ToolConfig,
"memory": MemoryConfig,
"debug": DebugConfig,
"voice": VoiceConfig,