摘要:年初,我们与国内大量互联网大厂一起,调研国内外 AI 辅助研发的现状,探讨了 AI 辅助研发的现状与未来。我们新增了 AutoDev 的大量功能,如精准测试、自定义团队提示词、自定义智能体等。与公司前 AI 部门,一起协作在客户侧,落地了 AutoDev 自动
在过去的一年里,我大量的时间都花费在了 AI 辅助研发的调研、方案与落地实践上:
年初,我们与国内大量互联网大厂一起,调研国内外 AI 辅助研发的现状,探讨了 AI 辅助研发的现状与未来。
我们新增了 AutoDev 的大量功能,如精准测试、自定义团队提示词、自定义智能体等。
与公司前 AI 部门,一起协作在客户侧,落地了 AutoDev 自动补全。
年中,创建了全新的 AISE 知识站点 aise.phodal.com,以记录我们的调研、实践与心得。
创建了下一代 AI IDE 插件 Shire,以探索 AI 辅助研发的新模式。
年末,在互联网客户侧,探索和落地了我们在 AI 辅助团队的方案 Team AI。
尽管,AI 辅助研发的现状并不是那么乐观,但是我们仍然看到了 AI 辅助研发的巨大潜力。结合这一年的实践中,我想分享自己的心得并吐槽一下国内的 AI 辅助研发工具的不上进。
商业化公司总是在一味鼓吹 AI 的短期效果,声称 AI 辅助研发可以提升 10%~30%+ 的效率。限于,我的开源工具和他们算是有利益冲突,这里就不点名了。从个人的角度来说,在这些商业公司发布裁员消息之前,这些数据都是不可信的 —— 尽管我的观点是 AI 会淘汰一部分程序,也会有新的 AI 开发机会。
一如我在先前的文章里分享 Thoughtworks 之前的统计数据,AI 辅助研发的全链路提升在 2% 到 13% 之间,对于大部分已有项目的提升会在 5% 以下。原因不外乎,原有遗留知识不全、开发流程限制、自动化流程不成熟、AI 工具不成熟。但是,总体来说,如果我们还采取现有的流程, 不限于需求流程、开发流程、发布审批流程等。
但是,我们也要看到好的一方面:
减少重复性工作。AI 对于规范、重复性的工作,还是有很大的帮助的。比如,已有规范体系完整下,它可以大量减少重复性工作,诸如于规范化的 开发文档、代码规范、测试用例等。
降低知识搜索成本。对于采用内网的开发的公司,诸如金融、通信等行业,模型内置的知识库就是一个非常好的搜索引擎。尽管它的准确性不高, 但是也过去相比,仍然具备非常大的优势 。
提升开发幸福感。通过自动完成一些繁琐的任务,AI 可以让开发者更加专注于创造性的工作,从而提高工作的满意度。
促进新技术学习。AI 可以作为一个学习工具,帮助开发者快速理解和掌握新的编程语言、框架和技术。
……
也因此,从成本的角度,能在内部跑上一个 70B+ 的模型,也能大大提升效率 —— 前提是配套上一些合适的 AI 插件和工具。
年初,我们在为某家商业银行设计 AI 辅助单元测试方案时,结合的是远程测试用例智能体 + AutoDev 的精准测试能力来生成。作为一个经常写测试的人,我发现 AI 生成的测试用例,有时候会有一些不准确的地方,诸如于:测试框架、数据准备、测试用例的边界条件等。这也是为什么在国内某商业 AI 辅助研发公司的竞品调研中, AutoDev 的测试能力是国内这些工具里最强的。在测试用例生成上,是基于确定性的开发框架、测试框架、函数输入输出来生成,以进一步降低 AI 生成的幻觉可能性 —— 尽管依然会有一些幻觉,但是与普通的聊天型 AI 相比,我们的幻觉要低很多,并且接受率更高,可以做到一键生成。
那么,作为确定性的输入应该包含哪些?
工具上下文知识。诸如于测试框架、开发框架、编程语言等。
业务知识。来自于实现开发功能前,我们已经有的业务知识,如需求文档、设计文档等。
领域知识。结合不同行业特点,包含一些特定的领域知识,如金融、电商等,以生成更加符合业务场景的内容。
规范性知识产出。诸如于在测试用例生成时,测试人员编写的测试用例、测试数据等。
所以,与之对应的另外一个难点是,团队过去沉淀过多少领域知识、规范性知识产出,以及如何将这些知识转化为 AI 可以理解的知识。
在国外流行的 AI 辅助工具里,诸如于 Cursor、GitHub Copilot、Continue 等都支持了一些手工的上下文能力。用户可以根据自己的场景,有选择性地 添加一些上下文信息如文件等,以这种方式来提升上下文的确定性,避免 AI 生成的幻觉。而在 AI 问答场景下,则往往会通过二次确认的方式,来让用户确认 其意图是否正确,以避免出现错误的意图理解。
那么,有哪些高效地手动介入方式呢?
使用注释或特定的标记语言,在代码中添加上下文信息。如:在 AutoDev 中的聊天输入框使用变量,如: $selectionlanguage等方式。
通过交互式界面,实时提供反馈和修正,以引导 AI 生成更准确的内容。如:在输入区域中,可以选择相关的文件,或者额外加入文件等。
建立模板或模式,让用户可以根据特定的场景选择和应用。如:在 JetBrains AI 插件中,可以选择提交信息、测试等的模板,以生成更加符合场景的内容。
自定义提示词,以让团队加入特有上下文信息。如:在 Continue 中,用户可以自定义一些提示词和 action 等,来生成更加符合团队的内容。
……
与之相匹配的是,这些手动介入的方式存在大量的学习成本,以及如何让用户更好地理解这些手动介入的方式,以提升用户的使用体验。
四月,我们开始构建 AutoDev 的 VSCode 版本,在这个版本中我们加入了两个 @workspace 似的聊天问答策略,以帮助用户更好地理解 AI 的生成内容。策略一参考的是 辅助知识理解的 Bloop 项目,它采用的是假设性代码生成的检索方式;策略二参考是 GitHub Copilot 的关键词生成方式,将用户的问答转换为关键词来进行检索。不论是哪种方式最后都会遇到挑战,一个项目的过去和现在的开发人员,并没有对如何命名达到一致的标准。这也就导致了 AI 并不总能很好地检索到相关的内容。
团队协作是靠共识来推动的,而共识是 AI 辅助团队的一个基础。在采用经典的软件工程方法,如领域驱动设计(DDD)等,我们是通过:
定义领域模型。通过领域模型,将业务领域中的概念和规则抽象出来,形成一致的语言和概念体系。
创建统一的语言。确保团队成员在沟通和开发过程中使用统一的语言和术语,减少误解和沟通成本。
应用领域驱动设计原则。通过划分 bounded context(限界上下文),明确不同部分的职责和交互,构建清晰的应用架构。
这也就意味着,我们需要通过工程的方式告知 AI 工具,模型、语言和上下文边界,避免长上下文导致 AI 迷失的问题。
构建统一领域语言的过程并非一帆风顺,它需要团队的共同努力和持续的维护更新。反向的,这就意味着,我们需要借助 AI 进行知识的重构,诸如于生成合乎命名 的代码、重构出更好的领域语言等。
七月,当我在休长期服务假时,我创建了全新的开源项目《AI辅助软件工程:实践与案例解析》:https://aise.phodal.com/。在这个项目中,我收集了国内外的大量 AI 辅助研发工具,并进行了大量的调研与案例分析。在这个过程中,我发现了一个有趣的现象:AI 辅助研发工具的领域知识检索方式是多样的,对于不同的工具团队,采纳的方式也是不同的。
通常来说,罗马不是一天建成的,我们可以简单地把 AI 辅助厂商分为两类 —— 基于已有的开发工具增强的,如 SourceGraph、JetBrains 等;基于新的 AI 工具增强的,如 Cursor 等。在历史包袱不同的情况下,它们的领域知识检索方式也是不同的。
结构化知识依旧是首选。尽管有大量的工具可以将你的 PDF、Word 等转换为 markdown,再去拆分 chunk,但是这并不是最好的方式。不同文档的结构化方式不同, 你需要根据不同的文档类型,采用不同的结构化方式。结合 AI 先进行初步的清洗,是值得去尝试的一条路径。
充分利用数字化工具是不可或缺的。诸如 SourceGraph Codey 就可以借助已有存储的代码搜索能力进行检查。而诸如于如果你的目标更为宏大,诸如于基于 Gitlab 或者 Confluence 构建统一的内部 API 市场与查询,那么你得考虑先进行数字化的 API 管理,其次再进行 AI 的检索。
不同环节考虑不同向量化模型。如果只是简单的代码检索,可以考虑直接使用本地的模型。而如果是需要跨团队、跨项目的检索,那么你需要考虑使用 云端的模型。
在没有进行结构化之前,向量化是效率最低、效果最低的一种方式,但是实践成本最低的一种方式。实践成本最低,并不意味着成本最低,只是上手成本最低。
AutoCRUD 是我们探索 AI 编码能力极限的第一个尝试。在这个试验里,我们将 AI 与编码的 CRUD 模式相结合,从而让 AI 实现自动的编码流程。尽管,这并 非主流的 AI 自动编码方式,现今的智能体都是基于 AI 来进行规划的。而 AI 规划是基于通用的知识库, 也就是在你这个场景之下,Controller-Service-Repository 分层之下,它的编码方式应该就是这么去修改的。当你添加新的功能时,也应该采用类似的方式。
而当你在利用 AI 来进行任务拆解的时候,它也是基于已有学习到的模型进行的拆解。而一旦你的代码中有一些不符合模式的时候,它就会出现问题,比如你的代码中 可能同时存在多种编程范式。
模式应用到规则化提示词。模型理解主流的各种编程范式,自然而言,我们只需要根据不同的语言,动态生成适用于不同语言的模式即可。
清晰的任务描述是规划的基础。我曾经大量使用 GitHub Copilot CodeSpaces 来进行代码生成,它可以结合我在 GitHub issue 的描述,来生成代码。当你的任务描述不清晰时,它就会出现问题;而当你的任务描述清晰时,它的问题就会减少,但是也写不出可运行的代码。
集成环境依然是智能体的最好介质。尽管有大量的云端 AI 编辑器,但是缺少 IDE 中的 I(Integration 集成)能力,AI 就难以自动化进行任务,诸如于语法修复、运行测试、辅助进行 debug 等。
也因此,它需要拿到足够的上下文才能做好任务的拆解,而如我们所知的它总是拿不到足够的上下文。
Unblocked 是我看到一个非常有创意的 AI 知识管理和消费工具 —— 它可以上你在 Web、macOS、JetBrain IDEs、VSCode、IM(如 Slack)上管理和运用你的知识。简单来说,它通常将来自 GitHub、Slack、Confluence、Linear 等平台的内容上下文整合进来,帮助您找到关于应用程序的准确答案。对于企业来说,这就是一个非常值得参考的点:将 Jira、Gitlab.com/码云、Confluence、IM 等平台的内容整合进来,帮助团队更好地管理和运用知识。再通过智能体或者 API 的方式,提供给 AI 工具,以帮助 AI 更好地理解团队的知识。诸如于 AutoDev 的智能体,就可以通过这种方式来应用企业提供的内部知识库。
十月,我们在探索 AI 辅助需求时,同样也遇到类似的知识挑战。知识工程是进一步提升 AI 辅助研发质量的关键,你需要考虑:
开发 AI 工具原型是基础。知识工程需要考虑到消费端的需求,进而设计出合适的知识库结构、工具与 API 体系。当然,自上而下规划也是一个不错的选择。
持续知识的运营与管理是不可或缺的。高质量的语料、高质量的知识固然很重要,但是人们缺的并不是这些,而是如何构建反馈回路的运行机制,来让知识不断地更新。
不过,在你进一步重构之前,你需要考虑,什么才是知识?
在最近的模型发布中,我们可以看到模型似乎已经到了一个瓶颈,无法再继续大幅提升。这也就意味着,我们需要通过其他方式来提升效果,而不仅仅是依赖模型的提升。
诸如于:StreamDiff 是当前阶段主流的问答代码生成方式,即根据问题,从头生成代码,再以类似于 patch 的方式展现给用户。AI 每次总是尽可能的从头生成一遍代码,而不是通过真正的 patch 方式来生成。尽管,我们相信 patch 的计算方式终会实现,但是目前的 AI 模型还无法做得很好。
依赖于生成式 AI 的概率机制,它总是会有一些不确定性,而这种不确定性是无法通过交互来解决的。
非普适式的问题难以解决。诸如于 Intellij IDEA 插件代码,模型很难得到准确的答案 —— 10 个里有 9 个是错的;而类似于这一类的问题,又特别的多。
代码中的数值问题。模型很难得到准确的数值,诸如于你调用 AI 来对你的算法生成测试,它可以实现逻辑上的正确,但是数值上的正确需要你自己来验证。
顾尾不顾头的问题。典型的问题是,在 Java 代码中 AI 会无意多或者少 import 一些包,导致代码无法运行。
……
而这样的 corner case 问题,特别特别的多,大量的这一类问题都需要通过规则来解决,而不是通过模型来解决。又或者是诸如于 StreamDiff 换一种新的方式来解决。
在这一年里,我发现很多工具和团队都在盲目追求 AI 辅助研发,但是却忽略了最基本的软件工程问题。我们经常看到这样的场景:
需求文档写得很差,就想要 AI 来帮忙分析需求
代码没有任何文档和注释,就想要 AI 来理解代码
缺乏代码审查机制,就期望 AI 能自动发现所有问题
运维流程全靠手动,就期望 AI 能自动化运维
监控告警体系不完善,就想要 AI 来预测系统故障
……
AI 辅助研发并不是万能的。如果你的团队连基本的软件工程实践都做不好,那么 AI 也帮不了你。相反,如果你的团队有良好的软件工程实践,那么 AI 就能够发挥更大的作用。换句话说,AI 辅助研发是在已有软件工程实践基础上的增强,而不是替代。它能帮助我们更高效地完成工作,但不能解决根本的工程问题。
因此,在探索 AI 辅助研发之前,我们应该考虑先建立完善的软件工程体系,同时:
培养团队的全流程工程能力
建立规范的开发与运维流程
完善自动化基础设施
构建可度量的改进机制
只有在这些基础之上,AI 辅助研发才能真正发挥价值,帮助团队提升效率和质量。否则,再先进的 AI 工具,也只能是空中楼阁。
来源:小周科技讲堂