From a8f45e7c061b0a295f0c7bf2bed9fa22f8797372 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 14 May 2025 14:41:11 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=A4=96=20=E8=87=AA=E5=8A=A8=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F=E5=8C=96=E4=BB=A3=E7=A0=81=20[skip=20ci]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../expressors/default_expressor.py | 14 +- src/chat/focus_chat/heartFC_chat.py | 4 +- src/chat/focus_chat/heartFC_sender.py | 2 +- .../focus_chat/heartflow_prompt_builder.py | 2 +- src/chat/normal_chat/normal_chat.py | 2 +- src/chat/utils/chat_message_builder.py | 2 +- src/chat/utils/statistic.py | 125 ++++++++++-------- src/chat/utils/utils.py | 34 +++-- src/experimental/Legacy_HFC/heartFC_chat.py | 9 +- .../Legacy_HFC/heart_flow/sub_mind.py | 4 +- src/experimental/PFC/PFC_idle/idle_chat.py | 3 - .../group_nickname/nickname_manager.py | 1 + 12 files changed, 118 insertions(+), 84 deletions(-) diff --git a/src/chat/focus_chat/expressors/default_expressor.py b/src/chat/focus_chat/expressors/default_expressor.py index 0fd31d25..4b253c6c 100644 --- a/src/chat/focus_chat/expressors/default_expressor.py +++ b/src/chat/focus_chat/expressors/default_expressor.py @@ -116,12 +116,14 @@ class DefaultExpressor: # 为 trigger_nickname_analysis 准备 bot_reply 参数 bot_reply_for_analysis = [] - if reply: # reply 是 List[Tuple[str, str]] + if reply: # reply 是 List[Tuple[str, str]] for seg_type, seg_data in reply: - if seg_type == "text": # 只取文本类型的数据 + if seg_type == "text": # 只取文本类型的数据 bot_reply_for_analysis.append(seg_data) - await nickname_manager.trigger_nickname_analysis(anchor_message, bot_reply_for_analysis, self.chat_stream) + await nickname_manager.trigger_nickname_analysis( + anchor_message, bot_reply_for_analysis, self.chat_stream + ) else: logger.warning(f"{self.log_prefix} 文本回复生成失败") @@ -260,7 +262,7 @@ class DefaultExpressor: mark_head = False _first_bot_msg: Optional[MessageSending] = None reply_message_ids = [] # 记录实际发送的消息ID - + sent_msg_list = [] for i, msg_text in enumerate(response_set): @@ -300,7 +302,7 @@ class DefaultExpressor: sent_msg = await self.heart_fc_sender.send_message(bot_message, has_thinking=True, typing=typing) reply_message_ids.append(part_message_id) # 记录我们生成的ID - + sent_msg_list.append((type, sent_msg)) except Exception as e: @@ -310,7 +312,7 @@ class DefaultExpressor: # 在尝试发送完所有片段后,完成原始的 thinking_id 状态 try: await self.heart_fc_sender.complete_thinking(chat_id, thinking_id) - + except Exception as e: logger.error(f"{self.log_prefix}完成思考状态 {thinking_id} 时出错: {e}") diff --git a/src/chat/focus_chat/heartFC_chat.py b/src/chat/focus_chat/heartFC_chat.py index eacc73f5..8c1dd293 100644 --- a/src/chat/focus_chat/heartFC_chat.py +++ b/src/chat/focus_chat/heartFC_chat.py @@ -925,7 +925,9 @@ class HeartFChatting: if action == "reply" and emoji: logger.debug(f"{self.log_prefix}[Planner] 大模型建议文字回复带表情: '{emoji}'") if random.random() > EMOJI_SEND_PRO: - logger.info(f"{self.log_prefix}但是麦麦这次不想加表情 ({1 - EMOJI_SEND_PRO:.0%}),忽略表情 '{emoji}'") + logger.info( + f"{self.log_prefix}但是麦麦这次不想加表情 ({1 - EMOJI_SEND_PRO:.0%}),忽略表情 '{emoji}'" + ) action_data["emojis"] = "" # 清空表情请求 else: logger.info(f"{self.log_prefix}好吧,加上表情 '{emoji}'") diff --git a/src/chat/focus_chat/heartFC_sender.py b/src/chat/focus_chat/heartFC_sender.py index bce43563..05766857 100644 --- a/src/chat/focus_chat/heartFC_sender.py +++ b/src/chat/focus_chat/heartFC_sender.py @@ -123,7 +123,7 @@ class HeartFCSender: sent_msg = await send_message(message) await self.storage.store_message(message, message.chat_stream) - + if sent_msg: return sent_msg else: diff --git a/src/chat/focus_chat/heartflow_prompt_builder.py b/src/chat/focus_chat/heartflow_prompt_builder.py index 5eb880e1..deea9aec 100644 --- a/src/chat/focus_chat/heartflow_prompt_builder.py +++ b/src/chat/focus_chat/heartflow_prompt_builder.py @@ -876,4 +876,4 @@ def weighted_sample_no_replacement(items, weights, k) -> list: init_prompt() -prompt_builder = PromptBuilder() \ No newline at end of file +prompt_builder = PromptBuilder() diff --git a/src/chat/normal_chat/normal_chat.py b/src/chat/normal_chat/normal_chat.py index a464925b..4ddfdd3d 100644 --- a/src/chat/normal_chat/normal_chat.py +++ b/src/chat/normal_chat/normal_chat.py @@ -524,4 +524,4 @@ class NormalChat: logger.info(f"[{self.stream_name}] 清理了 {len(thinking_messages)} 条未处理的思考消息。") except Exception as e: logger.error(f"[{self.stream_name}] 清理思考消息时出错: {e}") - logger.error(traceback.format_exc()) \ No newline at end of file + logger.error(traceback.format_exc()) diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index 667a9589..2d34b669 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -424,7 +424,7 @@ async def build_anonymous_messages(messages: List[Dict[str, Any]]) -> str: # 分配占位符 person_map = {} - current_char = ord('A') + current_char = ord("A") output_lines = [] for msg in messages: diff --git a/src/chat/utils/statistic.py b/src/chat/utils/statistic.py index da5b5b8b..1b9d1f14 100644 --- a/src/chat/utils/statistic.py +++ b/src/chat/utils/statistic.py @@ -102,7 +102,7 @@ def _format_online_time(online_seconds: int) -> str: :param online_seconds: 在线时间(秒) :return: 格式化后的在线时间字符串 """ - total_oneline_time = timedelta(seconds=int(online_seconds)) #确保是整数 + total_oneline_time = timedelta(seconds=int(online_seconds)) # 确保是整数 days = total_oneline_time.days hours = total_oneline_time.seconds // 3600 @@ -141,7 +141,7 @@ class StatisticOutputTask(AsyncTask): 记录文件路径 """ - now = datetime.now() # Renamed to avoid conflict with 'now' in methods + now = datetime.now() # Renamed to avoid conflict with 'now' in methods if "deploy_time" in local_storage: # 如果存在部署时间,则使用该时间作为全量统计的起始时间 deploy_time = datetime.fromtimestamp(local_storage["deploy_time"]) @@ -167,7 +167,7 @@ class StatisticOutputTask(AsyncTask): :param now: 基准当前时间 """ # 输出最近一小时的统计数据 - last_hour_stats = stats.get("last_hour", {}) # Ensure 'last_hour' key exists + last_hour_stats = stats.get("last_hour", {}) # Ensure 'last_hour' key exists output = [ self.SEP_LINE, @@ -191,7 +191,7 @@ class StatisticOutputTask(AsyncTask): stats = self._collect_all_statistics(now) # 输出统计数据到控制台 - if "last_hour" in stats: # Check if stats for last_hour were successfully collected + if "last_hour" in stats: # Check if stats for last_hour were successfully collected self._statistic_console_output(stats, now) else: logger.warning("无法输出最近一小时统计数据到控制台,因为数据缺失。") @@ -209,7 +209,7 @@ class StatisticOutputTask(AsyncTask): :param collect_period: 统计时间段 [(period_key, start_datetime), ...] """ - if not collect_period: + if not collect_period: return {} collect_period.sort(key=lambda x: x[1], reverse=True) @@ -236,21 +236,20 @@ class StatisticOutputTask(AsyncTask): } for period_key, _ in collect_period } - + # Determine the overall earliest start time for the database query # This assumes collect_period is not empty, which is checked at the beginning. overall_earliest_start_time = min(p[1] for p in collect_period) for record in db.llm_usage.find({"timestamp": {"$gte": overall_earliest_start_time}}): record_timestamp = record.get("timestamp") - if not isinstance(record_timestamp, datetime): # Ensure timestamp is a datetime object - try: # Attempt conversion if it's a number (e.g. Unix timestamp) + if not isinstance(record_timestamp, datetime): # Ensure timestamp is a datetime object + try: # Attempt conversion if it's a number (e.g. Unix timestamp) record_timestamp = datetime.fromtimestamp(float(record_timestamp)) except (ValueError, TypeError): logger.warning(f"Skipping LLM usage record with invalid timestamp: {record.get('_id')}") continue - for idx, (_current_period_key, period_start_time) in enumerate(collect_period): if record_timestamp >= period_start_time: for period_key_to_update, _ in collect_period[idx:]: @@ -285,7 +284,7 @@ class StatisticOutputTask(AsyncTask): stats[period_key_to_update][COST_BY_TYPE][request_type] += cost stats[period_key_to_update][COST_BY_USER][user_id] += cost stats[period_key_to_update][COST_BY_MODEL][model_name] += cost - break + break return stats @@ -308,7 +307,7 @@ class StatisticOutputTask(AsyncTask): } for period_key, _ in collect_period } - + overall_earliest_start_time = min(p[1] for p in collect_period) for record in db.online_time.find({"end_timestamp": {"$gte": overall_earliest_start_time}}): @@ -324,13 +323,13 @@ class StatisticOutputTask(AsyncTask): for idx, (_current_period_key, period_start_time) in enumerate(collect_period): if record_start_timestamp < now and actual_end_timestamp > period_start_time: overlap_start = max(record_start_timestamp, period_start_time) - overlap_end = min(actual_end_timestamp, now) + overlap_end = min(actual_end_timestamp, now) - if overlap_end > overlap_start: + if overlap_end > overlap_start: duration_seconds = (overlap_end - overlap_start).total_seconds() for period_key_to_update, _ in collect_period[idx:]: stats[period_key_to_update][ONLINE_TIME] += duration_seconds - break + break return stats @@ -354,37 +353,36 @@ class StatisticOutputTask(AsyncTask): } overall_earliest_start_timestamp_float = min(p[1].timestamp() for p in collect_period) - - for message in db.messages.find({"time": {"$gte": overall_earliest_start_timestamp_float}}): - chat_info = message.get("chat_info", {}) - user_info = message.get("user_info", {}) - message_time_ts = message.get("time") - if message_time_ts is None: + for message in db.messages.find({"time": {"$gte": overall_earliest_start_timestamp_float}}): + chat_info = message.get("chat_info", {}) + user_info = message.get("user_info", {}) + message_time_ts = message.get("time") + + if message_time_ts is None: logger.warning(f"Skipping message record with no timestamp: {message.get('_id')}") continue - + try: message_datetime = datetime.fromtimestamp(float(message_time_ts)) except (ValueError, TypeError): logger.warning(f"Skipping message record with invalid time format: {message.get('_id')}") continue - group_info = chat_info.get("group_info") chat_id = None chat_name = None if group_info and group_info.get("group_id"): - gid = group_info.get('group_id') + gid = group_info.get("group_id") chat_id = f"g{gid}" chat_name = group_info.get("group_name", f"群聊 {gid}") elif user_info and user_info.get("user_id"): - uid = user_info['user_id'] + uid = user_info["user_id"] chat_id = f"u{uid}" chat_name = user_info.get("user_nickname", f"用户 {uid}") - - if not chat_id: + + if not chat_id: continue current_mapping = self.name_mapping.get(chat_id) @@ -394,13 +392,12 @@ class StatisticOutputTask(AsyncTask): else: self.name_mapping[chat_id] = (chat_name, message_time_ts) - for idx, (_current_period_key, period_start_time) in enumerate(collect_period): if message_datetime >= period_start_time: for period_key_to_update, _ in collect_period[idx:]: stats[period_key_to_update][TOTAL_MSG_CNT] += 1 stats[period_key_to_update][MSG_CNT_BY_CHAT][chat_id] += 1 - break + break return stats @@ -428,7 +425,7 @@ class StatisticOutputTask(AsyncTask): ("last_24_hours", timedelta(days=1), "最近24小时"), ("last_hour", timedelta(hours=1), "最近1小时"), ] - self.stat_period = current_stat_periods_config # Update instance's stat_period if needed elsewhere + self.stat_period = current_stat_periods_config # Update instance's stat_period if needed elsewhere stat_start_timestamp_config = [] for period_name, delta, _ in current_stat_periods_config: @@ -446,23 +443,39 @@ class StatisticOutputTask(AsyncTask): final_stats[period_key].update(model_req_stat.get(period_key, {})) final_stats[period_key].update(online_time_stat.get(period_key, {})) final_stats[period_key].update(message_count_stat.get(period_key, {})) - + for stat_field_key in [ - TOTAL_REQ_CNT, REQ_CNT_BY_TYPE, REQ_CNT_BY_USER, REQ_CNT_BY_MODEL, - IN_TOK_BY_TYPE, IN_TOK_BY_USER, IN_TOK_BY_MODEL, - OUT_TOK_BY_TYPE, OUT_TOK_BY_USER, OUT_TOK_BY_MODEL, - TOTAL_TOK_BY_TYPE, TOTAL_TOK_BY_USER, TOTAL_TOK_BY_MODEL, - TOTAL_COST, COST_BY_TYPE, COST_BY_USER, COST_BY_MODEL, - ONLINE_TIME, TOTAL_MSG_CNT, MSG_CNT_BY_CHAT + TOTAL_REQ_CNT, + REQ_CNT_BY_TYPE, + REQ_CNT_BY_USER, + REQ_CNT_BY_MODEL, + IN_TOK_BY_TYPE, + IN_TOK_BY_USER, + IN_TOK_BY_MODEL, + OUT_TOK_BY_TYPE, + OUT_TOK_BY_USER, + OUT_TOK_BY_MODEL, + TOTAL_TOK_BY_TYPE, + TOTAL_TOK_BY_USER, + TOTAL_TOK_BY_MODEL, + TOTAL_COST, + COST_BY_TYPE, + COST_BY_USER, + COST_BY_MODEL, + ONLINE_TIME, + TOTAL_MSG_CNT, + MSG_CNT_BY_CHAT, ]: if stat_field_key not in final_stats[period_key]: # Initialize with appropriate default type if key is missing - if "BY_" in stat_field_key: # These are usually defaultdicts - final_stats[period_key][stat_field_key] = defaultdict(int if "CNT" in stat_field_key or "TOK" in stat_field_key else float) - elif "CNT" in stat_field_key or "TOK" in stat_field_key : - final_stats[period_key][stat_field_key] = 0 + if "BY_" in stat_field_key: # These are usually defaultdicts + final_stats[period_key][stat_field_key] = defaultdict( + int if "CNT" in stat_field_key or "TOK" in stat_field_key else float + ) + elif "CNT" in stat_field_key or "TOK" in stat_field_key: + final_stats[period_key][stat_field_key] = 0 elif "COST" in stat_field_key or ONLINE_TIME == stat_field_key: - final_stats[period_key][stat_field_key] = 0.0 + final_stats[period_key][stat_field_key] = 0.0 return final_stats # -- 以下为统计数据格式化方法 -- @@ -517,7 +530,7 @@ class StatisticOutputTask(AsyncTask): """ if stats.get(TOTAL_MSG_CNT, 0) > 0: output = ["聊天消息统计:", " 联系人/群组名称 消息数量"] - msg_cnt_by_chat = stats.get(MSG_CNT_BY_CHAT, {}) + msg_cnt_by_chat = stats.get(MSG_CNT_BY_CHAT, {}) for chat_id, count in sorted(msg_cnt_by_chat.items()): chat_name_display = self.name_mapping.get(chat_id, (f"未知 ({chat_id})", None))[0] output.append(f"{chat_name_display[:32]:<32} {count:>10}") @@ -539,21 +552,25 @@ class StatisticOutputTask(AsyncTask): deploy_time_dt = datetime.fromtimestamp(local_storage["deploy_time"]) except (TypeError, ValueError): logger.error("Invalid deploy_time in local_storage for HTML report. Using default.") - deploy_time_dt = datetime(2000,1,1) # Fallback + deploy_time_dt = datetime(2000, 1, 1) # Fallback else: # This should ideally not happen if __init__ or _collect_all_statistics ran logger.warning("deploy_time not found in local_storage for HTML report. Using default.") - deploy_time_dt = datetime(2000, 1, 1) # Fallback + deploy_time_dt = datetime(2000, 1, 1) # Fallback tab_list_html = [] tab_content_html_list = [] - for period_key, period_delta, period_display_name in self.stat_period: # Use self.stat_period as defined by _collect_all_statistics + for ( + period_key, + period_delta, + period_display_name, + ) in self.stat_period: # Use self.stat_period as defined by _collect_all_statistics tab_list_html.append( f'' ) - current_period_stats = stat_collection.get(period_key, {}) + current_period_stats = stat_collection.get(period_key, {}) if period_key == "all_time": start_time_dt_for_period = deploy_time_dt @@ -561,11 +578,12 @@ class StatisticOutputTask(AsyncTask): # Ensure period_delta is a timedelta object if isinstance(period_delta, timedelta): start_time_dt_for_period = now - period_delta - else: # Fallback if period_delta is not as expected (e.g. from old self.stat_period) - logger.warning(f"period_delta for {period_key} is not a timedelta. Using 'now'. Type: {type(period_delta)}") + else: # Fallback if period_delta is not as expected (e.g. from old self.stat_period) + logger.warning( + f"period_delta for {period_key} is not a timedelta. Using 'now'. Type: {type(period_delta)}" + ) start_time_dt_for_period = now - html_content_for_tab = f"""

