系统架构
Morphz:一个认知操作系统的实现
管理有限的上下文,调度并发线程,处理多个会话的输入输出。本文以软件发布为例,介绍 Morphz 如何通过上下文事务、线程调度和 Session I/O 支持智能体持续工作。
一个智能体正在准备软件发布。回归测试还在运行,兼容性检查已经发现了一个问题,发布说明也需要继续整理。这时,用户又发来一条消息:“Windows 版先不发,其他平台继续。”
智能体需要理解这句话,也需要让工作随之改变:更新发布范围,停止不再需要的分支,让其他线程继续运行。测试结束后,结果应该回到等待它的线程;用户询问进度时,也应该及时得到回复。与此同时,已经读完的日志不必一直占着上下文,仍然有效的判断却需要留给后续工作。
操作系统管理有限的物理内存,调度线程运行,并处理不同连接的输入输出。Morphz 面对的是类似的组织问题:哪些认知内容进入当前上下文,哪些工作线程继续执行,以及不同会话的消息如何送达。
工作集:让需要的内容留在上下文中
Linux 不需要把程序用过的所有数据一直留在物理内存里。内存紧张时,内核可以回收已有文件副本的干净缓存页;启用 swap 时,也可以把暂时不用的匿名页换出,等再次访问时调回。释放内存,并不意味着丢掉这些内容。参见 Linux 内核的内存管理说明。
工作集(Working Set)关注的是程序在一段时间内实际使用的那部分页面。Linux 的多代 LRU(Multi-Gen LRU)会跟踪页面的访问新旧程度,帮助内核决定哪些页面优先回收、哪些继续保留。参见多代 LRU 文档。
智能体也需要区分“保存下来”和“现在使用”。发布过程中读过的配置、日志和用户消息可以留在历史中,不必每次都交给模型。每次请求的 token 预算有限,智能体需要决定哪些观察记录和认知帧继续留在上下文里,哪些暂时移出,等需要时再恢复。
智能体通过上下文事务 context_tx 主动改变这些对象的状态。运行时检查版本、保护规则和操作是否合法,再提交修改。观察记录、认知帧和会话工作集,分别提供了不同粒度的管理方式。
观察记录:读完的日志可以先放下
观察(Observation)是一条进入上下文的输入记录,例如用户消息、工具结果或外部事件。它有独立的标识,原始内容保存在事件历史中。模型可以引用这条记录,也可以决定它是否还需要留在当前上下文里。
假设回归测试通过,工具返回了一份很长的日志,标识为 @e42。智能体读完后,后续打包主要需要知道测试已经通过,以及到哪里查阅原始结果。它可以在同一笔上下文事务中保存这项判断,再退役日志对应的观察记录。假设它读取的上下文版本是 17,这笔事务可以写成:
(context-tx
(base-version 17)
(reason "retain the regression result and release the consumed log")
(derive release/regression-result
(from @e42)
(fact (suite regression) (status passed)))
(retire @e42))
事务提交后,测试结论及其来源关系保留下来,@e42 立即退出活动上下文,释放它占用的输入空间。原始日志仍可查阅,需要重新展开时,可以通过 restore 恢复这条观察记录,也可以按引用召回相关内容。
有些输入只是已经处理完的过程记录,没有形成新的判断,就可以直接退役,不必每条都再生成一个认知帧。智能体持续做这样的整理,后续请求便能使用更新后的上下文,而不用一直携带全部原始输入。
认知帧:当前判断与历史认知之间的换入换出
认知帧(Frame)承载智能体已经形成的判断、约束、知识和计划。例如,“本次只发布 macOS 和 Linux”可以是一条认知,“某个依赖不支持目标平台”可以是另一条。每个帧都有稳定标识,可以单独修订、关联、保护、退役和恢复。
它们的生命周期与原始输入有所不同。退役一条观察记录会立即释放输入空间;普通认知帧收到 retire 后,先进入由认知时钟推进的整理窗口。在这个窗口内,帧仍然可见,也仍然占用容量,智能体有机会修订它、安排替代内容或恢复它。窗口结束后,帧退出活动编码,历史继续保留。如果同一笔事务已经建立符合规则的替代帧及来源、替代关系,旧帧也可以立即完成退役。
发布结束后,一些只与这次工作有关的认知可以退出活动上下文。以后排查这次发布的问题,智能体又可以用 restore 把有关帧恢复进来。对于仍需遵守的重要约束,则可以用 protect 防止直接退役。
这构成了认知层面的驻留管理:暂时不进入模型输入的内容仍有身份、历史和恢复路径,有限上下文能够容纳持续变化的当前认知。
Session Working Set:选择本轮需要关注的会话
同一认知上下文可以连接多个会话。一个会话正在准备发布,另一个可能是昨天的排障,第三个还在等待用户补充信息。它们没有必要在每次模型调用中全部展开。
Session Working Set 为本轮求值选择会话投影:有的完整呈现,有的只保留元信息,有的暂时不进入输入。运行时结合当前会话、活动状态、隔离范围和容量预算作出选择。
智能体也能通过 retire-session 主动把暂时不需要关注的会话移出自动工作集;restore-session 可以将它重新纳入候选,定向的新事件也会恢复对它的关注。当前或仍在执行工作的会话不能被这样直接移出。会话退出工作集时,历史事件和共享认知都不会被删除。
因此,单条观察记录、认知帧和整个会话都有各自的驻留边界。智能体可以放下一份已经处理的日志,也可以暂时放下整段会话,同时保留以后重新使用它们的能力。
调度:等待一项工作,其他线程继续运行
操作系统中的线程等待 I/O 时,可以进入阻塞状态。调度器让其他就绪线程使用执行资源,等 I/O 就绪,再恢复等待中的线程。
在 Morphz 中,测试、兼容性检查和发布说明也可以各自形成一条 Thread。这里的线程承载一条持续的逻辑工作流程,可以跨越多次模型调用、工具执行和等待。每条线程保留自己的身份、进度和依赖,同一智能体中的线程则共享认知。
智能体通过 schedule_tx 提交安排,创建并发分支、指定依赖,或者设置稍后的唤醒时间。调度内核 SchedulerKernel 检查并保存这些安排。运行时据此管理线程的执行阶段:
| 阶段 | 运行时中的含义 | 发布任务中的例子 |
|---|---|---|
| Runnable | 有待处理信号或排队中的执行,可以等待准入 | 兼容性检查已经排队 |
| Running | 有正在运行的执行激活或工具任务 | 模型正在分析依赖,或测试工具正在运行 |
| Waiting | 后续工作等待依赖、审批或调度条件 | 发布汇总等待各项检查返回 |
准入控制决定哪些工作获得执行机会,租约管理当前的执行权。多条线程可以分别获得资源,重叠进行模型调用和工具执行;对话与结果交付也可以获得预留容量,避免所有位置都被后台工作占满。
假设发布汇总需要等待回归测试。运行时会保留这一依赖,测试结果到达后,唤醒匹配的工作线程。等待期间,兼容性检查和文档线程可以继续推进,不需要让整个智能体停下来,也不需要为了等待不断调用模型询问“结束了吗”。
多个结果还可以通过 ThreadGroup 汇合。all 等待全部成员结束,any 则在满足任一成员完成条件时继续。线程结束和任务成功是两件事:测试可能以失败结果结束,恢复后的智能体仍需检查结果,再决定修复还是继续发布。
当用户撤回 Windows 发布要求时,智能体可以修订发布范围,并通过 thread_control 取消相关线程。认知中的决定和运行时的执行控制各有明确入口,其他分支不必跟着停止。更详细的调度过程见《一个 Agent,多条线程》。
Session I/O:共享认知,区分每条连接
操作系统用文件描述符区分不同的输入输出对象。一个程序可以同时处理多条连接,知道哪条连接有数据可读,也知道结果应该写回哪里。
Morphz 的 Session 承担智能体的输入输出连接和交互进度边界。同一 Context 下的 Session 共享 Mind,每次求值却都有明确的 active-session。输入带着来源进入,普通回复沿当前会话返回,不会因为共享认知就混淆消息的去向。
例如,Session A 正在准备发布,Session B 同时询问目标平台的兼容性。B 可以使用共享认知中已经提交的兼容性判断,回复仍然回到 B;A 的发布工作继续沿自己的线程推进。一个 Session 也可以包含多条工作线程,连接与执行流程并不是一一绑定的。
普通对话在各自 Session 内保留顺序,独立调度的工作则可以继续运行。测试工具的结果归属于发起它的线程,新来的用户消息不会接管旧线程的结果。
跨会话交互还区分两种操作:
send_message向另一个 Session 投递用户可见的消息,不触发那个会话的新一轮求值。session_signal向目标 Session 发送内部协调消息,并触发它继续求值,不改变当前求值的active-session。
假设 B 发现了新的兼容性问题。只需要把结果告知 A 的用户时,可以投递消息;如果需要 A 立即据此重新检查发布安排,则可以发送协调信号。共享认知负责保存共同理解,I/O 路由负责送达消息,唤醒机制负责让相关工作继续执行。
这些边界在会话与并发工作文档中有进一步说明。
让并发工作共同维护认知
工作集、调度和 I/O 最终围绕同一份认知状态协作。兼容性线程发现新限制,文档线程需要据此修订发布说明,对话线程也需要给用户一致的回答。
context_tx 为这些修改提供共同的提交边界。每笔事务携带基础版本,运行时按帧和关系等范围检查冲突。互不影响的修改可以保留;相关状态已经发生变化时,冲突事务会被拒绝,智能体重新读取后再作决定。同一 Context 的提交串行处理,各条线程的推理仍可以并发进行。
回到开头的发布任务:测试线程读取日志,把结果写入认知,再退役已经处理的观察记录;汇总线程在依赖满足后继续执行;用户从当前会话获得回复。发布完成后,不再需要常驻的帧和会话可以退出工作集,记录仍然留存。
一次模型调用由此成为持续工作中的一个执行片段。认知、线程、等待条件和输入输出连接都有跨越这次调用的生命周期。
认知操作系统的职责
操作系统让计算能力服务于许多持续运行的程序。Morphz 则组织模型的推理能力,让同一个智能体能够维护当前认知、推进多条工作线程,并在等待、交互与恢复之间持续运行。
模型判断哪些信息重要、任务怎样拆分、结果意味着什么。运行时为这些判断提供可操作的对象:带标识的观察记录和认知帧、有依赖和执行权的线程、能够路由消息并触发工作的会话。认知操作系统的职责,就落实在这些对象及其生命周期上。
本文讨论的是模型之上的认知运行时。实际进程、文件访问和设备仍由宿主操作系统管理,外部动作也仍受权限和沙箱约束。
关于计算模型,可以从《从聊天补全到结构化上下文求值》开始;上下文事务、容量维护与召回详见《不用 Compaction,Morphz 如何维护有限的上下文?》。本文涉及的上下文操作、调度内核和跨会话工具均可在源码中查看。