返回全部文章

工程机制

一个 Agent,多条线程:Morphz 的并发调度

测试还在运行,依赖检查和发布说明已经可以开始。Morphz 让同一个智能体通过多条线程并发工作,共享认知,并按依赖关系等待、恢复和汇合。

让一个智能体准备一次发布,往往包含几类工作:运行回归测试,核对依赖兼容性,整理发布说明。测试还在执行时,另外两项已经可以开始。用户也可能随时问起进度,或者改变发布范围。

这些事情有关联,却不需要排成一条长队。Morphz 的并发调度让同一个智能体拥有多条执行线程:每条线程推进自己的工作,共享同一份认知,并在需要时等待、协作和汇合。模型决定怎样组织工作,运行时保存这些安排,并在条件满足时启动对应的工作。

同一个智能体并发推进测试、兼容性检查与发布说明。测试等待工具结果时,其他线程继续工作;所需结果汇合后再检查并继续。线程共享已提交的认知状态,时间长度仅作示意。
等待测试结果只暂停相关线程,兼容性检查与文档工作可以继续;需要汇合时,再按依赖协调。 点击图片可放大查看。

并发的是工作线程

在 Morphz 中,线程(Thread)是一条有独立身份的逻辑执行流程。它可以经历多次模型调用、工具执行和等待,始终保留这项工作从哪里开始、已经做了什么、下一步在等什么。这里的线程不是操作系统线程,也不要求持续占用一个模型请求。

前面的发布准备可以形成三条执行线程。它们处于不同阶段时,一次新的进度询问还可以由对话线程处理:

同一个 Agent · 共享认知上下文
├─ 测试线程:等待回归测试结束
├─ 兼容性线程:检查各平台的依赖要求
├─ 文档线程:整理本次改动
└─ 对话线程:回答用户的进度询问

每条线程都可以调用模型,分析自己收到的结果,再决定后续动作。测试线程可能读日志、定位失败原因、重新运行检查;文档线程则可以继续核对改动。多个线程的模型请求和工具执行可以在资源允许时重叠进行。

这比一轮请求里同时调用几个工具多了一层连续性。并行工具调用处理这一轮动作,线程则承载整项工作,直到得到结果或明确结束。Morphz 也支持委派给子智能体;这里讨论的并发发生在同一个智能体内部,共享认知,不必为每个分支另建一个智能体。

模型安排工作,运行时负责调度

智能体通过 schedule_tx 提交调度安排,创建执行线程、指定何时开始,以及需要等待哪些结果。几项互不依赖的检查可以一起启动;打包需要等待测试通过,就保留这项先后关系。拆分哪些工作、如何分工,仍由模型根据任务判断。

这些安排会成为运行时保存的线程、调度和依赖记录。调度内核检查安排是否合法,再提交相应状态变化。后续执行依据这些记录推进,不需要反复从聊天历史里寻找一句“等测试完再打包”。

运行时通过租约管理一条线程当前的执行权。租约有时限,继续执行需要续租,两个运行实例不能任意重复推进同一条线程。不同线程则可以分别获得执行机会。调度器控制总并发量,也可以为对话和结果交付保留容量,避免后台任务占满所有位置。排队时间同样参与调度,长时间等待的工作会逐步获得更高的优先级。

这让模型能够把可以并行处理的事情真正安排出去,同时为有依赖的步骤保留顺序。

等待只暂停相关工作

回归测试可能需要几分钟,审批可能更久。这段时间里,智能体没有必要不断询问模型“结束了吗”。Morphz 可以把后续工作挂到具体的等待条件上,在结果到达、审批完成或定时器到期时再恢复执行。

等待条件属于特定线程。测试结果回到测试线程,审批决定回到等待这次审批的线程。新的对话拥有自己的身份,不会接走旧任务的工具结果;一个分支在等待,也不要求其他分支停下来。

等待中的工作仍然存在。它的依赖、进度和已有结果保存在运行时中,暂时不继续推理,并不意味着任务已经结束。执行恢复时,模型收到与这项工作相关的输入,从原来的因果路径继续。

多条线程共享同一份认知

并发工作还需要共同的理解。假设兼容性检查发现一个依赖不支持目标平台,这既影响构建,也影响发布说明。让各条线程各自保留一份互不相干的笔记,很容易产生分歧。

Morphz 的线程共享认知上下文。其中的认知帧,是带有标识、内容和来源的知识单元,可以记录判断、约束和计划。智能体通过上下文事务 context_tx 修改这些帧:兼容性线程可以更新平台要求,文档线程可以补充改动说明。提交后,其他线程在后续模型调用中读取相关认知时,可以使用这些变化。

