核心服务模块
羽忆在工程实现上可以是单体部署,但在职责划分上必须先把模块边界切清楚。这样做的目的不是为了将来一定拆成微服务,而是为了防止业务规则散落到 Controller、Adapter 或前端页面里。
模块总览
| 模块 | 主要职责 |
|---|---|
| API Gateway | 统一入口、请求校验、统一响应、错误翻译 |
| Identity & Namespace | 身份解析、Scope 推断、权限边界 |
| Ingest Service | 所有写入类请求的统一收口 |
| Memory Judge | 写入价值判断、类型推断、覆盖策略 |
| Stable Memory Service | 稳定记忆 CRUD、版本控制、状态管理 |
| History Recall Service | 历史材料写入、查询、生命周期管理 |
| Recall Orchestrator | 联合检索、排序、压缩、Token 预算控制 |
| Memory Control Service | 删除、归档、失效、模式切换、查看控制面 |
| Search & Index Service | 词法检索、向量检索、混合排序、过滤 |
| Security Service | 认证、限流、敏感扫描、审计、脱敏 |
API Gateway
API Gateway 是对外唯一统一入口。它不负责具体业务判断,但负责把所有外部请求拉回统一协议面,包括:
- 认证与鉴权
- 参数格式校验
- 统一响应结构
- 统一错误码和错误信息
- 限流和访问日志
把这些逻辑统一收口的价值在于:不同 Adapter 不需要各自猜测服务端的边界条件,也不会因为底层模块抛出的异常形态不同而出现前端展示漂移。
Identity & Namespace
这个模块专门处理“这条数据属于谁、在哪个范围内可见、当前调用方能否读写”的问题。它之所以独立存在,是为了避免 Scope 与权限逻辑散落在各个业务服务里,后续一旦扩展 team 或 tenant 级能力,会非常难收口。
Ingest Service
Ingest Service 统一收口所有“进入系统的数据”。稳定记忆写入、历史材料写入、摘要入库甚至未来的导入能力,都应该先经过这里,而不是直接操作存储层。
这样设计可以保证没有任何一条写入路径能绕开 Judge 和安全扫描。
Memory Judge
Judge 是写入链路的守门人,负责回答三类问题:
- 值不值得存
- 应该进哪一层
- 如何分类、打标签和处理覆盖关系
它之所以单独成模块,是因为写入判断本身就是产品能力,而不是数据库 insert 前面的几个 if。
Stable Memory Service
这个模块管理长期稳定记忆,重点不只是 CRUD,而是:
semantic_key覆盖与去重- 版本号维护
- 状态流转
- 按 Scope、类型、标签查询
也就是说,它真正承载的是稳定记忆的存储规则,而不只是数据表访问。
History Recall Service
历史材料的重点不是精炼,而是为召回提供过程上下文。这个模块要保证:
- 追加式写入通路稳定
- 可以按项目、时间、来源和标签查询
- 可以支持 recent recall
- 可以按生命周期策略清理或归档
把它和 Stable Memory 拆开,是为了避免用一套偏长期记忆的规则硬套历史层。
Recall Orchestrator
Recall Orchestrator 是整个系统最接近“产品核心价值”的模块。它把检索底座、作用域规则、排序、去重、冲突标注和 Token 预算拼在一起,最后生成可以直接给模型消费的 Recall Context Block。
它不应该退化成“搜索接口的二次包装”,否则召回质量会很快失控。
Memory Control Service
很多记忆系统把重点都放在“怎么写入”和“怎么召回”,却忽略了用户控制面。羽忆把这个模块单独列出来,是因为一套无法查看、删除、归档和切换模式的记忆系统,本质上就不可控。
Search & Index Service
这个模块向上为 Recall Orchestrator 和显式搜索服务,向下承接词法、向量、过滤与混合排序能力。它的边界要清楚:负责产生候选集和基础相关性,不负责最终面向任务的压缩与消费编排。
Security Service
安全模块从第一阶段就必须存在,不能等系统跑起来后再补。它至少要覆盖:
- 管理员 Session 与 API Token 双凭证
- 写入前敏感内容扫描
- 请求限流
- 日志脱敏
- 审计记录
只有这样,记忆系统才配得上承载偏好、项目决策和潜在敏感上下文。