Code-Text-Code:语义也需要一道闸门
Specification-Based Code-Text-Code Reengineering for LLM-Mediated Software Evolution我在 arXiv 上搜semantic drift找到了这篇论文。作者是 EPAM Systems 的工程师Vasyl Yaremovych。他在做一件很实际的事用 LLM 把代码从语言 A 转换到语言 B比如 Python 转 Java或者 SQL 方言互转。这听起来很普通但论文开头第一句话就抓住了我Direct code-to-code transformation remains challenging to control because it can preserve surface-level syntax while introducing semantic drift.直接做 Code2Code 转换表面语法能保留但意思可能已经悄悄变了。这不就是我在界面层看到的问题吗1. 不是翻译是重工程论文的核心不是怎么让 LLM 写更好的代码而是怎么让 LLM 在转换代码时不丢失意思。作者发现直接给 LLM 一段 Python 代码让它生成 Java 代码会出现四种问题语法对了但意思变了Python 的列表推导式被翻译成 Java 的 for 循环语法没问题但副作用、数据依赖、异常处理逻辑可能全变了模型自己加戏LLM 会脑补缺失的信息实现一些原始代码里没有的行为业务语义丢失生成的代码看起来能跑但业务逻辑、数据约束、非功能需求被丢掉了可追溯性断裂你不知道生成的 Java 代码对应 Python 代码的哪一行出了问题无法归因这和我们每天看到的问题一模一样。代码层LLM 把 Python 转 Java语法对了语义漂移了。语义层LLM 生成一个删除账户按钮颜色对了语义漂移了——蓝色实心而不是红色空心没有二次确认用户一点账户没了。两者都是表面合规语义漂移。2. 在转换之间加一层规范作者的解法不是优化 Prompt也不是换更强的模型。他们的解法是在 Code 和 Code 之间加一层 Text Specification中性文本规范。流程变成Code源代码 → Text Specification中性文本规范 → Code目标代码这层 Text Specification 不是普通的注释或文档而是一份受控的语义表示a neutral textual specification that captures program behavior, identifiers, computational flow, conditions, side effects, data dependencies, and domain-specific intent without directly transferring the source language syntax一份中性的文本规范捕获程序行为、标识符、计算流、条件、副作用、数据依赖和领域特定意图——但不直接转移源语言的语法。作者在代码层我在语义层。作者Code源代码我设计意图设计师脑子里的这个场景下不能做什么作者Text Specification中性文本规范我语义契约YAML 规则文件作者Code目标代码我AI 生成的界面/代码作者语义漂移semantic drift我意思跑偏删除按钮变蓝色、Critical 变严重两者都在做同一件事在生成之前先把意思固定下来。我吸取了论文的核心设计方法在转换链条中插入一层受控的规范层把意思和语法解耦。论文用自然语言规范来解耦代码语法和代码语义。我用 YAML 语义契约来解耦界面样式和界面语义。样式可以变但语义必须被规范锁住。3. 三个确认3.1. 确认 1语义漂移不是边缘 case是结构性必然论文做了大量实验覆盖 Java、C、Python、SQL 等多种语言和方言。结果证明Code2Code 转换在任何语言中都会引入语义漂移。这说明漂移不是某个模型的 bug是 LLM 做转换这件事时的内禀属性。概率采样机制决定了 LLM 天生就会变着花样说表面语法对了语义可能悄悄跑偏。我在日常工作中看到的Critical→严重删除按钮变蓝色和论文在代码层看到的副作用丢失数据依赖断裂是同一个根因。确认 2中间规范层是学术界认可的解法方向论文没有说用更好的 prompt 来消除漂移而是说加一层规范把意思和语法解耦。这和我放弃用更好的 prompt 来约束 AI、转而做语义契约的思路完全一致。Prompt 是请求不是约束。规范层才是约束。论文还做了对比实验直接转换 vs 伪代码中间层 vs 自然语言中间层 vs 图中间层 vs 编译器中间层。结果证明自然语言中间层最适合 LLM 做转换。这进一步确认了我的选择YAML 作为自然语言结构化数据的混合体是语义层最合适的中间规范格式。确认 3验证必须是闭环的不能只有生成没有检查论文的框架包含Code2Text 生成 → 迭代验证 → Text2Code 生成 → 目标代码验证 → 转换损失估计。对应到我的四个环节看组件识别状况 → 找原因确定模式 → 写规矩机器能懂 → 做测试证明有效。两者都强调不能只有生成必须有验证而且验证要能量化损失。4.规范驱动重工程在不同领域被验证论文的 Code-Text-Code 架构本质上是一种规范驱动重工程的设计方法。这种方法不是只适用于代码迁移它在不同领域都有验证代码层EPAM Systems在 Python 和 Java 之间做迁移用中性文本规范锁住业务语义防止语法转换时意思跑偏。数据层阿里云在《构建可审计、可进化的 AI Agent 底座》中用约束基建Constraint Infrastructure锁住数据定义和业务流程防止数据 schema 漂移。语义层我在 AI 生成界面时把设计规范写成代码格式Schema-As-Code锁住设计意图防止按钮颜色、文案、错误状态的意思跑偏。三者是同一套设计方法在不同层级的实现代码层规范锁住代码语义数据层规范锁住业务规则语义层规范锁住设计意图关键洞察规范层不是某个领域的特例是 AI 时代的通用基础设施。当 AI 参与生成内容时无论是代码、数据、界面还是文案都需要一层规范来防止表面合规语义漂移。5. 五、从论文到我的认知跃迁读这篇论文之前我对自己工作的定位很朴素Schema-As-Code 是一个工具用来把设计规范写成机器可读的格式。就像把语雀文档翻译成 YAML让机器能看懂。读完之后我意识到这个定位窄了。论文作者把LLM 辅助的代码转换从直接生成重新定义为受控的重工程过程。他们不是在优化一个翻译工具而是让转换过程中的语义漂移被规范层拦截。我把这个思路搬到语义层重新理解了我正在做的三件事Schema-As-Code不是把文档写成代码格式而是在 AI 生成之前先把设计意图固定下来。它是规范层回答这个场景下意味着什么。Constraint as Code不是写规则文件而是把意图变成可执行的约束。它是契约层回答绝对不能做什么、必须做什么。Validation Toolkit不是测试工具而是验证约束是否生效的审计层。它回答加了约束后漂移有没有被拦住。三层合在一起不是三个独立工具而是一个受控的语义约束流程设计意图Schema-As-Code→ 可执行约束Constraint as Code→ 审计验证Validation Toolkit论文的 Code-Text-Code 是代码层的规范驱动重工程。我的三层架构是语义层的规范驱动重工程——对象从代码换成了按钮、文案和错误状态但根因和解法哲学完全一样。当 AI 生成界面时设计意图在偏离。我不是在做一个把规范写成 YAML的工具我是在建立一套让语义漂移被拦截的语义约束流程。六、一句话总结Vasyl Yaremovych在代码层证明了LLM 做转换时表面语法对了语义会悄悄漂移。解法是在中间加一层规范把意思和语法解耦。我在语义层做的是同一个根因、同一个解法哲学——只不过对象从代码换成了按钮、文案和错误状态。不是只做一个工具而是建立一套语义约束流程Schema-As-Code把设计意图固定下来→ Constraint as Code把意图变成可执行的约束→ Validation Toolkit验证漂移有没有被拦住。当 AI 生成界面时设计意图在偏离。语义层也需要一道闸门。