- PersonaConfig 新增 NarrativePersona 字段,在 system prompt 的「你的身份」和「你的性格」之间插入「## 你的叙事人格」 - Loader.NewLoader 自动读取同目录 persona.md 注入所有 config;Reload 同步热更新 - RAG IngestDirectory 跳过 persona.md 和 _index.md,避免重复检索浪费token - 新增 docs/dev-plan/12-next-phase-optimization.md 下一阶段优化大纲 Co-Authored-By: Claude <noreply@anthropic.com>
10 KiB
12 — 下一阶段优化大纲
日期:2026-06-22
来源:对照 Cyrene 人格、记忆及功能拓展架构设计文档,逐项比对现状后梳理
状态:大纲,待拆分为详细实施计划
目录
1. P0 — 自主思考分层
现状
所有后台思考(periodic / silence / post_chat / startup)共用同一个 LLM 模型和同一套 system prompt。高频短思考(如每分钟检查状态)和低频深度反思(如每 5 分钟整理记忆)没有区分,浪费 token。
目标
┌─────────────┐ 唤醒 ┌─────────────┐
│ 简单思考 │ ──────────────► │ 复杂思考 │
│ (下位模型) │ │ (思考模型) │
│ 高频/轻量 │ │ 低频/深度 │
│ 例: 每分钟 │ │ 例: 每5分钟 │
└──────┬───────┘ └──────┬───────┘
│ 可调用工具 │ 可调用工具
│ 可主动消息 │ 可主动消息
│ 可追加继续 │ 可追加继续
▼ ▼
共享 ProactiveGuard 频率控制
要点
- 模型配置:简单思考用 fast/flash 模型(temperature 0.3),复杂思考用 thinking 模型(temperature 0.7)
- 周期:简单思考 30-60s / 复杂思考 300s(可配置)
- 唤醒:简单思考可判定"需要深思"→ 触发一次复杂思考
- 追加:两种思考都允许
continue信号追加(当前只有 post_chat 可追加) - 后处理:每次复杂思考结束后触发记忆整理
涉及文件
| 文件 | 改动 |
|---|---|
background/thinker.go |
Thinker 拆分为 SimpleThinker + DeepThinker 或增加双模式循环 |
config/loader.go → models.json |
新增 simple_think / deep_think 路由 |
background/thinker.go → buildThinkingSystemPrompt |
简单/复杂两套 prompt |
2. P1 — LLM 可自主操作提醒与日程
现状
Gateway 有 Reminder CRUD API,但 LLM 无法调用——没有注册 reminder_create / reminder_update / schedule_query 工具。昔涟不能在思考中说"明天早上 8 点提醒开拓者开会",因为这句话无法转化为实际的定时提醒。
目标
在 AI-Core 的 ToolRegistry 中新增 3-4 个提醒/日程工具,LLM 可在对话中或自主思考中调用。
要点
- 工具列表:
reminder_create(time, content, repeat?)→ 创建提醒reminder_list()→ 列出当前用户的提醒reminder_delete(id)→ 删除提醒schedule_query(date)→ 查询某一天的日程
- 实现方式:HTTP 调用 Gateway
/api/v1/remindersAPI(已有后端 CRUD) - 自主思考可调用:加入
AutonomousToolPolicy.AllowedTools白名单 - 防止阻塞:配置
THINK_SCHEDULE_WINDOW环境变量,在提醒时间窗口内确保简单思考被唤醒
涉及文件
| 文件 | 改动 |
|---|---|
ai-core/internal/tools/reminder_tool.go |
新建 — 3-4 个 reminders 工具 |
ai-core/cmd/main.go |
注册提醒工具到 ToolRegistry |
background/thinker.go → AutonomousToolPolicy |
允许提醒工具在自主思考中调用 |
3. P2 — 对话后处理补全
3.1 自主思考后触发记忆整理
现状:记忆提取(ExtractMemoriesOnly)只在 platform_silent 和正常对话后触发。自主思考(periodic/silence/startup)结束后不触发。
目标:复杂思考结束后自动调用一次记忆整理。
涉及文件:background/thinker.go → performThink 的结尾逻辑
3.2 对话后思考可追加
现状:post_chat 思考支持追加(allowContinuation + triggerReason == "post_chat"),但 periodic / silence 不支持。
目标:所有思考类型都支持 continue 信号追加,通过 MaxContinuationRounds 限制防止死循环。
涉及文件:background/thinker.go → 思考循环的 allowContinuation 条件
4. P3 — 群聊并发(协会议话)
现状
一个 session 的消息处理是严格线性的。当多个 QQ 用户同时在群里 @ 昔涟时:
- 消息按到达顺序排队
- 每条的 LLM 合成延迟 3-4s
- 第 3 条消息要等前面 2 条处理完才开始回复(6-8s 延迟)
目标
主会话 (session_id=platform_qq_<groupID>)
│
├─ 消息A → 主会话处理 (LLM 合成中...)
│
├─ 消息B (主会话繁忙) → 协会议话 B (独立 LLM 合成)
│ └─ 完成 → 结果写入主会话上下文
│
└─ 消息C (主会话繁忙) → 协会议话 C (独立 LLM 合成)
└─ 完成 → 结果写入主会话上下文
要点
- 并发检测:收到新消息时,检查主会话是否正在处理(
isProcessing标记) - 协会议话:独立 goroutine + 独立 LLM 调用,共享主会话的对话历史
- 结果合并:协会议话完成后,回复通过 platform-bridge 发送,上下文摘要写回主会话
- 数量限制:最多 3 个协会议话并行,超出则排队
- 身份一致性:每个协会议话携带相同的 persona config + 群聊上下文
涉及文件
| 文件 | 改动 |
|---|---|
ai-core/orchestrator/orchestrator.go |
ProcessInput 增加并发检测 + 协会议话创建 |
ai-core/orchestrator/concurrent_handler.go |
新建 — 协会议话管理器 |
platform-bridge/cmd/main.go |
可能需要支持协会议话的回复路由 |
5. P4 — 多平台前缀统一抽象
现状
QQ 平台标识(【QQ群聊:xxx】、【QQ私聊:xxx】)硬编码在 thinker.go 的 buildThinkingUserPrompt 里,extractProactiveMessage 里的 qqTargetRe 也只匹配 QQ。如果要接入 Telegram / Discord / 企业微信,需要在多个位置添加硬编码。
目标
将"平台前缀"抽象为一个统一的 PlatformRouteFormat 接口,每个 adapter 注册时声明自己的格式。
要点
PlatformRouteFormat接口:ProactiveMarker(chatType, channelID, atUserID string) string— 主动消息标记格式ChannelPrefix(channelID string) string— 消息来源前缀(如【QQ群聊:xxx】)
- 注册在
PlatformAdapter接口扩展中 - thinker prompt 和 extractProactiveMessage 从 router 获取当前已注册的格式列表
- 后向兼容:QQ 当前行为不变
涉及文件
| 文件 | 改动 |
|---|---|
platform-bridge/bridge/adapter.go |
PlatformAdapter 接口扩展 |
platform-bridge/bridge/router.go |
GetRouteFormats() 方法 |
platform-bridge/handler/bridge_handler.go |
API 端点暴露格式信息 |
ai-core/background/thinker.go |
从 bridge 获取格式替代硬编码 |
ai-core/cmd/main.go |
启动时拉取格式配置 |
6. P5 — 工具子会话增强
6.1 子会话返回时间戳
现状:子会话结果(SubSessionResult)没有记录创建时间和结束时间。
目标:每个子会话结果增加 CreatedAt / FinishedAt 字段。
涉及文件:model/sub_session.go + 各 provider 的 Execute() 方法
6.2 工具调用不阻塞主会话
现状:Synthesizer.ChatWithTools 的 LLM 工具调用循环(最多 5 轮)在主 goroutine 中执行,长工具调用(如 web_search + web_fetch 链)会阻塞流式输出。
目标:工具调用结果通过 channel 异步返回,Synthesizer 先输出等待提示(如"让我查一下..."),收到结果后再继续流式生成。
涉及文件:orchestrator/synthesizer.go — ChatWithTools 的调用模型改为 publish/subscribe
7. 实施顺序建议
Phase A (本节可做) ─────────────────────────────
P2.2 对话后思考可追加 ~10 行改动
P2.1 自主思考后触发记忆整理 ~5 行改动
P5.1 子会话返回时间戳 ~20 行改动
Phase B (需要跨服务协调) ───────────────────────
P1 LLM 可自主操作提醒与日程 新建 1 文件 + 注册工具
P0 自主思考分层 重构 thinker 核心循环
Phase C (架构级改动) ───────────────────────────
P4 多平台前缀统一抽象 跨 ai-core + platform-bridge
P3 群聊并发(协会议话) 跨 ai-core + platform-bridge
Phase D (后续优化) ─────────────────────────────
P5.2 工具调用不阻塞主会话 改造 synthesizer 调用模型
附:与架构设计文档的对照清单
| # | 设计要求 | 状态 | 对应章节 |
|---|---|---|---|
| 1 | 基础出人格库 | ✅ | — |
| 2 | 故事背景知识库 | ✅ | — |
| 3 | 多优先级自主增删改记忆 | ⚠️ 缺自主删改 | 待定 |
| 4 | 用户手动增删改知识库 | ✅ | — |
| 5 | IoT 功能调用知识库 | ✅ | — |
| 6 | 插件功能调用知识库 | ✅ | — |
| 7 | 定时任务模块 | ❌ | P1 |
| 8 | 定时任务自主增删改 | ❌ | P1 |
| 9 | 日程自主增删改 | ❌ | P1 |
| 10 | 简单思考(高频下位模型) | ❌ | P0 |
| 11 | 复杂思考(低频思考模型) | ⚠️ 有但未分层 | P0 |
| 12 | 简单思考可唤醒复杂思考 | ❌ | P0 |
| 13 | 两种思考均可追加 | ⚠️ 仅 post_chat | P2.2 |
| 14 | 两种思考均可调用工具 | ✅ | — |
| 15 | 主动通讯(客户端+平台) | ✅ | — |
| 16 | 思考后触发记忆整理 | ❌ | P2.1 |
| 17 | 回复一句一句发 | ✅ | — |
| 18 | 工具调用不阻塞主会话 | ⚠️ 部分阻塞 | P5.2 |
| 19 | 工具子会话返回时间戳 | ❌ | P5.1 |
| 20 | 群聊并发协会议话 | ❌ | P3 |
| 21 | 多平台消息前缀 | ⚠️ QQ 硬编码 | P4 |
| 22 | 多平台发送方式 | ✅ | — |
共 22 项设计要求:✅ 已完成 9 项,⚠️ 部分完成 5 项,❌ 未实现 8 项。