让 AI 打工人永不宕机:OpenClaw 离散状态机架构全解

一个几乎每个团队都踩过的坑 去年年底,某中型技术团队上线了一套"AI 自动编程流水线"——基于 GPT-4 和代码仓库,每天自动完成 Issue 分解、代码编写和 PR 提交。前三天一切顺利,团队颇有成就感。 第四天早上,他们发现:Agent 在凌晨 3:17 因为一次 API 超时陷入死循环,在 Slack 群里疯狂刷屏了 400 多条错误日志,但没有任何机制让它停下来。值班工程师被叫醒后花了 2 小时才手动终止进程、清空状态、重置上下文。 这不是某家公司的个别故障。当我们把 LLM 放进一个需要长时间运行的自动化流水线时,几乎必然遇到三个结构性难题:LLM 无状态、任务周期远超单次调用时长、API 不稳定。而大多数团队用来解决这些问题的方案,要么过度依赖人工盯守,要么干脆祈祷 API 别出问题。 OpenClaw1 试图回答一个更根本的问题:如果把 AI Agent 当作一台计算机而不是聊天机器人来设计,这些问题是否可以被工程化地解决? 为什么说"AI 编程助手"这个定位错了 在深入 OpenClaw 的架构之前,需要先纠正一个常见的理解偏差。 当我们用"AI 编程助手"来描述 Claude Code、Copilot Workspace 这类产品时,隐含的假设是:人类的每一次操作,都是一次独立的、完整的会话。用户给一个指令,AI 给一个回复,结束。 但一旦你开始构建自动化流水线,这个模型立刻崩塌——因为流水线的核心特征是:异步性(任务可能跨越数小时甚至数天)、容错性(中途可能有 API 超时、网络抖动、模型幻觉)和状态持久性(下一轮执行必须知道上一轮做到哪了)。 OpenClaw 的核心洞察是:LLM 本身是一个无状态的"CPU",而不是一个有记忆的"服务器"。 因此,要构建长期运转的 AI 流水线,必须给它配上一块"硬盘"——也就是持久化的状态文件。 这就是 OpenClaw 的架构起点。 离散状态机:把连续任务切成互不干扰的阶段 OpenClaw 采用了离散状态机(Discrete State Machine)的设计思想。简单来说:它不要求 AI 在一次调用中完成整个复杂任务,而是把任务切分成多个阶段(Phase),每个阶段都有明确的输入文件、输出交付物和状态转移条件。 stateDiagram-v2 [*] --> Idle: 项目初始化 Idle --> Phase1_Architecting: 启动架构设计 Phase1_Architecting --> Phase1_Architecting: 执行中 Phase1_Architecting --> Waiting_HITL: 架构文档生成完毕 Phase1_Architecting --> SelfHeal: 超时/崩溃检测 Waiting_HITL --> Phase2_Coding: 人类批准 Waiting_HITL --> [*]: 人类拒绝 SelfHeal --> Phase1_Architecting: 重试 SelfHeal --> Phase1_Architecting: 跳过(已完成) Phase2_Coding --> Phase2_Coding: 执行中 Phase2_Coding --> Waiting_HITL: 危险操作需确认 Phase2_Coding --> Phase3_Testing: 编码完成 Phase3_Testing --> Phase3_Testing: 执行中 Phase3_Testing --> [*]: 测试通过/终止 每一轮调度(通常是 Cron 触发),Agent 醒来后第一件事不是"直接干活",而是读取状态文件,确定自己处于哪个 Phase、上一轮完成了什么、接下来该做什么。 ...

March 19, 2026 · 2 min · Hypho

向量数据库已经很快了,为什么还要重排?RAG 系统中 Bi-Encoder 与 Cross-Encoder 的工程对决

一个让工程师失眠的 Bad Case 2025 年中,某金融科技公司在内部知识库问答系统中引入 RAG(检索增强生成)。系统上线后,用户反馈普遍不错——直到某天,一个风控团队的用户问:“我们有哪些客户曾经有过信用违约记录?” RAG 系统检索返回了三条"高相关"文档,AI 基于这些文档给出了自信满满的答案。风控经理看完后直接冷汗:系统返回的内容全是关于"信用良好客户"的正面案例,和用户的查询意图完全相反。 事后排查发现,问题出在向量检索阶段。用户的查询"信用违约记录"和文档中大量出现"信用"“违约"字眼的高频正面记录产生了极高的余弦相似度,而真正描述违约事件的文档因为语言表达更隐晦,反而相似度偏低,被 Top-N 过滤掉了。 这是一个典型的向量检索只看词不看语义关系的失败案例。1 向量检索的物理课:两个不相识的学生在各自考试 理解为什么向量检索会"看走眼”,需要先理解它的工作原理。 向量检索的核心是Bi-Encoder(双编码器)架构。当你把文档存入向量数据库时,每个文档都会通过一个 Encoder 被压缩成一个固定长度的向量——通常 768 维或 1024 维。这个过程发生在入库时,与用户未来的查询完全无关。 当用户发起查询时,查询文本同样通过 Encoder 生成一个查询向量。然后,数据库在高维空间中做最近邻搜索(通常用余弦相似度或内积),找出与查询向量"距离最近"的 N 个文档。 这个过程有一个非常关键的特征:Query 和 Document 的编码是独立完成的,它们从未"见面"。 斯坦福大学 NLP 组有一个很直观的比喻:就像两个学生分别在不同的考场同时参加考试,学生 A(Query 编码器)看了一眼题目后把答案写成压缩笔记,学生 B(Document 编码器)提前把教科书内容写成压缩笔记。考试结束后,系统只是比较这两份笔记的"形状"有多像,而不知道题目问的是什么。 这解释了为什么"信用违约记录"的查询会匹配到"信用良好客户"文档:两份文档都高频出现"信用"字眼,它们的向量在语义空间中距离很近,而模型根本不知道"违约"和"良好"是反义词。 重排模型:让 Query 和 Document 当面对质 Cross-Encoder(交叉编码器)采用了完全不同的策略。 它不做"独立压缩",而是把**[Query + Document] 拼接成一段完整文本**,一次性通过一个深度神经网络(如 BERT)。在这个过程中,模型的注意力机制(Self-Attention)会在每一个 token 层级做交叉比对——当读到 Query 中的"违约"时,它会立刻去 Document 中寻找是否存在"违约"、是否存在语义矛盾、是否存在否定结构。 这种"当面对质"的方式,让 Cross-Encoder 能捕捉到 Bi-Encoder 完全无法处理的关系: 语义否定:Query “如何不用 Python” vs Document “Python 教程”——Bi-Encoder 会给高分,Cross-Encoder 能识别"不"的否定作用 长距离依赖:查询涉及某个条件组合,文档在开头提到条件A、结尾提到条件B,Cross-Encoder 的注意力能跨越全文找到同时满足两个条件的文档 细微差异:两份文档语意相近但立场相反(如上面的违约案例),Cross-Encoder 能识别出差异 用一个直观的对比表总结: ...

March 19, 2026 · 2 min · Hypho