ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Code World Model:让 Coding Agent 用代码预演世界,实现可解释的状态推演

Code World Model:让 Coding Agent 用代码预演世界,实现可解释的状态推演 世界模型World Model与 Coding Agent 是当前 AI Agent 方向两个出现频率很高的词。前者强调智能体在内部重建环境动态后者强调用代码与外部环境交互。西湖大学团队提出的 Code World Model 把这二者放进同一句话让 Coding Agent 成为世界模型的大脑。初看这句话很像方向口号但拆开看它其实在回答一个问题世界模型里的状态转移函数能不能不再藏在一堆神经网络权重中而是写成一段可执行、可校验、可复现、可以被 Agent 修改和版本管理的代码。这篇文章不打算复述新闻而是从工程技术视角拆解这个概念。先说明 Coding Agent 为什么需要世界模型再给出 Code World Model 的组件化理解然后用一个最小 Python 示例演示“生成世界模型代码 - 执行模拟 - 基于模拟结果规划”的链路最后给出评测方法、常见坑和生产落地建议。对于正在做 Agent 编排、任务规划或 LLM 工具调用的开发者这篇文章的价值在于当你下一次准备让 Agent 直接回答“如果执行这个动作会发生什么”时可以先让它写一段环境转移代码再拿这份代码做推演。1. Code World Model 在回答 Coding Agent 的什么问题1.1 大多数 Coding Agent 只会“补全代码”不会“推演后果”国内很多团队把 Coding Agent 做成一个代码生成器给一个 issueAgent 读代码库、搜索相关文件、生成 diff、跑测试、提交 PR。这种模式更像“自动补全”而不是“智能体”。因为 Agent 对整个系统运行规律的理解基本停留在“读过上下文”这个层面。举一个常见现象。让 Agent 修复一个订单超卖问题它可能很快定位到扣减库存的那一行然后给出UPDATE语句。但如果追问一句这个改动在高并发下会怎样如果支付成功但库存扣减失败状态机怎么转下一次任务调度进来数据库里的中间状态是否会被重复消费很多 Agent 答不上来因为它没有可执行的“系统运行模型”。它只是根据经验生成了一段看起来合理的代码并没有验证这段代码在完整系统中会产生什么状态序列。Code World Model 要解决的正是这个缺口。它不再把 Coding Agent 当成“写代码的助手”而是让它先具备对世界状态的建模能力知道当前状态是什么知道某个动作会导致什么状态再基于这种预测做出决策。1.2 世界模型的核心价值是“预演未来”在强化学习里世界模型通常被定义成一个环境动态函数它接收当前状态和动作输出下一状态。形式化写出来是T(s, a) - s其中 s 表示环境状态a 表示智能体采取的动作s 表示动作发生后环境进入的新状态。有了这个转移函数智能体就能在内部反复试错不需要每次都去真实环境里踩坑。真实世界的运行成本很高代码发布有失败风险库存扣减不能随便回滚对话系统面对真实用户不能随意试错。因此任何一个能自主做事的 Agent都需要至少一个“内部环境”来低成本预演。世界模型就是那个内部环境。传统世界模型通常用神经网络直接拟合状态转移。它的优点是容量大能处理图像、文本等高维输入缺点是预测结果很难解释训练需要大量环境交互数据换一个环境就要重新训练。更麻烦的是模型学会了状态变化规律后你很难把它变成一段可以在复杂系统里集成、测试和审计的确定逻辑。1.3 代码版世界模型为什么值得尝试Code World Model 的核心假设很直接把状态转移函数从神经网络参数中拿出来写成一个可以被 Coding Agent 生成、修改和执行的核心函数。def step(state: dict, action: str) - dict: next_state ... return next_state这样一个函数天然具备几个优点可执行。给定当前状态和候选动作运行函数就能得到下一状态不需要估算。可解释。每一步状态转移都能通过代码审查确认。可测试。对同一个 world model 可以写多个 unit test断言它符合环境规则。可迭代。如果模型预测不准确不需要重新训练可以直接调整代码或增加观测数据让 Agent 重新生成函数。从工程视角看这就是“把世界模型从黑盒变成白盒”的过程。Coding Agent 成为世界模型的大脑并不是说 Agent 里有一个全知全能的世界模拟器而是说 Agent 可以承担“观察环境、理解规则、生成转移函数、基于模拟做决策”这一整条链路。注意Code World Model 并不是主张所有环境动态都能被确定性代码表达。对于高度随机、不可观测或依赖多智能体博弈的场景真实环境仍然需要在线反馈。代码模型更大的价值是提供一个“初步可推演、可修正”的内部环境。2. 拆解 Code World Model 的工作链路2.1 Coding Agent 如何成为“大脑”先建立一个框架一个 Agent 如果要做决策至少包含下面几个零件。感知把当前环境和任务转成结构化状态。建模从观测中推断环境规则。推演在主决策之前模拟多个动作的未来结果。决策在推演结果中选择最符合目标的动作序列。行动把决策转成真实世界的动作并执行。反馈吸收比较预测状态和真实状态找出偏差。绝大多数 Agent 工程都实现了感知、行动、反馈但没有独立建模和推演模块。它们把“未来预测”混在 prompt 里让 LLM 凭直觉说“下一步应该做什么”。这种做法在小规模任务里可用一旦动作空间变大LLM 很快就会遗忘前面几步也无法稳定处理长程因果。Code World Model 把“建模”和“推演”从直觉中剥离出来。Coding Agent 扮演的是大脑角色但它推演的方式不是直接生成下一个 token而是先生成世界模型代码再运行这份代码。传统 coding agent 是“用代码完成用户需求”而 Code World Model 是“用代码理解环境、预演未来、再完成需求”。2.2 一个典型的状态转移代码接口为了让世界模型能被 Agent 稳定生成和执行代码接口需要尽量统一。研究或工程落地时建议先定义好状态、动作和观测的数据结构。一个可用的最小接口是状态用 JSON 可序列化的 dict动作用字符串或字符串参数组合转移函数接收这两个输入后输出一个新的 dict。def step(state: dict, action: str) - dict: 返回执行 action 后的新状态不允许修改原始 state。为什么要用 dict因为世界模型生成结果要被下游模块消费。比如你希望 Agent 预测“库存未来 5 天会不会低于安全水位”输出就可以是{stock: 32, incoming: 0, out_of_stock: false}。这个结构人能看懂代码能计算JSON 能存储。一个真实世界模型代码的示意是这样def step(state: dict, action: str) - dict: s dict(state) if action reorder: s[incoming] 50 s[arrival_day] s[day] 3 s[cost] 150 if s[arrival_day] s[day]: s[stock] s[incoming] s[incoming] 0 s[arrival_day] -1 s[stock] - s[daily_demand] s[day] 1 return s这段代码明确描述了动作的副作用下单后不会立刻到货而是 3 天后入库每天结束时扣减需求。Coding Agent 判断“是否补货”时就可以反复调用这个 step 函数去模拟未来几天的库存而不是直接猜测答案。2.3 状态、动作、奖励和观测分别怎么定义在设计 Code World Model 时先区分几个概念否则 Agent 写出的 step 函数会缺少边界。状态state智能体认为的世界当前完整情况。观测observation智能体实际看到的信息状态中可以包含观测中不存在的内部变量。动作action能造成状态变化的外部操作。转移概率环境对每个动作的响应规则。奖励或目标用于评估状态好坏的信号。一个常见错误是让 Agent 把所有观测都塞进状态。比如让 World Model 模拟网页操作却把 HTML 全文放进 state再让 step 函数完整输出变化后 HTML。这样会导致建模成本过高、token 消耗过大step 函数也无法稳定输出。更好的做法是抽取“与决策相关的状态变量”。网页操作不需要记录整个 DOM只需要记录当前 URL、页面中的关键按钮状态、表单输入值、Cookie 登录状态等。组件含义典型示例state用于推演的完整状态{url: /cart, items: 3, stock: 12}action改变状态的操作click_checkout,reorder,waittransition动作作用于状态的结果step(state, action) 返回新状态reward状态好坏信号到达目标 1触发异常 -1observation真实环境返回的信息页面标题、接口响应内容2.4 世界模型更新不是“重训”而是“改代码”传统神经网络世界模型更新需要重新训练成本高频率低。Code World Model 的潜在优势是模型本身就是代码因此更新方式也变成代码版本迭代。当真实环境反馈与预测不一致时可以让 Agent 按以下顺序修正找到不一致出现在哪一步动作或状态上。对比真实状态序列和 world model 预测序列。用错误信息生成新的 step 函数或者生成一个补丁函数。在回归测试集中验证旧场景没有被破坏。这样模型更新就变成了 agent-driven 的代码修复任务。Agent 不再只写业务代码它还在维护一个关于世界变化规律的代码库。这一点是 Code World Model 与普通代码生成最本质的区别。3. 用 Python 实现一个最小 Code World Model Agent3.1 示例做什么先学会“建模”再学会“规划”下面给出一个最小但完整的实现。示例环境是一个 5x5 网格世界其中两个坐标是墙动作是上下左右和原地等待。目标是从(0,0)走到(4,4)。在传统方式中LLM 会直接输出一组动作可能对也可能错。在 Code World Model 方式中第一步让 LLM 生成一个step(state, action)函数描述环境规则第二步由执行器运行这个函数第三步用 BFS 在这个世界模型上搜索一条从起点到终点的路径。重要说明这个示例只用于演示 Code World Model 的工作原理不是西湖大学原研究代码。真实研究中的环境、训练和评估流程会比这里复杂得多。3.2 环境准备安装 OpenAI SDKpip install openai python-dotenv调用代码前设置环境变量。如果你使用云厂商兼容接口可以改成对应的 base_url 和 key。export OPENAI_API_KEYyour_api_key_here export MODEL_NAMEgpt-4o-mini注意示例使用 gpt-4o-mini 只是便于说明实际项目的版本和模型要在部署前根据可用模型列表确认。3.3 完整示例代码核心文件cwm_demo.py由五部分组成prompt 模板、代码安全校验、LLM 调用、世界模型执行、BFS 规划。# cwm_demo.py import ast import json import os import re from collections import deque from openai import OpenAI MODEL os.getenv(MODEL_NAME, gpt-4o-mini) client OpenAI(api_keyos.getenv(OPENAI_API_KEY)) WORLD_MODEL_SYSTEM_PROMPT 你是一个世界模型生成器。 用户会提供一个环境的抽象描述。你需要用纯 Python 函数表达环境的状态转移规则。 要求 - 只输出 Python 代码不要输出解释和 markdown。 - 不能 import 任何模块。 - 函数签名必须是 step(state: dict, action: str) - dict。 - 非法动作必须返回当前状态的拷贝。 - 函数只能使用常见的 Python 内置函数不能调用文件、网络、进程相关能力。 WORLD_MODEL_USER_PROMPT 环境描述 一个 5x5 网格世界坐标 x 和 y 都从 0 到 4。 坐标 (1,1) 和 (2,2) 是墙不能进入。 可执行动作left、right、up、down、rest。 rest 表示原地等待。 state 结构是 {x: int, y: int, steps: int}。 请生成对应的 step 函数。 SAFE_BUILTINS { dict: dict, list: list, tuple: tuple, bool: bool, int: int, float: float, str: str, len: len, range: range, min: min, max: max, abs: abs, sum: sum, sorted: sorted, enumerate: enumerate, } def validate_model_code(source: str) - None: tree ast.parse(source) for node in ast.walk(tree): if isinstance(node, (ast.Import, ast.ImportFrom)): raise ValueError(模型代码不允许 import) if isinstance(node, ast.Call) and isinstance(node.func, ast.Name): if node.func.id in { open, exec, eval, compile, __import__, input, globals, locals, }: raise ValueError(模型代码调用了禁止函数) def extract_code(text: str) - str: match re.search(r(?:python)?\s*(.*?), text, re.S) return match.group(1).strip() if match else text.strip() def generate_step(): resp client.chat.completions.create( modelMODEL, temperature0.2, messages[ {role: system, content: WORLD_MODEL_SYSTEM_PROMPT}, {role: user, content: WORLD_MODEL_USER_PROMPT}, ], ) raw resp.choices[0].message.content source extract_code(raw) validate_model_code(source) namespace {__builtins__: SAFE_BUILTINS} exec(source, namespace) step_func namespace.get(step) if step_func is None: raise ValueError(生成的代码里没有 step 函数) return source, step_func def bfs_plan(step_func, start, target, max_steps12): start json.loads(json.dumps(start)) queue deque() queue.append((start, [])) visited set() visited.add((start[x], start[y], start[steps])) while queue: state, path queue.popleft() if (state[x], state[y]) target: return path if len(path) max_steps: continue for action in (left, right, up, down, rest): next_state step_func(state, action) key (next_state[x], next_state[y], next_state[steps]) if key in visited: continue visited.add(key) queue.append((next_state, path [action])) return None if __name__ __main__: source, step_func generate_step() print( 生成的世界模型代码 ) print(source) plan bfs_plan(step_func, {x: 0, y: 0, steps: 0}, (4, 4)) print( 基于世界模型搜出的动作序列 ) print(json.dumps(plan, ensure_asciiFalse))3.4 这段代码每个环节在做什么代码里的WORLD_MODEL_SYSTEM_PROMPT要求 LLM 输出纯 Python 函数这是避免把世界模型写进自然语言再单独解析的关键。如果让 LLM 既写代码又写解释exec 前需要额外处理代码块解析也容易出错。validate_model_code做基础安全校验禁止模型生成的代码 import 模块也禁止调用文件读写和进程执行相关函数。这个函数不是完整沙箱只是降低本地演示风险。SAFE_BUILTINS限制了 exec 时的内建函数白名单。目的是防止模型生成的代码访问__import__或读取系统文件。真实生产环境应该把这一步替换成容器、VM 或 serverless 沙箱。bfs_plan不依赖 LLM 直接给路径而是在 LLM 生成的世界模型上执行确定性搜索。这个设计更符合 Code World Model 的定位LLM 负责抽象和建模规划器负责在模型上计算最终动作是计算后的结果。3.5 运行与预期结果运行命令python cwm_demo.py正常输出会包含两段内容。第一段是模型生成的世界模型代码。模型给出的step函数通常包含坐标更新、墙体判断和 steps 自增逻辑。第二段是一个动作数组例如[right, right, down, down, right, down, down, right, right]实际输出可能不同因为 LLM 生成代码时的局部判断存在差异。只要路径不经过墙、整个过程不超过 max_steps规划结果就有效。这里要强调该示例中的世界模型是从「环境文本描述」直接生成的。更多真实场景中环境规则不是靠一段描述给 Agent而是需要 Agent 从历史观测轨迹中归纳。差别在于多了一个“推断规律”的环节但核心链路仍然是同一个Coding Agent 用代码建模再用代码预演。4. 从“能跑”到“能评判”应该怎样评估一个 Code World Model4.1 单步状态转移准确率世界模型最重要的质量指标是预测是否准确。定义如下单步准确率 预测状态与真实状态一致的动作数 / 全部测试动作数如果是连续状态不能单纯比较相等则使用误差指标例如状态变量平均绝对误差。在大模型 Coding Agent 中可以用一组覆盖正常动作、非法动作、边界动作的测试用例来运行生成出来的 step 函数。一个简单的评估伪代码如下test_cases [ ({x: 0, y: 0, steps: 0}, left, {x: 0, y: 0, steps: 1}), ({x: 0, y: 0, steps: 0}, right, {x: 1, y: 0, steps: 1}), ({x: 1, y: 1, steps: 0}, up, {x: 1, y: 1, steps: 1}), ({x: 2, y: 1, steps: 0}, down, {x: 2, y: 2, steps: 1}), ]第三步和第四步分别覆盖墙阻止移动的边界情况。只有世界模型的单步输出与这些断言一致才能进入后续规划阶段。4.2 模拟器可执行率与代码质量LLM 生成的代码并不是总能执行。评估时需要统计可执行率生成的 step 函数能通过语法解析和本地 smoke test 的比例。无注入率模型生成代码中没有调用文件、网络、进程相关 API 的比例。可维护性函数状态字段是否与用户给定 schema 一致对非法动作是否返回状态拷贝。上下文一致率生成代码中的状态字段是否与 prompt 中给出的字段完全一致。一个典型失败是模型在代码里加了import random或
返回列表