From 88a2b9d2ee6072de8ac3952558cde5fb244f38fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A2=A8=E6=A2=93=E6=9F=92?= <1787882683@qq.com> Date: Sun, 4 May 2025 13:43:30 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0API=E6=9C=8D=E5=8A=A1?= =?UTF-8?q?=E5=99=A8=E9=85=8D=E7=BD=AE=E5=92=8CGraphQL=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=EF=BC=8C=E9=87=8D=E8=BD=BD=E9=85=8D=E7=BD=AE=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E6=9B=B4=E6=96=B0=E6=97=A5=E5=BF=97=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/config_api.py | 230 +++++++++++--------- src/api/{graphql => maigraphql}/__init__.py | 0 src/api/{graphql => maigraphql}/schema.py | 0 src/api/main.py | 2 +- src/api/reload_config.py | 5 +- 5 files changed, 136 insertions(+), 101 deletions(-) rename src/api/{graphql => maigraphql}/__init__.py (100%) rename src/api/{graphql => maigraphql}/schema.py (100%) diff --git a/src/api/config_api.py b/src/api/config_api.py index 6ecd4e6db..7279ac63a 100644 --- a/src/api/config_api.py +++ b/src/api/config_api.py @@ -1,155 +1,187 @@ -from typing import List, Optional +from typing import List, Optional, Dict, Any import strawberry - -# from packaging.version import Version, InvalidVersion -# from packaging.specifiers import SpecifierSet, InvalidSpecifier -# from ..config.config import global_config -# import os from packaging.version import Version +import os + +ROOT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) @strawberry.type -class BotConfig: +class APIBotConfig: """机器人配置类""" - INNER_VERSION: Version + INNER_VERSION: Version # 配置文件内部版本号 MAI_VERSION: str # 硬编码的版本信息 # bot - BOT_QQ: Optional[int] - BOT_NICKNAME: Optional[str] - BOT_ALIAS_NAMES: List[str] # 别名,可以通过这个叫它 + BOT_QQ: Optional[int] # 机器人QQ号 + BOT_NICKNAME: Optional[str] # 机器人昵称 + BOT_ALIAS_NAMES: List[str] # 机器人别名列表 # group - talk_allowed_groups: set - talk_frequency_down_groups: set - ban_user_id: set + talk_allowed_groups: List[int] # 允许回复消息的群号列表 + talk_frequency_down_groups: List[int] # 降低回复频率的群号列表 + ban_user_id: List[int] # 禁止回复和读取消息的QQ号列表 # personality - personality_core: str # 建议20字以内,谁再写3000字小作文敲谁脑袋 - personality_sides: List[str] + personality_core: str # 人格核心特点描述 + personality_sides: List[str] # 人格细节描述列表 + # identity - identity_detail: List[str] - height: int # 身高 单位厘米 - weight: int # 体重 单位千克 - age: int # 年龄 单位岁 + identity_detail: List[str] # 身份特点列表 + age: int # 年龄(岁) gender: str # 性别 - appearance: str # 外貌特征 + appearance: str # 外貌特征描述 # schedule ENABLE_SCHEDULE_GEN: bool # 是否启用日程生成 - PROMPT_SCHEDULE_GEN: str - SCHEDULE_DOING_UPDATE_INTERVAL: int # 日程表更新间隔 单位秒 - SCHEDULE_TEMPERATURE: float # 日程表温度,建议0.5-1.0 + ENABLE_SCHEDULE_INTERACTION: bool # 是否启用日程交互 + PROMPT_SCHEDULE_GEN: str # 日程生成提示词 + SCHEDULE_DOING_UPDATE_INTERVAL: int # 日程进行中更新间隔 + SCHEDULE_TEMPERATURE: float # 日程生成温度 TIME_ZONE: str # 时区 - # message - MAX_CONTEXT_SIZE: int # 上下文最大消息数 - emoji_chance: float # 发送表情包的基础概率 - thinking_timeout: int # 思考时间 - model_max_output_length: int # 最大回复长度 - message_buffer: bool # 消息缓冲器 + # platforms + platforms: Dict[str, str] # 平台信息 - ban_words: set - ban_msgs_regex: set - # heartflow - # enable_heartflow: bool = False # 是否启用心流 - sub_heart_flow_update_interval: int # 子心流更新频率,间隔 单位秒 - sub_heart_flow_freeze_time: int # 子心流冻结时间,超过这个时间没有回复,子心流会冻结,间隔 单位秒 - sub_heart_flow_stop_time: int # 子心流停止时间,超过这个时间没有回复,子心流会停止,间隔 单位秒 - heart_flow_update_interval: int # 心流更新频率,间隔 单位秒 - observation_context_size: int # 心流观察到的最长上下文大小,超过这个值的上下文会被压缩 - compressed_length: int # 不能大于observation_context_size,心流上下文压缩的最短压缩长度,超过心流观察到的上下文长度,会压缩,最短压缩长度为5 - compress_length_limit: int # 最多压缩份数,超过该数值的压缩上下文会被删除 + # chat + allow_focus_mode: bool # 是否允许专注模式 + base_normal_chat_num: int # 基础普通聊天次数 + base_focused_chat_num: int # 基础专注聊天次数 + observation_context_size: int # 观察上下文大小 + message_buffer: bool # 是否启用消息缓冲 + ban_words: List[str] # 禁止词列表 + ban_msgs_regex: List[str] # 禁止消息的正则表达式列表 - # willing + # normal_chat + MODEL_R1_PROBABILITY: float # 模型推理概率 + MODEL_V3_PROBABILITY: float # 模型普通概率 + emoji_chance: float # 表情符号出现概率 + thinking_timeout: int # 思考超时时间 willing_mode: str # 意愿模式 - response_willing_amplifier: float # 回复意愿放大系数 - response_interested_rate_amplifier: float # 回复兴趣度放大系数 - down_frequency_rate: float # 降低回复频率的群组回复意愿降低系数 - emoji_response_penalty: float # 表情包回复惩罚 - mentioned_bot_inevitable_reply: bool # 提及 bot 必然回复 - at_bot_inevitable_reply: bool # @bot 必然回复 + response_willing_amplifier: float # 回复意愿放大器 + response_interested_rate_amplifier: float # 回复兴趣率放大器 + down_frequency_rate: float # 降低频率率 + emoji_response_penalty: float # 表情回复惩罚 + mentioned_bot_inevitable_reply: bool # 提到机器人时是否必定回复 + at_bot_inevitable_reply: bool # @机器人时是否必定回复 - # response - response_mode: str # 回复策略 - MODEL_R1_PROBABILITY: float # R1模型概率 - MODEL_V3_PROBABILITY: float # V3模型概率 - # MODEL_R1_DISTILL_PROBABILITY: float # R1蒸馏模型概率 + # focus_chat + reply_trigger_threshold: float # 回复触发阈值 + default_decay_rate_per_second: float # 默认每秒衰减率 + consecutive_no_reply_threshold: int # 连续不回复阈值 + + # compressed + compressed_length: int # 压缩长度 + compress_length_limit: int # 压缩长度限制 # emoji - max_emoji_num: int # 表情包最大数量 - max_reach_deletion: bool # 开启则在达到最大数量时删除表情包,关闭则不会继续收集表情包 - EMOJI_CHECK_INTERVAL: int # 表情包检查间隔(分钟) - EMOJI_REGISTER_INTERVAL: int # 表情包注册间隔(分钟) - EMOJI_SAVE: bool # 偷表情包 - EMOJI_CHECK: bool # 是否开启过滤 - EMOJI_CHECK_PROMPT: str # 表情包过滤要求 + max_emoji_num: int # 最大表情符号数量 + max_reach_deletion: bool # 达到最大数量时是否删除 + EMOJI_CHECK_INTERVAL: int # 表情检查间隔 + EMOJI_REGISTER_INTERVAL: Optional[int] # 表情注册间隔(兼容性保留) + EMOJI_SAVE: bool # 是否保存表情 + EMOJI_CHECK: bool # 是否检查表情 + EMOJI_CHECK_PROMPT: str # 表情检查提示词 # memory - build_memory_interval: int # 记忆构建间隔(秒) - memory_build_distribution: list # 记忆构建分布,参数:分布1均值,标准差,权重,分布2均值,标准差,权重 - build_memory_sample_num: int # 记忆构建采样数量 - build_memory_sample_length: int # 记忆构建采样长度 + build_memory_interval: int # 构建记忆间隔 + memory_build_distribution: List[float] # 记忆构建分布 + build_memory_sample_num: int # 构建记忆样本数量 + build_memory_sample_length: int # 构建记忆样本长度 memory_compress_rate: float # 记忆压缩率 - - forget_memory_interval: int # 记忆遗忘间隔(秒) - memory_forget_time: int # 记忆遗忘时间(小时) - memory_forget_percentage: float # 记忆遗忘比例 - - memory_ban_words: list # 添加新的配置项默认值 + forget_memory_interval: int # 忘记记忆间隔 + memory_forget_time: int # 记忆忘记时间 + memory_forget_percentage: float # 记忆忘记百分比 + consolidate_memory_interval: int # 巩固记忆间隔 + consolidation_similarity_threshold: float # 巩固相似度阈值 + consolidation_check_percentage: float # 巩固检查百分比 + memory_ban_words: List[str] # 记忆禁止词列表 # mood - mood_update_interval: float # 情绪更新间隔 单位秒 + mood_update_interval: float # 情绪更新间隔 mood_decay_rate: float # 情绪衰减率 mood_intensity_factor: float # 情绪强度因子 - # keywords - keywords_reaction_rules: list # 关键词回复规则 + # keywords_reaction + keywords_reaction_enable: bool # 是否启用关键词反应 + keywords_reaction_rules: List[Dict[str, Any]] # 关键词反应规则 # chinese_typo - chinese_typo_enable: bool # 是否启用中文错别字生成器 - chinese_typo_error_rate: float # 单字替换概率 - chinese_typo_min_freq: int # 最小字频阈值 - chinese_typo_tone_error_rate: float # 声调错误概率 - chinese_typo_word_replace_rate: float # 整词替换概率 + chinese_typo_enable: bool # 是否启用中文错别字 + chinese_typo_error_rate: float # 中文错别字错误率 + chinese_typo_min_freq: int # 中文错别字最小频率 + chinese_typo_tone_error_rate: float # 中文错别字声调错误率 + chinese_typo_word_replace_rate: float # 中文错别字单词替换率 # response_splitter enable_response_splitter: bool # 是否启用回复分割器 - response_max_length: int # 回复允许的最大长度 - response_max_sentence_num: int # 回复允许的最大句子数 + response_max_length: int # 回复最大长度 + response_max_sentence_num: int # 回复最大句子数 + enable_kaomoji_protection: bool # 是否启用颜文字保护 + + model_max_output_length: int # 模型最大输出长度 # remote - remote_enable: bool # 是否启用远程控制 + remote_enable: bool # 是否启用远程功能 # experimental enable_friend_chat: bool # 是否启用好友聊天 - # enable_think_flow: bool # 是否启用思考流程 + talk_allowed_private: List[int] # 允许私聊的QQ号列表 enable_pfc_chatting: bool # 是否启用PFC聊天 # 模型配置 - llm_reasoning: dict[str, str] # LLM推理 - # llm_reasoning_minor: dict[str, str] - llm_normal: dict[str, str] # LLM普通 - llm_topic_judge: dict[str, str] # LLM话题判断 - llm_summary: dict[str, str] # LLM话题总结 - llm_emotion_judge: dict[str, str] # LLM情感判断 - embedding: dict[str, str] # 嵌入 - vlm: dict[str, str] # VLM - moderation: dict[str, str] # 审核 + llm_reasoning: Dict[str, Any] # 推理模型配置 + llm_normal: Dict[str, Any] # 普通模型配置 + llm_topic_judge: Dict[str, Any] # 主题判断模型配置 + llm_summary: Dict[str, Any] # 总结模型配置 + llm_emotion_judge: Optional[Dict[str, Any]] # 情绪判断模型配置(兼容性保留) + embedding: Dict[str, Any] # 嵌入模型配置 + vlm: Dict[str, Any] # VLM模型配置 + moderation: Optional[Dict[str, Any]] # 审核模型配置(兼容性保留) + llm_observation: Dict[str, Any] # 观察模型配置 + llm_sub_heartflow: Dict[str, Any] # 子心流模型配置 + llm_heartflow: Dict[str, Any] # 心流模型配置 + llm_plan: Optional[Dict[str, Any]] # 计划模型配置 + llm_PFC_action_planner: Optional[Dict[str, Any]] # PFC行动计划模型配置 + llm_PFC_chat: Optional[Dict[str, Any]] # PFC聊天模型配置 + llm_PFC_reply_checker: Optional[Dict[str, Any]] # PFC回复检查模型配置 + llm_tool_use: Optional[Dict[str, Any]] # 工具使用模型配置 - # 实验性 - llm_observation: dict[str, str] # LLM观察 - llm_sub_heartflow: dict[str, str] # LLM子心流 - llm_heartflow: dict[str, str] # LLM心流 - - api_urls: dict[str, str] # API URLs + api_urls: Optional[Dict[str, str]] # API地址配置 @strawberry.type -class EnvConfig: - pass +class APIEnvConfig: + """环境变量配置""" + + HOST: str # 服务主机地址 + PORT: int # 服务端口 + + PLUGINS: List[str] # 插件列表 + + MONGODB_HOST: str # MongoDB 主机地址 + MONGODB_PORT: int # MongoDB 端口 + DATABASE_NAME: str # 数据库名称 + + CHAT_ANY_WHERE_BASE_URL: str # ChatAnywhere 基础URL + SILICONFLOW_BASE_URL: str # SiliconFlow 基础URL + DEEP_SEEK_BASE_URL: str # DeepSeek 基础URL + + DEEP_SEEK_KEY: Optional[str] # DeepSeek API Key + CHAT_ANY_WHERE_KEY: Optional[str] # ChatAnywhere API Key + SILICONFLOW_KEY: Optional[str] # SiliconFlow API Key + + SIMPLE_OUTPUT: Optional[bool] # 是否简化输出 + CONSOLE_LOG_LEVEL: Optional[str] # 控制台日志等级 + FILE_LOG_LEVEL: Optional[str] # 文件日志等级 + DEFAULT_CONSOLE_LOG_LEVEL: Optional[str] # 默认控制台日志等级 + DEFAULT_FILE_LOG_LEVEL: Optional[str] # 默认文件日志等级 @strawberry.field def get_env(self) -> str: return "env" + + +print("当前路径:") +print(ROOT_PATH) \ No newline at end of file diff --git a/src/api/graphql/__init__.py b/src/api/maigraphql/__init__.py similarity index 100% rename from src/api/graphql/__init__.py rename to src/api/maigraphql/__init__.py diff --git a/src/api/graphql/schema.py b/src/api/maigraphql/schema.py similarity index 100% rename from src/api/graphql/schema.py rename to src/api/maigraphql/schema.py diff --git a/src/api/main.py b/src/api/main.py index be2259404..d4d3c62e7 100644 --- a/src/api/main.py +++ b/src/api/main.py @@ -14,7 +14,7 @@ router = APIRouter() logger = get_logger("api") # maiapi = FastAPI() -logger.info("API server started.") +logger.info("麦麦API服务器已启动") graphql_router = GraphQLRouter(schema=None, path="/") # Replace `None` with your actual schema router.include_router(graphql_router, prefix="/graphql", tags=["GraphQL"]) diff --git a/src/api/reload_config.py b/src/api/reload_config.py index d77cb536b..150194d08 100644 --- a/src/api/reload_config.py +++ b/src/api/reload_config.py @@ -1,17 +1,20 @@ from fastapi import HTTPException from rich.traceback import install from src.config.config import BotConfig +from src.common.logger_manager import get_logger import os install(extra_lines=3) +logger = get_logger("api") async def reload_config(): try: from src.config import config as config_module - + logger.debug("正在重载配置文件...") bot_config_path = os.path.join(BotConfig.get_config_dir(), "bot_config.toml") config_module.global_config = BotConfig.load_config(config_path=bot_config_path) + logger.debug("配置文件重载成功") return {"status": "reloaded"} except FileNotFoundError as e: raise HTTPException(status_code=404, detail=str(e)) from e