· 19 分钟阅读 · Seak(安天)

能“从零开发”,却不会“接盘维护”——国产大模型亟待突破的十二个瓶颈(引子·之一)

本文整理自创意安天论坛连载《国产大模型长程开发能力亟待突破的瓶颈的系列笔记》,合并引子篇与之一,原帖在此

引子

今年非常令人欣喜的是,国产主流模型编程能力已经有了空前进步。Kimi K3、GLM-5.2 这一级模型,在部分代码、终端操作和长程任务基准上已经进入国际第一梯队。例如,Kimi K3 官方公布的 Terminal-Bench 2.1 为 88.3、FrontierSWE 为 81.2;GLM-5.2 官方公布的 Terminal-Bench 2.1 为 81.0。

参考资料:Kimi K3 官方模型页Zhipu GLM-5.2 官方模型页

评测是一个很好的参考风向标,提供了国产模型走入全球用户视野的一个重要路径。同时,长程任务评测,也并非是“裸模型智商”的单一结果,而是“模型+Agent 挽具+上下文管理+算力预算”的组合,例如 Kimi K3 的评测说明明确显示:不同模型使用了 Kimi Code、Claude Code、Codex 等不同脚手架,Kimi K3 采用最大推理强度,部分结果是特定环境、内部基准或多次运行结果。一方面,要看到大模型能力的体系复杂,另一方面,也需要看测试中的表现,并不能代替最终的大量应用的检验。无论是从 WEB 入手,还是结合 Code 工具,国产模型在 WEB 前端开发的表现也都非常丝滑,在做类似数据处理分析小工具、前端演示方面,都能相对很快达成目标。这也是因此在类似 Aipy 的适配度测评,此类不追求长程任务评价中,可以有大量国产模型上榜,包括甚至把 GPT 甩在后面。

但我想指出的是,这些不能直接等价为:

  1. 可以有效完成其自身规划的一个大型软件。
  2. 可以稳定接管一个完成了 60% 的大型项目。
  3. 可以完成对原有 CC 或者 Codex 的相对复杂的项目的平移。

基于今年以来的使用、测试和开发工作,我对国产头部模型到目前状态的评价是:

代码智商已经很高,但工程人格、项目记忆和验收纪律依然不稳定。

工程人格、项目记忆、验收纪律,这些正是国产头部模型必须突破的。我想基于案例->总结的方式,写一组系列笔记,讲讲感受、经验和总结。

同事提醒说,谈国产大模型,如果是谈问题要先“叠甲”,表明一下立场。我觉得大可不必,因为立场是通过斗争考验,通过历史来检验的。更何况:

第一,我们自己就是国产模型的开发者,批评国产模型也是自我批判、推动提升的过程。

第二,我们也是挽具的开发者,挽具的部分价值是能局部对冲模型能力的不足。

第三,我们也是部分国产模型的用户和部分模型的安全生态合作者,用户本来就有批评厂商的权力,生态伙伴间的批评本来就是为了共同进步。

同时,我也无意和头部模型的专家们比拼大模型的理解,如果这样做就太班门弄斧了。我是以开发者的用户体感来写这组笔记的,我的分析“入口点”来自于自身作为一个“三线”开发者的感受。作为网安企业负责人,白天自然要见甲方爸爸、跑相关部门、见投资人、讨论研发项目进展、组织响应重大事件、写各种文档等。因此做一点点技术开发工作,也多数要到晚上十二点后进行。所以本文的案例,并不是对国产大模型实现的机理分析,而是基于个人使用国产大模型完成开发任务,包括和国际当前领先模型的一些对比。

与此同时,我对互联网开发的新的技术栈是不熟悉的,记得 2010 年,同事在给我的《数据救赎》写按语的时候,就写道“Seak 作为一个 DOS 时代的底层研究者,在安天成立伊始已经转身为技术管理者角色,其并不熟悉最新系统和 NTFS 分区结构。”。我的 AI 开发也是对流行技术栈的学习过程。

