避免try catch嵌套

pull/914/head
Bakadax 2025-05-02 22:42:49 +08:00
parent 76a37452a0
commit b8d243873b
1 changed files with 75 additions and 64 deletions

View File

@ -103,76 +103,87 @@ async def analyze_chat_for_nicknames(
# 清理可能的 Markdown 代码块标记
response_content = response_content.strip()
# 使用正则表达式处理各种 Markdown 代码块情况
markdown_code_regex = re.compile(r"^```(?:\w+)?\s*\n(.*?)\n\s*```$", re.DOTALL)
match = markdown_code_regex.match(response_content)
if match:
response_content = match.group(1).strip()
try:
result = json.loads(response_content)
if isinstance(result, dict) and "is_exist" in result:
if result["is_exist"] is True:
original_data = result.get("data") # 使用 .get() 更安全
if isinstance(original_data, dict) and original_data: # 确保 data 是非空字典
logger.info(f"LLM 找到的原始绰号映射: {original_data}")
# 解析 JSON
result = json.loads(response_content) # 可能抛出 json.JSONDecodeError
# --- 开始过滤 ---
filtered_data = {}
bot_qq_str = str(global_config.BOT_QQ) # 将机器人QQ转为字符串以便比较
for user_id, nickname in original_data.items():
# 检查 user_id 是否是字符串,以防万一
if not isinstance(user_id, str):
logger.warning(f"LLM 返回的 user_id '{user_id}' 不是字符串,跳过。")
continue
# 条件 1: 排除机器人自身
if user_id == bot_qq_str:
logger.debug(f"过滤掉机器人自身的映射: ID {user_id}")
continue
# 有了改名工具后,该过滤器已不适合了,尝试通过修改 prompt 获得更好的结果
# # 条件 2: 排除 nickname 与 person_name 相同的情况
# person_name = user_name_map.get(user_id) # 从传入的映射中查找 person_name
# if person_name and person_name == nickname:
# logger.debug(f"过滤掉用户 {user_id} 的映射: 绰号 '{nickname}' 与其名称 '{person_name}' 相同。")
# continue
# 如果通过所有过滤条件,则保留
filtered_data[user_id] = nickname
# --- 结束过滤 ---
# 检查过滤后是否还有数据
if not filtered_data:
logger.info("所有找到的绰号映射都被过滤掉了。")
return {"is_exist": False}
else:
logger.info(f"过滤后的绰号映射: {filtered_data}")
return {"is_exist": True, "data": filtered_data} # 返回过滤后的数据
else:
# is_exist 为 True 但 data 缺失、不是字典或为空
if "data" not in result:
logger.warning("LLM 响应格式错误: is_exist 为 True 但 'data' 键缺失。")
elif not isinstance(result.get("data"), dict):
logger.warning("LLM 响应格式错误: is_exist 为 True 但 'data' 不是字典。")
else: # data 为空字典
logger.debug("LLM 指示 is_exist=True 但 data 为空字典。视为 False 处理。")
return {"is_exist": False}
elif result["is_exist"] is False:
logger.info("LLM 未找到可靠的绰号映射。")
return {"is_exist": False}
else:
logger.warning("LLM 响应格式错误: 'is_exist' 不是布尔值。")
return {"is_exist": False}
else:
logger.warning("LLM 响应格式错误: 缺少 'is_exist' 键或不是字典。")
return {"is_exist": False}
except json.JSONDecodeError as json_err:
logger.error(f"解析 LLM 响应 JSON 失败: {json_err}\n原始响应: {response_content}")
# 检查 result 是否为字典
if not isinstance(result, dict):
logger.warning(f"LLM 响应不是一个有效的 JSON 对象 (字典类型)。响应内容: {response_content}")
return {"is_exist": False}
except Exception as e:
logger.error(f"绰号映射 LLM 调用或处理过程中出错: {e}", exc_info=True)
# 使用 get 获取 is_exist避免 KeyError
is_exist = result.get("is_exist") # 如果 result 不是字典,下面 get 会在 except AttributeError 中捕获
if is_exist is True:
original_data = result.get("data")
if isinstance(original_data, dict) and original_data: # 确保 data 是非空字典
logger.info(f"LLM 找到的原始绰号映射: {original_data}")
# --- 开始过滤 ---
filtered_data = {}
bot_qq_str = str(global_config.BOT_QQ)
for user_id, nickname in original_data.items():
if not isinstance(user_id, str):
logger.warning(f"LLM 返回的 user_id '{user_id}' 不是字符串,跳过。")
continue
if user_id == bot_qq_str:
logger.debug(f"过滤掉机器人自身的映射: ID {user_id}")
continue
# 有了改名工具后,该过滤器已不适合了,尝试通过修改 prompt 获得更好的结果
# # 条件 2: 排除 nickname 与 person_name 相同的情况
# person_name = user_name_map.get(user_id) # 从传入的映射中查找 person_name
# if person_name and person_name == nickname:
# logger.debug(f"过滤掉用户 {user_id} 的映射: 绰号 '{nickname}' 与其名称 '{person_name}' 相同。")
# continue
# 如果通过所有过滤条件,则保留
filtered_data[user_id] = nickname
# 检查过滤后是否还有数据
if not filtered_data:
logger.info("所有找到的绰号映射都被过滤掉了。")
return {"is_exist": False}
else:
logger.info(f"过滤后的绰号映射: {filtered_data}")
return {"is_exist": True, "data": filtered_data}
else:
# is_exist 为 True 但 data 缺失、不是字典或为空
if "data" not in result:
logger.warning("LLM 响应格式错误: is_exist 为 True 但 'data' 键缺失。")
elif not isinstance(original_data, dict):
logger.warning(f"LLM 响应格式错误: is_exist 为 True 但 'data' 不是字典。 原始 data: {original_data}")
else: # data 为空字典
logger.debug("LLM 指示 is_exist=True 但 data 为空字典。视为 False 处理。")
return {"is_exist": False}
elif is_exist is False:
logger.info("LLM 未找到可靠的绰号映射。")
return {"is_exist": False}
elif is_exist is None: # 处理 is_exist 键存在但值为 null/None 的情况
logger.warning("LLM 响应格式错误: 'is_exist' 键的值为 None。")
return {"is_exist": False}
else: # 处理 is_exist 存在但值不是 True/False/None 的情况
logger.warning(f"LLM 响应格式错误: 'is_exist' 的值 '{is_exist}' 不是预期的布尔值或 None。")
return {"is_exist": False}
except json.JSONDecodeError as json_err:
logger.error(f"解析 LLM 响应 JSON 失败: {json_err}\n原始响应: {response_content}")
return {"is_exist": False}
except AttributeError as attr_err:
# 这个理论上不应该发生,因为在调用 get 前检查了 result 是否是 dict
logger.error(f"处理 LLM 响应时发生属性错误 (可能尝试在非字典对象上使用 .get): {attr_err}\n原始响应: {response_content}")
return {"is_exist": False}
except Exception as e:
# 捕获其他所有未预料到的异常
logger.error(f"绰号映射 LLM 调用或处理过程中发生未预料的错误: {e}", exc_info=True)
return {"is_exist": False}