From 664f900f430cb5cd2c2924e6d091eb0d5bb00b4a Mon Sep 17 00:00:00 2001 From: SengokuCola <1026294844@qq.com> Date: Wed, 11 Mar 2026 21:25:35 +0800 Subject: [PATCH] =?UTF-8?q?ref=EF=BC=9A=E8=AE=A9MaiSaka=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E9=BA=A6=E9=BA=A6=E5=8E=9F=E6=9C=89=E7=9A=84pompt=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=EF=BC=8C=E9=85=8D=E7=BD=AE=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../maidairy_chat.prompt | 0 .../maidairy_cognition.prompt | 0 .../maidairy_context_summarize.prompt | 0 .../maidairy_emotion.prompt | 0 .../maidairy_knowledge_category.prompt | 0 .../maidairy_knowledge_extract.prompt | 0 .../maidairy_knowledge_retrieve.prompt | 0 .../maidairy_replyer.prompt | 0 .../maidairy_timing.prompt | 0 src/MaiDiary/main.py => saka.py | 12 +- src/MaiDiary/__init__.py | 3 + src/MaiDiary/config.py | 46 -------- src/MaiDiary/env.example | 58 ---------- src/MaiDiary/prompt_loader.py | 84 -------------- .../prompts/_example_with_vars.prompt | 14 --- src/config/config.py | 4 + src/config/official_configs.py | 107 ++++++++++++++++++ src/{MaiDiary => maisaka}/LICENSE | 0 src/{MaiDiary => maisaka}/cli.py | 0 src/maisaka/config.py | 61 ++++++++++ src/{MaiDiary => maisaka}/debug_client.py | 0 src/{MaiDiary => maisaka}/debug_viewer.py | 0 src/{MaiDiary => maisaka}/emotion.py | 4 +- src/{MaiDiary => maisaka}/input_reader.py | 0 src/{MaiDiary => maisaka}/knowledge.py | 0 src/{MaiDiary => maisaka}/knowledge_store.py | 0 .../llm_service/__init__.py | 0 src/{MaiDiary => maisaka}/llm_service/base.py | 0 .../llm_service/openai_impl.py | 48 ++++++-- .../llm_service/prompts.py | 4 +- .../llm_service/utils.py | 0 .../mcp_client/__init__.py | 0 .../mcp_client/config.py | 0 .../mcp_client/connection.py | 0 .../mcp_client/manager.py | 0 src/{MaiDiary => maisaka}/mcp_config.json | 0 .../mcp_config.json.template | 0 src/{MaiDiary => maisaka}/replyer.py | 6 +- src/{MaiDiary => maisaka}/timing.py | 0 src/{MaiDiary => maisaka}/tool_handlers.py | 0 40 files changed, 230 insertions(+), 221 deletions(-) rename src/MaiDiary/prompts/chat.system.prompt => prompts/maidairy_chat.prompt (100%) rename src/MaiDiary/prompts/cognition.system.prompt => prompts/maidairy_cognition.prompt (100%) rename src/MaiDiary/prompts/context_summarize.system.prompt => prompts/maidairy_context_summarize.prompt (100%) rename src/MaiDiary/prompts/emotion.system.prompt => prompts/maidairy_emotion.prompt (100%) rename src/MaiDiary/prompts/knowledge_category.system.prompt => prompts/maidairy_knowledge_category.prompt (100%) rename src/MaiDiary/prompts/knowledge_extract.system.prompt => prompts/maidairy_knowledge_extract.prompt (100%) rename src/MaiDiary/prompts/knowledge_retrieve.system.prompt => prompts/maidairy_knowledge_retrieve.prompt (100%) rename src/MaiDiary/prompts/replyer.system.prompt => prompts/maidairy_replyer.prompt (100%) rename src/MaiDiary/prompts/timing.system.prompt => prompts/maidairy_timing.prompt (100%) rename src/MaiDiary/main.py => saka.py (67%) create mode 100644 src/MaiDiary/__init__.py delete mode 100644 src/MaiDiary/config.py delete mode 100644 src/MaiDiary/env.example delete mode 100644 src/MaiDiary/prompt_loader.py delete mode 100644 src/MaiDiary/prompts/_example_with_vars.prompt rename src/{MaiDiary => maisaka}/LICENSE (100%) rename src/{MaiDiary => maisaka}/cli.py (100%) create mode 100644 src/maisaka/config.py rename src/{MaiDiary => maisaka}/debug_client.py (100%) rename src/{MaiDiary => maisaka}/debug_viewer.py (100%) rename src/{MaiDiary => maisaka}/emotion.py (92%) rename src/{MaiDiary => maisaka}/input_reader.py (100%) rename src/{MaiDiary => maisaka}/knowledge.py (100%) rename src/{MaiDiary => maisaka}/knowledge_store.py (100%) rename src/{MaiDiary => maisaka}/llm_service/__init__.py (100%) rename src/{MaiDiary => maisaka}/llm_service/base.py (100%) rename src/{MaiDiary => maisaka}/llm_service/openai_impl.py (89%) rename src/{MaiDiary => maisaka}/llm_service/prompts.py (98%) rename src/{MaiDiary => maisaka}/llm_service/utils.py (100%) rename src/{MaiDiary => maisaka}/mcp_client/__init__.py (100%) rename src/{MaiDiary => maisaka}/mcp_client/config.py (100%) rename src/{MaiDiary => maisaka}/mcp_client/connection.py (100%) rename src/{MaiDiary => maisaka}/mcp_client/manager.py (100%) rename src/{MaiDiary => maisaka}/mcp_config.json (100%) rename src/{MaiDiary => maisaka}/mcp_config.json.template (100%) rename src/{MaiDiary => maisaka}/replyer.py (92%) rename src/{MaiDiary => maisaka}/timing.py (100%) rename src/{MaiDiary => maisaka}/tool_handlers.py (100%) diff --git a/src/MaiDiary/prompts/chat.system.prompt b/prompts/maidairy_chat.prompt similarity index 100% rename from src/MaiDiary/prompts/chat.system.prompt rename to prompts/maidairy_chat.prompt diff --git a/src/MaiDiary/prompts/cognition.system.prompt b/prompts/maidairy_cognition.prompt similarity index 100% rename from src/MaiDiary/prompts/cognition.system.prompt rename to prompts/maidairy_cognition.prompt diff --git a/src/MaiDiary/prompts/context_summarize.system.prompt b/prompts/maidairy_context_summarize.prompt similarity index 100% rename from src/MaiDiary/prompts/context_summarize.system.prompt rename to prompts/maidairy_context_summarize.prompt diff --git a/src/MaiDiary/prompts/emotion.system.prompt b/prompts/maidairy_emotion.prompt similarity index 100% rename from src/MaiDiary/prompts/emotion.system.prompt rename to prompts/maidairy_emotion.prompt diff --git a/src/MaiDiary/prompts/knowledge_category.system.prompt b/prompts/maidairy_knowledge_category.prompt similarity index 100% rename from src/MaiDiary/prompts/knowledge_category.system.prompt rename to prompts/maidairy_knowledge_category.prompt diff --git a/src/MaiDiary/prompts/knowledge_extract.system.prompt b/prompts/maidairy_knowledge_extract.prompt similarity index 100% rename from src/MaiDiary/prompts/knowledge_extract.system.prompt rename to prompts/maidairy_knowledge_extract.prompt diff --git a/src/MaiDiary/prompts/knowledge_retrieve.system.prompt b/prompts/maidairy_knowledge_retrieve.prompt similarity index 100% rename from src/MaiDiary/prompts/knowledge_retrieve.system.prompt rename to prompts/maidairy_knowledge_retrieve.prompt diff --git a/src/MaiDiary/prompts/replyer.system.prompt b/prompts/maidairy_replyer.prompt similarity index 100% rename from src/MaiDiary/prompts/replyer.system.prompt rename to prompts/maidairy_replyer.prompt diff --git a/src/MaiDiary/prompts/timing.system.prompt b/prompts/maidairy_timing.prompt similarity index 100% rename from src/MaiDiary/prompts/timing.system.prompt rename to prompts/maidairy_timing.prompt diff --git a/src/MaiDiary/main.py b/saka.py similarity index 67% rename from src/MaiDiary/main.py rename to saka.py index 7232850a..77e8ac08 100644 --- a/src/MaiDiary/main.py +++ b/saka.py @@ -1,7 +1,7 @@ """ MaiSaka - 程序入口 使用方法: - python main.py + python saka.py 环境变量 (可通过 .env 文件设置): OPENAI_API_KEY - API 密钥 @@ -11,6 +11,16 @@ MaiSaka - 程序入口 """ import asyncio +import sys +from pathlib import Path + +# 添加项目根目录和 src/maisaka 到 Python 路径 +_root = Path(__file__).parent +_maisaka_path = _root / "src" / "maisaka" +if str(_root) not in sys.path: + sys.path.insert(0, str(_root)) +if str(_maisaka_path) not in sys.path: + sys.path.insert(0, str(_maisaka_path)) from config import console from cli import BufferCLI diff --git a/src/MaiDiary/__init__.py b/src/MaiDiary/__init__.py new file mode 100644 index 00000000..b4f49daf --- /dev/null +++ b/src/MaiDiary/__init__.py @@ -0,0 +1,3 @@ +""" +maisaka - MaiSaka 对话系统 +""" diff --git a/src/MaiDiary/config.py b/src/MaiDiary/config.py deleted file mode 100644 index d20b572a..00000000 --- a/src/MaiDiary/config.py +++ /dev/null @@ -1,46 +0,0 @@ -""" -MaiSaka - 全局配置 -环境变量加载、Rich Console 实例、主题定义。 -""" - -import os -from dotenv import load_dotenv -from rich.console import Console -from rich.theme import Theme - -# ──────────────────── 加载 .env ──────────────────── - -load_dotenv() - -# ──────────────────── 模块开关配置 ──────────────────── - -ENABLE_EMOTION_MODULE = os.getenv("ENABLE_EMOTION_MODULE", "true").strip().lower() == "true" -ENABLE_COGNITION_MODULE = os.getenv("ENABLE_COGNITION_MODULE", "true").strip().lower() == "true" -# Timing 模块已包含自我反思功能 -ENABLE_TIMING_MODULE = os.getenv("ENABLE_TIMING_MODULE", "true").strip().lower() == "true" -ENABLE_KNOWLEDGE_MODULE = os.getenv("ENABLE_KNOWLEDGE_MODULE", "true").strip().lower() == "true" -ENABLE_MCP = os.getenv("ENABLE_MCP", "true").strip().lower() == "true" -ENABLE_WRITE_FILE = os.getenv("ENABLE_WRITE_FILE", "true").strip().lower() == "true" -ENABLE_READ_FILE = os.getenv("ENABLE_READ_FILE", "true").strip().lower() == "true" -ENABLE_LIST_FILES = os.getenv("ENABLE_LIST_FILES", "true").strip().lower() == "true" - -# ──────────────────── QQ 工具配置 ──────────────────── - -ENABLE_QQ_TOOLS = os.getenv("ENABLE_QQ_TOOLS", "false").strip().lower() == "true" -QQ_API_BASE_URL = os.getenv("QQ_API_BASE_URL", "").strip() -QQ_API_KEY = os.getenv("QQ_API_KEY", "").strip() - -# ──────────────────── Rich 主题 & Console ──────────────────── - -custom_theme = Theme( - { - "info": "cyan", - "success": "green", - "warning": "yellow", - "error": "bold red", - "muted": "dim", - "accent": "bold magenta", - } -) - -console = Console(theme=custom_theme) diff --git a/src/MaiDiary/env.example b/src/MaiDiary/env.example deleted file mode 100644 index a3861303..00000000 --- a/src/MaiDiary/env.example +++ /dev/null @@ -1,58 +0,0 @@ -# MaiSaka - LLM API 配置 -# 复制本文件为 .env 并填入你的配置 - -# 必填: API 密钥 -OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx - -# 可选: API 基地址 (如使用第三方兼容接口或自建代理) -OPENAI_BASE_URL=https://api.openai.com/v1 - -# 可选: 模型名称 (默认 gpt-4o, 需支持视觉能力以处理图片) -OPENAI_MODEL=gpt-4o - -# 可选: 是否启用 LLM 思考模式 (true/false, 不设置则不发送该参数) -# 设为 true 时允许 LLM 先进行思考再输出,设为 false 时直接输出 -ENABLE_THINKING=true - -# 可选: 是否启用情绪猜测模块 (true/false, 默认 true) -# 设为 false 时禁用情绪分析,可节省 API 调用成本 -ENABLE_EMOTION_MODULE=true - -# 可选: 是否启用认知感知模块 (true/false, 默认 true) -# 设为 false 时禁用意图分析,可节省 API 调用成本 -ENABLE_COGNITION_MODULE=true - -# 可选: 是否启用记忆模块 (true/false, 默认 true) -# 设为 false 时禁用记忆存储和检索功能 -# 注意: 关闭记忆模块不会影响了解(Knowledge)模块 -ENABLE_MEMORY_MODULE=true - -# 可选: 是否启用 Timing 模块 (true/false, 默认 true) -# 设为 false 时禁用时间节奏分析,可节省 API 调用成本 -# 注意: Timing 模块已包含自我反思功能 -ENABLE_TIMING_MODULE=true - -# 可选: 是否启用文件写入工具 (true/false, 默认 true) -# 设为 false 时禁用 write_file 工具 -ENABLE_WRITE_FILE=false - -# 可选: 是否启用文件读取工具 (true/false, 默认 true) -# 设为 false 时禁用 read_file 工具 -ENABLE_READ_FILE=false - -# 可选: 是否启用文件列表工具 (true/false, 默认 true) -# 设为 false 时禁用 list_files 工具 -ENABLE_LIST_FILES=false - -# 可选: 是否启用 QQ 工具 (true/false, 默认 false) -# 设为 true 时启用 get_qq_chat_info、send_info、list_qq_chats 工具 -ENABLE_QQ_TOOLS=false - -# 可选: QQ API 基地址 (启用 QQ_TOOLS 时必填) -# 指向提供 QQ 聊天功能的 HTTP 服务端点 -# 示例: http://localhost:8017 -QQ_API_BASE_URL=http://localhost:8017 - -# 可选: QQ API 密钥 (如果服务需要认证) -# 留空则不发送认证头 -QQ_API_KEY=your-api-key \ No newline at end of file diff --git a/src/MaiDiary/prompt_loader.py b/src/MaiDiary/prompt_loader.py deleted file mode 100644 index 413bc703..00000000 --- a/src/MaiDiary/prompt_loader.py +++ /dev/null @@ -1,84 +0,0 @@ -""" -MaiSaka - Prompt 加载器 -支持从 .prompt 文件加载模板,并进行变量替换。 -""" - -import os -from pathlib import Path -from typing import Any - - -class PromptLoader: - """Prompt 模板加载器""" - - def __init__(self, prompts_dir: str | None = None): - """ - 初始化加载器。 - - Args: - prompts_dir: prompts 目录路径,默认为项目根目录下的 prompts/ - """ - if prompts_dir is None: - # 默认为项目根目录下的 prompts/ - project_root = Path(__file__).parent - prompts_dir = project_root / "prompts" - - self.prompts_dir = Path(prompts_dir) - self._cache: dict[str, str] = {} - - def load(self, name: str, **kwargs: Any) -> str: - """ - 加载并渲染 prompt 模板。 - - Args: - name: 模板文件名(不含 .prompt 后缀) - **kwargs: 模板变量 - - Returns: - 渲染后的 prompt 文本 - """ - # 从缓存读取 - if name not in self._cache: - template_path = self.prompts_dir / f"{name}.prompt" - if not template_path.exists(): - raise FileNotFoundError(f"Prompt template not found: {template_path}") - - self._cache[name] = template_path.read_text(encoding="utf-8") - - template = self._cache[name] - - # 变量替换 - if kwargs: - try: - return template.format(**kwargs) - except KeyError as e: - raise ValueError(f"Missing template variable: {e}") from e - - return template - - def clear_cache(self): - """清空缓存""" - self._cache.clear() - - -# 全局单例 -_loader = PromptLoader() - - -def load_prompt(name: str, **kwargs: Any) -> str: - """ - 加载并渲染 prompt 模板(全局函数)。 - - Args: - name: 模板文件名(不含 .prompt 后缀) - **kwargs: 模板变量 - - Returns: - 渲染后的 prompt 文本 - """ - return _loader.load(name, **kwargs) - - -def reload_prompts(): - """重新加载所有 prompt(清空缓存)""" - _loader.clear_cache() diff --git a/src/MaiDiary/prompts/_example_with_vars.prompt b/src/MaiDiary/prompts/_example_with_vars.prompt deleted file mode 100644 index 2e23fc9b..00000000 --- a/src/MaiDiary/prompts/_example_with_vars.prompt +++ /dev/null @@ -1,14 +0,0 @@ -# 这是一个带变量替换的示例模板 -# 使用 {variable_name} 语法定义变量 -# 调用时使用 load_prompt("example_with_vars", name="麦麦", mood="开心") - -你好 {name}! - -今天看起来你心情{mood}。 - -作为你的 AI 助手,我会: -1. {task1} -2. {task2} -3. {task3} - -祝你今天愉快! diff --git a/src/config/config.py b/src/config/config.py index 6797b0a0..70c4a6fb 100644 --- a/src/config/config.py +++ b/src/config/config.py @@ -31,6 +31,7 @@ from .official_configs import ( DebugConfig, WebUIConfig, DatabaseConfig, + MaiSakaConfig, ) from .model_configs import ModelInfo, ModelTaskConfig, APIProvider from .config_base import ConfigBase, Field, AttributeData @@ -127,6 +128,9 @@ class Config(ConfigBase): database: DatabaseConfig = Field(default_factory=DatabaseConfig) """数据库配置类""" + maisaka: MaiSakaConfig = Field(default_factory=MaiSakaConfig) + """MaiSaka对话系统配置类""" + class ModelConfig(ConfigBase): """模型配置类""" diff --git a/src/config/official_configs.py b/src/config/official_configs.py index 78fc2955..60153dac 100644 --- a/src/config/official_configs.py +++ b/src/config/official_configs.py @@ -1501,3 +1501,110 @@ class DatabaseConfig(ConfigBase): 若禁用,则消息中的二进制将会在识别后删除,并在消息中使用识别结果替代,无法二次识别 该配置项仅影响新存储的消息,已有消息不会受到影响 """ + + +class MaiSakaConfig(ConfigBase): + """MaiSaka 对话系统配置类""" + + __ui_label__ = "MaiSaka" + __ui_icon__ = "message-circle" + __ui_parent__ = "experimental" + + enable_emotion_module: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "heart", + }, + ) + """启用情绪感知模块""" + + enable_cognition_module: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "brain", + }, + ) + """启用认知分析模块""" + + enable_timing_module: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "clock", + }, + ) + """启用时间感知模块(含自我反思功能)""" + + enable_knowledge_module: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "book", + }, + ) + """启用知识库模块""" + + enable_mcp: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "zap", + }, + ) + """启用 MCP (Model Context Protocol) 支持""" + + enable_write_file: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "file-plus", + }, + ) + """启用文件写入工具""" + + enable_read_file: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "file-text", + }, + ) + """启用文件读取工具""" + + enable_list_files: bool = Field( + default=True, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "list", + }, + ) + """启用文件列表工具""" + + enable_qq_tools: bool = Field( + default=False, + json_schema_extra={ + "x-widget": "switch", + "x-icon": "users", + }, + ) + """启用 QQ 工具(获取聊天记录、发送消息等)""" + + qq_api_base_url: str = Field( + default="", + json_schema_extra={ + "x-widget": "input", + "x-icon": "server", + }, + ) + """QQ API 基地址""" + + qq_api_key: str = Field( + default="", + json_schema_extra={ + "x-widget": "input", + "x-icon": "key", + }, + ) + """QQ API 密钥""" diff --git a/src/MaiDiary/LICENSE b/src/maisaka/LICENSE similarity index 100% rename from src/MaiDiary/LICENSE rename to src/maisaka/LICENSE diff --git a/src/MaiDiary/cli.py b/src/maisaka/cli.py similarity index 100% rename from src/MaiDiary/cli.py rename to src/maisaka/cli.py diff --git a/src/maisaka/config.py b/src/maisaka/config.py new file mode 100644 index 00000000..486f1388 --- /dev/null +++ b/src/maisaka/config.py @@ -0,0 +1,61 @@ +""" +MaiSaka - 全局配置 +从主项目配置系统读取配置、Rich Console 实例、主题定义。 +""" + +import sys +from pathlib import Path +from rich.console import Console +from rich.theme import Theme + +# 添加项目根目录到路径以导入主配置 +_root = Path(__file__).parent.parent.parent.absolute() +if str(_root) not in sys.path: + sys.path.insert(0, str(_root)) + +# ──────────────────── 从主配置读取 ──────────────────── + +def _get_maisaka_config(): + """获取 MaiSaka 配置""" + try: + from src.config.config import config_manager + return config_manager.config.maisaka + except Exception: + # 如果配置加载失败,返回默认值 + from src.config.official_configs import MaiSakaConfig + return MaiSakaConfig() + +_maisaka_config = _get_maisaka_config() + +# ──────────────────── 模块开关配置 ──────────────────── + +ENABLE_EMOTION_MODULE = _maisaka_config.enable_emotion_module +ENABLE_COGNITION_MODULE = _maisaka_config.enable_cognition_module +# Timing 模块已包含自我反思功能 +ENABLE_TIMING_MODULE = _maisaka_config.enable_timing_module +ENABLE_KNOWLEDGE_MODULE = _maisaka_config.enable_knowledge_module +ENABLE_MCP = _maisaka_config.enable_mcp +ENABLE_WRITE_FILE = _maisaka_config.enable_write_file +ENABLE_READ_FILE = _maisaka_config.enable_read_file +ENABLE_LIST_FILES = _maisaka_config.enable_list_files + +# ──────────────────── QQ 工具配置 ──────────────────── + +ENABLE_QQ_TOOLS = _maisaka_config.enable_qq_tools +QQ_API_BASE_URL = _maisaka_config.qq_api_base_url +QQ_API_KEY = _maisaka_config.qq_api_key + +# ──────────────────── Rich 主题 & Console ──────────────────── + +custom_theme = Theme( + { + "info": "cyan", + "success": "green", + "warning": "yellow", + "error": "bold red", + "muted": "dim", + "accent": "bold magenta", + } +) + +console = Console(theme=custom_theme) diff --git a/src/MaiDiary/debug_client.py b/src/maisaka/debug_client.py similarity index 100% rename from src/MaiDiary/debug_client.py rename to src/maisaka/debug_client.py diff --git a/src/MaiDiary/debug_viewer.py b/src/maisaka/debug_viewer.py similarity index 100% rename from src/MaiDiary/debug_viewer.py rename to src/maisaka/debug_viewer.py diff --git a/src/MaiDiary/emotion.py b/src/maisaka/emotion.py similarity index 92% rename from src/MaiDiary/emotion.py rename to src/maisaka/emotion.py index 8878e822..4c0e85ae 100644 --- a/src/MaiDiary/emotion.py +++ b/src/maisaka/emotion.py @@ -2,8 +2,8 @@ MaiSaka - Emotion 模块 情绪感知分析,分析用户的情绪状态和言语态度。 -注意:EQ_SYSTEM_PROMPT 已迁移至 prompts/emotion.system.prompt -使用 prompt_loader.load_prompt("emotion.system") 加载。 +注意:emotion.prompt 已迁移至主项目 prompts/ 目录 +使用 prompt_manager.get_prompt("maidairy_emotion") 加载。 """ from typing import List, Optional diff --git a/src/MaiDiary/input_reader.py b/src/maisaka/input_reader.py similarity index 100% rename from src/MaiDiary/input_reader.py rename to src/maisaka/input_reader.py diff --git a/src/MaiDiary/knowledge.py b/src/maisaka/knowledge.py similarity index 100% rename from src/MaiDiary/knowledge.py rename to src/maisaka/knowledge.py diff --git a/src/MaiDiary/knowledge_store.py b/src/maisaka/knowledge_store.py similarity index 100% rename from src/MaiDiary/knowledge_store.py rename to src/maisaka/knowledge_store.py diff --git a/src/MaiDiary/llm_service/__init__.py b/src/maisaka/llm_service/__init__.py similarity index 100% rename from src/MaiDiary/llm_service/__init__.py rename to src/maisaka/llm_service/__init__.py diff --git a/src/MaiDiary/llm_service/base.py b/src/maisaka/llm_service/base.py similarity index 100% rename from src/MaiDiary/llm_service/base.py rename to src/maisaka/llm_service/base.py diff --git a/src/MaiDiary/llm_service/openai_impl.py b/src/maisaka/llm_service/openai_impl.py similarity index 89% rename from src/MaiDiary/llm_service/openai_impl.py rename to src/maisaka/llm_service/openai_impl.py index ae57eb25..d3e3d444 100644 --- a/src/MaiDiary/llm_service/openai_impl.py +++ b/src/maisaka/llm_service/openai_impl.py @@ -8,13 +8,29 @@ from typing import Callable, List, Optional from openai import AsyncOpenAI +import asyncio + from .base import BaseLLMService, ChatResponse, ModelInfo, ToolCall from .prompts import get_enabled_chat_tools from .utils import format_chat_history, format_chat_history_for_eq, filter_for_api -from prompt_loader import load_prompt +from src.prompt.prompt_manager import prompt_manager from knowledge import extract_category_ids_from_result +def _load_prompt_sync(name: str, **kwargs) -> str: + """同步加载并渲染 prompt(用于非异步上下文)""" + prompt = prompt_manager.get_prompt(name) + for key, value in kwargs.items(): + prompt.add_context(key, value) + # 在新事件循环中运行异步渲染 + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + return loop.run_until_complete(prompt_manager.render_prompt(prompt)) + finally: + loop.close() + + class OpenAILLMService(BaseLLMService): """ 基于 OpenAI 兼容 API 的 LLM 服务实现。 @@ -81,7 +97,7 @@ class OpenAILLMService(BaseLLMService): tools_section = "" # 加载提示词模板并注入工具部分 - self._chat_system_prompt = load_prompt("chat.system", file_tools_section=tools_section) + self._chat_system_prompt = _load_prompt_sync("maidairy_chat", file_tools_section=tools_section) else: self._chat_system_prompt = chat_system_prompt @@ -239,8 +255,9 @@ class OpenAILLMService(BaseLLMService): if msg.get("_type") != "perception" and msg.get("role") != "system" ] formatted = format_chat_history(filtered_history) + timing_prompt = prompt_manager.get_prompt("maidairy_timing") timing_messages = [ - {"role": "system", "content": load_prompt("timing.system")}, + {"role": "system", "content": await prompt_manager.render_prompt(timing_prompt)}, { "role": "user", "content": ( @@ -272,8 +289,9 @@ class OpenAILLMService(BaseLLMService): # 使用情商模块专用格式化函数:只包含用户回复、助手思考、助手说 formatted = format_chat_history_for_eq(recent_messages) + emotion_prompt = prompt_manager.get_prompt("maidairy_emotion") eq_messages = [ - {"role": "system", "content": load_prompt("emotion.system")}, + {"role": "system", "content": await prompt_manager.render_prompt(emotion_prompt)}, { "role": "user", "content": f"以下是最近几轮对话记录,请分析其中用户的情绪状态和言语态度:\n\n{formatted}", @@ -302,8 +320,9 @@ class OpenAILLMService(BaseLLMService): # 使用情商模块专用格式化函数:只包含用户回复、助手思考、助手说 formatted = format_chat_history_for_eq(recent_messages) + cognition_prompt = prompt_manager.get_prompt("maidairy_cognition") cognition_messages = [ - {"role": "system", "content": load_prompt("cognition.system")}, + {"role": "system", "content": await prompt_manager.render_prompt(cognition_prompt)}, { "role": "user", "content": f"以下是最近几轮对话记录,请分析其中用户的意图、认知状态和目的:\n\n{formatted}", @@ -329,8 +348,9 @@ class OpenAILLMService(BaseLLMService): filtered_messages = [msg for msg in context_messages if msg.get("role") != "system"] formatted = format_chat_history(filtered_messages) + summarize_prompt = prompt_manager.get_prompt("maidairy_context_summarize") summarize_messages = [ - {"role": "system", "content": load_prompt("context_summarize.system")}, + {"role": "system", "content": await prompt_manager.render_prompt(summarize_prompt)}, { "role": "user", "content": f"请对以下对话内容进行总结,以便存入记忆系统:\n\n{formatted}", @@ -368,7 +388,9 @@ class OpenAILLMService(BaseLLMService): return [] # 加载分类分析 prompt - prompt = load_prompt("knowledge_category.system", categories_summary=categories_summary) + category_prompt = prompt_manager.get_prompt("maidairy_knowledge_category") + category_prompt.add_context("categories_summary", categories_summary) + prompt = await prompt_manager.render_prompt(category_prompt) category_messages = [ {"role": "system", "content": prompt}, @@ -407,7 +429,9 @@ class OpenAILLMService(BaseLLMService): return "" # 加载内容提取 prompt - prompt = load_prompt("knowledge_extract.system", category_name=category_name) + extract_prompt = prompt_manager.get_prompt("maidairy_knowledge_extract") + extract_prompt.add_context("category_name", category_name) + prompt = await prompt_manager.render_prompt(extract_prompt) extract_messages = [ {"role": "system", "content": prompt}, @@ -454,10 +478,10 @@ class OpenAILLMService(BaseLLMService): formatted = format_chat_history(recent_messages) # 加载需求分析 prompt - prompt = load_prompt("knowledge_retrieve.system", - chat_context=formatted, - categories_summary=categories_summary - ) + retrieve_prompt = prompt_manager.get_prompt("maidairy_knowledge_retrieve") + retrieve_prompt.add_context("chat_context", formatted) + retrieve_prompt.add_context("categories_summary", categories_summary) + prompt = await prompt_manager.render_prompt(retrieve_prompt) need_messages = [ {"role": "system", "content": prompt}, diff --git a/src/MaiDiary/llm_service/prompts.py b/src/maisaka/llm_service/prompts.py similarity index 98% rename from src/MaiDiary/llm_service/prompts.py rename to src/maisaka/llm_service/prompts.py index e1d9787d..c678ac59 100644 --- a/src/MaiDiary/llm_service/prompts.py +++ b/src/maisaka/llm_service/prompts.py @@ -2,8 +2,8 @@ MaiSaka - LLM 工具定义 所有 Tool Schema 集中管理。 -注意:所有 Prompt 模板已迁移至 prompts/ 目录,使用 .prompt 文件存储。 -使用 prompt_loader.load_prompt() 加载模板。 +注意:所有 Prompt 模板已迁移至主项目 prompts/ 目录,使用 .prompt 文件存储。 +使用 prompt_manager.get_prompt("maidairy_xxx") 加载模板。 """ # ──────────────────── 工具定义 ──────────────────── diff --git a/src/MaiDiary/llm_service/utils.py b/src/maisaka/llm_service/utils.py similarity index 100% rename from src/MaiDiary/llm_service/utils.py rename to src/maisaka/llm_service/utils.py diff --git a/src/MaiDiary/mcp_client/__init__.py b/src/maisaka/mcp_client/__init__.py similarity index 100% rename from src/MaiDiary/mcp_client/__init__.py rename to src/maisaka/mcp_client/__init__.py diff --git a/src/MaiDiary/mcp_client/config.py b/src/maisaka/mcp_client/config.py similarity index 100% rename from src/MaiDiary/mcp_client/config.py rename to src/maisaka/mcp_client/config.py diff --git a/src/MaiDiary/mcp_client/connection.py b/src/maisaka/mcp_client/connection.py similarity index 100% rename from src/MaiDiary/mcp_client/connection.py rename to src/maisaka/mcp_client/connection.py diff --git a/src/MaiDiary/mcp_client/manager.py b/src/maisaka/mcp_client/manager.py similarity index 100% rename from src/MaiDiary/mcp_client/manager.py rename to src/maisaka/mcp_client/manager.py diff --git a/src/MaiDiary/mcp_config.json b/src/maisaka/mcp_config.json similarity index 100% rename from src/MaiDiary/mcp_config.json rename to src/maisaka/mcp_config.json diff --git a/src/MaiDiary/mcp_config.json.template b/src/maisaka/mcp_config.json.template similarity index 100% rename from src/MaiDiary/mcp_config.json.template rename to src/maisaka/mcp_config.json.template diff --git a/src/MaiDiary/replyer.py b/src/maisaka/replyer.py similarity index 92% rename from src/MaiDiary/replyer.py rename to src/maisaka/replyer.py index 107b2f91..543ad5c5 100644 --- a/src/MaiDiary/replyer.py +++ b/src/maisaka/replyer.py @@ -5,7 +5,7 @@ MaiSaka - Reply 回复生成器 from typing import Optional from datetime import datetime -from prompt_loader import load_prompt +from src.prompt.prompt_manager import prompt_manager from llm_service import BaseLLMService from llm_service.utils import format_chat_history @@ -60,8 +60,10 @@ class Replyer: formatted_history = format_chat_history(filtered_history) # 构建回复消息 + replyer_prompt = prompt_manager.get_prompt("maidairy_replyer") + system_prompt = await prompt_manager.render_prompt(replyer_prompt) messages = [ - {"role": "system", "content": load_prompt("replyer.system")}, + {"role": "system", "content": system_prompt}, { "role": "user", "content": ( diff --git a/src/MaiDiary/timing.py b/src/maisaka/timing.py similarity index 100% rename from src/MaiDiary/timing.py rename to src/maisaka/timing.py diff --git a/src/MaiDiary/tool_handlers.py b/src/maisaka/tool_handlers.py similarity index 100% rename from src/MaiDiary/tool_handlers.py rename to src/maisaka/tool_handlers.py