笔记案例会来自几类:

  1. 垂直响应平台中我负责的工具 ASearch 搜索等,智甲 EDR 中我负责的配套工具,所以这些都是最大不过几千行到几万行级别代码的小型独立任务。
  2. 挽具 AVL Code 的开发测试,我们必然要在同样的任务和文档条件下,进行用同一个挽具使用不同模型的输出对比,或者同一个模型,不同挽具的对比。
  3. 客户在部署使用 AVL Code 中遇到的一些问题,经我们分析属于模型问题的。(获得了客户分享的同意)
  4. 作为大学兼职教师,给所担任课程做的课件,中遇到的问题。

每套模型 + 挽具都有其频繁出错的低级梗,在选取案例时把握的原则是:案例都取自导致“翻车级”结果的情况,而不是类似在交互或者迭代中出的一些低级错误。

我们不会在所有案例中提及具体模型的名字,这些案例都是今年以来遇到的,也并不尽然一定是模型的问题,同样有可能是挽具的问题。

包括有些可能对应的模型已经有了调整,我们的重点不在于具体的问题,而在于通过案例引出若干共性问题。

如果未来几天后半夜的时间有保证,我拟用每天一篇笔记的节奏,大概用十天左右的时间完成这次盖楼。

空目录看妆容,历史项目见内力

从零开发和接盘维护,是两种完全不同的体验。

如果你要看模型是否有精致妆容,就给它一个空目录;如果你想考验模型是否有深厚的内力,就给它一个历史项目。

在从零开发上,国产模型已经可以做得相当不错。做一个 React 或 Vue 页面,写一个 Python 小工具,实现一组常规后端接口,很多时候不仅速度很快,视觉和功能效果也会让人眼前一亮。

Kimi K3 刚发布的那几天,我曾经用 AVL Code 配合 Kimi K3,生成了一个老式计算机操作演示站 cs.avlcode.cn。整个过程的 API 计费消耗约为 200 元人民币,最后呈现出来的效果总体令人满意。这就是老张在博客中,说我向他“致敬”的页面,其实这个页面不是给老张的,真正“献给老张”的页面遇到了一个值得总结的坑,我会在另一篇瓶颈点讲。

Moonshot 对 Kimi K3 的官方定位也已经明确包括长程编码、大型仓库导航和终端工具编排,说明国产头部模型的目标早已不再局限于代码补全。

从实际应用看,前端页面、脚本工具和相对标准的业务接口,已经足以覆盖相当一部分机构的日常数字化需求。即便进入 C++、Rust 等技术栈,只要需求边界清晰,把国产模型作为 IDE 的增强器,用来补齐代码、解释接口、查找调用关系和生成局部实现,也有很大价值。问题在于,未来衡量编程模型和 Agent 挽具的,不是传统软件工程的场景。真正的软件工程变化,是编程正在从少数人的专业技能,逐渐变成一种按需生产能力。越来越多非专业开发者会从零起手,通过自然语言生成软件,再根据反馈持续迭代。传统意义上的“程序员”和“用户”之间,正在出现一个人数更大、边界更模糊的新群体。

这个新群体与国产模型结合中,共同面对一个大坑和一座大山。

一、需要填的大坑:历史项目不是一张白纸

所谓大坑,就是历史项目的接盘。国产模型现在通常已经能够读懂相当复杂的代码。把一个仓库交给它,让它解释模块关系、梳理调用链、说明某个函数在做什么,结果未必比国际主流模型差很多。但“看懂”和“动手”之间,隔着一道很深的沟。我曾经把一款历史跨平台工具的代码和文档,分别交给国产模型和国际主流模型做理解与迁移测试。单看代码解释,两者差距并不明显。可当第一个实际任务变成“恢复技术栈和编译环境,并成功完成构建”时,差别立刻出现了。国际模型很快沿着原有技术栈完成了编译。国产模型则判断这个项目技术栈复杂、陈旧、维护价值不高,建议直接换一套新技术栈重构。这类建议从文字上看甚至很有道理。老技术栈难维护,文档残缺,构建工具过时,代码风格混乱,重构似乎比修修补补更“先进”。但接下来真正让模型执行长程重构时,它又往往驾驭不了这个过程:旧系统没有完全理解,新系统没有真正建立,接口兼容和异常路径被逐渐遗漏,最后留下一个既不能替代旧版本、也无法独立交付的新工程。

