feat:日志上线数量可更改

pull/1465/head
SengokuCola 2025-12-31 00:07:55 +08:00
parent 4bb28097ea
commit 67c24f84cd
15 changed files with 38 additions and 40 deletions

View File

@ -113,8 +113,6 @@ from .core.claude_config import (
) )
from .tool_chain import ( from .tool_chain import (
ToolChainDefinition, ToolChainDefinition,
ToolChainStep,
ChainExecutionResult,
tool_chain_manager, tool_chain_manager,
) )
@ -1651,7 +1649,7 @@ class MCPStatusCommand(BaseCommand):
tool_name = f"chain_{name}".replace("-", "_").replace(".", "_") tool_name = f"chain_{name}".replace("-", "_").replace(".", "_")
if component_registry.get_component_info(tool_name, ComponentType.TOOL): if component_registry.get_component_info(tool_name, ComponentType.TOOL):
registered += 1 registered += 1
lines = [f"✅ 已重新加载工具链配置"] lines = ["✅ 已重新加载工具链配置"]
lines.append(f"📋 配置数: {len(chains)}") lines.append(f"📋 配置数: {len(chains)}")
lines.append(f"🔧 已注册: {registered} 个(可被 LLM 调用)") lines.append(f"🔧 已注册: {registered} 个(可被 LLM 调用)")
if chains: if chains:
@ -1698,7 +1696,7 @@ class MCPStatusCommand(BaseCommand):
output_preview += "..." output_preview += "..."
lines.append(output_preview) lines.append(output_preview)
else: else:
lines.append(f"❌ 工具链执行失败") lines.append("❌ 工具链执行失败")
lines.append(f"错误: {result.error}") lines.append(f"错误: {result.error}")
if result.step_results: if result.step_results:
lines.append("") lines.append("")
@ -1777,9 +1775,9 @@ class MCPStatusCommand(BaseCommand):
cb = info.get("circuit_breaker", {}) cb = info.get("circuit_breaker", {})
cb_state = cb.get("state", "closed") cb_state = cb.get("state", "closed")
if cb_state == "open": if cb_state == "open":
lines.append(f" ⚡ 断路器熔断中") lines.append(" ⚡ 断路器熔断中")
elif cb_state == "half_open": elif cb_state == "half_open":
lines.append(f" ⚡ 断路器试探中") lines.append(" ⚡ 断路器试探中")
if info["consecutive_failures"] > 0: if info["consecutive_failures"] > 0:
lines.append(f" ⚠️ 连续失败 {info['consecutive_failures']}") lines.append(f" ⚠️ 连续失败 {info['consecutive_failures']}")

View File

@ -14,12 +14,11 @@ MCP Workflow 模块 v1.9.0
- ReAct 软流程互补用户可选择合适的执行方式 - ReAct 软流程互补用户可选择合适的执行方式
""" """
import asyncio
import json import json
import re import re
import time import time
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Tuple, Type from typing import Any, Dict, List, Optional, Tuple
try: try:
from src.common.logger import get_logger from src.common.logger import get_logger

View File