多条线程同时推理,并不意味着可以无条件覆盖彼此的修改。运行时串行提交同一上下文的事务,但不会因此把所有模型推理也排成串行。如果两笔事务修改的帧和关系互不影响,即使从同一个旧版本出发,也可以保留两边的结果;如果它们碰到了已经变化的相关内容,运行时会拒绝冲突事务,让智能体重新读取并调整修改。

正在进行的模型请求不会凭空获得一份新输入。因此,“共享”也不意味着一条刚提交的判断会瞬间出现在所有进行中的推理里。它提供的是各条工作可以继续读取和修订的共同状态。

共享认知与外部文件的并发访问还要分别处理。两个线程修改同一个文件,仍需协调分工、检查文件版本,并在必要时重新读取。上下文事务保护认知状态,不能代替文件系统和外部服务的并发控制。

上一篇《不用 Compaction,Morphz 如何维护有限的上下文?》介绍了这些事务如何维护有限的输入空间。放到并发场景中,同一套机制也让多条线程能够共同维护智能体的认识。

并行结果需要汇合

三条线程都启动了,只是工作的开始。发布准备还需要一个明确的收口:检查是否通过,失败是否解决,说明是否与实际改动一致。

Morphz 用线程组(Thread Group)表达一组工作之间的等待关系。例如,把测试、兼容性和文档线程放进一个需要等待全部成员的组。各条线程结束时,运行时保存结果并更新组状态;满足等待条件后,负责汇总的工作继续执行。

失败也会形成结果。一次测试失败不能被当作“这个分支已经做完了,所以发布成功”。智能体需要检查返回的结果,再决定修复、重新安排检查,或者报告阻塞。运行时记录线程是否结束,模型判断这些结果是否满足任务要求。

需要跨多轮持续推进的工作,还可以由目标(Objective)监督。目标保存要完成的事情、当前状态和等待关系,一个目标可以组织多条线程。智能体也可以同时推进多个目标,它们各自保持执行进度,并共享相关认知。

线程、目标和依赖都有持久身份。进程重启后,运行时据此恢复仍然有效的工作;旧运行的迟到结果不能越过已取消或已替换的执行状态,继续推动新的工作。具体的监督与恢复边界见线程、激活与目标

工作期间仍然可以对话

后台工作与用户交互不必互相排斥。发布准备还没结束,用户可以询问进度,也可以提出新的要求。会话(Session)记录消息从哪里来、回复应当去哪里;线程则区分这些消息和工具结果分别属于哪项工作。一个会话可以包含多条线程,同一认知上下文也可以服务多个会话。

这不要求把同一会话里相邻的用户消息全部并发处理。普通对话仍有自己的顺序,已经独立调度的执行工作则可以继续运行。用户因此可以在智能体工作时与它交流,而不必先终止旧任务。

如果用户把某个平台移出本次发布,智能体需要更新发布范围,并控制不再需要的工作。thread_control 可以暂停、恢复或取消指定线程;它与 Dashboard 使用同一套运行时控制入口。只取消一个定时唤醒,并不等于取消整条线程;只在认知里写下“不做了”,也不会自动停止现实中的执行。

共享认知让智能体理解新要求,明确的控制操作让执行随之改变。其他不受影响的工作可以继续推进。更多会话边界见会话与并发工作

成本与边界

并发的价值取决于任务中有多少工作可以独立推进。拆出更多线程,会增加模型调用、上下文输入和协调开销;多个分支反复修改同一处内容,还可能让冲突处理抵消节省的时间。实际收益需要结合任务完成质量、总耗时和用量一起衡量,不能用线程数量推算加速倍数。

共享上下文同样需要控制输入范围。运行时为每次请求选择有界的会话工作集,智能体继续通过事务维护认知,而不是把每条线程的全部历史无限叠加。前缀缓存的复用仍受输入变化和模型接口影响,相关机制与实验已在上一篇文章的前缀缓存一节说明。

并发调度不会扩大工具权限,取消也不能撤销已经发生的外部操作。恢复时,如果一项操作的结果无法确认,就需要核对真实状态,不能简单地从头再执行一遍。

Morphz 提供的是一种组织模型能力的方式:让可以独立推进的工作同时进行,让相关工作共享认知,让等待与完成都有明确的位置。模型的分析、规划和工具使用能力,可以由此用于多条持续推进的工作,而不只服务于眼前的一轮回复。

本文涉及的调度内核并发容量管理取消与中断契约均已开源。