这不是个别项目的偶然。国内软件工程的发展极不均衡。一些大厂和大型企业积累了成熟的工程体系,但作坊式开发也长期大量存在。很多历史项目文档不全,代码与文档不一致,构建环境依赖某一台旧电脑,关键逻辑只存在于原作者的记忆里。还有一些代码,经过十几年人员更替和需求叠加,早已形成了只有“考古”才能解释的结构。

这些项目本身就是一个巨大的历史遗留层。

模型进入这类仓库后,很容易出现几种典型行为:

  • 不理解某段“看起来很丑”的代码为什么不能动;
  • 不知道现有抽象背后承担着哪些历史兼容责任;
  • 放着已有工具类不用,重新实现一套;
  • 绕过原有错误处理、日志、配置和生命周期框架;
  • 为完成一个局部任务,破坏公共接口或模块边界。

其中最危险的,不是模型写不出代码,而是它能够写出一段局部合理、全局错误,而且可以顺利通过编译的代码

案例:一个小任务,怎样变成六个死循环

这是我们协助客户进行 AVL Code + 某国产模型移植的一个典型案例,项目前期约 60% 的代码由 Opus 协助完成,随后转交给某国产模型继续开发。事故涉及的文件是一个约 1600 行的 Manifest.cpp,接盘的首个任务看起来极小:为十个 List* 查询函数补上 sqlite3_reset

模型的理解是:这就是一个十行修改。找到十个位置,各插入一行 sqlite3_reset,编译,测试,结束。

但这项任务真正的形状并不是“十行插入”,而是“确认十个调用点是否符合语句缓存的所有权契约”。

这个契约其实并不隐蔽,就写在文件最前面的 120 行里:

  • 缓存命中时,StmtCache::Get 会统一执行 sqlite3_resetsqlite3_clear_bindings
  • 缓存析构时,会统一 finalize 所有语句;
  • 数据库关闭前,Manifest::Close 会先释放语句缓存,再关闭数据库连接。

也就是说,调用方原则上不拥有这些 SQLite 语句的最终释放权;下一次复用时,缓存层本身也已经负责 reset。那十个调用点并不存在必须补 reset 的正确性缺口。所谓“十个函数缺少 reset”,本身就是建立在错误诊断上的一张假工单。

模型没有读这段契约。它拿到交接摘要后,直接把一个所有权问题降维成了行号编辑问题。最终十个预定落点中,只有两个位置正确;六个 reset 被插进了查询循环体;另外两个甚至落进了任务清单之外的相邻函数。只要数据库中存在一行查询结果,循环体内的 sqlite3_reset 就会让下一次 sqlite3_step 从头重新执行查询,再次返回第一行,最终形成死循环,并让结果容器持续增长。

结果是:

十处修改,二处正确,六处埋下死循环,两处改错函数。

更危险的是,这份代码编译通过了。

模型还运行了一个样例测试。恰好,这个测试只经过十个函数中位置正确的那个函数,没有触及六个已经受损的查询路径。于是测试转绿,模型宣布“核心功能修复完成”。

这次事故最值得注意的地方,不是模型不知道 sqlite3_reset 怎么用。

恰恰相反,它知道这个 API,也知道如何插入代码,能够处理编译错误,甚至能够根据链接错误临时补写一个缺失函数。

它真正没有理解的是:

reset 的责任究竟属于调用方,还是属于语句缓存?

这才是整个任务的逻辑关窍。

如果模型先读懂了缓存所有权契约,就会发现十处修改一处都不应该做。真正需要完成的任务,只有补上另一个链接所需的缺失函数,并为它增加行为测试。

它把不需要做的十件事做了一遍,还做错了其中八件。

事故中还有一个很有象征意味的细节。

模型接盘时,工作区里残留着上一轮修改失败形成的畸形代码:重复的 return true、多余的右花括号,以及位置错误的 reset。模型认为这些是垃圾,直接执行 git checkout 将文件恢复,而且没有先 stash。