@ -11,7 +11,7 @@ import json
import os import os
import sys import sys
import glob import glob
from collections import Counter, defaultdict from collections import Counter
from datetime import datetime from datetime import datetime
from typing import Dict, List, Set, Tuple from typing import Dict, List, Set, Tuple
@ -147,7 +147,7 @@ def print_file_stats(stats: Dict, index: int = None):
if stats["last_updated"]: if stats["last_updated"]:
print(f"最后更新: {stats['last_updated']}") print(f"最后更新: {stats['last_updated']}")
print(f"\n【记录统计】") print("\n【记录统计】")
print(f" 文件中的 total_count: {stats['total_count']}") print(f" 文件中的 total_count: {stats['total_count']}")
print(f" 实际记录数: {stats['actual_count']}") print(f" 实际记录数: {stats['actual_count']}")
@ -155,18 +155,18 @@ def print_file_stats(stats: Dict, index: int = None):
diff = stats['total_count'] - stats['actual_count'] diff = stats['total_count'] - stats['actual_count']
print(f" ⚠️ 数量不一致,差值: {diff:+d}") print(f" ⚠️ 数量不一致,差值: {diff:+d}")
print(f"\n【评估结果统计】") print("\n【评估结果统计】")
print(f" 通过 (suitable=True): {stats['suitable_count']} 条 ({stats['suitable_rate']:.2f}%)") print(f" 通过 (suitable=True): {stats['suitable_count']} 条 ({stats['suitable_rate']:.2f}%)")
print(f" 不通过 (suitable=False): {stats['unsuitable_count']} 条 ({100 - stats['suitable_rate']:.2f}%)") print(f" 不通过 (suitable=False): {stats['unsuitable_count']} 条 ({100 - stats['suitable_rate']:.2f}%)")
print(f"\n【唯一性统计】") print("\n【唯一性统计】")
print(f" 唯一 (situation, style) 对: {stats['unique_pairs']}") print(f" 唯一 (situation, style) 对: {stats['unique_pairs']}")
if stats['actual_count'] > 0: if stats['actual_count'] > 0:
duplicate_count = stats['actual_count'] - stats['unique_pairs'] duplicate_count = stats['actual_count'] - stats['unique_pairs']
duplicate_rate = (duplicate_count / stats['actual_count'] * 100) if stats['actual_count'] > 0 else 0 duplicate_rate = (duplicate_count / stats['actual_count'] * 100) if stats['actual_count'] > 0 else 0
print(f" 重复记录: {duplicate_count} 条 ({duplicate_rate:.2f}%)") print(f" 重复记录: {duplicate_count} 条 ({duplicate_rate:.2f}%)")
print(f"\n【评估者统计】") print("\n【评估者统计】")
if stats['evaluators']: if stats['evaluators']:
for evaluator, count in stats['evaluators'].most_common(): for evaluator, count in stats['evaluators'].most_common():
rate = (count / stats['actual_count'] * 100) if stats['actual_count'] > 0 else 0 rate = (count / stats['actual_count'] * 100) if stats['actual_count'] > 0 else 0
@ -174,7 +174,7 @@ def print_file_stats(stats: Dict, index: int = None):
else: else:
print(" 无评估者信息") print(" 无评估者信息")
print(f"\n【时间统计】") print("\n【时间统计】")
if stats['date_range']: if stats['date_range']:
print(f" 最早评估时间: {stats['date_range']['start']}") print(f" 最早评估时间: {stats['date_range']['start']}")
print(f" 最晚评估时间: {stats['date_range']['end']}") print(f" 最晚评估时间: {stats['date_range']['end']}")
@ -182,7 +182,7 @@ def print_file_stats(stats: Dict, index: int = None):
else: else:
print(" 无时间信息") print(" 无时间信息")
print(f"\n【字段统计】") print("\n【字段统计】")
print(f" 包含 expression_id: {'' if stats['has_expression_id'] else ''}") print(f" 包含 expression_id: {'' if stats['has_expression_id'] else ''}")
print(f" 包含 reason: {'' if stats['has_reason'] else ''}") print(f" 包含 reason: {'' if stats['has_reason'] else ''}")
if stats['has_reason']: if stats['has_reason']:
@ -200,13 +200,13 @@ def print_summary(all_stats: List[Dict]):
valid_files = [s for s in all_stats if not s.get("error")] valid_files = [s for s in all_stats if not s.get("error")]
error_files = [s for s in all_stats if s.get("error")] error_files = [s for s in all_stats if s.get("error")]
print(f"\n【文件统计】") print("\n【文件统计】")
print(f" 总文件数: {total_files}") print(f" 总文件数: {total_files}")
print(f" 成功解析: {len(valid_files)}") print(f" 成功解析: {len(valid_files)}")
print(f" 解析失败: {len(error_files)}") print(f" 解析失败: {len(error_files)}")
if error_files: if error_files:
print(f"\n 失败文件列表:") print("\n 失败文件列表:")
for stats in error_files: for stats in error_files:
print(f" - {stats['file_name']}: {stats['error']}") print(f" - {stats['file_name']}: {stats['error']}")
@ -232,7 +232,7 @@ def print_summary(all_stats: List[Dict]):
except Exception: except Exception:
pass pass
print(f"\n【记录汇总】") print("\n【记录汇总】")
print(f" 总记录数: {total_records:,}") print(f" 总记录数: {total_records:,}")
print(f" 通过: {total_suitable:,} 条 ({total_suitable / total_records * 100:.2f}%)" if total_records > 0 else " 通过: 0 条") print(f" 通过: {total_suitable:,} 条 ({total_suitable / total_records * 100:.2f}%)" if total_records > 0 else " 通过: 0 条")
print(f" 不通过: {total_unsuitable:,} 条 ({total_unsuitable / total_records * 100:.2f}%)" if total_records > 0 else " 不通过: 0 条") print(f" 不通过: {total_unsuitable:,} 条 ({total_unsuitable / total_records * 100:.2f}%)" if total_records > 0 else " 不通过: 0 条")
@ -248,7 +248,7 @@ def print_summary(all_stats: List[Dict]):
for stats in valid_files: for stats in valid_files:
all_evaluators.update(stats['evaluators']) all_evaluators.update(stats['evaluators'])
print(f"\n【评估者汇总】") print("\n【评估者汇总】")
if all_evaluators: if all_evaluators:
for evaluator, count in all_evaluators.most_common(): for evaluator, count in all_evaluators.most_common():
rate = (count / total_records * 100) if total_records > 0 else 0 rate = (count / total_records * 100) if total_records > 0 else 0
@ -264,7 +264,7 @@ def print_summary(all_stats: List[Dict]):
if all_dates: if all_dates:
min_date = min(all_dates) min_date = min(all_dates)
max_date = max(all_dates) max_date = max(all_dates)
print(f"\n【时间汇总】") print("\n【时间汇总】")
print(f" 最早评估时间: {min_date.isoformat()}") print(f" 最早评估时间: {min_date.isoformat()}")
print(f" 最晚评估时间: {max_date.isoformat()}") print(f" 最晚评估时间: {max_date.isoformat()}")
print(f" 总时间跨度: {(max_date - min_date).days + 1}") print(f" 总时间跨度: {(max_date - min_date).days + 1}")
@ -272,7 +272,7 @@ def print_summary(all_stats: List[Dict]):
# 文件大小汇总 # 文件大小汇总
total_size = sum(s['file_size'] for s in valid_files) total_size = sum(s['file_size'] for s in valid_files)
avg_size = total_size / len(valid_files) if valid_files else 0 avg_size = total_size / len(valid_files) if valid_files else 0
print(f"\n【文件大小汇总】") print("\n【文件大小汇总】")
print(f" 总大小: {total_size:,} 字节 ({total_size / 1024 / 1024:.2f} MB)") print(f" 总大小: {total_size:,} 字节 ({total_size / 1024 / 1024:.2f} MB)")
print(f" 平均大小: {avg_size:,.0f} 字节 ({avg_size / 1024:.2f} KB)") print(f" 平均大小: {avg_size:,.0f} 字节 ({avg_size / 1024:.2f} KB)")

