Optimize string concatenation in loops: replace += with list.join() (#3246)
* Initial plan * Fix string concatenation performance issues in loops Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> * Address code review feedback: Fix plugin list logic and add comment Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> * Improve comment clarity for at_parts accumulation Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: LIghtJUNction <106986785+LIghtJUNction@users.noreply.github.com>
This commit is contained in:
@@ -250,14 +250,15 @@ async def migration_persona_data(
|
||||
try:
|
||||
begin_dialogs = persona.get("begin_dialogs", [])
|
||||
mood_imitation_dialogs = persona.get("mood_imitation_dialogs", [])
|
||||
mood_prompt = ""
|
||||
parts = []
|
||||
user_turn = True
|
||||
for mood_dialog in mood_imitation_dialogs:
|
||||
if user_turn:
|
||||
mood_prompt += f"A: {mood_dialog}\n"
|
||||
parts.append(f"A: {mood_dialog}\n")
|
||||
else:
|
||||
mood_prompt += f"B: {mood_dialog}\n"
|
||||
parts.append(f"B: {mood_dialog}\n")
|
||||
user_turn = not user_turn
|
||||
mood_prompt = "".join(parts)
|
||||
system_prompt = persona.get("prompt", "")
|
||||
if mood_prompt:
|
||||
system_prompt += f"Here are few shots of dialogs, you need to imitate the tone of 'B' in the following dialogs to respond:\n {mood_prompt}"
|
||||
|
||||
@@ -21,8 +21,9 @@ class BaiduAipStrategy(ContentSafetyStrategy):
|
||||
if "data" not in res:
|
||||
return False, ""
|
||||
count = len(res["data"])
|
||||
info = f"百度审核服务发现 {count} 处违规:\n"
|
||||
parts = [f"百度审核服务发现 {count} 处违规:\n"]
|
||||
for i in res["data"]:
|
||||
info += f"{i['msg']};\n"
|
||||
info += "\n判断结果:" + res["conclusion"]
|
||||
parts.append(f"{i['msg']};\n")
|
||||
parts.append("\n判断结果:" + res["conclusion"])
|
||||
info = "".join(parts)
|
||||
return False, info
|
||||
|
||||
@@ -246,12 +246,13 @@ class ResultDecorateStage(Stage):
|
||||
elif (
|
||||
result.use_t2i_ is None and self.ctx.astrbot_config["t2i"]
|
||||
) or result.use_t2i_:
|
||||
plain_str = ""
|
||||
parts = []
|
||||
for comp in result.chain:
|
||||
if isinstance(comp, Plain):
|
||||
plain_str += "\n\n" + comp.text
|
||||
parts.append("\n\n" + comp.text)
|
||||
else:
|
||||
break
|
||||
plain_str = "".join(parts)
|
||||
if plain_str and len(plain_str) > self.t2i_word_threshold:
|
||||
render_start = time.time()
|
||||
try:
|
||||
|
||||
@@ -91,33 +91,34 @@ class AstrMessageEvent(abc.ABC):
|
||||
return self.message_str
|
||||
|
||||
def _outline_chain(self, chain: list[BaseMessageComponent] | None) -> str:
|
||||
outline = ""
|
||||
if not chain:
|
||||
return outline
|
||||
return ""
|
||||
|
||||
parts = []
|
||||
for i in chain:
|
||||
if isinstance(i, Plain):
|
||||
outline += i.text
|
||||
parts.append(i.text)
|
||||
elif isinstance(i, Image):
|
||||
outline += "[图片]"
|
||||
parts.append("[图片]")
|
||||
elif isinstance(i, Face):
|
||||
outline += f"[表情:{i.id}]"
|
||||
parts.append(f"[表情:{i.id}]")
|
||||
elif isinstance(i, At):
|
||||
outline += f"[At:{i.qq}]"
|
||||
parts.append(f"[At:{i.qq}]")
|
||||
elif isinstance(i, AtAll):
|
||||
outline += "[At:全体成员]"
|
||||
parts.append("[At:全体成员]")
|
||||
elif isinstance(i, Forward):
|
||||
# 转发消息
|
||||
outline += "[转发消息]"
|
||||
parts.append("[转发消息]")
|
||||
elif isinstance(i, Reply):
|
||||
# 引用回复
|
||||
if i.message_str:
|
||||
outline += f"[引用消息({i.sender_nickname}: {i.message_str})]"
|
||||
parts.append(f"[引用消息({i.sender_nickname}: {i.message_str})]")
|
||||
else:
|
||||
outline += "[引用消息]"
|
||||
parts.append("[引用消息]")
|
||||
else:
|
||||
outline += f"[{i.type}]"
|
||||
outline += " "
|
||||
return outline
|
||||
parts.append(f"[{i.type}]")
|
||||
parts.append(" ")
|
||||
return "".join(parts)
|
||||
|
||||
def get_message_outline(self) -> str:
|
||||
"""获取消息概要。
|
||||
|
||||
@@ -315,6 +315,8 @@ class AiocqhttpAdapter(Platform):
|
||||
abm.message.append(a)
|
||||
elif t == "at":
|
||||
first_at_self_processed = False
|
||||
# Accumulate @ mention text for efficient concatenation
|
||||
at_parts = []
|
||||
|
||||
for m in m_group:
|
||||
try:
|
||||
@@ -354,13 +356,15 @@ class AiocqhttpAdapter(Platform):
|
||||
first_at_self_processed = True
|
||||
else:
|
||||
# 非第一个@机器人或@其他用户,添加到message_str
|
||||
message_str += f" @{nickname}({m['data']['qq']}) "
|
||||
at_parts.append(f" @{nickname}({m['data']['qq']}) ")
|
||||
else:
|
||||
abm.message.append(At(qq=str(m["data"]["qq"]), name=""))
|
||||
except ActionFailed as e:
|
||||
logger.error(f"获取 @ 用户信息失败: {e},此消息段将被忽略。")
|
||||
except BaseException as e:
|
||||
logger.error(f"获取 @ 用户信息失败: {e},此消息段将被忽略。")
|
||||
|
||||
message_str += "".join(at_parts)
|
||||
else:
|
||||
for m in m_group:
|
||||
a = ComponentTypes[t](**m["data"])
|
||||
|
||||
@@ -113,18 +113,18 @@ class DiscordPlatformEvent(AstrMessageEvent):
|
||||
message: MessageChain,
|
||||
) -> tuple[str, list[discord.File], discord.ui.View | None, list[discord.Embed]]:
|
||||
"""将 MessageChain 解析为 Discord 发送所需的内容"""
|
||||
content = ""
|
||||
content_parts = []
|
||||
files = []
|
||||
view = None
|
||||
embeds = []
|
||||
reference_message_id = None
|
||||
for i in message.chain: # 遍历消息链
|
||||
if isinstance(i, Plain): # 如果是文字类型的
|
||||
content += i.text
|
||||
content_parts.append(i.text)
|
||||
elif isinstance(i, Reply):
|
||||
reference_message_id = i.id
|
||||
elif isinstance(i, At):
|
||||
content += f"<@{i.qq}>"
|
||||
content_parts.append(f"<@{i.qq}>")
|
||||
elif isinstance(i, Image):
|
||||
logger.debug(f"[Discord] 开始处理 Image 组件: {i}")
|
||||
try:
|
||||
@@ -238,6 +238,7 @@ class DiscordPlatformEvent(AstrMessageEvent):
|
||||
else:
|
||||
logger.debug(f"[Discord] 忽略了不支持的消息组件: {i.type}")
|
||||
|
||||
content = "".join(content_parts)
|
||||
if len(content) > 2000:
|
||||
logger.warning("[Discord] 消息内容超过2000字符,将被截断。")
|
||||
content = content[:2000]
|
||||
|
||||
@@ -222,39 +222,41 @@ class SlackAdapter(Platform):
|
||||
if element.get("type") == "rich_text_section":
|
||||
# 处理富文本段落
|
||||
section_elements = element.get("elements", [])
|
||||
text_content = ""
|
||||
|
||||
text_parts = []
|
||||
for section_element in section_elements:
|
||||
element_type = section_element.get("type", "")
|
||||
|
||||
if element_type == "text":
|
||||
# 普通文本
|
||||
text_content += section_element.get("text", "")
|
||||
text_parts.append(section_element.get("text", ""))
|
||||
elif element_type == "user":
|
||||
# @用户提及
|
||||
user_id = section_element.get("user_id", "")
|
||||
if user_id:
|
||||
# 将之前的文本内容先添加到组件中
|
||||
text_content = "".join(text_parts)
|
||||
if text_content.strip():
|
||||
message_components.append(
|
||||
Plain(text=text_content),
|
||||
)
|
||||
text_content = ""
|
||||
text_parts = []
|
||||
# 添加@提及组件
|
||||
message_components.append(At(qq=user_id, name=""))
|
||||
elif element_type == "channel":
|
||||
# #频道提及
|
||||
channel_id = section_element.get("channel_id", "")
|
||||
text_content += f"#{channel_id}"
|
||||
text_parts.append(f"#{channel_id}")
|
||||
elif element_type == "link":
|
||||
# 链接
|
||||
url = section_element.get("url", "")
|
||||
link_text = section_element.get("text", url)
|
||||
text_content += f"[{link_text}]({url})"
|
||||
text_parts.append(f"[{link_text}]({url})")
|
||||
elif element_type == "emoji":
|
||||
# 表情符号
|
||||
emoji_name = section_element.get("name", "")
|
||||
text_content += f":{emoji_name}:"
|
||||
text_parts.append(f":{emoji_name}:")
|
||||
|
||||
text_content = "".join(text_parts)
|
||||
|
||||
if text_content.strip():
|
||||
message_components.append(Plain(text=text_content))
|
||||
|
||||
@@ -148,14 +148,15 @@ class SlackMessageEvent(AstrMessageEvent):
|
||||
)
|
||||
except Exception:
|
||||
# 如果块发送失败,尝试只发送文本
|
||||
fallback_text = ""
|
||||
parts = []
|
||||
for segment in message.chain:
|
||||
if isinstance(segment, Plain):
|
||||
fallback_text += segment.text
|
||||
parts.append(segment.text)
|
||||
elif isinstance(segment, File):
|
||||
fallback_text += f" [文件: {segment.name}] "
|
||||
parts.append(f" [文件: {segment.name}] ")
|
||||
elif isinstance(segment, Image):
|
||||
fallback_text += " [图片] "
|
||||
parts.append(" [图片] ")
|
||||
fallback_text = "".join(parts)
|
||||
|
||||
if self.get_group_id():
|
||||
await self.web_client.chat_postMessage(
|
||||
|
||||
@@ -146,14 +146,15 @@ class ProviderDashscope(ProviderOpenAIOfficial):
|
||||
# RAG 引用脚标格式化
|
||||
output_text = re.sub(r"<ref>\[(\d+)\]</ref>", r"[\1]", output_text)
|
||||
if self.output_reference and response.output.get("doc_references", None):
|
||||
ref_str = ""
|
||||
ref_parts = []
|
||||
for ref in response.output.get("doc_references", []) or []:
|
||||
ref_title = (
|
||||
ref.get("title", "")
|
||||
if ref.get("title")
|
||||
else ref.get("doc_name", "")
|
||||
)
|
||||
ref_str += f"{ref['index_id']}. {ref_title}\n"
|
||||
ref_parts.append(f"{ref['index_id']}. {ref_title}\n")
|
||||
ref_str = "".join(ref_parts)
|
||||
output_text += f"\n\n回答来源:\n{ref_str}"
|
||||
|
||||
llm_response = LLMResponse("assistant")
|
||||
|
||||
@@ -51,15 +51,15 @@ class CommandFilter(HandlerFilter):
|
||||
self._cmpl_cmd_names: list | None = None
|
||||
|
||||
def print_types(self):
|
||||
result = ""
|
||||
parts = []
|
||||
for k, v in self.handler_params.items():
|
||||
if isinstance(v, type):
|
||||
result += f"{k}({v.__name__}),"
|
||||
parts.append(f"{k}({v.__name__}),")
|
||||
elif isinstance(v, types.UnionType) or typing.get_origin(v) is typing.Union:
|
||||
result += f"{k}({v}),"
|
||||
parts.append(f"{k}({v}),")
|
||||
else:
|
||||
result += f"{k}({type(v).__name__})={v},"
|
||||
result = result.rstrip(",")
|
||||
parts.append(f"{k}({type(v).__name__})={v},")
|
||||
result = "".join(parts).rstrip(",")
|
||||
return result
|
||||
|
||||
def init_handler_md(self, handle_md: StarHandlerMetadata):
|
||||
|
||||
@@ -66,7 +66,7 @@ class CommandGroupFilter(HandlerFilter):
|
||||
event: AstrMessageEvent | None = None,
|
||||
cfg: AstrBotConfig | None = None,
|
||||
) -> str:
|
||||
result = ""
|
||||
parts = []
|
||||
for sub_filter in sub_command_filters:
|
||||
if isinstance(sub_filter, CommandFilter):
|
||||
custom_filter_pass = True
|
||||
@@ -74,31 +74,32 @@ class CommandGroupFilter(HandlerFilter):
|
||||
custom_filter_pass = sub_filter.custom_filter_ok(event, cfg)
|
||||
if custom_filter_pass:
|
||||
cmd_th = sub_filter.print_types()
|
||||
result += f"{prefix}├── {sub_filter.command_name}"
|
||||
line = f"{prefix}├── {sub_filter.command_name}"
|
||||
if cmd_th:
|
||||
result += f" ({cmd_th})"
|
||||
line += f" ({cmd_th})"
|
||||
else:
|
||||
result += " (无参数指令)"
|
||||
line += " (无参数指令)"
|
||||
|
||||
if sub_filter.handler_md and sub_filter.handler_md.desc:
|
||||
result += f": {sub_filter.handler_md.desc}"
|
||||
line += f": {sub_filter.handler_md.desc}"
|
||||
|
||||
result += "\n"
|
||||
parts.append(line + "\n")
|
||||
elif isinstance(sub_filter, CommandGroupFilter):
|
||||
custom_filter_pass = True
|
||||
if event and cfg:
|
||||
custom_filter_pass = sub_filter.custom_filter_ok(event, cfg)
|
||||
if custom_filter_pass:
|
||||
result += f"{prefix}├── {sub_filter.group_name}"
|
||||
result += "\n"
|
||||
result += sub_filter.print_cmd_tree(
|
||||
sub_filter.sub_command_filters,
|
||||
prefix + "│ ",
|
||||
event=event,
|
||||
cfg=cfg,
|
||||
parts.append(f"{prefix}├── {sub_filter.group_name}\n")
|
||||
parts.append(
|
||||
sub_filter.print_cmd_tree(
|
||||
sub_filter.sub_command_filters,
|
||||
prefix + "│ ",
|
||||
event=event,
|
||||
cfg=cfg,
|
||||
)
|
||||
)
|
||||
|
||||
return result
|
||||
return "".join(parts)
|
||||
|
||||
def custom_filter_ok(self, event: AstrMessageEvent, cfg: AstrBotConfig) -> bool:
|
||||
for custom_filter in self.custom_filter_list:
|
||||
|
||||
@@ -213,11 +213,12 @@ class AstrBotDashboard:
|
||||
|
||||
raise Exception(f"端口 {port} 已被占用")
|
||||
|
||||
display = f"\n ✨✨✨\n AstrBot v{VERSION} WebUI 已启动,可访问\n\n"
|
||||
display += f" ➜ 本地: http://localhost:{port}\n"
|
||||
parts = [f"\n ✨✨✨\n AstrBot v{VERSION} WebUI 已启动,可访问\n\n"]
|
||||
parts.append(f" ➜ 本地: http://localhost:{port}\n")
|
||||
for ip in ip_addr:
|
||||
display += f" ➜ 网络: http://{ip}:{port}\n"
|
||||
display += " ➜ 默认用户名和密码: astrbot\n ✨✨✨\n"
|
||||
parts.append(f" ➜ 网络: http://{ip}:{port}\n")
|
||||
parts.append(" ➜ 默认用户名和密码: astrbot\n ✨✨✨\n")
|
||||
display = "".join(parts)
|
||||
|
||||
if not ip_addr:
|
||||
display += (
|
||||
|
||||
@@ -134,12 +134,13 @@ class ConversationCommands:
|
||||
size_per_page,
|
||||
)
|
||||
|
||||
history = ""
|
||||
parts = []
|
||||
for context in contexts:
|
||||
if len(context) > 150:
|
||||
context = context[:150] + "..."
|
||||
history += f"{context}\n"
|
||||
parts.append(f"{context}\n")
|
||||
|
||||
history = "".join(parts)
|
||||
ret = (
|
||||
f"当前对话历史记录:"
|
||||
f"{history or '无历史记录'}\n\n"
|
||||
@@ -154,7 +155,7 @@ class ConversationCommands:
|
||||
provider = self.context.get_using_provider(message.unified_msg_origin)
|
||||
if provider and provider.meta().type == "dify":
|
||||
"""原有的Dify处理逻辑保持不变"""
|
||||
ret = "Dify 对话列表:\n"
|
||||
parts = ["Dify 对话列表:\n"]
|
||||
assert isinstance(provider, ProviderDify)
|
||||
data = await provider.api_client.get_chat_convs(message.unified_msg_origin)
|
||||
idx = 1
|
||||
@@ -162,12 +163,17 @@ class ConversationCommands:
|
||||
ts_h = datetime.datetime.fromtimestamp(conv["updated_at"]).strftime(
|
||||
"%m-%d %H:%M",
|
||||
)
|
||||
ret += f"{idx}. {conv['name']}({conv['id'][:4]})\n 上次更新:{ts_h}\n"
|
||||
parts.append(
|
||||
f"{idx}. {conv['name']}({conv['id'][:4]})\n 上次更新:{ts_h}\n"
|
||||
)
|
||||
idx += 1
|
||||
if idx == 1:
|
||||
ret += "没有找到任何对话。"
|
||||
parts.append("没有找到任何对话。")
|
||||
dify_cid = provider.conversation_ids.get(message.unified_msg_origin, None)
|
||||
ret += f"\n\n用户: {message.unified_msg_origin}\n当前对话: {dify_cid}\n使用 /switch <序号> 切换对话。"
|
||||
parts.append(
|
||||
f"\n\n用户: {message.unified_msg_origin}\n当前对话: {dify_cid}\n使用 /switch <序号> 切换对话。"
|
||||
)
|
||||
ret = "".join(parts)
|
||||
message.set_result(MessageEventResult().message(ret))
|
||||
return
|
||||
|
||||
@@ -185,7 +191,7 @@ class ConversationCommands:
|
||||
end_idx = start_idx + size_per_page
|
||||
conversations_paged = conversations_all[start_idx:end_idx]
|
||||
|
||||
ret = "对话列表:\n---\n"
|
||||
parts = ["对话列表:\n---\n"]
|
||||
"""全局序号从当前页的第一个开始"""
|
||||
global_index = start_idx + 1
|
||||
|
||||
@@ -204,10 +210,13 @@ class ConversationCommands:
|
||||
)
|
||||
persona_id = persona["name"]
|
||||
title = _titles.get(conv.cid, "新对话")
|
||||
ret += f"{global_index}. {title}({conv.cid[:4]})\n 人格情景: {persona_id}\n 上次更新: {datetime.datetime.fromtimestamp(conv.updated_at).strftime('%m-%d %H:%M')}\n"
|
||||
parts.append(
|
||||
f"{global_index}. {title}({conv.cid[:4]})\n 人格情景: {persona_id}\n 上次更新: {datetime.datetime.fromtimestamp(conv.updated_at).strftime('%m-%d %H:%M')}\n"
|
||||
)
|
||||
global_index += 1
|
||||
|
||||
ret += "---\n"
|
||||
parts.append("---\n")
|
||||
ret = "".join(parts)
|
||||
curr_cid = await self.context.conversation_manager.get_curr_conversation_id(
|
||||
message.unified_msg_origin,
|
||||
)
|
||||
|
||||
@@ -59,10 +59,11 @@ class PersonaCommands:
|
||||
.use_t2i(False),
|
||||
)
|
||||
elif l[1] == "list":
|
||||
msg = "人格列表:\n"
|
||||
parts = ["人格列表:\n"]
|
||||
for persona in self.context.provider_manager.personas:
|
||||
msg += f"- {persona['name']}\n"
|
||||
msg += "\n\n*输入 `/persona view 人格名` 查看人格详细信息"
|
||||
parts.append(f"- {persona['name']}\n")
|
||||
parts.append("\n\n*输入 `/persona view 人格名` 查看人格详细信息")
|
||||
msg = "".join(parts)
|
||||
message.set_result(MessageEventResult().message(msg))
|
||||
elif l[1] == "view":
|
||||
if len(l) == 2:
|
||||
|
||||
@@ -13,14 +13,17 @@ class PluginCommands:
|
||||
|
||||
async def plugin_ls(self, event: AstrMessageEvent):
|
||||
"""获取已经安装的插件列表。"""
|
||||
plugin_list_info = "已加载的插件:\n"
|
||||
parts = ["已加载的插件:\n"]
|
||||
for plugin in self.context.get_all_stars():
|
||||
plugin_list_info += f"- `{plugin.name}` By {plugin.author}: {plugin.desc}"
|
||||
line = f"- `{plugin.name}` By {plugin.author}: {plugin.desc}"
|
||||
if not plugin.activated:
|
||||
plugin_list_info += " (未启用)"
|
||||
plugin_list_info += "\n"
|
||||
if plugin_list_info.strip() == "":
|
||||
line += " (未启用)"
|
||||
parts.append(line + "\n")
|
||||
|
||||
if len(parts) == 1:
|
||||
plugin_list_info = "没有加载任何插件。"
|
||||
else:
|
||||
plugin_list_info = "".join(parts)
|
||||
|
||||
plugin_list_info += "\n使用 /plugin help <插件名> 查看插件帮助和加载的指令。\n使用 /plugin on/off <插件名> 启用或者禁用插件。"
|
||||
event.set_result(
|
||||
@@ -103,14 +106,14 @@ class PluginCommands:
|
||||
command_names.append(filter_.group_name)
|
||||
|
||||
if len(command_handlers) > 0:
|
||||
help_msg += "\n\n🔧 指令列表:\n"
|
||||
parts = ["\n\n🔧 指令列表:\n"]
|
||||
for i in range(len(command_handlers)):
|
||||
help_msg += f"- {command_names[i]}"
|
||||
line = f"- {command_names[i]}"
|
||||
if command_handlers[i].desc:
|
||||
help_msg += f": {command_handlers[i].desc}"
|
||||
help_msg += "\n"
|
||||
|
||||
help_msg += "\nTip: 指令的触发需要添加唤醒前缀,默认为 /。"
|
||||
line += f": {command_handlers[i].desc}"
|
||||
parts.append(line + "\n")
|
||||
parts.append("\nTip: 指令的触发需要添加唤醒前缀,默认为 /。")
|
||||
help_msg += "".join(parts)
|
||||
|
||||
ret = f"🧩 插件 {plugin_name} 帮助信息:\n" + help_msg
|
||||
ret += "更多帮助信息请查看插件仓库 README。"
|
||||
|
||||
@@ -19,38 +19,39 @@ class ProviderCommands:
|
||||
umo = event.unified_msg_origin
|
||||
|
||||
if idx is None:
|
||||
ret = "## 载入的 LLM 提供商\n"
|
||||
parts = ["## 载入的 LLM 提供商\n"]
|
||||
for idx, llm in enumerate(self.context.get_all_providers()):
|
||||
id_ = llm.meta().id
|
||||
ret += f"{idx + 1}. {id_} ({llm.meta().model})"
|
||||
line = f"{idx + 1}. {id_} ({llm.meta().model})"
|
||||
provider_using = self.context.get_using_provider(umo=umo)
|
||||
if provider_using and provider_using.meta().id == id_:
|
||||
ret += " (当前使用)"
|
||||
ret += "\n"
|
||||
line += " (当前使用)"
|
||||
parts.append(line + "\n")
|
||||
|
||||
tts_providers = self.context.get_all_tts_providers()
|
||||
if tts_providers:
|
||||
ret += "\n## 载入的 TTS 提供商\n"
|
||||
parts.append("\n## 载入的 TTS 提供商\n")
|
||||
for idx, tts in enumerate(tts_providers):
|
||||
id_ = tts.meta().id
|
||||
ret += f"{idx + 1}. {id_}"
|
||||
line = f"{idx + 1}. {id_}"
|
||||
tts_using = self.context.get_using_tts_provider(umo=umo)
|
||||
if tts_using and tts_using.meta().id == id_:
|
||||
ret += " (当前使用)"
|
||||
ret += "\n"
|
||||
line += " (当前使用)"
|
||||
parts.append(line + "\n")
|
||||
|
||||
stt_providers = self.context.get_all_stt_providers()
|
||||
if stt_providers:
|
||||
ret += "\n## 载入的 STT 提供商\n"
|
||||
parts.append("\n## 载入的 STT 提供商\n")
|
||||
for idx, stt in enumerate(stt_providers):
|
||||
id_ = stt.meta().id
|
||||
ret += f"{idx + 1}. {id_}"
|
||||
line = f"{idx + 1}. {id_}"
|
||||
stt_using = self.context.get_using_stt_provider(umo=umo)
|
||||
if stt_using and stt_using.meta().id == id_:
|
||||
ret += " (当前使用)"
|
||||
ret += "\n"
|
||||
line += " (当前使用)"
|
||||
parts.append(line + "\n")
|
||||
|
||||
ret += "\n使用 /provider <序号> 切换 LLM 提供商。"
|
||||
parts.append("\n使用 /provider <序号> 切换 LLM 提供商。")
|
||||
ret = "".join(parts)
|
||||
|
||||
if tts_providers:
|
||||
ret += "\n使用 /provider tts <序号> 切换 TTS 提供商。"
|
||||
@@ -128,16 +129,17 @@ class ProviderCommands:
|
||||
.use_t2i(False),
|
||||
)
|
||||
return
|
||||
i = 1
|
||||
ret = "下面列出了此模型提供商可用模型:"
|
||||
for model in models:
|
||||
ret += f"\n{i}. {model}"
|
||||
i += 1
|
||||
parts = ["下面列出了此模型提供商可用模型:"]
|
||||
for i, model in enumerate(models, 1):
|
||||
parts.append(f"\n{i}. {model}")
|
||||
|
||||
curr_model = prov.get_model() or "无"
|
||||
ret += f"\n当前模型: [{curr_model}]"
|
||||
parts.append(f"\n当前模型: [{curr_model}]")
|
||||
parts.append(
|
||||
"\nTips: 使用 /model <模型名/编号>,即可实时更换模型。如目标模型不存在于上表,请输入模型名。"
|
||||
)
|
||||
|
||||
ret += "\nTips: 使用 /model <模型名/编号>,即可实时更换模型。如目标模型不存在于上表,请输入模型名。"
|
||||
ret = "".join(parts)
|
||||
message.set_result(MessageEventResult().message(ret).use_t2i(False))
|
||||
elif isinstance(idx_or_name, int):
|
||||
models = []
|
||||
@@ -180,14 +182,15 @@ class ProviderCommands:
|
||||
if index is None:
|
||||
keys_data = prov.get_keys()
|
||||
curr_key = prov.get_current_key()
|
||||
ret = "Key:"
|
||||
for i, k in enumerate(keys_data):
|
||||
ret += f"\n{i + 1}. {k[:8]}"
|
||||
parts = ["Key:"]
|
||||
for i, k in enumerate(keys_data, 1):
|
||||
parts.append(f"\n{i}. {k[:8]}")
|
||||
|
||||
ret += f"\n当前 Key: {curr_key[:8]}"
|
||||
ret += "\n当前模型: " + prov.get_model()
|
||||
ret += "\n使用 /key <idx> 切换 Key。"
|
||||
parts.append(f"\n当前 Key: {curr_key[:8]}")
|
||||
parts.append("\n当前模型: " + prov.get_model())
|
||||
parts.append("\n使用 /key <idx> 切换 Key。")
|
||||
|
||||
ret = "".join(parts)
|
||||
message.set_result(MessageEventResult().message(ret).use_t2i(False))
|
||||
else:
|
||||
keys_data = prov.get_keys()
|
||||
|
||||
@@ -119,13 +119,13 @@ class LongTermMemory:
|
||||
if event.get_message_type() == MessageType.GROUP_MESSAGE:
|
||||
datetime_str = datetime.datetime.now().strftime("%H:%M:%S")
|
||||
|
||||
final_message = f"[{event.message_obj.sender.nickname}/{datetime_str}]: "
|
||||
parts = [f"[{event.message_obj.sender.nickname}/{datetime_str}]: "]
|
||||
|
||||
cfg = self.cfg(event)
|
||||
|
||||
for comp in event.get_messages():
|
||||
if isinstance(comp, Plain):
|
||||
final_message += f" {comp.text}"
|
||||
parts.append(f" {comp.text}")
|
||||
elif isinstance(comp, Image):
|
||||
if cfg["image_caption"]:
|
||||
try:
|
||||
@@ -137,11 +137,13 @@ class LongTermMemory:
|
||||
cfg["image_caption_provider_id"],
|
||||
cfg["image_caption_prompt"],
|
||||
)
|
||||
final_message += f" [Image: {caption}]"
|
||||
parts.append(f" [Image: {caption}]")
|
||||
except Exception as e:
|
||||
logger.error(f"获取图片描述失败: {e}")
|
||||
else:
|
||||
final_message += " [Image]"
|
||||
parts.append(" [Image]")
|
||||
|
||||
final_message = "".join(parts)
|
||||
logger.debug(f"ltm | {event.unified_msg_origin} | {final_message}")
|
||||
self.session_chats[event.unified_msg_origin].append(final_message)
|
||||
if len(self.session_chats[event.unified_msg_origin]) > cfg["max_cnt"]:
|
||||
|
||||
@@ -203,14 +203,15 @@ class Main(star.Star):
|
||||
if not reminders:
|
||||
yield event.plain_result("没有正在进行的待办事项。")
|
||||
else:
|
||||
reminder_str = "正在进行的待办事项:\n"
|
||||
parts = ["正在进行的待办事项:\n"]
|
||||
for i, reminder in enumerate(reminders):
|
||||
time_ = reminder.get("datetime", "")
|
||||
if not time_:
|
||||
cron_expr = reminder.get("cron", "")
|
||||
time_ = reminder.get("cron_h", "") + f"(Cron: {cron_expr})"
|
||||
reminder_str += f"{i + 1}. {reminder['text']} - {time_}\n"
|
||||
reminder_str += "\n使用 /reminder rm <id> 删除待办事项。\n"
|
||||
parts.append(f"{i + 1}. {reminder['text']} - {time_}\n")
|
||||
parts.append("\n使用 /reminder rm <id> 删除待办事项。\n")
|
||||
reminder_str = "".join(parts)
|
||||
yield event.plain_result(reminder_str)
|
||||
|
||||
@reminder.command("rm")
|
||||
|
||||
Reference in New Issue
Block a user