事后复核才发现,那些代码虽然编译不过,但其中保留了前任正确的修改意图——reset 原本准备放在查询循环闭合之后,只是在复制代码时把 return 和右花括号一并带了进去。

换句话说:

前任留下的是“语法错误但意图基本正确”的代码;接盘模型把它清掉之后,写出了“语法正确但语义危险”的代码。

前一种错误会被编译器拦住,后一种错误却可能进入版本。

这就是接盘维护最典型的风险:模型把代码库看成了一块等待自己重新书写的画布,而不是一个已经运行多年、充满历史约束和所有权关系的系统。

二、需要越过的大山:如何让更多中国使用者摆脱国外模型与工具的依赖

如果说历史代码是大坑,那么更大的那座山,是当前国内产业领域中,不得不最终摆脱的国外模型与工具供应依赖。

问题并不只是把 API 地址从一家换成另一家。

编程智能体已经深度介入:项目理解、架构设计、代码生成、调试、测试、文档、发布、版本交接、团队知识沉淀。

当一个项目长期使用 Claude Code 和 Opus 开发后,模型的行为方式实际上已经进入了项目的生产过程。切换到国产模型,不只是“换一个更便宜的推理接口”,而是在更换一名熟悉项目历史、工具习惯和工作节奏的虚拟工程师。

支撑这个迁移过程比当年的 WPS 对决 Office 更困难,更低的价格、做好百分之二十的常见功能,这些打法有用,但效用不是太灵,办公软件迁移的主要问题是文件格式、功能习惯和生态兼容;编程模型迁移还多了一层:新模型必须理解并延续旧模型参与塑造的软件系统。

案例:模型如何以编译环境为最后的借口

我们指导客户进行工程迁移时,一家 AVL Code 客户此前也是基于 Claude Code 和 Opus 开发,完成了一个万行级的客户端工具。后来,希望把后续开发迁移到某国产模型 API。

客户配置 AVL Code 完成对接后,首先要求模型根据工程代码和文档检查编译环境。模型判断环境已经完备,同时发现了主机路径差异,也指出原编译脚本中的路径不一致,并成功编译出了第一个版本。

到这里,一切很顺利。但在实施一个很小的功能改进时,模型开始长时间陷入各种错误。几小时后,它给出的结论竟然是:

“终于定位到问题,编译环境并不完整。”

但这个过程中,它莫名其妙地修改了部分头文件。

客户指出,同一个项目此前也曾在 Codex 和 Claude Code 之间迁移,主机技术栈环境同样存在差异,却没有发生这种反复推翻结论、又把环境问题转化成源码修改的问题。在之前的移植过程中,并不需要单独让 Claude Code 去理解环境差异,其会自然地重构编译脚本。

当然这里是一个个案,并不是说 Claude Code 或 Codex 不会犯错,Codex 的“我删”模式已经是多人都遇到过的严重事故。

但我们需要看到的是,它们在接管既有项目时,通常更能把以下几件事区分开:环境问题、构建脚本问题、代码问题、本次修改引入的问题、仓库原有问题。

而能力不足或工程纪律较弱的模型,容易在这些问题之间来回漂移。一开始说环境完整,后来又说环境缺失;一开始说路径有误,后来直接修改头文件;编译失败时不断缝补,最终已经说不清自己是在修功能,还是在重造构建环境。

从 AVL Code 开发者的角度,我们当然要不断通过技术栈标准化、环境指纹、编译探针、Plugin、Skill、任务状态机和验证门禁来改善这些问题。但对于已经重度依赖 Claude Code、Opus、Codex 和 GPT 系列模型的用户来说,他们不会用“某个国产模型已经比过去进步很多”作为评价标准。

他们真正比较的是:能否给与一套国产模型 + 挽具同样的心智信任。这就形成了一个双重痛苦期。一方面,国产模型需要接续此前由国际模型生成和维护的版本;另一方面,已经习惯了 Codex 与 Claude Code“双枪并用”的开发者,也必须重新调整自己的能力预期、任务拆分方式和使用习惯。

它不仅要接代码,还要接前任模型的设计决策、临时方案、命名习惯、测试空白,甚至接前任留下的错误。

