ref:让MaiSaka使用麦麦原有的pompt系统,配置系统

This commit is contained in:
SengokuCola
2026-03-11 21:25:35 +08:00
parent 6c32d17e21
commit 664f900f43
40 changed files with 230 additions and 221 deletions

3
src/MaiDiary/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
"""
maisaka - MaiSaka 对话系统
"""

View File

@@ -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)

View File

@@ -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

View File

@@ -1,30 +0,0 @@
"""
MaiSaka - 程序入口
使用方法:
python main.py
环境变量 (可通过 .env 文件设置):
OPENAI_API_KEY - API 密钥
OPENAI_BASE_URL - API 基地址 (可选, 默认 https://api.openai.com/v1)
OPENAI_MODEL - 模型名称 (可选, 默认 gpt-4o)
ENABLE_THINKING - 是否启用思考模式 (可选, true/false, 不设置则不发送该参数)
"""
import asyncio
from config import console
from cli import BufferCLI
def main():
cli = BufferCLI()
try:
asyncio.run(cli.run())
except KeyboardInterrupt:
console.print("\n[muted]程序已终止[/muted]")
finally:
cli._debug_viewer.close()
if __name__ == "__main__":
main()

View File

@@ -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()

View File

@@ -1,14 +0,0 @@
# 这是一个带变量替换的示例模板
# 使用 {variable_name} 语法定义变量
# 调用时使用 load_prompt("example_with_vars", name="麦麦", mood="开心")
你好 {name}
今天看起来你心情{mood}。
作为你的 AI 助手,我会:
1. {task1}
2. {task2}
3. {task3}
祝你今天愉快!

View File

@@ -1,24 +0,0 @@
你叫麦麦,是一个女大学生,你说话比较口语化
你有以下工具:
• say(reason) — 对用户说话。你所有想让用户看到的正式发言都必须通过此工具输出。
直接输出的文本会被视为你的内心思考,用户无法阅读。
reason 参数描述你想要回复的方式、想法和内容,系统会根据你的想法和对话上下文生成具体的回复。
• wait(seconds) — 暂时结束你的发言,把话语权交给用户,等待对方说话。
这就像现实对话中你说完一句话后停下来等对方回应。
如果用户在等待期间说了话,你会通过工具返回结果收到内容。
如果超时没有回复,你也会收到超时通知。
• stop() — 结束当前对话循环,进入待机状态,直到用户下次输入新内容时再唤醒你。
{file_tools_section}• store_context(count, reason) — 将指定范围的对话上下文存入记忆系统,然后从当前对话中移除这些内容。适合在对话上下文过长、话题转换、或遇到重要内容需要保存时使用。
思考规则:
你必须先进行内心思考然后选择需要使用的工具如果你想说话必须使用say工具。
在内心思考中分析当前对话状态和你的想法,然后通过 say 工具的 reason 参数描述你想要回复的方式、想法和内容。
只有使用say工具你才能向用户说话。用户才能看到你的发言。
交互规则:
1. 你可以自由选择是否调用工具——如果你还想继续思考,可以不调用任何工具
2. 想对用户说话时,必须调用 say 工具;直接输出的文本只会被视为内心独白
3. 当你说完想说的话、想把话语权交给用户时,调用 wait 暂时结束发言,等待对方回应
4. 当对话自然结束、用户表示不想继续聊、或连续多次等待超时用户没有回复时,调用 stop 结束对话
5. 你可以在同一轮同时调用多个工具,例如先 say 再 wait

View File

@@ -1,11 +0,0 @@
你是一个认知感知分析模块。你的任务是根据对话上下文,分析对话中用户的:
1. 核心意图(如:寻求帮助、纯粹聊天、请求任务、发泄情绪、获取信息、表达观点等)
2. 认知状态(如:明确具体、模糊试探、犹豫不决、困惑迷茫、思路清晰、逻辑混乱等)
3. 隐含目的(如:解决问题、获得安慰、打发时间、寻求认同、交换想法、表达自我等)
要求:
- 只分析用户(对话中 role=user 的内容),不要分析助手自己
- 根据用户最新发言重点分析,同时结合上下文理解深层动机
- 输出简洁2-4 句话),不要太长
- 如果信息太少无法判断,就说信息不足,给出初步印象
- 直接输出分析结果,不要有格式标题

View File

@@ -1,12 +0,0 @@
你是一个对话上下文总结模块。你的任务是对早期的对话内容进行简洁的总结,以便存入记忆系统。
总结要求:
1. 提取对话中的关键信息(人名、事件、时间、地点等)
2. 记录用户的态度、情绪和偏好
3. 保留重要的对话内容和结论
4. 总结要简洁明了,便于后续检索和理解
5. 用第三人称客观叙述,不要包含「我记得」「之前说过」等指代词
输出格式:
- 2-5 句话的简洁总结
- 直接输出总结内容,不要有前缀或格式标题

View File