@@ -630,7 +648,7 @@ class StatisticOutputTask(AsyncTask): cost_by_user = current_period_stats.get(COST_BY_USER, defaultdict(float)) if req_cnt_by_user: for user_id, count in sorted(req_cnt_by_user.items()): - user_display_name = self.name_mapping.get(user_id, (user_id, None))[0] + user_display_name = self.name_mapping.get(user_id, (user_id, None))[0] html_content_for_tab += ( f"" f"{user_display_name}" @@ -645,7 +663,9 @@ class StatisticOutputTask(AsyncTask): html_content_for_tab += "无数据" html_content_for_tab += "" - html_content_for_tab += "

聊天消息统计

" + html_content_for_tab += ( + "

聊天消息统计

联系人/群组名称消息数量
" + ) msg_cnt_by_chat = current_period_stats.get(MSG_CNT_BY_CHAT, {}) if msg_cnt_by_chat: for chat_id, count in sorted(msg_cnt_by_chat.items()): @@ -653,11 +673,10 @@ class StatisticOutputTask(AsyncTask): html_content_for_tab += f"" else: html_content_for_tab += "" - html_content_for_tab += "
联系人/群组名称消息数量
{chat_name_display}{count}
无数据
" + html_content_for_tab += "" tab_content_html_list.append(html_content_for_tab) - html_template = ( """ diff --git a/src/chat/utils/utils.py b/src/chat/utils/utils.py index 9df77726..c058d2e7 100644 --- a/src/chat/utils/utils.py +++ b/src/chat/utils/utils.py @@ -20,8 +20,9 @@ from ...config.config import global_config logger = get_module_logger("chat_utils") # 预编译正则表达式以提高性能 -_L_REGEX = regex.compile(r'\p{L}') # 匹配任何Unicode字母 -_HAN_CHAR_REGEX = regex.compile(r'\p{Han}') # 匹配汉字 (Unicode属性) +_L_REGEX = regex.compile(r"\p{L}") # 匹配任何Unicode字母 +_HAN_CHAR_REGEX = regex.compile(r"\p{Han}") # 匹配汉字 (Unicode属性) + def is_letter_not_han(char_str: str) -> bool: """ @@ -40,16 +41,19 @@ def is_letter_not_han(char_str: str) -> bool: is_han = _HAN_CHAR_REGEX.fullmatch(char_str) is not None return not is_han + def is_han_character(char_str: str) -> bool: """检查字符是否为汉字 (使用 \p{Han} Unicode 属性)""" if not isinstance(char_str, str) or len(char_str) != 1: return False return _HAN_CHAR_REGEX.fullmatch(char_str) is not None + def is_english_letter(char: str) -> bool: """检查字符是否为英文字母(忽略大小写)""" return "a" <= char.lower() <= "z" + def db_message_to_str(message_dict: dict) -> str: logger.debug(f"message_dict: {message_dict}") time_str = time.strftime("%m-%d %H:%M:%S", time.localtime(message_dict["time"])) @@ -101,7 +105,8 @@ def is_mentioned_bot_in_message(message: MessageRecv) -> tuple[bool, float]: if not is_mentioned: # 判断是否被回复 if re.match( - f"\\[回复 [\\s\\S]*?\\({str(global_config.BOT_QQ)}\\):[\\s\\S]*?\\],说:", message.processed_plain_text + f"\\[回复 [\\s\\S]*?\\({str(global_config.BOT_QQ)}\\):[\\s\\S]*?\\],说:", + message.processed_plain_text, ): is_mentioned = True else: @@ -211,6 +216,7 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: # 2. 处理换行符和其他分隔符的组合 (增加了 . 和 —) text = regex.sub(r"\n\s*([—。.,,;\s\xa0])", r"\1", text) text = regex.sub(r"([—。.,,;\s\xa0])\s*\n", r"\1", text) + # 3. 处理两个汉字中间的换行符 def replace_han_newline(match): char1 = match.group(1) @@ -218,6 +224,7 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: if is_han_character(char1) and is_han_character(char2): return char1 + "。" + char2 return match.group(0) + text = regex.sub(r"(.)\n(.)", replace_han_newline, text) len_text = len(text) @@ -239,7 +246,7 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: if char in separators: can_split = True - if char == ' ' or char == '\xa0': + if char == " " or char == "\xa0": if 0 < i < len(text) - 1: prev_char = text[i - 1] next_char = text[i + 1] @@ -251,9 +258,9 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: if can_split: if current_segment: segments.append((current_segment, char)) - elif char not in [' ', '\xa0']: + elif char not in [" ", "\xa0"]: segments.append(("", char)) - elif char in [' ', '\xa0']: + elif char in [" ", "\xa0"]: segments.append(("", char)) current_segment = "" else: @@ -268,9 +275,9 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: temp_segments_for_filter = [] for content, sep in segments: if content.strip(): - temp_segments_for_filter.append((content,sep)) - elif sep and sep not in [' ', '\xa0']: - temp_segments_for_filter.append((content,sep)) + temp_segments_for_filter.append((content, sep)) + elif sep and sep not in [" ", "\xa0"]: + temp_segments_for_filter.append((content, sep)) segments = temp_segments_for_filter if not segments: @@ -280,7 +287,7 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: current_sentence_build = "" for content, sep in segments: current_sentence_build += content - if sep and sep not in [' ', '\xa0']: + if sep and sep not in [" ", "\xa0"]: current_sentence_build += sep if current_sentence_build.strip(): preliminary_final_sentences.append(current_sentence_build.strip()) @@ -310,7 +317,7 @@ def split_into_sentences_w_remove_punctuation(text: str) -> list[str]: temp_sentence = preliminary_final_sentences[0] for i in range(1, len(preliminary_final_sentences)): if random.random() < merge_probability and temp_sentence: - temp_sentence += " " + preliminary_final_sentences[i] + temp_sentence += " " + preliminary_final_sentences[i] else: if temp_sentence: final_sentences_merged.append(temp_sentence) @@ -448,7 +455,7 @@ def calculate_typing_time( total_time = 0 for char in input_string: - if is_han_character(char): # 使用 is_han_character 进行判断 + if is_han_character(char): # 使用 is_han_character 进行判断 total_time += chinese_time else: total_time += english_time @@ -462,7 +469,6 @@ def calculate_typing_time( return total_time - def cosine_similarity(v1, v2): """计算余弦相似度""" dot_product = np.dot(v1, v2) @@ -578,7 +584,7 @@ def get_western_ratio(paragraph): if not alnum_chars: return 0.0 - western_count = sum(1 for char in alnum_chars if is_english_letter(char)) # 保持使用 is_english_letter + western_count = sum(1 for char in alnum_chars if is_english_letter(char)) # 保持使用 is_english_letter return western_count / len(alnum_chars) diff --git a/src/experimental/Legacy_HFC/heartFC_chat.py b/src/experimental/Legacy_HFC/heartFC_chat.py index 31e875e4..8f1d4f00 100644 --- a/src/experimental/Legacy_HFC/heartFC_chat.py +++ b/src/experimental/Legacy_HFC/heartFC_chat.py @@ -17,7 +17,14 @@ from .heart_flow.sub_mind import SubMind from .heart_flow.utils_chat import get_chat_type_and_target_info from src.manager.mood_manager import mood_manager from src.chat.message_receive.chat_stream import ChatStream, chat_manager -from src.chat.message_receive.message import MessageRecv, BaseMessageInfo, MessageThinking, MessageSending, Seg, UserInfo +from src.chat.message_receive.message import ( + MessageRecv, + BaseMessageInfo, + MessageThinking, + MessageSending, + Seg, + UserInfo, +) from src.chat.utils.utils import process_llm_response from src.chat.utils.utils_image import image_path_to_base64 from src.chat.emoji_system.emoji_manager import emoji_manager diff --git a/src/experimental/Legacy_HFC/heart_flow/sub_mind.py b/src/experimental/Legacy_HFC/heart_flow/sub_mind.py index 9e4d822d..0937398a 100644 --- a/src/experimental/Legacy_HFC/heart_flow/sub_mind.py +++ b/src/experimental/Legacy_HFC/heart_flow/sub_mind.py @@ -567,7 +567,7 @@ class SubMind: # ---------- 5. 构建最终提示词 ---------- # --- Choose template based on chat type --- - nickname_injection_str = "" # 初始化为空字符串 + nickname_injection_str = "" # 初始化为空字符串 if is_group_chat: template_name = "sub_heartflow_prompt_before" @@ -584,7 +584,7 @@ class SubMind: ) nickname_injection_str = await nickname_manager.get_nickname_prompt_injection( chat_stream, message_list_for_nicknames - ) + ) prompt = (await global_prompt_manager.get_prompt_async(template_name)).format( extra_info=self.structured_info_str, diff --git a/src/experimental/PFC/PFC_idle/idle_chat.py b/src/experimental/PFC/PFC_idle/idle_chat.py index f03a06e4..dff5d954 100644 --- a/src/experimental/PFC/PFC_idle/idle_chat.py +++ b/src/experimental/PFC/PFC_idle/idle_chat.py @@ -264,8 +264,6 @@ class IdleChat: # 获取关系值 relationship_value = 0 try: - - # 尝试获取person_id person_id = None try: @@ -428,7 +426,6 @@ class IdleChat: async def _get_chat_stream(self) -> Optional[ChatStream]: """获取聊天流实例""" try: - existing_chat_stream = chat_manager.get_stream(self.stream_id) if existing_chat_stream: logger.debug(f"[私聊][{self.private_name}]从chat_manager找到现有聊天流") diff --git a/src/plugins/group_nickname/nickname_manager.py b/src/plugins/group_nickname/nickname_manager.py index 27da4abc..7e2a74e7 100644 --- a/src/plugins/group_nickname/nickname_manager.py +++ b/src/plugins/group_nickname/nickname_manager.py @@ -18,6 +18,7 @@ from src.chat.person_info.relationship_manager import relationship_manager from src.chat.message_receive.chat_stream import ChatStream from src.chat.message_receive.message import MessageRecv from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat + logger = get_logger("NicknameManager") logger_helper = get_logger("AsyncLoopHelper") # 为辅助函数创建单独的 logger