chore: 恢复PR改动并适配官方最新版本
在官方更新到4936a6d后,选择性恢复PR中的功能改动: Maizone插件修复(6个文件): - 优化成功/失败反馈机制(直接反馈,不使用AI生成) - 实现QQ空间Cookie失效自动重试机制 - 修复评论回复被分割导致标点符号丢失的问题 - 修复QQ空间转发内容提取错误 - 改进maizone图片识别模型配置,支持自动fallback - 优化maizone说说生成规则 适配器响应处理(bot.py): - 添加adapter_response消息处理逻辑 - 适配新的DatabaseMessages架构 - 在message_process早期阶段优先处理adapter_response Web搜索引擎扩展: - 添加Serper搜索引擎支持 LLM成本计算修复: - 修复LLM使用统计中成本计算错误的bug - 调整LLM相关日志级别为DEBUG 其他优化: - 优化NapCat adapter响应处理 - 优化person_info关系推理逻辑 注:本次恢复已跳过与官方冲突的部分,保留官方的新架构改进 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -15,11 +15,11 @@ from .payload_content.message import Message, MessageBuilder
|
||||
logger = get_logger("消息压缩工具")
|
||||
|
||||
|
||||
def compress_messages(messages: list[Message], img_target_size: int = 2 * 1024 * 1024) -> list[Message]:
|
||||
def compress_messages(messages: list[Message], img_target_size: int = 1 * 1024 * 1024) -> list[Message]:
|
||||
"""
|
||||
压缩消息列表中的图片
|
||||
:param messages: 消息列表
|
||||
:param img_target_size: 图片目标大小,默认2MB
|
||||
:param img_target_size: 图片目标大小,默认1MB
|
||||
:return: 压缩后的消息列表
|
||||
"""
|
||||
|
||||
@@ -30,7 +30,7 @@ def compress_messages(messages: list[Message], img_target_size: int = 2 * 1024 *
|
||||
:return: 转换后的图片数据
|
||||
"""
|
||||
try:
|
||||
image = Image.open(io.BytesIO(image_data))
|
||||
image = Image.open(image_data)
|
||||
|
||||
if image.format and (image.format.upper() in ["JPEG", "JPG", "PNG", "WEBP"]):
|
||||
# 静态图像,转换为JPEG格式
|
||||
@@ -51,7 +51,7 @@ def compress_messages(messages: list[Message], img_target_size: int = 2 * 1024 *
|
||||
:return: 缩放后的图片数据
|
||||
"""
|
||||
try:
|
||||
image = Image.open(io.BytesIO(image_data))
|
||||
image = Image.open(image_data)
|
||||
|
||||
# 原始尺寸
|
||||
original_size = (image.width, image.height)
|
||||
@@ -156,13 +156,9 @@ class LLMUsageRecorder:
|
||||
endpoint: str,
|
||||
time_cost: float = 0.0,
|
||||
):
|
||||
prompt_tokens = getattr(model_usage, "prompt_tokens", 0)
|
||||
completion_tokens = getattr(model_usage, "completion_tokens", 0)
|
||||
total_tokens = getattr(model_usage, "total_tokens", 0)
|
||||
|
||||
input_cost = (prompt_tokens / 1000000) * model_info.price_in
|
||||
output_cost = (completion_tokens / 1000000) * model_info.price_out
|
||||
round(input_cost + output_cost, 6)
|
||||
input_cost = (model_usage.prompt_tokens / 1000000) * model_info.price_in
|
||||
output_cost = (model_usage.completion_tokens / 1000000) * model_info.price_out
|
||||
total_cost = round(input_cost + output_cost, 6)
|
||||
|
||||
session = None
|
||||
try:
|
||||
@@ -175,10 +171,10 @@ class LLMUsageRecorder:
|
||||
user_id=user_id,
|
||||
request_type=request_type,
|
||||
endpoint=endpoint,
|
||||
prompt_tokens=prompt_tokens,
|
||||
completion_tokens=completion_tokens,
|
||||
total_tokens=total_tokens,
|
||||
cost=1.0,
|
||||
prompt_tokens=model_usage.prompt_tokens or 0,
|
||||
completion_tokens=model_usage.completion_tokens or 0,
|
||||
total_tokens=model_usage.total_tokens or 0,
|
||||
cost=total_cost,
|
||||
time_cost=round(time_cost or 0.0, 3),
|
||||
status="success",
|
||||
timestamp=datetime.now(), # SQLAlchemy 会处理 DateTime 字段
|
||||
@@ -190,8 +186,8 @@ class LLMUsageRecorder:
|
||||
logger.debug(
|
||||
f"Token使用情况 - 模型: {model_usage.model_name}, "
|
||||
f"用户: {user_id}, 类型: {request_type}, "
|
||||
f"提示词: {prompt_tokens}, 完成: {completion_tokens}, "
|
||||
f"总计: {total_tokens}"
|
||||
f"提示词: {model_usage.prompt_tokens}, 完成: {model_usage.completion_tokens}, "
|
||||
f"总计: {model_usage.total_tokens}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"记录token使用情况失败: {e!s}")
|
||||
|
||||
@@ -534,7 +534,7 @@ class _RequestExecutor:
|
||||
model_name = model_info.name
|
||||
retry_interval = api_provider.retry_interval
|
||||
|
||||
if isinstance(e, NetworkConnectionError | ReqAbortException):
|
||||
if isinstance(e, (NetworkConnectionError, ReqAbortException)):
|
||||
return await self._check_retry(remain_try, retry_interval, "连接异常", model_name)
|
||||
elif isinstance(e, RespNotOkException):
|
||||
return await self._handle_resp_not_ok(e, model_info, api_provider, remain_try, messages_info)
|
||||
@@ -1009,15 +1009,12 @@ class LLMRequest:
|
||||
# 步骤1: 更新内存中的统计数据,用于负载均衡
|
||||
stats = self.model_usage[model_info.name]
|
||||
|
||||
# 安全地获取 token 使用量, embedding 模型可能不返回 completion_tokens
|
||||
total_tokens = getattr(usage, "total_tokens", 0)
|
||||
|
||||
# 计算新的平均延迟
|
||||
new_request_count = stats.request_count + 1
|
||||
new_avg_latency = (stats.avg_latency * stats.request_count + time_cost) / new_request_count
|
||||
|
||||
self.model_usage[model_info.name] = stats._replace(
|
||||
total_tokens=stats.total_tokens + total_tokens,
|
||||
total_tokens=stats.total_tokens + usage.total_tokens,
|
||||
avg_latency=new_avg_latency,
|
||||
request_count=new_request_count,
|
||||
)
|
||||
@@ -1064,8 +1061,7 @@ class LLMRequest:
|
||||
# 遍历工具的参数
|
||||
for param in tool.get("parameters", []):
|
||||
# 严格验证参数格式是否为包含5个元素的元组
|
||||
assert isinstance(param, tuple), "参数必须是元组"
|
||||
assert len(param) == 5, "参数必须包含5个元素"
|
||||
assert isinstance(param, tuple) and len(param) == 5, "参数必须是包含5个元素的元组"
|
||||
builder.add_param(
|
||||
name=param[0],
|
||||
param_type=param[1],
|
||||
|
||||
Reference in New Issue
Block a user