core/services —— 业务服务组合层¶
把内核各包组合成可运行的业务:对话回合的编排、媒体支路、后台维护、控制台
呈现、子进程宿主与开发者工具。决策的语义在 src/core/agent/
(见 core/agent),记忆的算法在 src/core/memory/
(见 core/memory),本包负责「什么时候调用谁、失败怎么记账、
结果怎么投递」。
职责边界¶
- 负责:回合编排(
chat/)、图片理解 / 表情包 / TTS(media/)、联想边衰减 与黑话学习等后台维护(maintenance/)、终端与面板的回合呈现(console/)、 适配器与桌宠外壳的子进程拉起(host/)、开发者命令与重放(dev/)、 主动消息投放(proactive.py)。 - 不负责:回复内容与门控判据(
src/core/agent/,本包只装配与调度)、主动 行为的规则计算(src/core/awareness/的纯决策函数,proactive.py只编排)、 日程生成(src/core/schedule/)。
包入口 src/core/services/__init__.py 只放包说明,不做再导出;chat/ 子包
的入口则相反,见下。
chat/ —— 对话编排¶
src/core/services/chat/__init__.py只做再导出。chat拆包前是单文件模块,全项目以from src.core.services.chat import ChatService引用,拆包后保持同一入口。src/core/services/chat/service.pyChatService本体与回合主循环(约 3300 行),由十个 mixin 组合而成。持有 按角色拆分的 LLM provider、MemoryStore、Persona与日程服务,把入站消息 推进为一次回合,并通过 WebSocket push 把事件推给 Electron 主进程。src/core/services/chat/state.py回合与会话的内部数据结构:缓冲消息、批次门控结果、流式解析状态、召回留痕、 等待句柄等。只被service使用,对包外不构成接口。src/core/services/chat/constants.py编排常量集中地。单独成模块是因为各 mixin 也要读同一批常量——留在service会让 mixin 反向导入service,与service导入 mixin 组装类形成导入环。src/core/services/chat/helpers.py不依赖实例的模块级纯函数:召回事实到提示词条目(含同槽冲突整组补齐)、 解析事件到出站分句的收集、表情命中到助手历史标签的序列化等。src/core/services/chat/gating.py批次门控:把睡眠状态、名字命中、@ 事实与回复必要性评分汇成三态门控结果 (DROP/FORCE/DELIBERATE),并给出群聊扩展触发模式的读取口径。src/core/services/chat/context_build.py回合上下文组装:关系与人格配置、表达习惯挑选、工作记忆排序、事实召回与 会话印象、黑话查表、日程描述,渲染成系统提示词与消息序列,产出组装完成的 回合上下文。src/core/services/chat/agent_protocol.pyAgent 协议渲染:把门控事实、可选消息预览与动作空间渲染成规划器读的协议 文本;预览与历史的消息编号口径必须一致,模型才能指认目标。src/core/services/chat/capabilities.py平台能力判据:把配置开关与协议端实测能力合成一个判据,决定表情包、表情 回应与戳一戳在当前出口是否可选——两者取与,未收到能力上报按不可用处理。src/core/services/chat/outbound.py解析事件的消费与出站投递:副作用写库、台词按打字节奏切气泡逐条投递、引用 目标解析、非桌面平台的出站发送。切分前置才能让平台出站、助手历史与控制台 渲染看到完全一致的气泡。src/core/services/chat/background.py回合之外的四条后台队列:情节摘要、事实抽取、画像刷新、表达学习。按批取 输入、成功才推进游标;失败计数达上限跳批——这是确定性失败(如同样的输入 永远得到同样的拒绝)不至死锁的出口。src/core/services/chat/follow_up.py私聊跟进:记录正常回复时刻、按配置安排定时追问、对方开始输入时决定是否 催促、新消息到达撤掉待发跟进。群聊不走这条路径。src/core/services/chat/group_observe.py群聊观察与历史回填:把没轮到她开口的消息记成观察事件;首次进群按协议端 提供的历史消息补齐空白,识别已见过的外部消息 ID、播种游标、按批写入。src/core/services/chat/profiles.py人物画像与身份呈现:整理画像供管理面板读取;组装回合上下文时解析发言者 身份(合并多平台身份引用、挑展示名)。src/core/services/chat/scene.py场景观察调度:让观察 Agent 在后台读一段刻意宽于工作记忆的历史,产出场景 画像并转成可注入提示词的文本行。
media/ —— 媒体支路¶
src/core/services/media/__init__.py包说明。三条支路彼此不互相依赖,都由对话编排在回合中调用。src/core/services/media/chat_image.py聊天图片的中文客观描述:后台按来源下载,表情包先按 SHA-256 查已有标签, 未命中才调视觉模型;失败统一返回 None,由调用方保留占位符,不得猜测图片 内容。src/core/services/media/emoji.py表情包库(全包最大):按内容 SHA-256 存文件、按情绪语义检索。启动必须verify_integrity重算全部文件哈希,不一致即阻止启动;入库有三道闸门 (封禁表查哈希、大小上限、可选的视觉内容审查),后台按确定性 SQL 淘汰 最冷条目并清理孤儿文件。src/core/services/media/tts.py台词转语音:从模型路由取 TTS 候选,支持 OpenAI 兼容与厂商协议,同音色同 文本走进程内缓存;连续失败达上限后停止接受新任务,音频只在内存处理。
maintenance/ —— 后台维护¶
src/core/services/maintenance/__init__.py包说明。这些服务以后台循环或队列运行,不参与单次回合的同步路径。src/core/services/maintenance/edge_decay.py联想边的后台冻结。边与事实共用衰减语义但时间尺度差一个量级(边半衰期 720 小时),因此不共用调度点:事实走MemoryStore.sweep,边用低频轮询承载一次 全表扫描。src/core/services/maintenance/jargon_learn.py黑话学习的后台服务:每会话独立游标、攒批提取、推断调用数与推断词条数都有 上限常量(不节流就是四位数的调用量)。业务语义全在src/core/agent/jargon_mine.py,本层只回答何时学、学多少、推断谁。src/core/services/maintenance/jargon_stats.py高频词表快照的后台重建:只重建有新消息的会话,首轮全量一次让新部署立刻 有表可用。src/core/services/maintenance/memory_feedback.py反馈纠错:事实进过提示词之后被用户纠正时写回库里。链路四段(登记锚点、 关键词预筛、模型判定、按置信度应用),默认全关;纯否定不造事实,只写 「已被纠正」标记由注入侧硬过滤。src/core/services/maintenance/vector.py向量服务:事实与知识向量的生成、历史数据补算、查询向量计算。未配置嵌入 客户端时保持禁用;嵌入失败只影响对应向量操作,不阻断正文写入与关键词 召回。
console/ —— 回合呈现¶
src/core/services/console/__init__.py包说明。只负责把已有事实排版成人读得懂的形态,不产生新事实。src/core/services/console/turn_panel.py按回合聚合各级模型调用(决策、回复生成、各次认知检索),渲染成嵌套面板。 收集走ContextVar:模型路由只管上报调用,不需要知道自己属于哪个回合, 并发会话互不混淆。写入方是src/core/llm_models/router.py。src/core/services/console/trace_console.py把回合合成嵌套彩色面板,一次写到终端与webui_logs,三端呈现一致;回合外 调用(视觉、摘要、抽取、日程)独立成框。非彩色或非交互场景全部渲染函数 保持无操作。
host/ —— 子进程宿主¶
src/core/services/host/__init__.py包说明。Python 是进程入口之后,适配器与外壳都由本进程拉起,退出按相反 顺序收走。src/core/services/host/adapter_host.py按config/adapter.toml声明拉起 QQ 适配器进程:只做「解析声明 → 组装 命令行」,进程行为由src/core/runtime/child_process.py提供;适配器可选, 没有声明时告警跳过。src/core/services/host/desktop_shell.py按桌宠开关决定是否拉起 Electron 外壳并解析启动命令行:有开发依赖走npm run dev,只有构建产物直接用本地 Electron 可执行文件,不做猜测。[desktop_pet] enabled = false时什么都不产出——这正是无头部署形态。src/core/services/host/lifecycle.pyLifecycleManager:按注册顺序启动服务、异常即停、关闭按逆序并记录单个 错误。模块级lifecycle是进程范围的默认管理器。
dev/ —— 开发者工具¶
src/core/services/dev/__init__.py包说明。只服务于调试与观察,正常对话路径不依赖它们。src/core/services/dev/dev_commands.py开发者命令/git与/version的只读处理:只负责解析与执行,匹配与鉴权 属于src/core/commands/的命令通道。/git是全项目唯一 fork 外部进程的 位置,「用户文本不进入子进程」的边界不得放宽。src/core/services/dev/install_stats.py开发者命令/inst:读遥测服务端的GET /stats,用 matplotlib 画折线图, 经出站图片契约发到聊天里。绘图依赖在可选 extrachart,缺失时退回纯文字; 服务端地址或YUELI_STATS_TOKEN为空时命令不注册。src/core/services/dev/prompt_records.py分阶段模型调用记录的读取侧:把落盘目录扫成可分页摘要、按任务读单份完整 内容;写入方是src/core/llm_models/snapshot.py。src/core/services/dev/replay.py不进入业务服务的隔离模型重放:拿历史事件与当时的提示词资源重建一次调用, 用于改提示词后的对照。
proactive.py —— 主动消息¶
src/core/services/proactive.pyAwarenessService:接收前台窗口事件,调用src/core/awareness/的纯决策 函数(意图、兴趣、预算、睡眠),维护待投放意图与每日预算,经ChatService生成桌面主动消息。规则计算与平台协议都不在这里。
对外接口与调用方¶
ChatService:src/main.py装配构造(测试另有 40 个文件直接引用);proactive.py经它投放主动消息,InboundMessage是入站消息的统一形态。 认知动作由service包装成执行器、连同工具插件的声明一起登记进它持有的src/core/tooling/注册表——插件侧只认工具协议,不直接 import 本包。- 各后台服务(
VectorService、TtsService、EdgeDecayService、JargonStatsService、JargonLearnService、MemoryFeedbackService):src/main.py构造并经lifecycle注册启停。 register_prompt_entries/marked_fact_ids:被chat/context_build.py与chat/helpers.py调用——锚点登记发生在事实真正进提示词的时刻。note_model_call/begin_turn:模型路由写入、trace_console渲染;render_observation被chat/group_observe.py复用。replay_event与prompt_records的三个读取函数:被src/core/api/http.py的开发者路由调用。build_adapter_process/build_desktop_shell_process/lifecycle:src/main.py的启动编排。
依赖方向¶
- 本包是全库最大的组合点,依赖
agent、memory、persona、awareness、schedule、llm_models、observe、platform_io、config、commands、tooling、prompts、runtime与src/core/webui/logs.py。 - 反向不允许:
agent与memory不 import 本包;协作经由函数参数与注入。 包内chat/的 mixin 只依赖state、constants、helpers,不允许反向 导入service(导入环)。 console/只读不写:它消费模型路由上报的调用记录,不产生任何业务事实;dev/的命令全部只读,不改仓库状态、不写数据库(/git的提交计数除外, 它只读本地仓库)。