feat:添加了月度计划 # 我要混提交
This commit is contained in:
121
docs/schedule_enhancement (1).md
Normal file
121
docs/schedule_enhancement (1).md
Normal file
@@ -0,0 +1,121 @@
|
||||
# “月层计划”系统架构设计文档
|
||||
|
||||
## 1. 系统概述与目标
|
||||
|
||||
本系统旨在为Bot引入一个动态的、由大型语言模型(LLM)驱动的“月层计划”机制。其核心目标是取代静态、预设的任务模板,转而利用LLM在程序启动时自动生成符合Bot人设的、具有时效性的月度计划。这些计划将被存储、管理,并在构建每日日程时被动态抽取和使用,从而极大地丰富日程内容的个性和多样性。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心设计原则
|
||||
|
||||
- **动态性与智能化:** 所有计划内容均由LLM实时生成,确保其独特性和创造性。
|
||||
- **人设一致性:** 计划的生成将严格围绕Bot的核心人设进行,强化角色形象。
|
||||
- **持久化与可管理:** 生成的计划将被存入专用数据库表,便于管理和追溯。
|
||||
- **消耗性与随机性:** 计划在使用后有一定几率被消耗(删除),模拟真实世界中计划的完成与迭代。
|
||||
|
||||
---
|
||||
|
||||
## 3. 系统核心流程规划
|
||||
|
||||
本系统包含两大核心流程:**启动时的计划生成流程**和**日程构建时的计划使用流程**。
|
||||
|
||||
### 3.1 流程一:启动时计划生成
|
||||
|
||||
此流程在每次程序启动时触发,负责填充当月的计划池。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[程序启动] --> B{检查当月计划池};
|
||||
B -- 计划数量低于阈值 --> C[构建LLM Prompt];
|
||||
C -- prompt包含Bot人设、月份等信息 --> D[调用LLM服务];
|
||||
D -- LLM返回多个计划文本 --> E[解析并格式化计划];
|
||||
E -- 逐条处理 --> F[存入`monthly_plans`数据库表];
|
||||
F --> G[完成启动任务];
|
||||
B -- 计划数量充足 --> G;
|
||||
```
|
||||
|
||||
### 3.2 流程二:日程构建时计划使用
|
||||
|
||||
此流程在构建每日日程的提示词(Prompt)时触发。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
H[构建日程Prompt] --> I{查询数据库};
|
||||
I -- 读取当月未使用的计划 --> J[随机抽取N个计划];
|
||||
J --> K[将计划文本嵌入日程Prompt];
|
||||
K --> L{随机数判断};
|
||||
L -- 概率命中 --> M[将已抽取的计划标记为删除];
|
||||
M --> N[完成Prompt构建];
|
||||
L -- 概率未命中 --> N;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据库模型设计
|
||||
|
||||
为支撑本系统,需要新增一个数据库表。
|
||||
|
||||
**表名:** `monthly_plans`
|
||||
|
||||
| 字段名 | 类型 | 描述 |
|
||||
| :--- | :--- | :--- |
|
||||
| `id` | Integer | 主键,自增。 |
|
||||
| `plan_text` | Text | 由LLM生成的计划内容原文。 |
|
||||
| `target_month` | String(7) | 计划所属的月份,格式为 "YYYY-MM"。 |
|
||||
| `is_deleted` | Boolean | 软删除标记,默认为 `false`。 |
|
||||
| `created_at` | DateTime | 记录创建时间。 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 详细模块规划
|
||||
|
||||
### 5.1 LLM Prompt生成模块
|
||||
|
||||
- **职责:** 构建高质量的Prompt以引导LLM生成符合要求的计划。
|
||||
- **输入:** Bot人设描述、当前月份、期望生成的计划数量。
|
||||
- **输出:** 一个结构化的Prompt字符串。
|
||||
- **Prompt示例:**
|
||||
```
|
||||
你是一个[此处填入Bot人设描述,例如:活泼开朗、偶尔有些小迷糊的虚拟助手]。
|
||||
请为即将到来的[YYYY年MM月]设计[N]个符合你身份的月度计划或目标。
|
||||
|
||||
要求:
|
||||
1. 每个计划都是独立的、积极向上的。
|
||||
2. 语言风格要自然、口语化,符合你的性格。
|
||||
3. 每个计划用一句话或两句话简短描述。
|
||||
4. 以JSON格式返回,格式为:{"plans": ["计划一", "计划二", ...]}
|
||||
```
|
||||
|
||||
### 5.2 数据库交互模块
|
||||
|
||||
- **职责:** 提供对 `monthly_plans` 表的增、删、改、查接口。
|
||||
- **规划函数列表:**
|
||||
- `add_new_plans(plans: list[str], month: str)`: 批量添加新生成的计划。
|
||||
- `get_active_plans_for_month(month: str) -> list`: 获取指定月份所有未被删除的计划。
|
||||
- `soft_delete_plans(plan_ids: list[int])`: 将指定ID的计划标记为软删除。
|
||||
|
||||
### 5.3 配置项规划
|
||||
|
||||
需要在主配置文件 `config/bot_config.toml` 中添加以下配置项,以控制系统行为。
|
||||
|
||||
```toml
|
||||
# ----------------------------------------------------------------
|
||||
# 月层计划系统设置 (Monthly Plan System Settings)
|
||||
# ----------------------------------------------------------------
|
||||
[monthly_plan_system]
|
||||
|
||||
# 是否启用本功能
|
||||
enable = true
|
||||
|
||||
# 启动时,如果当月计划少于此数量,则触发LLM生成
|
||||
generation_threshold = 10
|
||||
|
||||
# 每次调用LLM期望生成的计划数量
|
||||
plans_per_generation = 5
|
||||
|
||||
# 计划被使用后,被删除的概率 (0.0 到 1.0)
|
||||
deletion_probability_on_use = 0.5
|
||||
```
|
||||
|
||||
---
|
||||
**文档结束。** 本文档纯粹为架构规划,旨在提供清晰的设计思路和开发指引,不包含任何实现代码。
|
||||
68
src/common/database/monthly_plan_db.py
Normal file
68
src/common/database/monthly_plan_db.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# mmc/src/common/database/monthly_plan_db.py
|
||||
|
||||
import datetime
|
||||
from typing import List
|
||||
from src.common.database.sqlalchemy_models import MonthlyPlan, get_db_session
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("monthly_plan_db")
|
||||
|
||||
def add_new_plans(plans: List[str], month: str):
|
||||
"""
|
||||
批量添加新生成的月度计划到数据库。
|
||||
|
||||
:param plans: 计划内容列表。
|
||||
:param month: 目标月份,格式为 "YYYY-MM"。
|
||||
"""
|
||||
with get_db_session() as session:
|
||||
try:
|
||||
new_plan_objects = [
|
||||
MonthlyPlan(plan_text=plan, target_month=month)
|
||||
for plan in plans
|
||||
]
|
||||
session.add_all(new_plan_objects)
|
||||
session.commit()
|
||||
logger.info(f"成功向数据库添加了 {len(new_plan_objects)} 条 {month} 的月度计划。")
|
||||
except Exception as e:
|
||||
logger.error(f"添加月度计划时发生错误: {e}")
|
||||
session.rollback()
|
||||
raise
|
||||
|
||||
def get_active_plans_for_month(month: str) -> List[MonthlyPlan]:
|
||||
"""
|
||||
获取指定月份所有未被软删除的计划。
|
||||
|
||||
:param month: 目标月份,格式为 "YYYY-MM"。
|
||||
:return: MonthlyPlan 对象列表。
|
||||
"""
|
||||
with get_db_session() as session:
|
||||
try:
|
||||
plans = session.query(MonthlyPlan).filter(
|
||||
MonthlyPlan.target_month == month,
|
||||
MonthlyPlan.is_deleted == False
|
||||
).all()
|
||||
return plans
|
||||
except Exception as e:
|
||||
logger.error(f"查询 {month} 的有效月度计划时发生错误: {e}")
|
||||
return []
|
||||
|
||||
def soft_delete_plans(plan_ids: List[int]):
|
||||
"""
|
||||
将指定ID的计划标记为软删除。
|
||||
|
||||
:param plan_ids: 需要软删除的计划ID列表。
|
||||
"""
|
||||
if not plan_ids:
|
||||
return
|
||||
|
||||
with get_db_session() as session:
|
||||
try:
|
||||
session.query(MonthlyPlan).filter(
|
||||
MonthlyPlan.id.in_(plan_ids)
|
||||
).update({"is_deleted": True}, synchronize_session=False)
|
||||
session.commit()
|
||||
logger.info(f"成功软删除了 {len(plan_ids)} 条月度计划。")
|
||||
except Exception as e:
|
||||
logger.error(f"软删除月度计划时发生错误: {e}")
|
||||
session.rollback()
|
||||
raise
|
||||
@@ -509,6 +509,19 @@ class CacheEntries(Base):
|
||||
Index('idx_cache_entries_created_at', 'created_at'),
|
||||
)
|
||||
|
||||
class MonthlyPlan(Base):
|
||||
"""月层计划模型"""
|
||||
__tablename__ = 'monthly_plans'
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
plan_text = Column(Text, nullable=False)
|
||||
target_month = Column(String(7), nullable=False, index=True) # "YYYY-MM"
|
||||
is_deleted = Column(Boolean, nullable=False, default=False, index=True)
|
||||
created_at = Column(DateTime, nullable=False, default=datetime.datetime.now)
|
||||
|
||||
__table_args__ = (
|
||||
Index('idx_monthlyplan_target_month_is_deleted', 'target_month', 'is_deleted'),
|
||||
)
|
||||
|
||||
# 数据库引擎和会话管理
|
||||
_engine = None
|
||||
|
||||
@@ -434,6 +434,7 @@ MODULE_COLORS = {
|
||||
"dependency_manager": "\033[38;5;30m", # 深青色
|
||||
"manifest_utils": "\033[38;5;39m", # 蓝色
|
||||
"schedule_manager": "\033[38;5;27m", # 深蓝色
|
||||
"monthly_plan_manager": "\033[38;5;171m",
|
||||
|
||||
# 聊天和多媒体扩展
|
||||
"chat_voice": "\033[38;5;87m", # 浅青色
|
||||
@@ -536,6 +537,7 @@ MODULE_ALIASES = {
|
||||
"dependency_manager": "依赖管理",
|
||||
"manifest_utils": "清单工具",
|
||||
"schedule_manager": "计划管理",
|
||||
"monthly_plan_manager": "月度计划",
|
||||
|
||||
# 聊天和多媒体扩展
|
||||
"chat_voice": "语音处理",
|
||||
|
||||
@@ -114,6 +114,7 @@ class ModelTaskConfig(ValidatedConfigBase):
|
||||
lpmm_rdf_build: TaskConfig = Field(..., description="LPMM RDF构建模型配置")
|
||||
lpmm_qa: TaskConfig = Field(..., description="LPMM问答模型配置")
|
||||
schedule_generator: TaskConfig = Field(..., description="日程生成模型配置")
|
||||
monthly_plan_generator: TaskConfig = Field(..., description="月层计划生成模型配置")
|
||||
emoji_vlm: TaskConfig = Field(..., description="表情包识别模型配置")
|
||||
anti_injection: TaskConfig = Field(..., description="反注入检测专用模型配置")
|
||||
|
||||
|
||||
@@ -43,7 +43,8 @@ from src.config.official_configs import (
|
||||
WebSearchConfig,
|
||||
TavilyConfig,
|
||||
AntiPromptInjectionConfig,
|
||||
PluginsConfig
|
||||
PluginsConfig,
|
||||
MonthlyPlanSystemConfig
|
||||
)
|
||||
|
||||
from .api_ada_configs import (
|
||||
@@ -388,6 +389,7 @@ class Config(ValidatedConfigBase):
|
||||
web_search: WebSearchConfig = Field(default_factory=lambda: WebSearchConfig(), description="网络搜索配置")
|
||||
tavily: TavilyConfig = Field(default_factory=lambda: TavilyConfig(), description="Tavily配置")
|
||||
plugins: PluginsConfig = Field(default_factory=lambda: PluginsConfig(), description="插件配置")
|
||||
monthly_plan_system: MonthlyPlanSystemConfig = Field(default_factory=lambda: MonthlyPlanSystemConfig(), description="月层计划系统配置")
|
||||
|
||||
|
||||
class APIAdapterConfig(ValidatedConfigBase):
|
||||
|
||||
@@ -652,3 +652,12 @@ class PluginsConfig(ValidatedConfigBase):
|
||||
"""插件配置"""
|
||||
|
||||
centralized_config: bool = Field(default=True, description="是否启用插件配置集中化管理")
|
||||
|
||||
|
||||
class MonthlyPlanSystemConfig(ValidatedConfigBase):
|
||||
"""月层计划系统配置类"""
|
||||
|
||||
enable: bool = Field(default=True, description="是否启用本功能")
|
||||
generation_threshold: int = Field(default=10, ge=0, description="启动时,如果当月计划少于此数量,则触发LLM生成")
|
||||
plans_per_generation: int = Field(default=5, ge=1, description="每次调用LLM期望生成的计划数量")
|
||||
deletion_probability_on_use: float = Field(default=0.5, ge=0.0, le=1.0, description="计划被使用后,被删除的概率")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# 有一个人想混点提交()
|
||||
# 什么?混提交不带我一个喵~
|
||||
# 我要混提交
|
||||
import asyncio
|
||||
import time
|
||||
import signal
|
||||
@@ -19,6 +20,7 @@ from src.common.server import get_global_server, Server
|
||||
from src.mood.mood_manager import mood_manager
|
||||
from rich.traceback import install
|
||||
from src.manager.schedule_manager import schedule_manager
|
||||
from src.schedule.monthly_plan_manager import MonthlyPlanManager
|
||||
# from src.api.main import start_api_server
|
||||
|
||||
# 导入新的插件管理器和热重载管理器
|
||||
@@ -177,6 +179,12 @@ MaiMbot-Pro-Max(第三方改版)
|
||||
await self.individuality.initialize()
|
||||
# 初始化日程管理器
|
||||
if global_config.schedule.enable:
|
||||
logger.info("正在初始化月度计划...")
|
||||
try:
|
||||
await MonthlyPlanManager.initialize_monthly_plans()
|
||||
logger.info("月度计划初始化完成")
|
||||
except Exception as e:
|
||||
logger.error(f"月度计划初始化失败: {e}")
|
||||
logger.info("日程表功能已启用,正在初始化管理器...")
|
||||
await schedule_manager.load_or_generate_today_schedule()
|
||||
await schedule_manager.start_daily_schedule_generation()
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import json
|
||||
import asyncio
|
||||
import random
|
||||
from datetime import datetime, time, timedelta
|
||||
from typing import Optional, List, Dict, Any
|
||||
from pydantic import BaseModel, ValidationError, validator
|
||||
|
||||
from src.common.database.sqlalchemy_models import Schedule, get_db_session
|
||||
from src.common.database.monthly_plan_db import get_active_plans_for_month, soft_delete_plans
|
||||
from src.config.config import global_config, model_config
|
||||
from src.llm_models.utils_model import LLMRequest
|
||||
from src.common.logger import get_logger
|
||||
@@ -168,9 +170,28 @@ class ScheduleManager:
|
||||
logger.error(f"加载或生成日程时出错: {e}")
|
||||
|
||||
async def generate_and_save_schedule(self):
|
||||
today_str = datetime.now().strftime("%Y-%m-%d")
|
||||
weekday = datetime.now().strftime("%A")
|
||||
|
||||
now = datetime.now()
|
||||
today_str = now.strftime("%Y-%m-%d")
|
||||
current_month_str = now.strftime("%Y-%m")
|
||||
weekday = now.strftime("%A")
|
||||
|
||||
# 获取月度计划作为额外参考
|
||||
monthly_plans_block = ""
|
||||
used_plan_ids = []
|
||||
if global_config.monthly_plan_system and global_config.monthly_plan_system.enable:
|
||||
active_plans = get_active_plans_for_month(current_month_str)
|
||||
if active_plans:
|
||||
# 随机抽取最多3个计划
|
||||
num_to_sample = min(len(active_plans), 3)
|
||||
sampled_plans = random.sample(active_plans, num_to_sample)
|
||||
used_plan_ids = [p.id for p in sampled_plans] # type: ignore
|
||||
|
||||
plan_texts = "\n".join([f"- {p.plan_text}" for p in sampled_plans])
|
||||
monthly_plans_block = f"""
|
||||
**我这个月的一些小目标/计划 (请在今天的日程中适当体现)**:
|
||||
{plan_texts}
|
||||
"""
|
||||
|
||||
guidelines = global_config.schedule.guidelines or DEFAULT_SCHEDULE_GUIDELINES
|
||||
personality = global_config.personality.personality_core
|
||||
personality_side = global_config.personality.personality_side
|
||||
@@ -180,10 +201,10 @@ class ScheduleManager:
|
||||
|
||||
**关于我**:
|
||||
- **核心人设**: {personality}
|
||||
- **具体习惯与兴趣**:
|
||||
- **具体习惯与兴趣**:
|
||||
{personality_side}
|
||||
|
||||
**我今天的规划原则**:
|
||||
{monthly_plans_block}
|
||||
**我今天的规划原则**:
|
||||
{guidelines}
|
||||
|
||||
**重要要求**:
|
||||
@@ -219,15 +240,18 @@ class ScheduleManager:
|
||||
existing_schedule = session.query(Schedule).filter(Schedule.date == today_str).first()
|
||||
if existing_schedule:
|
||||
# 更新现有日程
|
||||
existing_schedule.schedule_data = json.dumps(schedule_data)
|
||||
existing_schedule.updated_at = datetime.now()
|
||||
session.query(Schedule).filter(Schedule.date == today_str).update({
|
||||
Schedule.schedule_data: json.dumps(schedule_data),
|
||||
Schedule.updated_at: datetime.now()
|
||||
})
|
||||
else:
|
||||
# 创建新日程
|
||||
new_schedule = Schedule()
|
||||
new_schedule.date = today_str
|
||||
new_schedule.schedule_data = json.dumps(schedule_data)
|
||||
new_schedule = Schedule(
|
||||
date=today_str,
|
||||
schedule_data=json.dumps(schedule_data)
|
||||
)
|
||||
session.add(new_schedule)
|
||||
session.commit()
|
||||
session.commit()
|
||||
|
||||
# 美化输出
|
||||
schedule_str = f"已成功生成并保存今天的日程 ({today_str}):\n"
|
||||
@@ -236,6 +260,13 @@ class ScheduleManager:
|
||||
logger.info(schedule_str)
|
||||
|
||||
self.today_schedule = schedule_data
|
||||
|
||||
# 成功生成日程后,根据概率软删除使用过的月度计划
|
||||
if used_plan_ids and global_config.monthly_plan_system:
|
||||
if random.random() < global_config.monthly_plan_system.deletion_probability_on_use:
|
||||
logger.info(f"根据概率,将使用过的月度计划 {used_plan_ids} 标记为已完成。")
|
||||
soft_delete_plans(used_plan_ids)
|
||||
|
||||
return
|
||||
else:
|
||||
logger.warning(f"第 {attempt + 1} 次生成的日程验证失败,正在重试...")
|
||||
|
||||
106
src/schedule/monthly_plan_manager.py
Normal file
106
src/schedule/monthly_plan_manager.py
Normal file
@@ -0,0 +1,106 @@
|
||||
# mmc/src/schedule/monthly_plan_manager.py
|
||||
# 我要混提交
|
||||
import datetime
|
||||
from src.config.config import global_config
|
||||
from src.common.database.monthly_plan_db import get_active_plans_for_month, add_new_plans
|
||||
from src.schedule.plan_generator import PlanGenerator
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("monthly_plan_manager")
|
||||
|
||||
class MonthlyPlanManager:
|
||||
"""
|
||||
管理月度计划的生成和填充。
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
async def initialize_monthly_plans():
|
||||
"""
|
||||
程序启动时调用,检查并按需填充当月的计划池。
|
||||
"""
|
||||
config = global_config.monthly_plan_system
|
||||
if not config or not config.enable:
|
||||
logger.info("月层计划系统未启用,跳过初始化。")
|
||||
return
|
||||
|
||||
now = datetime.datetime.now()
|
||||
current_month_str = now.strftime("%Y-%m")
|
||||
|
||||
try:
|
||||
# 1. 检查当月已有计划数量
|
||||
existing_plans = get_active_plans_for_month(current_month_str)
|
||||
plan_count = len(existing_plans)
|
||||
|
||||
header = "📅 月度计划检查"
|
||||
|
||||
# 2. 判断是否需要生成新计划
|
||||
if plan_count >= config.generation_threshold:
|
||||
summary = f"计划数量充足 ({plan_count}/{config.generation_threshold}),无需生成。"
|
||||
log_message = (
|
||||
f"\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"
|
||||
f"┃ {header}\n"
|
||||
f"┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"
|
||||
f"┃ 月份: {current_month_str}\n"
|
||||
f"┃ 状态: {summary}\n"
|
||||
f"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
||||
)
|
||||
logger.info(log_message)
|
||||
return
|
||||
|
||||
# 3. 计算需要生成的计划数量并调用生成器
|
||||
needed_plans = config.generation_threshold - plan_count
|
||||
summary = f"计划不足 ({plan_count}/{config.generation_threshold}),需要生成 {needed_plans} 条。"
|
||||
generation_info = f"即将生成 {config.plans_per_generation} 条新计划..."
|
||||
log_message = (
|
||||
f"\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"
|
||||
f"┃ {header}\n"
|
||||
f"┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"
|
||||
f"┃ 月份: {current_month_str}\n"
|
||||
f"┃ 状态: {summary}\n"
|
||||
f"┃ 操作: {generation_info}\n"
|
||||
f"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
||||
)
|
||||
logger.info(log_message)
|
||||
|
||||
generator = PlanGenerator()
|
||||
new_plans = await generator.generate_plans(
|
||||
year=now.year,
|
||||
month=now.month,
|
||||
count=config.plans_per_generation # 每次生成固定数量以保证质量
|
||||
)
|
||||
|
||||
# 4. 将新计划存入数据库
|
||||
if new_plans:
|
||||
add_new_plans(new_plans, current_month_str)
|
||||
completion_header = "✅ 月度计划生成完毕"
|
||||
completion_summary = f"成功添加 {len(new_plans)} 条新计划。"
|
||||
|
||||
# 构建计划详情
|
||||
plan_details = "\n".join([f"┃ - {plan}" for plan in new_plans])
|
||||
|
||||
log_message = (
|
||||
f"\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"
|
||||
f"┃ {completion_header}\n"
|
||||
f"┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"
|
||||
f"┃ 月份: {current_month_str}\n"
|
||||
f"┃ 结果: {completion_summary}\n"
|
||||
f"┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"
|
||||
f"{plan_details}\n"
|
||||
f"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
||||
)
|
||||
logger.info(log_message)
|
||||
else:
|
||||
completion_header = "❌ 月度计划生成失败"
|
||||
completion_summary = "未能生成任何新的月度计划。"
|
||||
log_message = (
|
||||
f"\n┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n"
|
||||
f"┃ {completion_header}\n"
|
||||
f"┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n"
|
||||
f"┃ 月份: {current_month_str}\n"
|
||||
f"┃ 结果: {completion_summary}\n"
|
||||
f"┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛"
|
||||
)
|
||||
logger.warning(log_message)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"初始化月度计划时发生严重错误: {e}", exc_info=True)
|
||||
118
src/schedule/plan_generator.py
Normal file
118
src/schedule/plan_generator.py
Normal file
@@ -0,0 +1,118 @@
|
||||
# mmc/src/schedule/plan_generator.py
|
||||
|
||||
import json
|
||||
import random
|
||||
from typing import List
|
||||
from src.config.config import global_config, model_config
|
||||
from src.llm_models.model_client.base_client import client_registry
|
||||
from src.llm_models.payload_content.message import Message, RoleType
|
||||
from src.llm_models.payload_content.resp_format import RespFormat, RespFormatType
|
||||
from src.common.logger import get_logger
|
||||
|
||||
logger = get_logger("plan_generator")
|
||||
|
||||
class PlanGenerator:
|
||||
"""
|
||||
负责生成月度计划。
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.bot_personality = self._get_bot_personality()
|
||||
|
||||
def _get_bot_personality(self) -> str:
|
||||
"""
|
||||
从全局配置中获取Bot的人设描述。
|
||||
"""
|
||||
core = global_config.personality.personality_core or ""
|
||||
side = global_config.personality.personality_side or ""
|
||||
identity = global_config.personality.identity or ""
|
||||
return f"核心人设: {core}\n侧面人设: {side}\n身份设定: {identity}"
|
||||
|
||||
def _build_prompt(self, year: int, month: int, count: int) -> str:
|
||||
"""
|
||||
构建用于生成月度计划的Prompt。
|
||||
"""
|
||||
prompt_template = f"""
|
||||
你是一个富有想象力的助手,你的任务是为一位虚拟角色生成月度计划。
|
||||
|
||||
**角色设定:**
|
||||
---
|
||||
{self.bot_personality}
|
||||
---
|
||||
|
||||
请为即将到来的 **{year}年{month}月** 设计 **{count}** 个符合该角色身份的、独立的、积极向上的月度计划或小目标。
|
||||
|
||||
**要求:**
|
||||
1. 每个计划都应简短、清晰,用一两句话描述。
|
||||
2. 语言风格必须自然、口语化,严格符合角色的性格设定。
|
||||
3. 计划内容要具有创造性,避免陈词滥调。
|
||||
4. 请以严格的JSON格式返回,格式为:{{"plans": ["计划一", "计划二", ...]}}
|
||||
5. 除了JSON对象,不要包含任何额外的解释、注释或前后导语。
|
||||
"""
|
||||
return prompt_template.strip()
|
||||
|
||||
async def generate_plans(self, year: int, month: int, count: int) -> List[str]:
|
||||
"""
|
||||
调用LLM生成指定月份的计划。
|
||||
|
||||
:param year: 年份
|
||||
:param month: 月份
|
||||
:param count: 需要生成的计划数量
|
||||
:return: 生成的计划文本列表
|
||||
"""
|
||||
try:
|
||||
# 1. 获取模型任务配置
|
||||
task_config = model_config.model_task_config.get_task("monthly_plan_generator")
|
||||
|
||||
# 2. 随机选择一个模型
|
||||
model_name = random.choice(task_config.model_list)
|
||||
model_info = model_config.get_model_info(model_name)
|
||||
api_provider = model_config.get_provider(model_info.api_provider)
|
||||
|
||||
# 3. 获取客户端实例
|
||||
llm_client = client_registry.get_client_class_instance(api_provider)
|
||||
|
||||
# 4. 构建Prompt和消息体
|
||||
prompt = self._build_prompt(year, month, count)
|
||||
message_list = [Message(role=RoleType.User, content=prompt)]
|
||||
|
||||
logger.info(f"正在使用模型 '{model_name}' 为 {year}-{month} 生成 {count} 个月度计划...")
|
||||
|
||||
# 5. 调用LLM
|
||||
response = await llm_client.get_response(
|
||||
model_info=model_info,
|
||||
message_list=message_list,
|
||||
temperature=task_config.temperature,
|
||||
max_tokens=task_config.max_tokens,
|
||||
response_format=RespFormat(format_type=RespFormatType.JSON_OBJ) # 请求JSON输出
|
||||
)
|
||||
|
||||
if not response or not response.content:
|
||||
logger.error("LLM未能返回有效的计划内容。")
|
||||
return []
|
||||
|
||||
# 6. 解析LLM返回的JSON
|
||||
try:
|
||||
# 移除可能的Markdown代码块标记
|
||||
clean_content = response.content.strip()
|
||||
if clean_content.startswith("```json"):
|
||||
clean_content = clean_content[7:]
|
||||
if clean_content.endswith("```"):
|
||||
clean_content = clean_content[:-3]
|
||||
|
||||
data = json.loads(clean_content.strip())
|
||||
plans = data.get("plans", [])
|
||||
|
||||
if isinstance(plans, list) and all(isinstance(p, str) for p in plans):
|
||||
logger.info(f"成功生成并解析了 {len(plans)} 个月度计划。")
|
||||
return plans
|
||||
else:
|
||||
logger.error(f"LLM返回的JSON格式不正确或'plans'键不是字符串列表: {response.content}")
|
||||
return []
|
||||
except json.JSONDecodeError:
|
||||
logger.error(f"无法解析LLM返回的JSON: {response.content}")
|
||||
return []
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"调用LLM生成月度计划时发生未知错误: {e}", exc_info=True)
|
||||
return []
|
||||
@@ -1,5 +1,5 @@
|
||||
[inner]
|
||||
version = "6.3.10"
|
||||
version = "6.3.11"
|
||||
|
||||
#----以下是给开发人员阅读的,如果你只是部署了麦麦,不需要阅读----
|
||||
#如果你想要修改配置文件,请递增version的值
|
||||
@@ -381,3 +381,16 @@ search_strategy = "single" # 搜索策略: "single"(使用第一个可用引擎)
|
||||
|
||||
[plugins] # 插件配置
|
||||
centralized_config = true # 是否启用插件配置集中化管理
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# 月层计划系统设置 (Monthly Plan System Settings)
|
||||
# ----------------------------------------------------------------
|
||||
[monthly_plan_system]
|
||||
# 是否启用本功能
|
||||
enable = true
|
||||
# 启动时,如果当月计划少于此数量,则触发LLM生成
|
||||
generation_threshold = 30
|
||||
# 每次调用LLM期望生成的计划数量
|
||||
plans_per_generation = 5
|
||||
# 计划被使用后,被删除的概率 (0.0 到 1.0)
|
||||
deletion_probability_on_use = 0.5
|
||||
@@ -1,5 +1,5 @@
|
||||
[inner]
|
||||
version = "1.2.6"
|
||||
version = "1.2.7"
|
||||
|
||||
# 配置文件版本号迭代规则同bot_config.toml
|
||||
|
||||
@@ -193,6 +193,11 @@ model_list = ["moonshotai-Kimi-K2-Instruct"] # 使用快速的小模
|
||||
temperature = 0.1 # 低温度确保检测结果稳定
|
||||
max_tokens = 200 # 检测结果不需要太长的输出
|
||||
|
||||
[model_task_config.monthly_plan_generator] # 月层计划生成模型
|
||||
model_list = ["deepseek-v3"]
|
||||
temperature = 0.7
|
||||
max_tokens = 1000
|
||||
|
||||
#嵌入模型
|
||||
[model_task_config.embedding]
|
||||
model_list = ["bge-m3"]
|
||||
|
||||
Reference in New Issue
Block a user