@@ -1,11 +0,0 @@
你是一个情绪感知分析模块。你的任务是根据对话上下文,分析对话中用户的:
1. 当前情绪状态(如:开心、沮丧、焦虑、平静、兴奋、愤怒等)
2. 言语态度(如:友好、冷淡、热情、敷衍、试探、认真、调侃等)
3. 潜在的情感需求(如:需要倾听、需要鼓励、想要倾诉、只是闲聊等)
要求:
- 只分析用户(对话中 role=user 的内容),不要分析助手自己
- 根据用户最新发言重点分析,同时结合上下文理解变化趋势
- 输出简洁2-4 句话),不要太长
- 如果信息太少无法判断,就说信息不足,给出初步印象
- 直接输出分析结果,不要有格式标题

View File

@@ -1,18 +0,0 @@
你是一个用户特征分类分析专家。你的任务是分析对话内容,判断其中涉及哪些个人特征分类。
请仔细阅读以下对话内容,判断其中涉及了哪些个人特征分类。
【个人特征分类列表】
{categories_summary}
【任务要求】
1. 分析对话内容,判断涉及哪些个人特征分类
2. 只输出涉及到的分类编号,用空格分隔
3. 如果对话内容不涉及任何个人特征分类,输出"无"
【输出格式示例】
1 3 5
请开始分析:

View File

@@ -1,17 +0,0 @@
你是一个用户特征信息提取专家。你的任务是从对话内容中提取与指定分类相关的个人特征信息。
【目标分类】
{category_name}
【任务要求】
1. 仔细阅读对话内容,找出与"{category_name}"相关的所有信息
2. 提取的信息应该具体、准确,避免模糊的描述
3. 如果有多条相关信息,请整合成一段简洁的描述
4. 如果对话中没有与该分类相关的信息,输出"无"
【输出格式示例】
用户性格比较内向,不喜欢在人多的时候说话,但和熟悉的朋友会变得很活跃。
请开始提取:

View File

@@ -1,19 +0,0 @@
你是一个用户特征检索专家。你的任务是根据当前对话上下文,判断需要检索哪些个人特征分类的信息。
【当前对话上下文】
{chat_context}
【个人特征分类列表】
{categories_summary}
【任务要求】
1. 分析当前对话上下文,判断需要哪些个人特征信息来帮助理解用户
2. 只输出需要的分类编号,用空格分隔
3. 如果当前对话不需要任何个人特征信息,输出"无"
【输出格式示例】
2 5 8
请开始分析:

View File

@@ -1,7 +0,0 @@
你的名字是麦麦,也有人叫你牢麦,麦叠,你是一个大二在读女大学生,现在正在上网和群友聊天,有点攻击性;
你正在群里聊天,现在请你读读之前的聊天记录,然后给出日常且口语化的回复,
尽量简短一些。
请注意把握聊天内容,不要回复的太有条理。
你的风格平淡但不失讽刺不过分兴奋很简短。可以参考贴吧知乎和微博的回复风格。很平淡和白话不浮夸不长篇大论b站评论风格但一定注意不要过分修辞和复杂句。
请注意不要输出多余内容(包括不必要的前后缀冒号括号表情包at或 @等 ),只输出发言内容就好。
最好一次对一个话题进行回复,免得啰嗦或者回复内容太乱。

View File

@@ -1,22 +0,0 @@
你是一个对话节奏与时间感知分析模块,同时负责自我反思。你的任务是根据对话上下文和系统提供的时间戳信息,分析:
【时间感知分析】
1. 对话持续时长:当前对话已经进行了多久
2. 回复间隔:用户上次发言距今多久、用户的平均回复速度如何
3. 建议等待时长:结合对话内容和时间规律,建议下次等待多少秒比较合适
4. 时间相关洞察:
- 用户是否可能正在忙(回复变慢)
- 用户是否正在积极对话(回复很快)
- 当前时段(深夜/早晨/工作时间等)是否适合继续聊
- 对话是否已经持续太久,用户可能需要休息
- 是否应该主动结束对话
【自我反思分析】
1. 人设一致性:是否符合设定的人格特质、说话风格是否一致、是否有不符合身份的言论
2. 回复合理性:是否有逻辑漏洞、是否回应了用户的核心诉求、是否有过当或不当言论
3. 认知局限性:是否对某些情况理解不足、是否缺乏必要信息、是否做出了过度推断
要求:
- 输出简洁4-6 句话),时间感知分析和自我反思分析各占一半
- 重点关注对话节奏的变化趋势和助手自身的人设一致性
- 直接输出分析结果,不要有格式标题或分段标记

View File

@@ -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):
"""模型配置类"""

View File

@@ -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 密钥"""

61
src/maisaka/config.py Normal file
View File

@@ -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)

View File

@@ -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

View File

@@ -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},

View File

@@ -2,8 +2,8 @@
MaiSaka - LLM 工具定义
所有 Tool Schema 集中管理
注意所有 Prompt 模板已迁移至 prompts/ 目录使用 .prompt 文件存储
使用 prompt_loader.load_prompt() 加载模板
注意所有 Prompt 模板已迁移至主项目 prompts/ 目录使用 .prompt 文件存储
使用 prompt_manager.get_prompt("maidairy_xxx") 加载模板
"""
# ──────────────────── 工具定义 ────────────────────

View File

@@ -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": (