当交接文档与代码不一致时,模型必须知道应该相信谁;当旧代码很丑时,必须先判断这是技术债、兼容层,还是不能动的业务规则;当构建失败时,必须区分环境异常和代码回归;当局部测试通过时,还必须知道验证面是否覆盖了修改面。

这些能力,远远超过“根据需求生成代码”。

三、“尊重代码”不是态度,而是一套方法

回到这个系列第一篇想讨论的瓶颈,我的核心感受是:

国产主流模型已经越来越能看懂“代码做了什么”,但不一定能推断出“为什么当初必须这么做”。

而在历史项目中,后者往往比前者更重要。

所以,从体验上说,我很想给当前的国产编程大模型——特别是我们自己的模型——一个不太客气的评价:

会写代码,不会尊重代码。

这里的“尊重”不是拟人化的道德要求,也不是要求模型迷信旧代码,我始终反对对大模型人格化想象——这是一种人的“认知幻觉”。

尊重代码,是模型 + 挽具的工程方法,我们总结本文中的案例,可以看到:

  1. 契约先于工单。 涉及缓存、句柄、连接、线程和对象生命周期时,先找到所有权中枢,再修改调用点。
  2. 代码先于交接叙事。 上一轮说“已经完成”,不等于仓库里真的存在;接盘第一步应当是逐项对账。
  3. 疤痕先于清理。 畸形工作区不一定只是垃圾,也可能保存着前任尚未表达完整的修改意图;回滚前必须保全。
  4. 模式验证先于编译通过。 批量修改十个位置,就要逐点检查十个位置;编译器只能证明语法成立,不能证明语义正确。
  5. 验证面不能小于改动面。 修改十个函数,只运行一条恰好不触及错误路径的测试,那个绿色没有多少意义。
  6. 完成声明必须建立在证据上。 编译命令、退出码、测试覆盖范围和未验证项,应当比模型的总结更可信。

这次事故复盘给出的五步防线——读契约、做疤痕考古、复核工单、验证批量落点、让测试覆盖全部改动面——其中任何一步,都足以独立终止事故链。

因此,我非常反对把国产模型仍然存在的不足简单归结为“国产模型参数不够大”。模型当然需要继续提高软件演化、因果调试和长程工程能力;但编程智能体和 Agent 挽具同样必须承担责任。模型容易忘记的约束,就不应该只写在提示词里;模型容易夸大的完成状态,就应该由证据系统裁决;模型容易随意扩大的修改范围,就应该被 Diff 预算和接口锁限制。我们不能指望靠一句“请充分理解项目后再修改”解决工程纪律问题。

四、土壤不够肥沃,但空间足够宽广

写到这里,我要再次明确这个系列不是一份国产模型的败绩清单。

中国的软件开发者从宽口径计算约千万,即使对照美国 BLS 的全职程序员标准统计,也可能有 400 万之多,已经是美国的两倍。中国拥有毋庸置疑的巨大的软件需求、开发者生态和数字化市场。过去几十年,这片土地上产生了大量优秀的软件,也留下了数量更多、质量参差不齐的历史项目。它们可能没有完整文档,没有稳定测试,没有统一架构,甚至连编译环境都无法轻易恢复。这些田地谈不上肥沃,更谈不上精耕细作。但它足够广阔。

对于国产编程大模型来说,有价值的下一步,不是再生成一个更漂亮的 Todo List,不是在空目录里更快地搭出一个网页,甚至不是去刷新一些旧的和新的榜单记录,而是走进这些真实、混乱、带着历史伤痕的项目里,把它们接住。先理解它为什么会变成今天这样,再决定什么应该保留,什么可以修改,什么必须重构。

一个模型只有在动手之前开始追问:

这段代码为什么还存在?
谁在依赖它?
它背后有什么没有写出来的契约?
我真的有必要动它吗?

它才算真正从“会写代码”,走向了“会做软件工程”。

而当我们的国产模型开始学会“尊重代码”,它就将接住中国软件产业真正庞大、真正复杂,也真正有价值的历史,也能更好、更完全的承载住它的使命。

相关文章