View File

@ -470,7 +470,7 @@ def _run_embedding_helper() -> None:
test_path.rename(archive_path) test_path.rename(archive_path)
except Exception as exc: # pragma: no cover - 防御性兜底 except Exception as exc: # pragma: no cover - 防御性兜底
logger.error("归档 embedding_model_test.json 失败: %s", exc) logger.error("归档 embedding_model_test.json 失败: %s", exc)
print(f"[ERROR] 归档 embedding_model_test.json 失败,请检查文件权限与路径。错误详情已写入日志。") print("[ERROR] 归档 embedding_model_test.json 失败,请检查文件权限与路径。错误详情已写入日志。")
return return
print( print(

View File

@ -2,7 +2,7 @@ import json
import asyncio import asyncio
import random import random
from collections import OrderedDict from collections import OrderedDict
from typing import List, Dict, Optional, Any, Callable from typing import List, Dict, Optional, Callable
from json_repair import repair_json from json_repair import repair_json
from peewee import fn from peewee import fn
@ -11,14 +11,8 @@ from src.common.database.database_model import Jargon
from src.llm_models.utils_model import LLMRequest from src.llm_models.utils_model import LLMRequest
from src.config.config import model_config, global_config from src.config.config import model_config, global_config
from src.chat.message_receive.chat_stream import get_chat_manager from src.chat.message_receive.chat_stream import get_chat_manager
from src.chat.utils.chat_message_builder import (
build_readable_messages_with_id,
)
from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.chat.utils.prompt_builder import Prompt, global_prompt_manager
from src.bw_learner.learner_utils import ( from src.bw_learner.learner_utils import (
is_bot_message,
build_context_paragraph,
contains_bot_self_name,
parse_chat_id_list, parse_chat_id_list,
chat_id_list_contains, chat_id_list_contains,
update_chat_id_list, update_chat_id_list,

View File

@ -7,9 +7,8 @@ from .kg_manager import KGManager
# from .lpmmconfig import global_config # from .lpmmconfig import global_config
from .utils.dyn_topk import dyn_select_top_k from .utils.dyn_topk import dyn_select_top_k
from src.llm_models.utils_model import LLMRequest
from src.chat.utils.utils import get_embedding from src.chat.utils.utils import get_embedding
from src.config.config import global_config, model_config from src.config.config import global_config
MAX_KNOWLEDGE_LENGTH = 10000 # 最大知识长度 MAX_KNOWLEDGE_LENGTH = 10000 # 最大知识长度

View File

@ -4,6 +4,8 @@ from pathlib import Path
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from uuid import uuid4 from uuid import uuid4
from src.config.config import global_config
class PlanReplyLogger: class PlanReplyLogger:
"""独立的Plan/Reply日志记录器负责落盘和容量控制。""" """独立的Plan/Reply日志记录器负责落盘和容量控制。"""
@ -11,9 +13,13 @@ class PlanReplyLogger:
_BASE_DIR = Path("logs") _BASE_DIR = Path("logs")
_PLAN_DIR = _BASE_DIR / "plan" _PLAN_DIR = _BASE_DIR / "plan"
_REPLY_DIR = _BASE_DIR / "reply" _REPLY_DIR = _BASE_DIR / "reply"
_MAX_PER_CHAT = 1000
_TRIM_COUNT = 100 _TRIM_COUNT = 100
@classmethod
def _get_max_per_chat(cls) -> int:
"""从配置中获取每个聊天流最大保存的日志数量"""
return getattr(global_config.chat, "plan_reply_log_max_per_chat", 1000)
@classmethod @classmethod
def log_plan( def log_plan(
cls, cls,
@ -85,7 +91,8 @@ class PlanReplyLogger:
def _trim_overflow(cls, chat_dir: Path) -> None: def _trim_overflow(cls, chat_dir: Path) -> None:
"""超过阈值时删除最老的若干文件,避免目录无限增长。""" """超过阈值时删除最老的若干文件,避免目录无限增长。"""
files = sorted(chat_dir.glob("*.json"), key=lambda p: p.stat().st_mtime) files = sorted(chat_dir.glob("*.json"), key=lambda p: p.stat().st_mtime)
if len(files) <= cls._MAX_PER_CHAT: max_per_chat = cls._get_max_per_chat()
if len(files) <= max_per_chat:
return return
# 删除最老的 TRIM_COUNT 条 # 删除最老的 TRIM_COUNT 条
for old_file in files[: cls._TRIM_COUNT]: for old_file in files[: cls._TRIM_COUNT]:

View File

@ -122,6 +122,9 @@ class ChatConfig(ConfigBase):
- dynamic: think_level由planner动态给出根据planner返回的think_level决定 - dynamic: think_level由planner动态给出根据planner返回的think_level决定
""" """
plan_reply_log_max_per_chat: int = 1024
"""每个聊天流最大保存的Plan/Reply日志数量超过此数量时会自动删除最老的日志"""
def _parse_stream_config_to_chat_id(self, stream_config_str: str) -> Optional[str]: def _parse_stream_config_to_chat_id(self, stream_config_str: str) -> Optional[str]:
"""与 ChatStream.get_stream_id 一致地从 "platform:id:type" 生成 chat_id。""" """与 ChatStream.get_stream_id 一致地从 "platform:id:type" 生成 chat_id。"""
try: try:

View File

@ -189,7 +189,6 @@ async def generate_dream_summary(
summary_model = get_dream_summary_model() summary_model = get_dream_summary_model()
dream_content, (reasoning, model_name, _) = await summary_model.generate_response_async( dream_content, (reasoning, model_name, _) = await summary_model.generate_response_async(
dream_prompt, dream_prompt,
max_tokens=512,
temperature=0.8, temperature=0.8,
) )

View File

@ -15,7 +15,7 @@ from json_repair import repair_json
from src.common.logger import get_logger from src.common.logger import get_logger
from src.common.data_models.database_data_model import DatabaseMessages from src.common.data_models.database_data_model import DatabaseMessages
from src.config.config import global_config, model_config from src.config.config import model_config
from src.llm_models.utils_model import LLMRequest from src.llm_models.utils_model import LLMRequest
from src.plugin_system.apis import message_api from src.plugin_system.apis import message_api
from src.chat.utils.chat_message_builder import build_readable_messages from src.chat.utils.chat_message_builder import build_readable_messages

View File

@ -3,7 +3,6 @@
用于在记忆检索过程中主动查询未知词语或黑话的含义 用于在记忆检索过程中主动查询未知词语或黑话的含义
""" """
from typing import List, Optional
from src.common.logger import get_logger from src.common.logger import get_logger
from src.bw_learner.jargon_explainer import retrieve_concepts_with_jargon from src.bw_learner.jargon_explainer import retrieve_concepts_with_jargon
from .tool_registry import register_memory_retrieval_tool from .tool_registry import register_memory_retrieval_tool

View File

@ -12,7 +12,6 @@ import time
from typing import List, Dict, Any, Tuple, Optional from typing import List, Dict, Any, Tuple, Optional
from src.common.data_models.database_data_model import DatabaseMessages from src.common.data_models.database_data_model import DatabaseMessages
from src.common.database.database_model import Images from src.common.database.database_model import Images
from src.config.config import global_config
from src.chat.utils.utils import is_bot_self from src.chat.utils.utils import is_bot_self
from src.chat.utils.chat_message_builder import ( from src.chat.utils.chat_message_builder import (
get_raw_msg_by_timestamp, get_raw_msg_by_timestamp,

View File

@ -3,7 +3,6 @@ WebUI 防爬虫模块
提供爬虫检测和阻止功能保护 WebUI 不被搜索引擎和恶意爬虫访问 提供爬虫检测和阻止功能保护 WebUI 不被搜索引擎和恶意爬虫访问
""" """
import os
import time import time
import ipaddress import ipaddress
import re import re

View File

@ -1,7 +1,7 @@
"""表达方式管理 API 路由""" """表达方式管理 API 路由"""
from fastapi import APIRouter, HTTPException, Header, Query, Cookie from fastapi import APIRouter, HTTPException, Header, Query, Cookie
from pydantic import BaseModel, NonNegativeFloat from pydantic import BaseModel
from typing import Optional, List, Dict from typing import Optional, List, Dict
from src.common.logger import get_logger from src.common.logger import get_logger
from src.common.database.database_model import Expression, ChatStreams from src.common.database.database_model import Expression, ChatStreams

View File

@ -1,5 +1,5 @@
[inner] [inner]
version = "7.3.1" version = "7.3.2"
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读---- #----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
# 如果你想要修改配置文件请递增version的值 # 如果你想要修改配置文件请递增version的值
@ -116,6 +116,8 @@ max_context_size = 30 # 上下文长度
planner_smooth = 3 # 规划器平滑增大数值会减小planner负荷略微降低反应速度推荐1-50为关闭必须大于等于0 planner_smooth = 3 # 规划器平滑增大数值会减小planner负荷略微降低反应速度推荐1-50为关闭必须大于等于0
think_mode = "dynamic" # 思考模式可选classic默认浅度思考和回复、deep会进行比较长的深度回复、dynamic动态选择两种模式 think_mode = "dynamic" # 思考模式可选classic默认浅度思考和回复、deep会进行比较长的深度回复、dynamic动态选择两种模式
plan_reply_log_max_per_chat = 1024 # 每个聊天保存最大的Plan/Reply日志数量超过此数量时会自动删除最老的日志
enable_talk_value_rules = true # 是否启用动态发言频率规则 enable_talk_value_rules = true # 是否启用动态发言频率规则
# 动态发言频率规则:按时段/按chat_id调整 talk_value优先匹配具体chat再匹配全局 # 动态发言频率规则:按时段/按chat_id调整 talk_value优先匹配具体chat再匹配全局